...
diff --git a/1.9.10/README.txt b/1.9.10/README.txt new file mode 100644 index 0000000..c8f9179 --- /dev/null +++ b/1.9.10/README.txt
@@ -0,0 +1,51 @@ +== Jackson Json-processor == + +This is the Jackson Json-processor package. Project home page can be found +from: + +http://jackson.codehaus.org/ + +which also has links to support forums such as mailing lists, as well +as links to obtain source code and binary artifacts. + +=== Functionality === + +Jackson implements functionality for: + +* Reading (parsing) and writing (generation) of Json content +* Data-binding (data-mapping, [de-]serialization) support to + allow for converting between Json and Java objects +* Support for converting to/from other data formats and access APIs, + to improve interoperability. + +=== Requirements === + +Jackson can be used on standard J2SE 1.5 platform. Some effort is made +to support other non-standard platforms as well. + +=== Licensing === + +Jackson can be used for any purpose, but to (re)distribute it, distributors +(such as libraries and frameworks that use Jackson) will need to +choose which License they want to apply to distribution, and to use appropriate +jars that enclose license documentation. +No work needed beyond choosing the appropriate jar(s). + +Currently two Open Source licenses are available for use: + +* Apache License 2.0 (AL 2.0) +* Lesser/Library General Public License (LGPL 2.1) + +These licenses have proven adequate to cover all current use cases. + +=== Contributing === + +All code contributions are to be made according the +Contributor Agreement document found from under DEV/ directory within source +repository and downloadable source archives. + +CA is needed to allow Jackson project to publish under different Licenses, +and to indicate good faith effort to comply with copyright rules governing +use and distribution of the source code (and its equivalents as outlined +in the agreement) involved. This is also useful for (re)distributors to +reduce their need to independently verify origin of source code.
diff --git a/1.9.10/ant/build-clirr.xml b/1.9.10/ant/build-clirr.xml new file mode 100644 index 0000000..05af071 --- /dev/null +++ b/1.9.10/ant/build-clirr.xml
@@ -0,0 +1,21 @@ +<?xml version="1.0" standalone="yes" ?> +<project name="Compatibility testing to ensure compatibility between minor versions" + default="check-compatibility" +> + <path id="clirr.lib"> + <fileset dir="${basedir}/regression" includes="clirr*.jar" /> + </path> + <taskdef classpathref="clirr.lib" resource="clirrtask.properties" /> + + <target name="check-compatibility"> + <clirr> + <origFiles dir="${basedir}/regression"> + <include name="jackson*.jar" /> + </origFiles> + <newFiles dir="${basedir}/build"> + <include name="jackson-core-asl*.jar" /> + <include name="jackson-mapper-asl*.jar" /> + </newFiles> + </clirr> + </target> +</project>
diff --git a/1.9.10/ant/build-coverage.xml b/1.9.10/ant/build-coverage.xml new file mode 100644 index 0000000..d4522e2 --- /dev/null +++ b/1.9.10/ant/build-coverage.xml
@@ -0,0 +1,89 @@ +<?xml version="1.0" standalone='yes'?> + +<!-- This Ant build file fragment contains targets needed to run + code coverage analysis + --> +<project name="Code coverage tasks for Jackson" basedir="."> + + <!-- Support for Cobertura code coverage tool --> + <property name="cobertura.coverage.dir" value="${dir.build}/coverage" /> + <path id="cobertura.lib"> + <fileset dir="${dir.lib}/cobertura" includes="*.jar" /> + <fileset dir="${dir.lib}/ext/asm" includes="*.jar" /> + </path> + <taskdef classpathref="cobertura.lib" resource="tasks.properties" /> + + <!-- Code coverage using Cobertura: --> + + <target name="build.coverage" depends="test.compile"> + <!-- First, need to instrument classes --> + <property name="cobertura.instr.dir" value="${dir.build}/cobertura-instr" /> + <cobertura-instrument todir="${cobertura.instr.dir}"> + <fileset dir="${dir.build.classes.core}"> + <include name="org/codehaus/jackson/**/*.class"/> + </fileset> + <fileset dir="${dir.build.classes.mapper}"> + <include name="org/codehaus/jackson/map/**/*.class"/> + <include name="org/codehaus/jackson/node/**/*.class"/> + <include name="org/codehaus/jackson/schema/**/*.class"/> + </fileset> + </cobertura-instrument> + + <junit fork="once" printsummary="yes" haltonfailure="no" showoutput="yes" + maxmemory="300M" + > + <sysproperty key="net.sourceforge.cobertura.datafile" file="${basedir}/cobertura.ser" /> + <batchtest fork="no" todir="${dir.test.xmlresults}"> + <fileset dir="${dir.test.classes}"> + <!-- Need to exclude inner classes... --> + <exclude name="**/*$*.class"/> + <!-- and one particularly slow test? --> + <exclude name="**/TestStringGeneration.class"/> + <include name="**/Test*.class"/> + </fileset> + </batchtest> + <formatter type="xml" /> + <!-- Order is important: must first have instrumented classes --> + <classpath location="${cobertura.instr.dir}" /> + + <!-- Actual tests: --> + <classpath path="${dir.test.classes}" /> + <!-- Cobertura support: --> + <classpath refid="cobertura.lib" /> + <classpath> + <!-- Note: while this may seem superfluous, it is actually + needed because Cobertura does not instrument things + like interfaces. So some of the class files are + needed from non-instrumented location + --> + <pathelement path="${dir.build.classes.core}" /> + <pathelement path="${dir.build.classes.mapper}" /> + <pathelement path="${dir.build.classes.xc}" /> + <path refid="test-libs"/> + </classpath> + </junit> + <!-- and then reporting --> + <cobertura-report format="html" destdir="${cobertura.coverage.dir}" > + <fileset dir="${dir.src.java.core}"> + <include name="org/codehaus/**/*.java" /> + </fileset> + <fileset dir="${dir.src.java.mapper}"> + <include name="org/codehaus/**/*.java" /> + </fileset> + <fileset dir="${dir.src.java.xc}"> + <include name="org/codehaus/**/*.java" /> + </fileset> + </cobertura-report> + + <!-- Let's also report junit results? (at least if they fail) --> +<!-- + <junitreport todir="${dir.test.results}"> + <fileset dir="${dir.test.xmlresults}"> + <include name="TEST-*.xml" /> + </fileset> + <report todir="${dir.test.results}" /> + </junitreport> +--> + </target> + +</project>
diff --git a/1.9.10/ant/build-jarjar-asm.xml b/1.9.10/ant/build-jarjar-asm.xml new file mode 100644 index 0000000..94f5968 --- /dev/null +++ b/1.9.10/ant/build-jarjar-asm.xml
@@ -0,0 +1,17 @@ +<?xml version="1.0" standalone="yes" ?> +<project name="Ant task(s) to repackage Asm under Jackson class hierarchy, to + avoid version problems" + default="repackage-asm" +> + <target name="repackage-asm"> + <taskdef name="jarjar" classname="com.tonicsystems.jarjar.JarJarTask" + classpath="lib/ext/jarjar/jarjar-1.0.jar" + /> + <jarjar jarfile="lib/repackaged/jackson-asm-3.3.jar"> + <zipfileset src="lib/ext/asm/asm-3.3.jar"/> + <rule pattern="org.objectweb.asm.**" + result="org.codehaus.jackson.org.objectweb.asm.@1" + /> + </jarjar> + </target> +</project>
diff --git a/1.9.10/ant/build-maven-deploy.xml b/1.9.10/ant/build-maven-deploy.xml new file mode 100644 index 0000000..76aff57 --- /dev/null +++ b/1.9.10/ant/build-maven-deploy.xml
@@ -0,0 +1,220 @@ +<?xml version="1.0" standalone='yes'?> +<!-- This Ant build file fragment contains targets for + deploying artifacts to Maven repositories + --> + +<project name="Tasks for Maven deployment" basedir="." + xmlns:artifact="antlib:org.apache.maven.artifact.ant" +> + + <typedef resource="org/apache/maven/artifact/ant/antlib.xml" + uri="urn:maven-artifact-ant" + > + <classpath> + <fileset dir="${dir.lib}/ant"> + <include name="maven-ant*.jar" /> + </fileset> + </classpath> + </typedef> + + <target name="maven.init"> + <!-- First regular release poms --> + <artifact:pom id="pom.asl.core" file="${dir.dist}/jackson-core-asl-${IMPL_VERSION}.pom" /> + <artifact:pom id="pom.asl.mapper" file="${dir.dist}/jackson-mapper-asl-${IMPL_VERSION}.pom" /> + <artifact:pom id="pom.lgpl.core" file="${dir.dist}/jackson-core-lgpl-${IMPL_VERSION}.pom" /> + <artifact:pom id="pom.lgpl.mapper" file="${dir.dist}/jackson-mapper-lgpl-${IMPL_VERSION}.pom" /> + <artifact:pom id="pom.jaxrs" file="${dir.dist}/jackson-jaxrs-${IMPL_VERSION}.pom" /> + <artifact:pom id="pom.xc" file="${dir.dist}/jackson-xc-${IMPL_VERSION}.pom" /> + <artifact:pom id="pom.smile" file="${dir.dist}/jackson-smile-${IMPL_VERSION}.pom" /> + <artifact:pom id="pom.mrbean" file="${dir.dist}/jackson-mrbean-${IMPL_VERSION}.pom" /> + + <!-- And then snapshots --> + <artifact:pom id="pom.snapshot.core" file="${dir.snapshot}/jackson-core-asl-${IMPL_VERSION}-SNAPSHOT.pom" /> + <artifact:pom id="pom.snapshot.mapper" file="${dir.snapshot}/jackson-mapper-asl-${IMPL_VERSION}-SNAPSHOT.pom" /> + <artifact:pom id="pom.snapshot.jaxrs" file="${dir.snapshot}/jackson-jaxrs-${IMPL_VERSION}-SNAPSHOT.pom" /> + <artifact:pom id="pom.snapshot.xc" file="${dir.snapshot}/jackson-xc-${IMPL_VERSION}-SNAPSHOT.pom" /> + <artifact:pom id="pom.snapshot.smile" file="${dir.snapshot}/jackson-smile-${IMPL_VERSION}-SNAPSHOT.pom" /> + <artifact:pom id="pom.snapshot.mrbean" file="${dir.snapshot}/jackson-mrbean-${IMPL_VERSION}-SNAPSHOT.pom" /> + </target> + + <target name="maven.repos" depends="maven.init"> + <!-- need user, password: --> + <fail unless="user" message="Must define -Duser" /> + <fail unless="password" message="Must define -Dpassword" /> + + <!-- uploads done using webdav, need to register --> + <artifact:install-provider artifactId="wagon-webdav" version="1.0-beta-1" /> + + <echo message="(authenticating as user '${user}')" /> + <artifact:remoteRepository id="repo.release" + url="dav:https://dav.codehaus.org/repository/jackson" + > + <authentication username="${user}" password="${password}" /> + <releases enabled="true"/> + <snapshots enabled="false"/> + </artifact:remoteRepository> + + <artifact:remoteRepository id="repo.snapshot" + url="dav:https://dav.codehaus.org/snapshots.repository/jackson" + > + <authentication username="${user}" password="${password}" /> + <releases enabled="false"/> + <snapshots enabled="true"/> + </artifact:remoteRepository> + </target> + + <!-- target for installing release versions locally --> + <target name="maven.local.release" depends="maven.init"> + <artifact:install pomRefId="pom.asl.core" + file="${dir.dist}/jackson-core-asl-${IMPL_VERSION}.jar"> + <attach file="${dir.dist}/jackson-core-asl-${IMPL_VERSION}-sources.jar" type="jar" classifier="sources" /> + <attach file="${dir.dist}/jackson-core-asl-${IMPL_VERSION}-javadoc.jar" type="jar" classifier="sources" /> + </artifact:install> + <artifact:install pomRefId="pom.asl.mapper" + file="${dir.dist}/jackson-mapper-asl-${IMPL_VERSION}.jar"> + <attach file="${dir.dist}/jackson-mapper-asl-${IMPL_VERSION}-sources.jar" type="source" classifier="sources" /> + <attach file="${dir.dist}/jackson-mapper-asl-${IMPL_VERSION}-javadoc.jar" type="source" classifier="sources" /> + </artifact:install> + <artifact:install pomRefId="pom.lgpl.core" + file="${dir.dist}/jackson-core-lgpl-${IMPL_VERSION}.jar"> + <attach file="${dir.dist}/jackson-core-lgpl-${IMPL_VERSION}-sources.jar" type="source" classifier="sources" /> + </artifact:install> + <artifact:install pomRefId="pom.lgpl.mapper" + file="${dir.dist}/jackson-mapper-lgpl-${IMPL_VERSION}.jar"> + <attach file="${dir.dist}/jackson-mapper-lgpl-${IMPL_VERSION}-sources.jar" type="source" classifier="sources" /> + </artifact:install> + <artifact:install pomRefId="pom.jaxrs" + file="${dir.dist}/jackson-jaxrs-${IMPL_VERSION}.jar"> + <attach file="${dir.dist}/jackson-jaxrs-${IMPL_VERSION}-sources.jar" type="source" classifier="sources" /> + </artifact:install> + <artifact:install pomRefId="pom.xc" + file="${dir.dist}/jackson-xc-${IMPL_VERSION}.jar"> + <attach file="${dir.dist}/jackson-xc-${IMPL_VERSION}-sources.jar" type="source" classifier="sources" /> + </artifact:install> + <artifact:install pomRefId="pom.smile" + file="${dir.dist}/jackson-smile-${IMPL_VERSION}.jar"> + <attach file="${dir.dist}/jackson-smile-${IMPL_VERSION}-sources.jar" type="source" classifier="sources" /> + </artifact:install> + <artifact:install pomRefId="pom.mrbean" + file="${dir.dist}/jackson-mrbean-${IMPL_VERSION}.jar"> + <attach file="${dir.dist}/jackson-mrbean-${IMPL_VERSION}-sources.jar" type="source" classifier="sources" /> + </artifact:install> + </target> + + <!-- target for deploying SNAPSHOT versions in "real" Maven + - repository + - + - about settings: + - + - + uniqueVersion=true, so we get proper (?) names + --> + <target name="maven.remote.snapshot" depends="maven.repos"> + + <artifact:deploy pomRefId="pom.snapshot.core" uniqueVersion="true" + file="${dir.dist}/jackson-core-asl-${IMPL_VERSION}.jar" + > + <remoteRepository refid="repo.snapshot" /> + <attach file="${dir.dist}/jackson-core-asl-${IMPL_VERSION}-sources.jar" type="jar" classifier="sources" /> + </artifact:deploy> + + <artifact:deploy pomRefId="pom.snapshot.mapper" uniqueVersion="true" + file="${dir.dist}/jackson-mapper-asl-${IMPL_VERSION}.jar" + > + <remoteRepository refid="repo.snapshot" /> + <attach file="${dir.dist}/jackson-mapper-asl-${IMPL_VERSION}-sources.jar" type="jar" classifier="sources" /> + </artifact:deploy> + + <artifact:deploy pomRefId="pom.snapshot.jaxrs" uniqueVersion="true" + file="${dir.dist}/jackson-jaxrs-${IMPL_VERSION}.jar" + > + <remoteRepository refid="repo.snapshot" /> + <attach file="${dir.dist}/jackson-jaxrs-${IMPL_VERSION}-sources.jar" type="jar" classifier="sources" /> + </artifact:deploy> + + <artifact:deploy pomRefId="pom.snapshot.xc" uniqueVersion="true" + file="${dir.dist}/jackson-xc-${IMPL_VERSION}.jar" + > + <remoteRepository refid="repo.snapshot" /> + <attach file="${dir.dist}/jackson-xc-${IMPL_VERSION}-sources.jar" type="jar" classifier="sources" /> + </artifact:deploy> + + <artifact:deploy pomRefId="pom.snapshot.smile" uniqueVersion="true" + file="${dir.dist}/jackson-smile-${IMPL_VERSION}.jar" + > + <remoteRepository refid="repo.snapshot" /> + <attach file="${dir.dist}/jackson-smile-${IMPL_VERSION}-sources.jar" type="jar" classifier="sources" /> + </artifact:deploy> + + <artifact:deploy pomRefId="pom.snapshot.mrbean" uniqueVersion="true" + file="${dir.dist}/jackson-mrbean-${IMPL_VERSION}.jar" + > + <remoteRepository refid="repo.snapshot" /> + <attach file="${dir.dist}/jackson-mrbean-${IMPL_VERSION}-sources.jar" type="jar" classifier="sources" /> + </artifact:deploy> + </target> + + <!-- target for deploying release versions in "real" Maven + - + - about settings: "uniqueVersion" set to false, to support + - possible redeployment + --> + <target name="maven.remote.release" depends="maven.repos"> + <artifact:deploy pomRefId="pom.asl.core" uniqueVersion="false" + file="${dir.dist}/jackson-core-asl-${IMPL_VERSION}.jar" + > + <remoteRepository refid="repo.release" /> + <attach file="${dir.dist}/jackson-core-asl-${IMPL_VERSION}-sources.jar" type="jar" classifier="sources" /> + </artifact:deploy> + + <artifact:deploy pomRefId="pom.asl.mapper" uniqueVersion="false" + file="${dir.dist}/jackson-mapper-asl-${IMPL_VERSION}.jar" + > + <remoteRepository refid="repo.release" /> + <attach file="${dir.dist}/jackson-mapper-asl-${IMPL_VERSION}-sources.jar" type="jar" classifier="sources" /> + </artifact:deploy> + + <artifact:deploy pomRefId="pom.lgpl.core" uniqueVersion="false" + file="${dir.dist}/jackson-core-lgpl-${IMPL_VERSION}.jar" + > + <remoteRepository refid="repo.release" /> + <attach file="${dir.dist}/jackson-core-lgpl-${IMPL_VERSION}-sources.jar" type="jar" classifier="sources" /> + </artifact:deploy> + + <artifact:deploy pomRefId="pom.lgpl.mapper" uniqueVersion="false" + file="${dir.dist}/jackson-mapper-lgpl-${IMPL_VERSION}.jar" + > + <remoteRepository refid="repo.release" /> + <attach file="${dir.dist}/jackson-mapper-lgpl-${IMPL_VERSION}-sources.jar" type="jar" classifier="sources" /> + </artifact:deploy> + + <artifact:deploy pomRefId="pom.jaxrs" uniqueVersion="false" + file="${dir.dist}/jackson-jaxrs-${IMPL_VERSION}.jar" + > + <remoteRepository refid="repo.release" /> + <attach file="${dir.dist}/jackson-jaxrs-${IMPL_VERSION}-sources.jar" type="jar" classifier="sources" /> + </artifact:deploy> + + <artifact:deploy pomRefId="pom.xc" uniqueVersion="false" + file="${dir.dist}/jackson-xc-${IMPL_VERSION}.jar" + > + <remoteRepository refid="repo.release" /> + <attach file="${dir.dist}/jackson-xc-${IMPL_VERSION}-sources.jar" type="jar" classifier="sources" /> + </artifact:deploy> + + <artifact:deploy pomRefId="pom.smile" uniqueVersion="false" + file="${dir.dist}/jackson-smile-${IMPL_VERSION}.jar" + > + <remoteRepository refid="repo.release" /> + <attach file="${dir.dist}/jackson-smile-${IMPL_VERSION}-sources.jar" type="jar" classifier="sources" /> + </artifact:deploy> + + <artifact:deploy pomRefId="pom.mrbean" uniqueVersion="false" + file="${dir.dist}/jackson-mrbean-${IMPL_VERSION}.jar" + > + <remoteRepository refid="repo.release" /> + <attach file="${dir.dist}/jackson-mrbean-${IMPL_VERSION}-sources.jar" type="jar" classifier="sources" /> + </artifact:deploy> + + </target> + +</project>
diff --git a/1.9.10/ant/build-mini.xml b/1.9.10/ant/build-mini.xml new file mode 100644 index 0000000..a9ca05f --- /dev/null +++ b/1.9.10/ant/build-mini.xml
@@ -0,0 +1,45 @@ +<?xml version="1.0" standalone='yes'?> +<!-- This Ant build file fragment contains target(s) needed to build + "mini" version of the core parser+generator package + --> + +<project name="Mini-build tasks for Jackson" basedir="."> + <property name="dir.build.classes.mini" location="${dir.build}/classes/mini" /> + <target name="compile.mini" depends="prepare"> + <mkdir dir="${dir.build.classes.mini}" /> + <javac srcdir="${dir.src.java.core}" destdir="${dir.build.classes.mini}" + source="1.5" target="1.5" + debug="false" includeantruntime="false" + > + <compilerarg value="-Xlint:unchecked" /> + <exclude name="**/package-info.java" /> + <!-- and do NOT compile things that we can live without: --> + <exclude name="org/codehaus/jackson/annotate/*.java" /> + <exclude name="org/codehaus/jackson/util/TokenBuffer.java" /> + <include name="org/codehaus/**/*.java" /> + </javac> + <copy file="${dir.build}/VERSION.txt" toDir="${dir.build.classes.core}/org/codehaus/jackson/impl" /> + + <!-- + --> + </target> + + <target name="jar.mini" depends="compile.mini"> + <jar jarfile="${dir.build}/jackson-mini-${IMPL_VERSION}.jar" filesonly="true" > + <manifest> + <attribute name="Built-By" value="${user.name}"/> + <attribute name="Specification-Title" value="${JSON_TITLE}"/> + <attribute name="Specification-Version" value="${JSON_VERSION}"/> + <attribute name="Specification-Vendor" value="${JSON_VENDOR}"/> + <attribute name="Implementation-Title" value="${IMPL_TITLE_CORE}"/> + <attribute name="Implementation-Version" value="${IMPL_VERSION}"/> + <attribute name="Implementation-Vendor" value="${IMPL_VENDOR}"/> + </manifest> + <fileset dir="${dir.build.classes.mini}"> + <include name="org/codehaus/jackson/**/*.class" /> + </fileset> + </jar> + </target> + +</project> +
diff --git a/1.9.10/ant/build-osgi.xml b/1.9.10/ant/build-osgi.xml new file mode 100644 index 0000000..2d0ba75 --- /dev/null +++ b/1.9.10/ant/build-osgi.xml
@@ -0,0 +1,426 @@ +<?xml version="1.0" standalone='yes'?> +<!-- This Ant build file fragment contains targets needed to build + distributable OSGi-aware artifacts, + as well as "jackson-all" non-bundle jar + --> + +<project name="OSGi export tasks for Jackson" basedir="."> + + <!-- Need BND task for OSGi bundle/metadata creation --> + <taskdef name="osgiJar" classname="net.luminis.build.plugin.bnd.BuildTask"> + <classpath> + <fileset dir="${basedir}/lib/ant" includes="bndtask*.jar" /> + </classpath> + </taskdef> + + <target name="jars.asl" depends="jar.core.asl, jar.mapper.asl" /> + <target name="jars.lgpl" depends="jar.core.lgpl, jar.mapper.lgpl" /> + <target name="jars.other" depends="jar.jaxrs, jar.xc, jar.smile, jar.mrbean" /> + <target name="jars.tools" depends="jar.tool.smile" /> + + <!-- Let's build our JARs as OSGi bundles; then they work + both within and outside of OSGi containers + --> + + <!-- Jackson requires Java5 (enums, some generics) --> + <!-- 02-Feb-2011, tatu: As per [JACKSON-481], it looks like OSGi + requires adding _all_ applicable envs... yuck + --> + <property name="REQ_JDK_VERSION" value="J2SE-1.5, JavaSE-1.6" /> + + <!-- ASL-licensed: core, mapper jars --> + + <target name="jar.core.asl" depends="compile.core"> + <osgiJar + outputdir="${dir.build}" + bundleName="${IMPL_TITLE_CORE}" + bundleVendor="${IMPL_VENDOR}" + bundleSymbolicName="jackson-core-asl" + bundleVersion="${IMPL_VERSION}" + bundleLicense="http://www.apache.org/licenses/LICENSE-2.0.txt" + bundleRequiredExecutionEnvironment="${REQ_JDK_VERSION}" + filename="jackson-core-asl-${IMPL_VERSION}" + exportpackage=" +org.codehaus.jackson;version=${IMPL_VERSION}, +org.codehaus.jackson.annotate;version=${IMPL_VERSION}, +org.codehaus.jackson.format;version=${IMPL_VERSION}, +org.codehaus.jackson.impl;version=${IMPL_VERSION}, +org.codehaus.jackson.io;version=${IMPL_VERSION}, +org.codehaus.jackson.sym;version=${IMPL_VERSION}, +org.codehaus.jackson.type;version=${IMPL_VERSION}, +org.codehaus.jackson.util;version=${IMPL_VERSION} +" + privatePackage="" + includeResource="META-INF=release-notes/asl" + includeIncludeResourceHeader="false" + > + <classpath><pathelement path="${dir.build.classes.core}" /></classpath> + <manifest> + <attribute name="Built-By" value="${user.name}"/> + <attribute name="Implementation-Title" value="${IMPL_TITLE_CORE}"/> + <attribute name="Implementation-Version" value="${IMPL_VERSION}"/> + <attribute name="Implementation-Vendor" value="${IMPL_VENDOR}"/> + <attribute name="Specification-Title" value="${JSON_TITLE}"/> + <attribute name="Specification-Version" value="${JSON_VERSION}"/> + <attribute name="Specification-Vendor" value="${JSON_VENDOR}"/> + </manifest> + </osgiJar> + </target> + + <target name="jar.mapper.asl" depends="compile.mapper"> + <osgiJar + outputdir="${dir.build}" + bundleName="${IMPL_TITLE_MAPPER}" + bundleVendor="${IMPL_VENDOR}" + bundleSymbolicName="jackson-mapper-asl" + bundleVersion="${IMPL_VERSION}" + bundleLicense="http://www.apache.org/licenses/LICENSE-2.0.txt" + bundleRequiredExecutionEnvironment="${REQ_JDK_VERSION}" + filename="jackson-mapper-asl-${IMPL_VERSION}" + importPackage=" +org.codehaus.jackson;version='${IMPL_VERSION}', +org.codehaus.jackson.annotate;version='${IMPL_VERSION}', +org.codehaus.jackson.format;version='${IMPL_VERSION}', +org.codehaus.jackson.impl;version='${IMPL_VERSION}', +org.codehaus.jackson.io;version='${IMPL_VERSION}', +org.codehaus.jackson.type;version='${IMPL_VERSION}', +org.codehaus.jackson.util;version='${IMPL_VERSION}', +org.xml.sax,org.w3c.dom, +javax.xml.datatype, javax.xml.namespace, javax.xml.parsers +" + dynamicImportPackage=" +org.joda.time, org.joda.time.format, +org.w3c.dom.ls, org.w3c.dom.bootstrap" + exportpackage=" +org.codehaus.jackson.map;version=${IMPL_VERSION}, +org.codehaus.jackson.map.annotate;version=${IMPL_VERSION}, +org.codehaus.jackson.map.deser;version=${IMPL_VERSION}, +org.codehaus.jackson.map.deser.impl;version=${IMPL_VERSION}, +org.codehaus.jackson.map.deser.std;version=${IMPL_VERSION}, +org.codehaus.jackson.map.exc;version=${IMPL_VERSION}, +org.codehaus.jackson.map.ext;version=${IMPL_VERSION}, +org.codehaus.jackson.map.introspect;version=${IMPL_VERSION}, +org.codehaus.jackson.map.jsontype;version=${IMPL_VERSION}, +org.codehaus.jackson.map.jsontype.impl;version=${IMPL_VERSION}, +org.codehaus.jackson.map.module;version=${IMPL_VERSION}, +org.codehaus.jackson.map.ser;version=${IMPL_VERSION}, +org.codehaus.jackson.map.ser.impl;version=${IMPL_VERSION}, +org.codehaus.jackson.map.ser.std;version=${IMPL_VERSION}, +org.codehaus.jackson.map.type;version=${IMPL_VERSION}, +org.codehaus.jackson.map.util;version=${IMPL_VERSION}, +org.codehaus.jackson.node;version=${IMPL_VERSION}, +org.codehaus.jackson.schema;version=${IMPL_VERSION} +" + privatePackage=" +org.codehaus.jackson.map.ext +" + includeResource="META-INF=release-notes/asl" + includeIncludeResourceHeader="false" + > + <classpath><pathelement path="${dir.build.classes.mapper}" /></classpath> + <manifest> + <attribute name="Built-By" value="${user.name}"/> + <attribute name="Implementation-Title" value="${IMPL_TITLE_MAPPER}"/> + <attribute name="Implementation-Version" value="${IMPL_VERSION}"/> + <attribute name="Implementation-Vendor" value="${IMPL_VENDOR}"/> + </manifest> + </osgiJar> + </target> + + <!-- LGPL-licensed: core, mapper jars --> + + <target name="jar.core.lgpl" depends="compile.core"> + <osgiJar + outputdir="${dir.build}" + bundleName="${IMPL_TITLE_CORE}" + bundleVendor="${IMPL_VENDOR}" + bundleSymbolicName="jackson-core-lgpl" + bundleVersion="${IMPL_VERSION}" + bundleLicense="http://www.gnu.org/licenses/lgpl-2.1.html" + bundleRequiredExecutionEnvironment="${REQ_JDK_VERSION}" + filename="jackson-core-lgpl-${IMPL_VERSION}" + exportpackage=' +org.codehaus.jackson;version=${IMPL_VERSION}, +org.codehaus.jackson.annotate;version=${IMPL_VERSION}, +org.codehaus.jackson.format;version=${IMPL_VERSION}, +org.codehaus.jackson.impl;version=${IMPL_VERSION}, +org.codehaus.jackson.io;version=${IMPL_VERSION}, +org.codehaus.jackson.sym;version=${IMPL_VERSION}, +org.codehaus.jackson.type;version=${IMPL_VERSION}, +org.codehaus.jackson.util;version=${IMPL_VERSION} +' + privatePackage="" + includeResource="META-INF=release-notes/lgpl" + includeIncludeResourceHeader="false" + > + <classpath> + <pathelement path="${dir.build.classes.core}" /> + </classpath> + <manifest> + <attribute name="Built-By" value="${user.name}"/> + <attribute name="Implementation-Title" value="${IMPL_TITLE_CORE}"/> + <attribute name="Implementation-Version" value="${IMPL_VERSION}"/> + <attribute name="Implementation-Vendor" value="${IMPL_VENDOR}"/> + <attribute name="Specification-Title" value="${JSON_TITLE}"/> + <attribute name="Specification-Version" value="${JSON_VERSION}"/> + <attribute name="Specification-Vendor" value="${JSON_VENDOR}"/> + </manifest> + </osgiJar> + </target> + + <target name="jar.mapper.lgpl" depends="compile.mapper"> + <osgiJar + outputdir="${dir.build}" + bundleName="${IMPL_TITLE_MAPPER}" + bundleVendor="${IMPL_VENDOR}" + bundleSymbolicName="jackson-mapper-lgpl" + bundleVersion="${IMPL_VERSION}" + bundleLicense="http://www.gnu.org/licenses/lgpl-2.1.html" + bundleRequiredExecutionEnvironment="${REQ_JDK_VERSION}" + filename="jackson-mapper-lgpl-${IMPL_VERSION}" + importPackage=" +org.codehaus.jackson;version='${IMPL_VERSION}', +org.codehaus.jackson.annotate;version='${IMPL_VERSION}', +org.codehaus.jackson.format;version='${IMPL_VERSION}', +org.codehaus.jackson.impl;version='${IMPL_VERSION}', +org.codehaus.jackson.io;version='${IMPL_VERSION}', +org.codehaus.jackson.type;version='${IMPL_VERSION}', +org.codehaus.jackson.util;version='${IMPL_VERSION}', +org.xml.sax, org.w3c.dom, +javax.xml.datatype, javax.xml.namespace, javax.xml.parsers +" + dynamicImportPackage=" +org.joda.time, org.joda.time.format, +org.w3c.dom.ls, org.w3c.dom.bootstrap" + exportpackage=" +org.codehaus.jackson.map;version=${IMPL_VERSION}, +org.codehaus.jackson.map.annotate;version=${IMPL_VERSION}, +org.codehaus.jackson.map.deser;version=${IMPL_VERSION}, +org.codehaus.jackson.map.deser.impl;version=${IMPL_VERSION}, +org.codehaus.jackson.map.deser.std;version=${IMPL_VERSION}, +org.codehaus.jackson.map.exc;version=${IMPL_VERSION}, +org.codehaus.jackson.map.ext;version=${IMPL_VERSION}, +org.codehaus.jackson.map.introspect;version=${IMPL_VERSION}, +org.codehaus.jackson.map.jsontype;version=${IMPL_VERSION}, +org.codehaus.jackson.map.jsontype.impl;version=${IMPL_VERSION}, +org.codehaus.jackson.map.module;version=${IMPL_VERSION}, +org.codehaus.jackson.map.ser;version=${IMPL_VERSION}, +org.codehaus.jackson.map.ser.impl;version=${IMPL_VERSION}, +org.codehaus.jackson.map.ser.std;version=${IMPL_VERSION}, +org.codehaus.jackson.map.type;version=${IMPL_VERSION}, +org.codehaus.jackson.map.util;version=${IMPL_VERSION}, +org.codehaus.jackson.node;version=${IMPL_VERSION}, +org.codehaus.jackson.schema;version=${IMPL_VERSION} +" + privatePackage=" +org.codehaus.jackson.map.ext +" + includeResource="META-INF=release-notes/lgpl" + includeIncludeResourceHeader="false" + > + <classpath><pathelement path="${dir.build.classes.mapper}" /></classpath> + <manifest> + <attribute name="Built-By" value="${user.name}"/> + <attribute name="Implementation-Title" value="${IMPL_TITLE_MAPPER}"/> + <attribute name="Implementation-Version" value="${IMPL_VERSION}"/> + <attribute name="Implementation-Vendor" value="${IMPL_VENDOR}"/> + </manifest> + </osgiJar> + </target> + + <!-- Others, ASL+LGPL licensed, just a single jar + (OSGi nominally just lists ASL, not sure if/how to + add multiple?) + --> + + <!-- First, JAX-RS provider jar --> + + <!-- 06-May-2009, tatu: Removed META-INF/services + registration as it could conflict with other + JAX-RS json providers. + + includeResource="META-INF/services=${dir.src.resource.jaxrs}" + + --> + <target name="jar.jaxrs" depends="compile.jaxrs"> + <osgiJar + outputdir="${dir.build}" + bundleName="${IMPL_TITLE_JAXRS}" + bundleVendor="${IMPL_VENDOR}" + bundleSymbolicName="jackson-jaxrs" + bundleVersion="${IMPL_VERSION}" + bundleLicense="http://www.apache.org/licenses/LICENSE-2.0.txt" + bundleRequiredExecutionEnvironment="${REQ_JDK_VERSION}" + filename="jackson-jaxrs-${IMPL_VERSION}" + importPackage=" +javax.ws.rs +,javax.ws.rs.core +,javax.ws.rs.ext +,org.codehaus.jackson;version='${IMPL_VERSION}' +,org.codehaus.jackson.map;version='${IMPL_VERSION}' +,org.codehaus.jackson.map.annotate;version='${IMPL_VERSION}' +,org.codehaus.jackson.map.introspect;version='${IMPL_VERSION}' +,org.codehaus.jackson.map.type;version='${IMPL_VERSION}' +,org.codehaus.jackson.map.util;version='${IMPL_VERSION}' +,org.codehaus.jackson.type;version='${IMPL_VERSION}' +,org.codehaus.jackson.util;version='${IMPL_VERSION}' +" + dynamicImportPackage="org.codehaus.jackson.xc" + exportpackage=" +org.codehaus.jackson.jaxrs;version=${IMPL_VERSION}" + includeResource="META-INF=release-notes/asl" + includeIncludeResourceHeader="false" + > + <classpath><pathelement path="${dir.build.classes.jaxrs}" /></classpath> + <manifest> + <attribute name="Built-By" value="${user.name}"/> + <attribute name="Implementation-Title" value="${IMPL_TITLE_JAXRS}"/> + <attribute name="Implementation-Version" value="${IMPL_VERSION}"/> + <attribute name="Implementation-Vendor" value="${IMPL_VENDOR}"/> + </manifest> + </osgiJar> + </target> + + <!-- "Mister Bean", the Bean Materializer --> + <target name="jar.mrbean" depends="compile.mrbean"> + <osgiJar + outputdir="${dir.build}" + bundleName="${IMPL_TITLE_MRBEAN}" + bundleVendor="${IMPL_VENDOR}" + bundleSymbolicName="jackson-mrbean" + bundleVersion="${IMPL_VERSION}" + bundleLicense="http://www.apache.org/licenses/LICENSE-2.0.txt" + bundleRequiredExecutionEnvironment="${REQ_JDK_VERSION}" + filename="jackson-mrbean-${IMPL_VERSION}" + importPackage=" +org.codehaus.jackson;version='${IMPL_VERSION}' +,org.codehaus.jackson.map;version='${IMPL_VERSION}' +,org.codehaus.jackson.map.type;version='${IMPL_VERSION}' +,org.codehaus.jackson.type;version='${IMPL_VERSION}' +,org.codehaus.jackson.util;version='${IMPL_VERSION}' +" + privatePackage="!org.codehaus.jackson.mrbean, *" + exportpackage=" +org.codehaus.jackson.mrbean;version=${IMPL_VERSION}" + includeResource="META-INF=release-notes/asl" + includeIncludeResourceHeader="false" + > + <classpath><pathelement path="${dir.build.classes.mrbean}" /></classpath> + <manifest> + <attribute name="Built-By" value="${user.name}"/> + <attribute name="Implementation-Title" value="${IMPL_TITLE_MRBEAN}"/> + <attribute name="Implementation-Version" value="${IMPL_VERSION}"/> + <attribute name="Implementation-Vendor" value="${IMPL_VENDOR}"/> + </manifest> + </osgiJar> + </target> + + <!-- Then XC (Xml Compatibility) jar, since 1.1 --> + <target name="jar.xc" depends="compile.xc"> + <osgiJar + outputdir="${dir.build}" + bundleName="${IMPL_TITLE_XC}" + bundleVendor="${IMPL_VENDOR}" + bundleSymbolicName="jackson-xc" + bundleVersion="${IMPL_VERSION}" + bundleLicense="http://www.apache.org/licenses/LICENSE-2.0.txt" + bundleRequiredExecutionEnvironment="${REQ_JDK_VERSION}" + filename="jackson-xc-${IMPL_VERSION}" + importPackage=" +javax.activation +,javax.xml.bind +,javax.xml.bind.annotation +,javax.xml.bind.annotation.adapters +,org.codehaus.jackson;version='${IMPL_VERSION}' +,org.codehaus.jackson.annotate;version='${IMPL_VERSION}' +,org.codehaus.jackson.map;version='${IMPL_VERSION}' +,org.codehaus.jackson.map.annotate;version='${IMPL_VERSION}' +,org.codehaus.jackson.map.deser;version='${IMPL_VERSION}' +,org.codehaus.jackson.map.deser.std;version='${IMPL_VERSION}' +,org.codehaus.jackson.map.introspect;version='${IMPL_VERSION}' +,org.codehaus.jackson.map.jsontype;version='${IMPL_VERSION}' +,org.codehaus.jackson.map.jsontype.impl;version='${IMPL_VERSION}' +,org.codehaus.jackson.map.ser;version='${IMPL_VERSION}' +,org.codehaus.jackson.map.ser.std;version='${IMPL_VERSION}' +,org.codehaus.jackson.map.type;version='${IMPL_VERSION}' +,org.codehaus.jackson.map.util;version='${IMPL_VERSION}' +,org.codehaus.jackson.node;version='${IMPL_VERSION}' +,org.codehaus.jackson.schema;version='${IMPL_VERSION}' +,org.codehaus.jackson.type;version='${IMPL_VERSION}' +,org.codehaus.jackson.util;version='${IMPL_VERSION}' +" + dynamicImportPackage="org.w3c.dom +,javax.xml.namespace, javax.xml.parsers, javax.xml.transform +" + exportPackage=" +org.codehaus.jackson.xc;version='${IMPL_VERSION}' +" + privatePackage=" +" + includeResource="META-INF=release-notes/asl" + includeIncludeResourceHeader="false" + > + <classpath><pathelement path="${dir.build.classes.xc}" /></classpath> + <manifest> + <attribute name="Built-By" value="${user.name}"/> + <attribute name="Implementation-Title" value="${IMPL_TITLE_XC}"/> + <attribute name="Implementation-Version" value="${IMPL_VERSION}"/> + <attribute name="Implementation-Vendor" value="${IMPL_VENDOR}"/> + </manifest> + </osgiJar> + </target> + + <!-- and finally Smile, binary format handler --> + <target name="jar.smile" depends="compile.smile"> + <osgiJar + outputdir="${dir.build}" + bundleName="${IMPL_TITLE_SMILE}" + bundleVendor="${IMPL_VENDOR}" + bundleSymbolicName="jackson-smile" + bundleVersion="${IMPL_VERSION}" + bundleLicense="http://www.apache.org/licenses/LICENSE-2.0.txt" + bundleRequiredExecutionEnvironment="${REQ_JDK_VERSION}" + filename="jackson-smile-${IMPL_VERSION}" + importPackage=" +org.codehaus.jackson;version='${IMPL_VERSION}', +org.codehaus.jackson.format;version='${IMPL_VERSION}', +org.codehaus.jackson.impl;version='${IMPL_VERSION}', +org.codehaus.jackson.io;version='${IMPL_VERSION}', +org.codehaus.jackson.sym;version='${IMPL_VERSION}', +org.codehaus.jackson.util;version='${IMPL_VERSION}' +" + exportpackage=" +org.codehaus.jackson.smile;version=${IMPL_VERSION}" + includeResource="META-INF=release-notes/asl" + includeIncludeResourceHeader="false" + > + <classpath><pathelement path="${dir.build.classes.smile}" /></classpath> + <manifest> + <attribute name="Built-By" value="${user.name}"/> + <attribute name="Implementation-Title" value="${IMPL_TITLE_SMILE}"/> + <attribute name="Implementation-Version" value="${IMPL_VERSION}"/> + <attribute name="Implementation-Vendor" value="${IMPL_VENDOR}"/> + </manifest> + </osgiJar> + </target> + + <!-- 29-Oct-2010, tatu: one new tool, to help debug Smile... --> + <target name="jar.tool.smile" depends="compile.smile, jar.core.asl, jar.smile"> + <jar jarfile="${dir.build}/smile-tool-${IMPL_VERSION}.jar"> + <manifest> + <attribute name="Built-By" value="${user.name}"/> + <attribute name="Implementation-Title" value="Smile Tool"/> + <attribute name="Implementation-Version" value="${IMPL_VERSION}"/> + <attribute name="Implementation-Vendor" value="${IMPL_VENDOR}"/> + <attribute name="Main-Class" value="org.codehaus.jackson.smile.Tool"/> + </manifest> + <!-- need everything from core, smile packages, but nothing else --> + <fileset dir="${dir.build.classes.core}"> + <include name="org/codehaus/jackson/**/*.class" /> + </fileset> + <fileset dir="${dir.build.classes.smile}"> + <include name="org/codehaus/jackson/**/*.class" /> + </fileset> + </jar> + </target> +</project>
diff --git a/1.9.10/ant/build-test.xml b/1.9.10/ant/build-test.xml new file mode 100644 index 0000000..7873692 --- /dev/null +++ b/1.9.10/ant/build-test.xml
@@ -0,0 +1,260 @@ +<?xml version="1.0" standalone='yes'?> +<!-- This Ant build file fragment contains targets needed + to run unit tests + --> + +<project name="Jackson Unit tests" basedir="."> + <!-- Source directories --> + <property name="dir.src.test" location="${dir.src}/test" /> + <!-- some support for perf testing --> + <property name="dir.build.classes.perf" location="${dir.build}/classes/perf" /> + <!-- Unit Tests --> + <property name="dir.test" location="${basedir}/test" /> + <property name="dir.test.classes" location="${dir.test}/classes" /> + <property name="dir.test.results" location="${dir.test}/results" /> + <property name="dir.test.xmlresults" location="${dir.test.results}/xml" /> + + <path id="test-libs"> + <fileset dir="${dir.lib}"> + <!-- for actual unit testing, junit --> + <include name="junit/*.jar" /> + </fileset> + </path> + <!-- Libs only needed for tests that check optional interoperability + extensions + --> + <path id="test-libs-ext"> + <fileset dir="${dir.lib}"> + <!-- For 1.5, need JAXB API jar too (and related) --> + <include name="jaxb/*.jar" /> + <!-- and some other misc libs for interoperability tests --> + <include name="ext/**/*.jar" /> + </fileset> + </path> + + <target name="test.prepare"> + <!-- make test output directories --> + <mkdir dir="${dir.test}" /> + <mkdir dir="${dir.test.classes}" /> + <mkdir dir="${dir.test.results}" /> + <mkdir dir="${dir.test.xmlresults}" /> + </target> + + <!--*********************************************************************--> + <!-- Tasks from here down are in support of junit tests. --> + <!--*********************************************************************--> + <target name="all-tests" depends="test" /> + + <!-- Compiling and running test cases + --> + + <target name="test.compile" depends="test.prepare, compile.mapper, +compile.xc, compile.jaxrs, compile.smile, compile.mrbean"> + <javac srcdir="${dir.src.test}" destdir="${dir.test.classes}" + source="1.5" target="1.5" + debug="true" includeantruntime="false" + > + <exclude name="org/codehaus/jackson/map/ext/*.java" /> + <exclude name="org/codehaus/jackson/map/interop/*.java" /> + <include name="**/*.java" /> + <classpath> + <pathelement path="${dir.build.classes.core}"/> + <pathelement path="${dir.build.classes.mapper}"/> + <pathelement path="${dir.build.classes.jaxrs}"/> + <pathelement path="${dir.build.classes.xc}"/> + <pathelement path="${dir.build.classes.smile}"/> + <pathelement path="${dir.build.classes.mrbean}"/> + <path refid="test-libs"/> + <fileset dir="${dir.lib}/jaxrs"> + <include name="*.jar" /> + </fileset> + </classpath> + </javac> + <javac srcdir="${dir.src.test}" destdir="${dir.test.classes}" + source="1.5" target="1.5" + debug="true" includeantruntime="false" + > + <include name="org/codehaus/jackson/map/ext/*.java" /> + <include name="org/codehaus/jackson/map/interop/*.java" /> + <classpath> + <pathelement path="${dir.build.classes.core}"/> + <pathelement path="${dir.build.classes.mapper}"/> + <path refid="test-libs"/> + <path refid="test-libs-ext"/> + </classpath> + </javac> + </target> + + + <target name="test" depends="test.run"> + <junitreport todir="${dir.test.results}"> + <fileset dir="${dir.test.xmlresults}"> + <include name="TEST-*.xml" /> + </fileset> + <report todir="${dir.test.results}" /> + </junitreport> + </target> + + <target name="test.run" depends="test.run.main, +test.run.interop, test.run.jaxrs, test.run.failing, test.run.versions" + /> + <target name="test.run.main" depends="test.compile"> + <!-- showoutput 'yes' to allow outputting debug msgs... --> + <junit fork="no" printsummary="yes" haltonfailure="no" showoutput="yes"> + <batchtest fork="no" todir="${dir.test.xmlresults}"> + <fileset dir="${dir.test.classes}"> + <!-- Need to exclude inner classes... --> + <exclude name="**/*$*.class"/> + <!-- and also interop tests, run later on --> + <exclude name="org/codehaus/jackson/jaxrs/*.class"/> + <exclude name="org/codehaus/jackson/failing/*.class"/> + <exclude name="org/codehaus/jackson/map/ext/Test*.class"/> + <exclude name="org/codehaus/jackson/map/interop/Test*.class"/> + <exclude name="org/codehaus/jackson/version/*.class"/> + <include name="**/Test*.class"/> + </fileset> + </batchtest> + <formatter type="xml" /> + <classpath> + <pathelement path="${dir.build.classes.core}" /> + <pathelement path="${dir.build.classes.mapper}" /> + <pathelement path="${dir.build.classes.xc}" /> + <pathelement path="${dir.build.classes.smile}" /> + <pathelement path="${dir.build.classes.mrbean}" /> + <pathelement location="${dir.test.classes}" /> + <path refid="test-libs"/> + </classpath> + </junit> + </target> + + <target name="test.run.interop" depends="test.compile"> + <!-- for interop tests, yes, we need to fork (classloading issues) --> + <junit fork="yes" printsummary="yes" haltonfailure="no" showoutput="yes"> + <batchtest fork="no" todir="${dir.test.xmlresults}"> + <fileset dir="${dir.test.classes}"> + <exclude name="**/*$*.class"/> + <!-- 25-Nov-2009, tatu: Argh. Looks like classloading + is problematic for this test; works when run + separately as single test... but not in sequence + --> + <exclude name="org/codehaus/jackson/map/interop/TestHibernate.class"/> + <include name="org/codehaus/jackson/map/interop/Test*.class"/> + </fileset> + </batchtest> + <formatter type="xml" /> + <classpath> + <pathelement path="${dir.build.classes.core}" /> + <pathelement path="${dir.build.classes.mapper}" /> + <pathelement location="${dir.test.classes}" /> + <path refid="test-libs"/> + <path refid="test-libs-ext"/> + </classpath> + </junit> + </target> + + <target name="test.run.jaxrs" depends="test.compile"> + <!-- And finally, minimal testing for jax-rs too --> + <junit fork="yes" printsummary="yes" haltonfailure="no" showoutput="yes"> + <batchtest fork="no" todir="${dir.test.xmlresults}"> + <fileset dir="${dir.test.classes}"> + <exclude name="**/*$*.class"/> + <include name="org/codehaus/jackson/jaxrs/*.class"/> + </fileset> + </batchtest> + <formatter type="xml" /> + <classpath> + <pathelement path="${dir.build.classes.core}" /> + <pathelement path="${dir.build.classes.mapper}" /> + <pathelement path="${dir.build.classes.jaxrs}" /> + <pathelement path="${dir.build.classes.xc}" /> + <pathelement location="${dir.test.classes}" /> + <path refid="test-libs"/> + <fileset dir="${dir.lib}/jaxrs"> + <include name="*.jar" /> + </fileset> + </classpath> + </junit> + </target> + + <!-- failing tests run during dev, disabled for maintenance versions --> + <target name="test.run.failing" depends="test.compile"> +<!-- + <junit fork="no" printsummary="yes" haltonfailure="no" showoutput="yes"> + <batchtest fork="no" todir="${dir.test.xmlresults}"> + <fileset dir="${dir.test.classes}"> + <exclude name="**/*$*.class"/> + <include name="org/codehaus/jackson/failing/Test*.class"/> + </fileset> + </batchtest> + <formatter type="xml" /> + <classpath> + <pathelement path="${dir.build.classes.core}" /> + <pathelement path="${dir.build.classes.mapper}" /> + <pathelement path="${dir.build.classes.mrbean}" /> + <pathelement path="${dir.build.classes.jaxrs}" /> + <pathelement path="${dir.build.classes.xc}" /> + <pathelement location="${dir.test.classes}" /> + <path refid="test-libs"/> + <path refid="test-libs-ext"/> + <fileset dir="${dir.lib}/jaxrs"> + <include name="*.jar" /> + </fileset> + </classpath> + </junit> +--> + </target> + + <target name="test.run.versions" depends="test.compile"> + <junit fork="yes" printsummary="yes" haltonfailure="no" showoutput="yes"> + <sysproperty key="FROM_ANT" value="true"/> + <batchtest fork="no" todir="${dir.test.xmlresults}"> + <fileset dir="${dir.test.classes}"> + <include name="org/codehaus/jackson/version/*.class"/> + </fileset> + </batchtest> + <formatter type="xml" /> + <classpath> + <pathelement path="${dir.build.classes.core}" /> + <pathelement path="${dir.build.classes.mapper}" /> + <pathelement path="${dir.build.classes.jaxrs}" /> + <pathelement path="${dir.build.classes.xc}" /> + <pathelement path="${dir.build.classes.mrbean}" /> + <pathelement path="${dir.build.classes.smile}" /> + <pathelement location="${dir.test.classes}" /> + <path refid="test-libs"/> + <fileset dir="${dir.lib}/jaxrs"> + <include name="*.jar" /> + </fileset> + </classpath> + </junit> + </target> + + <!-- Running a single Unit Test --> + <target name="test.single" depends="test.compile"> + <fail unless="test" message="Must define -Dtest" /> + <!-- showoutput 'yes' to allow outputting debug msgs... --> + <!-- 09-Apr-2010, tatu: Looks like we must fork, otherwise there may be + issues with junit version? + --> + <junit fork="yes" maxmemory="128M" showoutput="yes" printsummary="yes"> + <sysproperty key="FROM_ANT" value="true"/> + <formatter type="plain" usefile="no" /> + <test name="${test}" /> + <classpath> + <pathelement path="${dir.build.classes.core}" /> + <pathelement path="${dir.build.classes.mapper}" /> + <pathelement path="${dir.build.classes.xc}" /> + <pathelement path="${dir.build.classes.jaxrs}" /> + <pathelement path="${dir.build.classes.smile}" /> + <pathelement path="${dir.build.classes.mrbean}" /> + <pathelement location="${dir.test.classes}" /> + <path refid="test-libs"/> + <path refid="test-libs-ext"/> + <fileset dir="${dir.lib}/jaxrs"> + <include name="*.jar" /> + </fileset> + </classpath> + </junit> + </target> + +</project>
diff --git a/1.9.10/bin/profile-json-perf.sh b/1.9.10/bin/profile-json-perf.sh new file mode 100755 index 0000000..9cc457c --- /dev/null +++ b/1.9.10/bin/profile-json-perf.sh
@@ -0,0 +1,8 @@ +#!/bin/sh + +java -Xmx48m -server -cp build/classes/perf:build/classes/core\ +:build/classes/mapper:lib/perf/\* \ +-XX:CompileThreshold=2000 \ +-Xrunhprof:cpu=samples,depth=10,verbose=n,interval=2 \ + TestJsonPerf \ + $*
diff --git a/1.9.10/bin/profile-read-perf.sh b/1.9.10/bin/profile-read-perf.sh new file mode 100755 index 0000000..09cde2f --- /dev/null +++ b/1.9.10/bin/profile-read-perf.sh
@@ -0,0 +1,7 @@ +#!/bin/sh + +java -Xmx16m -server \ +-cp build/classes/perf:perflib/\* \ +-XX:CompileThreshold=2000 \ +-Xrunhprof:cpu=samples,depth=10,verbose=n,interval=2 \ +TestReadPerf $*
diff --git a/1.9.10/bin/run-copy-perf.sh b/1.9.10/bin/run-copy-perf.sh new file mode 100755 index 0000000..8f6485d --- /dev/null +++ b/1.9.10/bin/run-copy-perf.sh
@@ -0,0 +1,4 @@ +#!/bin/sh + +java -Xmx48m -server -cp build/classes \ + TestCopyPerf $*
diff --git a/1.9.10/bin/run-json-perf.sh b/1.9.10/bin/run-json-perf.sh new file mode 100755 index 0000000..837f817 --- /dev/null +++ b/1.9.10/bin/run-json-perf.sh
@@ -0,0 +1,6 @@ +#!/bin/sh + +java -Xmx48m -server -cp build/classes/perf:build/classes/core\ +:build/classes/mapper:lib/perf/\* \ + TestJsonPerf \ + $*
diff --git a/1.9.10/bin/run-read-perf.sh b/1.9.10/bin/run-read-perf.sh new file mode 100755 index 0000000..cd181cb --- /dev/null +++ b/1.9.10/bin/run-read-perf.sh
@@ -0,0 +1,5 @@ +#!/bin/sh + +java -Xmx16m -server \ +-cp build/classes/perf:perflib/\* \ +TestReadPerf $*
diff --git a/1.9.10/bin/run-ser-perf.sh b/1.9.10/bin/run-ser-perf.sh new file mode 100755 index 0000000..8f3a8c6 --- /dev/null +++ b/1.9.10/bin/run-ser-perf.sh
@@ -0,0 +1,6 @@ +#!/bin/sh + +java -Xmx48m -server -cp build/classes/perf:build/classes/core\ +:build/classes/mapper:lib/perf/\* \ + TestSerPerf \ + $*
diff --git a/1.9.10/build.xml b/1.9.10/build.xml new file mode 100644 index 0000000..f979593 --- /dev/null +++ b/1.9.10/build.xml
@@ -0,0 +1,534 @@ +<?xml version="1.0" standalone='yes'?> + + <project name="Jackson JSON processor" basedir="." default="readme"> + + <!-- Source directories --> + <property name="dir.src" location="${basedir}/src" /> + <property name="dir.src.java.core" location="${dir.src}/java" /> + <property name="dir.src.java.mapper" location="${dir.src}/mapper/java" /> + <property name="dir.src.java.jaxrs" location="${dir.src}/jaxrs/java" /> + <property name="dir.src.java.xc" location="${dir.src}/xc/java" /> + <property name="dir.src.java.smile" location="${dir.src}/smile/java" /> + <property name="dir.src.java.mrbean" location="${dir.src}/mrbean/java" /> + <property name="dir.src.resource.jaxrs" location="${dir.src}/jaxrs/resources" /> + <property name="dir.src.maven" location="${dir.src}/maven" /> + <property name="dir.src.sample" location="${dir.src}/sample" /> + <property name="dir.src.tools" location="${dir.src}/tools" /> + <property name="dir.releasenotes" location="${basedir}/release-notes" /> + + <!-- Libs --> + <property name="dir.lib" location="${basedir}/lib" /> + <!-- Build-related --> + <property name="dir.build" location="${basedir}/build" /> + <property name="dir.build.classes.core" location="${dir.build}/classes/core" /> + <property name="dir.build.classes.mapper" location="${dir.build}/classes/mapper" /> + <property name="dir.build.classes.jaxrs" location="${dir.build}/classes/jaxrs" /> + <property name="dir.build.classes.xc" location="${dir.build}/classes/xc" /> + <property name="dir.build.classes.smile" location="${dir.build}/classes/smile" /> + <property name="dir.build.classes.mrbean" location="${dir.build}/classes/mrbean" /> + <!-- both "sample" and "tools" java code goes under "extra" --> + <property name="dir.build.classes.extra" location="${dir.build}/classes/extra" /> + + <!-- Documentation --> + <property name="dir.doc" location="${basedir}/doc" /> + <property name="dir.javadoc" location="${dir.build}/javadoc" /> + + <!-- Distribution --> + <property name="dir.dist" location="${basedir}/dist" /> + <property name="dir.snapshot" location="${basedir}/build/snapshot" /> + + <!-- Version information --> + + <!-- Version --> + <property name="JSON_TITLE" value="JSON - JavaScript Object Notation" /> + <property name="JSON_VERSION" value="1.0" /> + <property name="JSON_VENDOR" value="http://www.ietf.org/rfc/rfc4627.txt" /> + <property name="IMPL_TITLE_CORE" value="Jackson JSON processor" /> + <property name="IMPL_TITLE_MAPPER" value="Data mapper for Jackson JSON processor" /> + <property name="IMPL_TITLE_JAXRS" value="JAX-RS provider for JSON content type, using Jackson data binding" /> + <property name="IMPL_TITLE_XC" value="XML Compatibility extensions for Jackson data binding" /> + <property name="IMPL_TITLE_SMILE" value="Jackson Binary format (aka Smile) handling functionality" /> + <property name="IMPL_TITLE_MRBEAN" value="Jackson Bean Materializer (aka Mr. Bean)" /> + + <property name="IMPL_VERSION" value="1.9.10" /> + <property name="IMPL_VENDOR" value="http://fasterxml.com" /> + + <patternset id="dist-all-source-files"> + <include name="README.txt" /> + <include name="ant/build*.xml" /> + <include name="build.xml" /> + <include name="release-notes/*" /> + <include name="DEV/contributor*" /> + <include name="src/**/*.java" /> + <include name="src/VERSION.txt" /> + <include name="src/java/**/*.html" /> + <include name="src/maven/*.pom" /> + <include name="release-notes/*" /> + <include name="release-notes/asl/*" /> + <include name="release-notes/lgpl/*" /> + <!-- need jars for auxiliary tasks (tests), although jackson + itself does not depend on any other packages, just JDK 1.5 + --> + <include name="lib/**/*.jar" /> + <include name="samples/**/*.jsn" /> + </patternset> + + <!-- some build tasks are refactored out of the main task --> + <import file="ant/build-osgi.xml" /> + <import file="ant/build-maven-deploy.xml" /> + <import file="ant/build-coverage.xml" /> + <import file="ant/build-test.xml" /> + <import file="ant/build-mini.xml" /> + + <!--*********************************************************************--> + <!-- The readme target shows a brief description of all targets --> + <!-- supported by this ant build file --> + <!--*********************************************************************--> + <target name="readme"> + <echo message = "${ant.project.name}'s Available Targets" /> + <echo message = "---------------------------------------------------" /> + <echo message = "1) readme - Displays this information (default target)." /> + <echo message = "2) clean - Remove any generated files/directories." /> + <echo message = "3) build - Compile all code, run unit tests" /> + <echo message = "4) jars - Compile and create all jars for non-test ${ant.project.name} code" /> + <echo message = "5) javadoc - Generate ${ant.project.name} code documentation." /> + <echo message = "6) test - Run JUnit tests." /> + <echo message = "7) dist - Create distribution directory and copy necessary files there" /> + <echo message = "8) all - Run clean, compile, test, javadoc," /> + <echo message = " and dist targets." /> + <echo message = "" /> + <echo message = "Available command-line arguments:" /> + <echo message = "---------------------------------" /> + <echo message = "none" /> + </target> + + <target name="prepare"> + <!-- make build directories --> + <mkdir dir="${dir.build}" /> + <mkdir dir="${dir.build.classes.core}" /> + <mkdir dir="${dir.build.classes.mapper}" /> + <mkdir dir="${dir.build.classes.jaxrs}" /> + <mkdir dir="${dir.build.classes.xc}" /> + <mkdir dir="${dir.build.classes.smile}" /> + <mkdir dir="${dir.build.classes.mrbean}" /> + <mkdir dir="${dir.build.classes.extra}" /> + + <!-- make docs directories --> + <mkdir dir="${dir.doc}" /> + <mkdir dir="${dir.javadoc}" /> + + <!-- and finally distribution dir --> + <mkdir dir="${dir.dist}" /> + <mkdir dir="${dir.snapshot}" /> + <!-- 1.6.0: also add VERSION marker file --> + <copy todir="${dir.build}"> + <fileset dir="${dir.src}" includes="VERSION.txt" /> + <filterset> + <filter token="VERSION" value="${IMPL_VERSION}" /> + </filterset> + </copy> + + </target> + + <!-- *********************************************** + - supporting dummy tasks + - ***********************************************--> + + + <!-- *********************************************** + - clean - Removes all generated files/directories + - ***********************************************--> + + <target name="clean"> + <delete dir="${dir.build}"/> + <delete dir="${dir.doc}"/> + <delete dir="${dir.test}"/> + <delete dir="${dir.dist}"/> + <delete file="cobertura.ser" /> + </target> + + <target name="build" depends="compile, all-tests" /> + + <target name="compile" depends="compile.all" /> + <target name="compile.all" depends=" +compile.main, test.compile, compile.extra, compile.perf" /> + <target name="compile.main" + depends="compile.core, compile.mapper, compile.jaxrs, compile.xc, +compile.smile, compile.mrbean" /> + + <target name="compile.core" depends="prepare"> + <javac srcdir="${dir.src.java.core}" destdir="${dir.build.classes.core}" + source="1.5" target="1.5" + debug="true" includeantruntime="false" + > + <compilerarg value="-Xlint:unchecked" /> + <exclude name="**/package-info.java" /> + <include name="org/codehaus/**/*.java" /> + </javac> + <!-- 1.6, [JACKSON-278]: need to copy VERSION info along (so unit tests see it) --> + <copy file="${dir.build}/VERSION.txt" toDir="${dir.build.classes.core}/org/codehaus/jackson/impl" /> + </target> + + <target name="compile.mapper" depends="compile.core"> + <javac srcdir="${dir.src.java.mapper}" destdir="${dir.build.classes.mapper}" + source="1.5" target="1.5" + debug="true" includeantruntime="false" + > + <compilerarg value="-Xlint:unchecked" /> + <exclude name="**/package-info.java" /> + <include name="org/codehaus/jackson/**/*.java" /> + <!-- mapper builds on core classes --> + <classpath> + <pathelement path="${dir.build.classes.core}"/> + <!-- We support some ext libs (like Joda time) --> + <fileset dir="${dir.lib}/ext"> + <include name="*.jar" /> + </fileset> + </classpath> + </javac> + <!-- 1.6, [JACKSON-278]: need to copy VERSION info along (so unit tests see it) --> + <copy file="${dir.build}/VERSION.txt" toDir="${dir.build.classes.mapper}/org/codehaus/jackson/map" /> + </target> + + <target name="compile.xc" depends="compile.mapper"> + <javac srcdir="${dir.src.java.xc}" destdir="${dir.build.classes.xc}" + source="1.5" target="1.5" + debug="true" includeantruntime="false" + > + <compilerarg value="-Xlint:unchecked" /> + <exclude name="**/package-info.java" /> + <include name="org/codehaus/jackson/**/*.java" /> + <!-- builds on core and mapper classes --> + <classpath> + <pathelement path="${dir.build.classes.core}"/> + <pathelement path="${dir.build.classes.mapper}"/> + <!-- For JDK 1.5 build, need JAXB API --> + <fileset dir="${dir.lib}/jaxb"> + <include name="*.jar" /> + </fileset> + </classpath> + </javac> + <!-- 1.6, [JACKSON-278]: need to copy VERSION info along (so unit tests see it) --> + <copy file="${dir.build}/VERSION.txt" toDir="${dir.build.classes.xc}/org/codehaus/jackson/xc" /> + <copy file="${dir.build}/VERSION.txt" toDir="${dir.build.classes.xc}/org/codehaus/jackson/xml" /> + </target> + + <target name="compile.jaxrs" depends="compile.mapper,compile.xc"> + <javac srcdir="${dir.src.java.jaxrs}" destdir="${dir.build.classes.jaxrs}" + source="1.5" target="1.5" + debug="true" includeantruntime="false" + > + <compilerarg value="-Xlint:unchecked" /> + <exclude name="**/package-info.java" /> + <include name="org/codehaus/jackson/**/*.java" /> + <!-- builds on core and mapper classes --> + <classpath> + <fileset dir="${dir.lib}/jaxrs"> + <include name="*.jar" /> + </fileset> + <pathelement path="${dir.build.classes.core}"/> + <pathelement path="${dir.build.classes.mapper}"/> + <!-- this is optional dependency, but needed for compilation --> + <pathelement path="${dir.build.classes.xc}"/> + </classpath> + </javac> + <!-- 1.6, [JACKSON-278]: need to copy VERSION info along (so unit tests see it) --> + <copy file="${dir.build}/VERSION.txt" toDir="${dir.build.classes.jaxrs}/org/codehaus/jackson/jaxrs" /> + </target> + + <target name="compile.smile" depends="compile.core"> + <javac srcdir="${dir.src.java.smile}" destdir="${dir.build.classes.smile}" + source="1.5" target="1.5" + debug="true" includeantruntime="false" + > + <compilerarg value="-Xlint:unchecked" /> + <exclude name="**/package-info.java" /> + <include name="org/codehaus/jackson/smile/**/*.java" /> + <!-- builds on core classes --> + <classpath> + <pathelement path="${dir.build.classes.core}"/> + </classpath> + </javac> + <!-- 1.6, [JACKSON-278]: need to copy VERSION info along (so unit tests see it) --> + <copy file="${dir.build}/VERSION.txt" toDir="${dir.build.classes.smile}/org/codehaus/jackson/smile" /> + </target> + + <target name="compile.mrbean" depends="compile.core"> + <javac srcdir="${dir.src.java.mrbean}" destdir="${dir.build.classes.mrbean}" + source="1.5" target="1.5" + debug="true" includeantruntime="false" + > + <compilerarg value="-Xlint:unchecked" /> + <exclude name="**/package-info.java" /> + <include name="org/codehaus/jackson/mrbean/**/*.java" /> + <!-- builds on core and mapper classes --> + <classpath> + <pathelement path="${dir.build.classes.core}"/> + <pathelement path="${dir.build.classes.mapper}"/> + <fileset dir="${dir.lib}/repackaged"> + <include name="jackson-asm*.jar" /> + </fileset> + </classpath> + <!-- 1.6, [JACKSON-278]: need to copy VERSION info along (so unit tests see it) --> + </javac> + <copy file="${dir.build}/VERSION.txt" toDir="${dir.build.classes.mrbean}/org/codehaus/jackson/mrbean" /> + <!-- also, unpack classes from repackaged asm jar, for OSGi bundle --> + <unjar dest="${dir.build.classes.mrbean}"> + <fileset dir="${dir.lib}/repackaged"> + <include name="jackson-asm*.jar" /> + </fileset> + </unjar> + </target> + + <target name="compile.extra" depends="compile.main"> + <javac destdir="${dir.build.classes.extra}" + source="1.5" target="1.5" + debug="true" includeantruntime="false" + > + <compilerarg value="-Xlint:unchecked" /> + <src path="${dir.src.sample}" /> + <src path="${dir.src.tools}" /> + <include name="**/*.java" /> + <!-- need core and mapper classes --> + <classpath> + <pathelement path="${dir.build.classes.core}"/> + <pathelement path="${dir.build.classes.mapper}"/> + <pathelement path="${dir.build.classes.smile}"/> + </classpath> + </javac> + </target> + + <target name="compile.perf" depends="compile.main"> + <mkdir dir="${dir.build.classes.perf}" /> + <!-- Let's also compile micro-benchmarks... --> + <javac srcdir="${dir.src}/perf" destdir="${dir.build.classes.perf}" + debug="true" includeantruntime="false" + > + <classpath> + <fileset dir="${dir.lib}/perf"> + <include name="*.jar" /> + </fileset> + <pathelement path="${dir.build.classes.core}"/> + <pathelement path="${dir.build.classes.mapper}"/> + <pathelement path="${dir.build.classes.smile}"/> + <pathelement path="${dir.build.classes.xc}"/> + </classpath> + <include name="perf/**/*.java" /> + </javac> + </target> + + <!-- Dummy target that just includes all individual jars... --> + <target name="jars" depends="jars.asl, jars.lgpl, jars.other, jar.all, jars.tools, jar.mini" /> + + <target name="javadoc" depends="compile.all"> + <!-- Build a dirpath that contains just the "source" tree --> + <javadoc windowtitle="Jackson JSON Processor" + destdir="${dir.javadoc}" + author="true" version="true" use="true"> + + <classpath> + <fileset dir="${dir.lib}/jaxrs"> + <include name="*.jar" /> + </fileset> + </classpath> + + <packageset dir="${dir.src.java.core}" defaultexcludes="yes"> + <include name="org/codehaus/**" /> + </packageset> + <packageset dir="${dir.src.java.mapper}" defaultexcludes="yes"> + <include name="org/codehaus/**" /> + </packageset> + <packageset dir="${dir.src.java.jaxrs}" defaultexcludes="yes"> + <include name="org/codehaus/jackson/jaxrs/**" /> + </packageset> + <packageset dir="${dir.src.java.xc}" defaultexcludes="yes"> + <include name="org/codehaus/jackson/xc/**" /> + <include name="org/codehaus/jackson/xml/**" /> + </packageset> + <packageset dir="${dir.src.java.smile}" defaultexcludes="yes"> + <include name="org/codehaus/jackson/smile/**" /> + </packageset> + <packageset dir="${dir.src.java.mrbean}" defaultexcludes="yes"> + <include name="org/codehaus/jackson/mrbean/**" /> + </packageset> + + <!-- External JavaDocs to link: --> + + <!-- Joda time... --> + <link href="http://joda-time.sourceforge.net/api-release" /> + <!-- Regular JDK 6 classes --> + <link href="http://docs.oracle.com/javase/6/docs/api" /> + <!-- And JAX-RS (jsr-311) as well --> + <link href="http://jackson.codehaus.org/javadoc/jax-rs/1.0" /> + + <group title="Jackson Core" packages="org.codehaus.jackson*" /> + <group title="Jackson Mapper" + packages="org.codehaus.jackson.map*:org.codehaus.jackson.node:org.codehaus.jackson.schema" + /> + <group title="Jackson JAX-RS provider" packages="org.codehaus.jackson.jaxrs" /> + <group title="Jackson XML Compatibility" packages="org.codehaus.jackson.xc" /> + <group title="Jackson Mr Bean" packages="org.codehaus.jackson.mrbean" /> + <group title="Jackson Smile Format" packages="org.codehaus.jackson.smile" /> + </javadoc> + </target> + + <!-- New with 1.6, "jackson-all" combo jar --> + <target name="jar.all" depends="jars.asl, jars.other"> + <jar jarfile="${dir.build}/jackson-all-${IMPL_VERSION}.jar" + filesonly="true" index="true" level="9"> +<!-- Bah: need Ant 1.8 for this: indexMetaInf="true" --> + <manifest> + <attribute name="Built-By" value="${user.name}"/> + <attribute name="Implementation-Title" value="Jackson"/> + <attribute name="Implementation-Version" value="${IMPL_VERSION}"/> + <attribute name="Implementation-Vendor" value="${IMPL_VENDOR}"/> + <attribute name="Specification-Title" value="${JSON_TITLE}"/> + <attribute name="Specification-Version" value="${JSON_VERSION}"/> + <attribute name="Specification-Vendor" value="${JSON_VENDOR}"/> + </manifest> + <metainf dir="${dir.releasenotes}/asl" includes="*" /> + <fileset dir="${dir.build.classes.core}" includes="**/*.class" /> + <fileset dir="${dir.build.classes.mapper}" includes="**/*.class" /> + <fileset dir="${dir.build.classes.jaxrs}" includes="**/*.class" /> + <fileset dir="${dir.build.classes.xc}" includes="**/*.class" /> + <fileset dir="${dir.build.classes.smile}" includes="**/*.class" /> + <fileset dir="${dir.build.classes.mrbean}" includes="**/*.class" /> + </jar> + </target> + + + <!-- Generic distribution target builds the structure we copy over + to the website. + --> + <target name="dist" depends="compile.all,jars,javadoc" + > + <!-- First, let's copy the binary jars to dist --> + <copy todir="${dir.dist}"> + <fileset dir="${dir.build}" includes="*.jar" /> + </copy> + + <!-- Then let's create the source distribution tar packages + --> + <!-- Need to first copy to a tmp dir, to get the additional + directory (so tar/zip contents won't explode directly + in current dir) + --> + <property name="DIST_FILENAME" value="jackson-src-${IMPL_VERSION}" /> + <property name="DIST_DIR" value="${DIST_FILENAME}" /> + + <!-- better always clean it up, if it exists... --> + <delete dir="${dir.build}/${DIST_DIR}" /> + <mkdir dir="${dir.build}/${DIST_DIR}" /> + + <copy todir="${dir.build}/${DIST_DIR}"> + <fileset dir="${basedir}"> + <patternset refid="dist-all-source-files" /> + </fileset> + </copy> + + <!-- then create tarball, zip --> + <tar basedir="${dir.build}" + includes="${DIST_DIR}/**" + destfile="${dir.dist}/${DIST_FILENAME}.tar.gz" + compression="gzip" + /> + <zip basedir="${dir.build}" + includes="${DIST_DIR}/**" + destfile="${dir.dist}/${DIST_FILENAME}.zip" + /> + + <!-- And create source jars for IDE support; separate for core, mapper + and both license types + --> + <jar destfile="${dir.dist}/jackson-core-asl-${IMPL_VERSION}-sources.jar" + filesonly="true" compress="true" basedir="${dir.src.java.core}" + includes="org/codehaus/jackson/**" + /> + <jar destfile="${dir.dist}/jackson-mapper-asl-${IMPL_VERSION}-sources.jar" + filesonly="true" compress="true" basedir="${dir.src.java.mapper}" + includes="org/codehaus/jackson/**" + /> + + <jar destfile="${dir.dist}/jackson-core-lgpl-${IMPL_VERSION}-sources.jar" + filesonly="true" compress="true" basedir="${dir.src.java.core}" + includes="org/codehaus/jackson/**" + /> + <jar destfile="${dir.dist}/jackson-mapper-lgpl-${IMPL_VERSION}-sources.jar" + filesonly="true" compress="true" basedir="${dir.src.java.mapper}" + includes="org/codehaus/jackson/**" + /> + <jar destfile="${dir.dist}/jackson-jaxrs-${IMPL_VERSION}-sources.jar" + filesonly="true" compress="true" basedir="${dir.src.java.jaxrs}" + includes="org/codehaus/jackson/jaxrs/**" + /> + <jar destfile="${dir.dist}/jackson-xc-${IMPL_VERSION}-sources.jar" + filesonly="true" compress="true" basedir="${dir.src.java.xc}" + includes="org/codehaus/jackson/xc/**" + /> + <jar destfile="${dir.dist}/jackson-smile-${IMPL_VERSION}-sources.jar" + filesonly="true" compress="true" basedir="${dir.src.java.smile}" + includes="org/codehaus/jackson/smile/**" + /> + <jar destfile="${dir.dist}/jackson-mrbean-${IMPL_VERSION}-sources.jar" + filesonly="true" compress="true" basedir="${dir.src.java.mrbean}" + includes="org/codehaus/jackson/mrbean/**" + /> + + <!-- Similarly package javadocs; sub-optimal since they are built just + once so there's plenty of replication. So let's actually + only do this for core and mapper, for now: + --> + <jar destfile="${dir.dist}/jackson-core-asl-${IMPL_VERSION}-javadoc.jar" + filesonly="true" compress="true" basedir="${dir.javadoc}" includes="**/*" + /> + <jar destfile="${dir.dist}/jackson-mapper-asl-${IMPL_VERSION}-javadoc.jar" + filesonly="true" compress="true" basedir="${dir.javadoc}" includes="**/*" + /> + + <!-- Then copy javadocs --> + <copy todir="${dir.dist}"> + <fileset dir="${dir.javadoc}/.." includes="javadoc/**/*" /> + </copy> + <!-- Plus, let's also just copy README and compatibility files, in + addition to being included in source package + --> + <copy todir="${dir.dist}" > + <fileset dir="." includes="release-notes/*" /> + <fileset dir="." includes="release-notes/asl/*" /> + <fileset dir="." includes="release-notes/lgpl/*" /> + </copy> + <!-- And also additional Maven stuff --> + <copy todir="${dir.dist}"> + <fileset dir="${dir.src}/maven" includes="*.pom" /> + <globmapper from="*.pom" to="*-${IMPL_VERSION}.pom" /> + <filterset> + <filter token="VERSION" value="${IMPL_VERSION}" /> + </filterset> + </copy> + + <!-- 12-Jun-2009, tatu: Trying to make Maven snapshots work... + --> + <copy todir="${dir.snapshot}"> + <fileset dir="${dir.src}/maven" includes="*.pom" /> + <globmapper from="*.pom" to="*-${IMPL_VERSION}-SNAPSHOT.pom" /> + <filterset> + <filter token="VERSION" value="${IMPL_VERSION}-SNAPSHOT" /> + </filterset> + </copy> + + <!-- 03-Dec-2008, tatu: Let's validate well-formedness of + resulting files (to avoid things like [JACKSON-25]) + --> + <xmlvalidate lenient="true"> + <!-- lenient: check only well-formedness, no dtd/schema (yet) --> + <fileset dir="${dir.dist}" includes="*.pom" /> + <fileset dir="${dir.snapshot}" includes="*.pom" /> + </xmlvalidate> + </target> + + <target name="all" depends="clean,javadoc,test,dist"> + <!-- This target simply depends on others to do its job --> + </target> + + +</project>
diff --git a/1.9.10/contrib/materialized-interface/BeanHelper.java b/1.9.10/contrib/materialized-interface/BeanHelper.java new file mode 100644 index 0000000..0cf4264 --- /dev/null +++ b/1.9.10/contrib/materialized-interface/BeanHelper.java
@@ -0,0 +1,251 @@ +package org.codehaus.jackson.map.deser; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.FieldVisitor; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; + +public class BeanHelper implements Opcodes { + public static class BeanBuilder { + protected Map<String, Class> properties = new LinkedHashMap<String, Class>(); + protected Map<String, ThrowMethodType> throwMethods = new LinkedHashMap<String, ThrowMethodType>(); + protected List<Class> implementing = new ArrayList<Class>(); + protected String className; + protected String internalClass; + + public BeanBuilder(String className) { + this.className = className; + this.internalClass = getInternalClassName(className); + } + + public BeanBuilder implement(Class parent) { + this.implementing.add(parent); + + for (Method m : parent.getMethods()) { + if (m.getName().startsWith("get") + || m.getName().startsWith("set")) { + String name = getFieldName(m.getName()); + Class propType = m.getName().startsWith("get") ? m + .getReturnType() : m.getParameterTypes()[0]; + + if (this.properties.containsKey(name) + && !this.properties.get(name).equals(propType)) { + throw new IllegalArgumentException("Duplicate property"); + } + + addProperty(name, propType); + } else { + addThrow(m.getName(), m.getParameterTypes(), m + .getReturnType(), + UnsupportedOperationException.class); + } + } + + return this; + } + + public BeanBuilder addProperty(String name, Class type) { + properties.put(name, type); + + return this; + } + + public BeanBuilder addThrow(String name, Class[] paramTypes, + Class returnType, Class exceptionType) { + this.throwMethods.put(name, new ThrowMethodType(name, paramTypes, + returnType, exceptionType)); + + return this; + } + + public Class load() { + ClassWriter cw = new ClassWriter(0); + + String[] parents = new String[implementing.size()]; + for (int i = 0; i < implementing.size(); i++) { + parents[i] = getInternalClassName(implementing.get(i).getName()); + } + cw.visit(V1_2, ACC_PUBLIC + ACC_SUPER, internalClass, null, + "java/lang/Object", parents); + cw.visitSource(className + ".java", null); + BeanHelper.generateDefaultConstructor(cw); + + for (Map.Entry<String, Class> propEntry : this.properties + .entrySet()) { + String propName = propEntry.getKey(); + Class propClass = propEntry.getValue(); + + BeanHelper.createField(cw, propName, propClass); + BeanHelper.createGetter(cw, internalClass, propName, propClass); + BeanHelper.createSetter(cw, internalClass, propName, propClass); + } + + for (Map.Entry<String, ThrowMethodType> throwEntry : this.throwMethods + .entrySet()) { + ThrowMethodType thr = throwEntry.getValue(); + + BeanHelper.createThrow(cw, this.internalClass, throwEntry + .getKey(), thr.paramTypes, thr.returnType, + thr.exceptionType); + } + + cw.visitEnd(); + + return loadClass(className, cw.toByteArray()); + } + } + + private static void generateDefaultConstructor(ClassWriter cw) { + MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, + null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V"); + mv.visitInsn(RETURN); + mv.visitMaxs(1, 1); + mv.visitEnd(); + } + + private static void createField(ClassWriter cw, String fieldName, + Class fieldType) { + String javaType = getLValue(fieldType); + FieldVisitor fv = cw.visitField(0, fieldName, javaType, null, null); + fv.visitEnd(); + } + + private static void createSetter(ClassWriter cw, String internalClassName, + String fieldName, Class fieldType) { + String methodName = getSetterName(fieldName); + String returnType = getLValue(fieldType); + MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, methodName, "(" + + returnType + ")V", null, null); + mv.visitVarInsn(ALOAD, 0); + mv.visitVarInsn(ALOAD, 1); + mv.visitFieldInsn(PUTFIELD, internalClassName, fieldName, returnType); + mv.visitInsn(RETURN); + mv.visitMaxs(2, 2); + mv.visitEnd(); + } + + private static void createGetter(ClassWriter cw, String internalClassName, + String fieldName, Class fieldType) { + String methodName = getGetterName(fieldName); + String returnType = getLValue(fieldType); + MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, methodName, "()" + + returnType, null, null); + mv.visitVarInsn(ALOAD, 0); + mv.visitFieldInsn(GETFIELD, internalClassName, fieldName, returnType); + mv.visitInsn(ARETURN); + mv.visitMaxs(1, 1); + mv.visitEnd(); + } + + private static void createThrow(ClassWriter cw, String internalClassName, + String methodName, Class[] inTypes, Class returnType, + Class exceptionType) { + String rTypeName = getLValue(returnType); + String exceptionName = getInternalClassName(exceptionType.getName()); + + String sig = "(" + getArgumentsType(inTypes) + ")" + rTypeName; + + MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, methodName, sig, null, + null); + + mv.visitTypeInsn(NEW, exceptionName); + mv.visitInsn(DUP); + mv.visitMethodInsn(INVOKESPECIAL, exceptionName, "<init>", "()V"); + mv.visitInsn(ATHROW); + mv.visitMaxs(2, 1 + inTypes.length); + mv.visitEnd(); + } + + private static Class loadClass(String className, byte[] b) { + // override classDefine (as it is protected) and define the class. + Class clazz = null; + try { + ClassLoader loader = ClassLoader.getSystemClassLoader(); + Class cls = Class.forName("java.lang.ClassLoader"); + java.lang.reflect.Method method = cls.getDeclaredMethod( + "defineClass", new Class[] { String.class, byte[].class, + int.class, int.class }); + + // protected method invocaton + method.setAccessible(true); + try { + Object[] args = new Object[] { className, b, new Integer(0), + new Integer(b.length) }; + clazz = (Class) method.invoke(loader, args); + } finally { + method.setAccessible(false); + } + } catch (Exception e) { + e.printStackTrace(); + System.exit(1); + } + return clazz; + } + + private static String getInternalClassName(String className) { + return className.replace(".", "/"); + } + + private static String getFieldName(String getterMethodName) { + char[] name = getterMethodName.substring(3).toCharArray(); + name[0] = Character.toLowerCase(name[0]); + final String propName = new String(name); + + return propName; + } + + private static String getLValue(Class fieldType) { + if (fieldType == null || fieldType.equals(void.class)) { + return "V"; + } + + String plainR = fieldType.getName(); + String rType = getInternalClassName(plainR); + String javaType = "L" + rType + ";"; + return javaType; + } + + private static String getGetterName(String fieldName) { + return "get" + fieldName.substring(0, 1).toUpperCase() + + fieldName.substring(1); + } + + private static String getSetterName(String fieldName) { + return "set" + fieldName.substring(0, 1).toUpperCase() + + fieldName.substring(1); + } + + private static String getArgumentsType(Class[] inTypes) { + StringBuilder list = new StringBuilder(); + + for (Class clazz : inTypes) { + list.append(getLValue(clazz)); + } + + return list.toString(); + } + + private static class ThrowMethodType { + public final String name; + public final Class[] paramTypes; + public final Class returnType; + public final Class exceptionType; + + public ThrowMethodType(String name, Class[] paramTypes, + Class returnType, Class exceptionType) { + this.name = name; + this.paramTypes = paramTypes; + this.returnType = returnType; + this.exceptionType = exceptionType; + } + } +}
diff --git a/1.9.10/contrib/materialized-interface/MaterializingDeserializerFactory.java b/1.9.10/contrib/materialized-interface/MaterializingDeserializerFactory.java new file mode 100644 index 0000000..809732a --- /dev/null +++ b/1.9.10/contrib/materialized-interface/MaterializingDeserializerFactory.java
@@ -0,0 +1,108 @@ +/** + * 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.codehaus.jackson.map.deser; + +import java.lang.reflect.Method; + +import org.codehaus.jackson.map.DeserializationConfig; +import org.codehaus.jackson.map.DeserializerProvider; +import org.codehaus.jackson.map.JsonDeserializer; +import org.codehaus.jackson.map.JsonMappingException; +import org.codehaus.jackson.map.type.TypeFactory; +import org.codehaus.jackson.type.JavaType; + +/** + * A very basic Jackson deserializer factory that extends the BeanSerializer + * factory to allow deserialization using interfaces. + */ +public class MaterializingDeserializerFactory extends BeanDeserializerFactory { + public MaterializingDeserializerFactory() { + super(); + } + + @Override + public JsonDeserializer<Object> createBeanDeserializer( + DeserializationConfig config, JavaType type, DeserializerProvider p) + throws JsonMappingException { + if (type.isInterface()) { + String className = "$org.codehaus.jackson.generated$" + + type.getRawClass().getName(); + BeanHelper.BeanBuilder builder = new BeanHelper.BeanBuilder( + className); + builder.implement(type.getRawClass()); + + return new BeanDeserializerProxyImpl(TypeFactory.fromClass(builder + .load())); + } + + return super.createBeanDeserializer(config, type, p); + } + + protected static class BeanDeserializerProxyImpl extends BeanDeserializer { + public BeanDeserializerProxyImpl(JavaType type) { + super(type); + + try { + this.setDefaultConstructor(type.getRawClass().getConstructor()); + } catch (Exception e) { + throw new RuntimeException(e); + } + + try { + populateSetters(type); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } + } + + private void populateSetters(JavaType type) + throws NoSuchMethodException { + Class clazz = type.getRawClass(); + for (Method m : clazz.getMethods()) { + String methodName = m.getName(); + if (methodName.startsWith("set") + && m.getParameterTypes() != null + && m.getParameterTypes().length == 1) { + Class fieldClass = m.getParameterTypes()[0]; + JavaType fieldType = TypeFactory.fromClass(fieldClass); + + Method setterMethod = getSetterMethod(clazz, methodName, + fieldClass); + + this.addProperty(new SettableBeanProperty.MethodProperty( + getFieldName(methodName), fieldType, + setterMethod)); + } + } + } + + private Method getSetterMethod(Class clazz, String methodName, + Class returnType) throws NoSuchMethodException { + return clazz.getMethod("set" + methodName.substring(3), returnType); + } + } + + private static String getFieldName(String getterMethodName) { + char[] name = getterMethodName.substring(3).toCharArray(); + name[0] = Character.toLowerCase(name[0]); + final String propName = new String(name); + + System.out.println(propName); + return propName; + } +}
diff --git a/1.9.10/contrib/materialized-interface/README b/1.9.10/contrib/materialized-interface/README new file mode 100644 index 0000000..8288aae --- /dev/null +++ b/1.9.10/contrib/materialized-interface/README
@@ -0,0 +1,3 @@ +Work in progress for "materialized interface" extension, contributed by Sunny Gleason. + +Exciting stuff, real source at GitHub (see [http://github.com/sunnygleason/g414-jackson]), but temporarily also cached here for convenience.
diff --git a/1.9.10/contrib/materialized-interface/TestMaterializingDeserializer.java b/1.9.10/contrib/materialized-interface/TestMaterializingDeserializer.java new file mode 100644 index 0000000..39f4354 --- /dev/null +++ b/1.9.10/contrib/materialized-interface/TestMaterializingDeserializer.java
@@ -0,0 +1,61 @@ +/** + * 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.example; + +import java.io.StringWriter; + +import junit.framework.TestCase; + +import org.codehaus.jackson.map.ObjectMapper; +import org.codehaus.jackson.map.deser.MaterializingDeserializerFactory; +import org.codehaus.jackson.map.deser.StdDeserializerProvider; + +import com.g414.jackson.proxy.ProxySerializerFactory; + +/** + * Exercise the deserializer... + */ +public class TestMaterializingDeserializer extends TestCase { + public void testExample() throws Exception { + ExampleImpl impl = new ExampleImpl(); + + ObjectMapper mapper = new ObjectMapper(); + mapper.setSerializerFactory(new ProxySerializerFactory()); + + MaterializingDeserializerFactory df = new MaterializingDeserializerFactory(); + StdDeserializerProvider dp = new StdDeserializerProvider(df); + mapper.setDeserializerProvider(dp); + + // Testing Example1 + StringWriter w1 = new StringWriter(); + mapper.writeValue(w1, impl.asExample1()); + String w1Value = w1.toString(); + Example1 w1in = mapper.readValue(w1Value, Example1.class); + + assertEquals("4660", w1in.getA().toString()); + assertEquals("Foo", w1in.getB().toString()); + + // Testing Example2 ... + StringWriter w2 = new StringWriter(); + mapper.writeValue(w2, impl.asExample2()); + String w2Value = w2.toString(); + + Example2 w2in = mapper.readValue(w2Value, Example2.class); + assertEquals("305419896", w2in.getC().toString()); + } +}
diff --git a/1.9.10/lib/ant/bndtask-0.2.0.jar b/1.9.10/lib/ant/bndtask-0.2.0.jar new file mode 100644 index 0000000..3c0e2d5 --- /dev/null +++ b/1.9.10/lib/ant/bndtask-0.2.0.jar Binary files differ
diff --git a/1.9.10/lib/ant/maven-ant-tasks-2.0.10.jar b/1.9.10/lib/ant/maven-ant-tasks-2.0.10.jar new file mode 100644 index 0000000..50c80cf --- /dev/null +++ b/1.9.10/lib/ant/maven-ant-tasks-2.0.10.jar Binary files differ
diff --git a/1.9.10/lib/cobertura/asm-tree-3.0.jar b/1.9.10/lib/cobertura/asm-tree-3.0.jar new file mode 100644 index 0000000..2a4b208 --- /dev/null +++ b/1.9.10/lib/cobertura/asm-tree-3.0.jar Binary files differ
diff --git a/1.9.10/lib/cobertura/cobertura-1.9.4.1.jar b/1.9.10/lib/cobertura/cobertura-1.9.4.1.jar new file mode 100644 index 0000000..438fe55 --- /dev/null +++ b/1.9.10/lib/cobertura/cobertura-1.9.4.1.jar Binary files differ
diff --git a/1.9.10/lib/cobertura/jakarta-oro-2.0.8.jar b/1.9.10/lib/cobertura/jakarta-oro-2.0.8.jar new file mode 100644 index 0000000..23488d2 --- /dev/null +++ b/1.9.10/lib/cobertura/jakarta-oro-2.0.8.jar Binary files differ
diff --git a/1.9.10/lib/cobertura/log4j-1.2.13.jar b/1.9.10/lib/cobertura/log4j-1.2.13.jar new file mode 100644 index 0000000..dde9972 --- /dev/null +++ b/1.9.10/lib/cobertura/log4j-1.2.13.jar Binary files differ
diff --git a/1.9.10/lib/ext/asm/asm-3.3.jar b/1.9.10/lib/ext/asm/asm-3.3.jar new file mode 100644 index 0000000..7638ae0 --- /dev/null +++ b/1.9.10/lib/ext/asm/asm-3.3.jar Binary files differ
diff --git a/1.9.10/lib/ext/cglib/cglib-nodep-2.2.jar b/1.9.10/lib/ext/cglib/cglib-nodep-2.2.jar new file mode 100644 index 0000000..ed07cb5 --- /dev/null +++ b/1.9.10/lib/ext/cglib/cglib-nodep-2.2.jar Binary files differ
diff --git a/1.9.10/lib/ext/google/google-collections-1.0.jar b/1.9.10/lib/ext/google/google-collections-1.0.jar new file mode 100644 index 0000000..8e394fa --- /dev/null +++ b/1.9.10/lib/ext/google/google-collections-1.0.jar Binary files differ
diff --git a/1.9.10/lib/ext/groovy/antlr-2.7.7.jar b/1.9.10/lib/ext/groovy/antlr-2.7.7.jar new file mode 100644 index 0000000..5e5f14b --- /dev/null +++ b/1.9.10/lib/ext/groovy/antlr-2.7.7.jar Binary files differ
diff --git a/1.9.10/lib/ext/groovy/groovy-1.7.4.jar b/1.9.10/lib/ext/groovy/groovy-1.7.4.jar new file mode 100644 index 0000000..ba57102 --- /dev/null +++ b/1.9.10/lib/ext/groovy/groovy-1.7.4.jar Binary files differ
diff --git a/1.9.10/lib/ext/hibernate/hibernate-cglib-repack-nodep-2.1_3-SNAPSHOT.jar b/1.9.10/lib/ext/hibernate/hibernate-cglib-repack-nodep-2.1_3-SNAPSHOT.jar new file mode 100644 index 0000000..5b6b85a --- /dev/null +++ b/1.9.10/lib/ext/hibernate/hibernate-cglib-repack-nodep-2.1_3-SNAPSHOT.jar Binary files differ
diff --git a/1.9.10/lib/ext/jarjar/jarjar-1.0.jar b/1.9.10/lib/ext/jarjar/jarjar-1.0.jar new file mode 100644 index 0000000..89390bf --- /dev/null +++ b/1.9.10/lib/ext/jarjar/jarjar-1.0.jar Binary files differ
diff --git a/1.9.10/lib/ext/joda-time-1.5.2.jar b/1.9.10/lib/ext/joda-time-1.5.2.jar new file mode 100644 index 0000000..247898f --- /dev/null +++ b/1.9.10/lib/ext/joda-time-1.5.2.jar Binary files differ
diff --git a/1.9.10/lib/jaxb/activation.jar b/1.9.10/lib/jaxb/activation.jar new file mode 100644 index 0000000..1b703ab --- /dev/null +++ b/1.9.10/lib/jaxb/activation.jar Binary files differ
diff --git a/1.9.10/lib/jaxb/jaxb-api-2.0.jar b/1.9.10/lib/jaxb/jaxb-api-2.0.jar new file mode 100644 index 0000000..3918383 --- /dev/null +++ b/1.9.10/lib/jaxb/jaxb-api-2.0.jar Binary files differ
diff --git a/1.9.10/lib/jaxrs/jersey-core-1.1.5.jar b/1.9.10/lib/jaxrs/jersey-core-1.1.5.jar new file mode 100644 index 0000000..097bfd8 --- /dev/null +++ b/1.9.10/lib/jaxrs/jersey-core-1.1.5.jar Binary files differ
diff --git a/1.9.10/lib/jaxrs/jersey-server-1.1.5.jar b/1.9.10/lib/jaxrs/jersey-server-1.1.5.jar new file mode 100644 index 0000000..751660b --- /dev/null +++ b/1.9.10/lib/jaxrs/jersey-server-1.1.5.jar Binary files differ
diff --git a/1.9.10/lib/jaxrs/jsr311-api-1.1.jar b/1.9.10/lib/jaxrs/jsr311-api-1.1.jar new file mode 100644 index 0000000..440c531 --- /dev/null +++ b/1.9.10/lib/jaxrs/jsr311-api-1.1.jar Binary files differ
diff --git a/1.9.10/lib/junit/junit-4.8.2.jar b/1.9.10/lib/junit/junit-4.8.2.jar new file mode 100644 index 0000000..5b4bb84 --- /dev/null +++ b/1.9.10/lib/junit/junit-4.8.2.jar Binary files differ
diff --git a/1.9.10/lib/perf/antlr-2.7.6.jar b/1.9.10/lib/perf/antlr-2.7.6.jar new file mode 100644 index 0000000..3702b64 --- /dev/null +++ b/1.9.10/lib/perf/antlr-2.7.6.jar Binary files differ
diff --git a/1.9.10/lib/perf/jackson-module-json-org-0.9.1.jar b/1.9.10/lib/perf/jackson-module-json-org-0.9.1.jar new file mode 100644 index 0000000..7ce491b --- /dev/null +++ b/1.9.10/lib/perf/jackson-module-json-org-0.9.1.jar Binary files differ
diff --git a/1.9.10/lib/perf/json-org.jar b/1.9.10/lib/perf/json-org.jar new file mode 100644 index 0000000..3e53d2e --- /dev/null +++ b/1.9.10/lib/perf/json-org.jar Binary files differ
diff --git a/1.9.10/lib/perf/json-smart-1.0.6.1.jar b/1.9.10/lib/perf/json-smart-1.0.6.1.jar new file mode 100644 index 0000000..b4d90c4 --- /dev/null +++ b/1.9.10/lib/perf/json-smart-1.0.6.1.jar Binary files differ
diff --git a/1.9.10/lib/repackaged/jackson-asm-3.3.jar b/1.9.10/lib/repackaged/jackson-asm-3.3.jar new file mode 100644 index 0000000..27f1a21 --- /dev/null +++ b/1.9.10/lib/repackaged/jackson-asm-3.3.jar Binary files differ
diff --git a/1.9.10/obsolete-src/README b/1.9.10/obsolete-src/README new file mode 100644 index 0000000..db449a4 --- /dev/null +++ b/1.9.10/obsolete-src/README
@@ -0,0 +1,4 @@ +This directory contains source code that has been in use at some point, +but not used or needed any more. However, there is a chance that such code +might be useful for some other use later on, and as such it is still retained +in a somewhat visible place (not just SCM system version history).
diff --git a/1.9.10/profile.sh b/1.9.10/profile.sh new file mode 100755 index 0000000..66e5623 --- /dev/null +++ b/1.9.10/profile.sh
@@ -0,0 +1,8 @@ +#!/bin/sh + +java -Xmx64m -server \ + -cp build/classes/core:build/classes/mapper:build/classes/extra\ +:build/classes/smile:build/classes/xc:build/classes/perf\ +:lib/xml/\*\ + -Xrunhprof:cpu=samples,depth=10,verbose=n,interval=2 \ +$*
diff --git a/1.9.10/regression/clirr-core-0.6-uber.jar b/1.9.10/regression/clirr-core-0.6-uber.jar new file mode 100644 index 0000000..d4245f4 --- /dev/null +++ b/1.9.10/regression/clirr-core-0.6-uber.jar Binary files differ
diff --git a/1.9.10/regression/jackson-core-asl-1.7.3.jar b/1.9.10/regression/jackson-core-asl-1.7.3.jar new file mode 100644 index 0000000..380c063 --- /dev/null +++ b/1.9.10/regression/jackson-core-asl-1.7.3.jar Binary files differ
diff --git a/1.9.10/regression/jackson-mapper-asl-1.7.3.jar b/1.9.10/regression/jackson-mapper-asl-1.7.3.jar new file mode 100644 index 0000000..d36c923 --- /dev/null +++ b/1.9.10/regression/jackson-mapper-asl-1.7.3.jar Binary files differ
diff --git a/1.9.10/release-notes/CREDITS b/1.9.10/release-notes/CREDITS new file mode 100644 index 0000000..c69cbcb --- /dev/null +++ b/1.9.10/release-notes/CREDITS
@@ -0,0 +1,935 @@ +Here are people who have contributed to Jackson JSON process development: +(version numbers in brackets indicate release in which the problem was fixed) + +Tatu Saloranta, tatu.saloranta@iki.fi: author + +Ryan Heaton, ryan@webcohesion.com: co-author + +Peter Harris, Peter.Harris@betfair.com: contributor + +Sunny Gleason, sunny@ning.com: contributor + +Alain Penders: + * Reported problem with JavaTypeMapper, where floating point numbers were + accidentally converted to Booleans. + [0.8] + +Mike Eastey: + * Reported problem with JavaTypeMapper had a bug which prevented custom + mappers (as well as slower interface-based introspection) from working, + provided path to specific underlying bugs. + [0.8.2] + +Augusto Callejas: + * Reported problem with JavaTypeMapper (and JsonTypeMapper), which + caused read operation not to handle EOF appropriately but instead + cause a NullPointerException. + [0.9] + +Maciej Pestka: + * JavaTypeMapper did not implicitly flush generator after mapping + objects: it should, and now will (note: JsonTypeMapper not directly + affected, flushing still needed) + [0.9] + +Tudor Bosman: + * Symbol table handling not thread-safe + [0.9.3] + +Michael Mangeng: + * Suggested [JACKSON-1]: make JsonNode implement Iterable<JsonNode> to + allow use of Java 5 foreach loop with container nodes. + [0.9.3] + +Johannes Link: + * Reported [JACKSON-8]: Serialization of BigDecimal broken with JavaTypeMapper + [0.9.3] + +Stanislaw Osinski: + * Reported [JACKSON-14], contributed code to resolve it and improve + generics-handling significantly. + [0.9.4] + +Michael Descher: + * Reported [JACKSON-18], ArrayIndexOutOfBounds on IntNode, due to + off-by-one problem with comparisons used for caching common values. + [0.9.4] + +Mike Goodwin: + * Suggested [JACKSON-9]: Add support for (non-standard) Json comments. + [0.9.4] + +Ray Racine: + * Pointed out [JACKSON-25]: Problems with Maven pom for lgpl version + [0.9.4-backport] + * Reported [JACKSON-619] SmileParser.getCurrentLocation(), getTokenLocation() + not reporting actual byte offsets. + [1.9.0] + +Scott Dixon: + * Contributed unit test (TestComplexJavaType) for verifying functioning + of object serialization + [0.9.5] + * Suggested [JACKSON-38] Allow serializing/deserializing DOM trees (Node, Document) + [1.4.0] + * Suggested [JACKSON-45]: Add convenience methods to simplify writing + custom serializers + [1.0.0] + +Justin Friedl: + * Requested [JACKSON-52]: ability to disable getter method auto-detection + [0.9.9] + * Reported [JACKSON-53] (and suggested way to fix it): problem serializing + iBatis bean classes generated (or wrapped) by CGLib. Probably would also + have caused problems with Hibernate and other frameworks. + [0.9.8] + * Requested [JACKSON-61]: Allow suppressing writing of bean properties + with null values + [0.9.9-3] + * Reported [JACKSON-62]: NPE with JsonMappingException + [0.9.9] + +Scott Anderson: + * Suggested [JACKSON-48]: Integrate ObjectMapper with JsonGenerator, + JsonParser; add MappingJsonFactory. + [0.9.9] + * Requested [JACKSON-84]: Add JsonGenerator.writeRawValue method(s). + [0.9.9-3] + * Requested [JACKSON-106]: Add 'org.codehaus.jackson.io.CharacterEscapes' which can + be registered with JsonFactory, JsonGenerator, to add fully customized character + escaping handling + [1.8.0] + +Kevin Grained: + * Reported [JACKSON-58] (and suggested a fix): NPE with String[] + serialization + [0.9.9] + +Eldar Abusalimov: + * Reported [JACKSON-81]: Data binding code could lead to unnecessary + blocking because it tried to advance parser (and stream) after binding + [0.9.9-3] + * Reported [JACKSON-99]: IOExceptions should not be wrapped during object + mapping. + [0.9.9-4] + +Stephen Duncan jr: + * Pointed out problem with JacksonJsonProvider where strict equality + comparison was used instead of using MediaType.isCompatible(). + [0.9.9-4] + +Ray Tsang: + * Reported [JACKSON-103] (problem with Groovy class serialization), + submitted fix + [0.9.9-7] + +Oleksandr Alesinskyy: + * Reported [JACKSON-104], problems with packaging, build. + [0.9.9-7] + +Christoph Strebin: + * Requested [JACKSON-102], ability to force escaping of non-ASCII characters + [1.8.0] + * Requested [JACKSON-105], proposed a way to implement it: + Allow suppressing output of "default values"; which + means value of a property when bean is constructed using the default + no-arg constructor + [1.1.0] + * Reported [JACKSON-568] Package 'org.codehaus.jackson.util' missing from + core/lgpl jar + [1.8.1] + * Suggested [JACKSON-531] Comparing actual and default value (for + JsonSerialize.Inclusion.NON_DEFAULT) should check array contents + [1.9.0] + +Peter Harris: + * Reported [JACKSON-139], provided patch for fixing it: Non-numeric + double values (NaN, Infinity) are serialized as invalid JSON tokens + (reported by Peter H) + [1.1.1] + +Dan Simpson: + * Reported [JACKSON-144]: Static "getter-like" methods mistaken for + getters (for serialization) + [1.1.2] + +Gregory Gerard: + * Reportd [JACKSON-143]: NPE on ArrayNode.equals() when comparing empty + array node to non-empty array node + [1.1.2] + +Dain Sundstrom: + * Suggested addition of "-use" for javadoc generation + [1.2.0] + * Suggested [JACKSON-136] JsonParser and JsonGenerator should implement + java.io.Closeable (since they already have close() method) + [1.2.0] + * Suggested [JACKSON-706] Joda support: add support for "org.joda.time.Period" + [1.9.2] + +Gabe Schnaubelt: + * Reported [JACKSON-155]: Failed to serialize java.io.File (with infinite + recursion) + [1.3.0] + +Benjamin Darfler: + * Suggested [JACKSON-164]: Improve null-handling in JsonGenerator.writeStringField() + [1.3.0] + * Suggested [JACKSON-165]: Add JsonParser.getBooleanValue() convenience method + [1.3.0] + +Troy Waldrep: + * Reported [JACKSON-162]: OSGi packaging problems for xc package. + [1.3.0] + +Randy Layma: + * Reported [JACKSON-171]: Self-referential types cause infinite recursion + when using only JAXB annotation introspector + [1.3.0] + +Shay Banon: + * Suggested [JACKSON-168] Make JsonLocation serializable (and deserializable) + [1.3.0] + * Reported [JACKSON-376] writing binary data as object field value with Smile fails + [1.6.1] + * Reported [JACKSON-424] ArrayIndexOutOfBounds with SmileGenerator, long Unicode + Strings + [1.6.3] + * Reported [JACKSON-525]: Problem with SmileGenerator, recycling of shared-names + buffer + [1.7.4] + * Reported [JACKSON-552] SmileParser not handling long field names properly, + failed with "this code path should never get executed" exception + [1.7.6] + +Brian McCallister: + * Suggested [JACKSON-173]: Add "JsonParser.Feature.ALLOW_SINGLE_QUOTES" + to handle commonly encountered invalid JSON content + [1.3.0] + * Reported [JACKSON-179] Single-long-arg factory Creators were not working + [1.3.0] + +Ted Bergeron: + * Reported [JACKSON-177]. + [1.3.0] + +Jeff Yu: + * Suggested [JACKSON-180]: Add 'JsonParser.Feature.INTERN_FIELD_NAMES' to + allow disabling field name intern()ing. + [1.3.0] + +Doug Daniels: + * Suggested [JACKSON-176]: Add a work-around for Javascript's problems + with big 64-bit longs (due to always representing numbers as 64-bit + doubles internally, thus truncating some long values) + [1.3.0] + +Nick Padgett: + * Reported [JACKSON-183]: Root-level 'JsonDeserialize' annotation + not handled completely; 'as' setting was not taking effect + [1.3.0] + +Nathan Ching: + * Reported [JACKSON-190]: Problem deserializing some nested generics + types + [1.3.1] + +Martin Lauer: + * Reported [JACKSON-194] ObjectMapper class loading issues on Android + [1.3.1] + +Edward Thorne: + * Reported [JACKSON-197]: 2 debug message print out to System.err + [1.3.1] + +Steve Lopez: + * Reported [JACKSON-200]: java.sql.Date deserialization not working well + [1.3.1] + * Reported [JACKSON-203]: Date deserializers should map empty String to null + [1.3.1] + +Mike Pilone: + * Suggested [JACKSON-201]: Allow serialization of "empty beans" (classes + without getters), if SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS is + disabled; or if class has recognized Jackson annotation + [1.4.0] + * Reported [JACKSON-202]: Non-public fields not deserialized properly + with JAXB annotations + [1.3.1] + +Stephen Friedrich: + * Reported additional issues with [JACKSON-203] + [1.3.2] + +Jeff Schnitzer: + * Reported [JACKSON-188]: problems running Jackson 1.3 on GAE, due + to dependency to JAXB API classes + [1.3.2] + +Elliot Shepherd: + * Reported [JACKSON-214], suggested fix: Enum types with subclasses + fail to serialize + [1.3.3] + +Gil Markham: + * Reported [JACKSON-196], suggested fix: Schema generation does not + respect the annotation configured serializer on a bean property + [1.4.0] + +Mark Stevens: + * Requested [JACKSON-208] Allow unquoted control characters (esp. tabs) + in JSON Strings and field names + [1.4.0] + +Mike Rheinheimer: + * Reported [JACKSON-216] Jackson JAXB annotation handler does not use + @XmlElement.type property for figuring out actual type + [1.4.0] + +Chris Carrier: + * Suggested [JACKSON-236]: Allow deserialization of timestamps-as-Strings + (not just timestamps as JSON integer numbers). + [1.5.0] + +Andrei Voden: + * Suggested [JACKSON-232]: Add 'SerializationConfig.Feature.DEFAULT_VIEW_INCLUSION' + to disable inclusion of non-annotated properties with explicit views + [1.5.0] + +Lars Clausen: + * For 1.5.0: + - [JACKSON-246]: JAXB property name determination not working correctly. + - [JACKSON-250]: Type name not always detected + - Concurrency bug in pre-1.5.0 version of @JsonSubTypes handling + +Pierre-Yves Ricay: + * Requested [JACKSON-244]: allow private fields processing without having to annotate them + [1.5.0] + +John Lister: + * Reported [JACKSON-256]: incorrect combining of serialization inclusion + values; suggested better way to do it + [1.5.0] + +Gennadiy Shafranovich: + * Reported [JACKSON-263]: BooleanNode.asToken() incorrectly returns 'true' + token for all nodes (not just 'false' ones) + [1.4.4, 1.5.0] + +Fabrice Delhoste: + * Suggested [JACKSON-254] Add 'SerializationConfig.Feature.WRITE_EMPTY_JSON_ARRAYS', + which can be used to suppress serialization of empty JSON arrays (unless + overridden by per-property annotations). + [1.9.0] + * Reported [JACKSON-265]: problems with generic type handling for + serialization + [1.5.1] + +Raymond Feng: + * Reported [JACKSON-269]: missing OSGi export by mapper (o.c.j.m.jsontype.impl) + needed by jackson-xc module + [1.5.1] + +Martin Tomko: + * Reported [JACKSON-266] Deserialization from JsonNode fails + [1.4.4, 1.5.2] + +Lukasz Dywicki: + * Reported [JACKSON-273] Problems with OSGi dependency declarations + [1.5.2] + +Aron Atkins: + * Reported [JACKSON-281] JsonGenerator.writeObject() only supports subset of + wrapper types (when not specifying ObjectCodec) + [1.5.2] + +Eric Sirianni: + * Reported [JACKSON-311]: Problems handling polymorphic type information for + 'untyped' (Object) bean properties, default typing + [1.5.4] + +Geoffrey Arnold: + * Reported [JACKSON-318]: Missing deserialization support for + java.util.Currency + [1.5.5] + +Christopher Currie: + * Reported [JACKSON-319], pointed out solution: issues trying to deserialize + polymorphic instances with no data (just type info) + [1.5.5] + (requested by Chris C) + * Suggested [JACKSON-638] TypeFactory methods for constructing "raw" map or collection types + [1.9.0] + * Requested [JACKSON-639] Change BasicClassIntrospector.forClassAnnotations + to take JavaType (not raw Class) + [1.9.0] + * Requested [JACKSON-665] Add AnnotatedWithParams.getIndex() + [1.9.0] + +Steve Crane: + * Suggested [JACKSON-324], calling releaseBuffers() within finally block + (JsonParserBase.close()) + [1.5.5] + +Yuanchen Zhu: + * Reported [JACKSON-327], submitted patch: CustomSerializerFactory incorrectly + looks up serializer for interfaces + [1.5.5] + * Reported [JACKSON-329], type information was not properly serialized for + Iterator or Iterable serializers + [1.5.6] + * Reported [JACKSON-340] Meta annotations missing for @JsonTypeResolver + [1.5.6] + +Henry Lai: + * Reported [JACKSON-352] Polymorphic deserialization for Object always + assumes array-wrapper style + [1.5.7] + +Adam Sussman: + * Reported [JACKSON-355] Handling of BigInteger with JsonNode not correct + [1.5.7] + +Lubomir Konstantinov: + * Reported [JACKSON-363] CustomDeserializerFactory did not work for custom + array deserializers. + * Reported [JACKSON-373] Interface inheritance not traversed when looking up + custom serializers + +Dimitry Lisay: + * Reported [JACKSON-370] TreeTraversingParser.skipChildren() was not + correctly skipping children + [1.5.7] + +Kirill Stokoz: + * Reported [JACKSON-377] ThrowableDeserializer was not properly using information from + @JsonCreator or @JsonAnySetter + [1.5.7] + * Reported [JACKSON-383] @JsonAnySetter gets called for ignorable properties if + FAIL_ON_UNKNOWN_PROPERTIES set to false (related to [JACKSON-313]) + [1.6.1] + * Reported [JACKSON-456], provided unit tests: Type check issues with Jackson JAX-RS provider + [1.7.1] + * Reported [JACKSON-504]: FilterProvider registration directly via + SerializationConfig was not working + [1.7.4] + * Reported [506]: problems with type handling for java.util.Date + when using @JsonTypeInfo on field/method + [1.7.4] + * Reported [JACKSON-518]: Problems with JAX-RS, type variables + [1.7.4] + +Brian Oberman: + * Requested [JACKSON-289] Ability to serialize char[] values as JSON Arrays + with String values of length 1 (and accepting these on deserialization) + [1.6.0] + +Paul R Brown: + * Requested [JACKSON-193] Ability to use @JsonCreator and @JsonValue with + enum types + [1.6.0] + +Ketan G: + * Requested [JACKSON-300] Add 'JsonParser.Feature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER + to allow non-standard character escapes like \'. + [1.6.0] + +Rob Ottway: + * Requested [JACKSON-301] Allow JsonMappingException to return name of "bad" + (unrecognized) field + [1.6.0] + +Thomas Dudziak: + * Reported [JACKSON-328] Incorrect precedence between property fields, "getter-as-setter" + fallbacks (former should have higher precedence) + [1.6.0] + * Suggested [JACKSON-420] Add 'DeserializationConfig.Feature.FAIL_ON_NULL_FOR_PRIMITIVES' + to optionally prevent JSON null from mapping to default value + [1.7.0] + +Ant Elder: + * Suggested [JACKSON-295] Create "jackson-all" jar for more convenient + deployment + [1.6.0] + +David Melia: + * Reported [JACKSON-303] JAXB annotation @XmlAccessorType(XmlAccessType.NONE) seems + to not work correctly during deserialisation process + [1.6.0] + +Valentin Brasov: + * Reported [JACKSON-268] Property ordering for JAXB did not work with "raw" property + names (but just with renamed names like with Jackson annotations) + [1.6.0] + +Igor Kolomets: + * Suggested [JACKSON-308] Configurable date formatting support for XMLGregorianCalendar, + XMLGregorianCalendar now uses same Date/Calendar serialization as other date types. + [1.6.0] + +Shilpa Panaganti: + * Suggested [JACKSON-360] Convert "" to null for Joda date/time types + [1.6.1] + +Larry Yogman: + * Reported [JACKSON-371] Provide path of type error in ObjectMapper.convertValue() + [1.6.1] + * Reported [JACKSON-458]: Problems with ObjectMapper.convertValue(), TokenBuffer, SerializedString + [1.7.1] + +Bruce Ritchie: + * Reported [JACKSON-384] @JsonAnyGetter values were duplicated if method name was valid + as a regular getter name + [1.6.1] + +Patrick Ryan: + * Reported [JACKSON-366] Type metadata not written for empty beans + [1.6.2] + * Reported [JACKSON-428] Type information, Map key deserializer definitions don't + work together + [1.6.4] + +Manuel Alejandro de Brito Fontes: + * Reported [JACKSON-403]: XMLGregorianCalendar could not be deserialized from timestamp + [1.6.2] + +Davide: + * Reported [JACKSON-404]: Problem with XmlAdapter, generic types, deserialization + [1.6.2] + +Kent Rancourt: + * Reported [JACKSON-288]: Problems with JAXB annotation handling for combination of + @XmlJavaTypeAdapter, @XmlElement + [1.6.2] + +Claudio Rossetto: + * Reported [JACKSON-228], suggested correct solution: XmlJavaTypeAdapter not + properly handled with package-level annotations + [1.6.3] + +Sean Parmelee: + * Reported [JACKSON-415]: XmlElement.type() ignored for Schema generation + [1.6.3] + * Reported [JACKSON-416]: XmlElement.type() doesn't override type during + serialization + [1.6.3] + * Reported [JACKSON-423]: Incorrect serialization of BigDecimal, BigInteger, + when using TokenBuffer + [1.6.3] + * Reported [JACKSON-436]: @XmlElementType not working correctly with Collection + type properties + [1.6.4] + * Reported [JACKSON-450] JAXB annotations chosen incorrectly from interface method + (instead of method definition in class), when serializing + [1.7.0] + * Reported [JACKSON-472] Custom bean deserializers are not cached when using + JAXB annotation introspector + [1.6.5] + * Reported [JACKSON-476] ContextualDeserializer handling not completely working + [1.7.2] + +Joe Jensen: + * Reported [JACKSON-417] Deserialization of "native" types (String, Integer, + Boolean) failed with abstract types + [1.6.3] + +Peter Litvak: + * Reported [JACKSON-387]: Deserialization fails for certain objects serialized + with enableDefaultTyping + [1.6.3] + * Suggested [JACKSON-432]: Add 'ObjectMapper.enableDefaultTypingAsProperty()' to allow + specifying inclusion type 'As.PROPERTY' and property name to use + [1.7.0] + +Hannu Leinonen: + * Reported [JACKSON-431] Deserialization fails with JSON array with beans + with @JsonCreator, unmapped properties before and after creator properties + [1.6.4] + +Tim Williamson: + * Reported [JACKSON-461] ArrayIndexOutOfBoundsException when property is subclass of + Map with fewer type parameters + [1.6.5 + * Reported [JACKSON-465] Deserialization with @JsonCreator that takes in + a Map fails + [1.6.5] + * Reported [JACKSON-470] ArrayIndexOutOfBoundsException if @JsonCreator + constructor has @JsonParameter parameters with same name + [1.6.5] + * Suggested [JACKSON-548]: enabling ALLOW_SINGLE_QUOTES should allow backslash-escaping + [1.8.0] + +Christian Naeger: + * [JACKSON-468] Method-bound type variables (public <T> T getValue()) not handled + [1.6.5] + +Steven Schlansker: + * Reported [JACKSON-473] JsonMapping$Reference not Serializable + [1.6.5] + * Reported [JACKSON-543] Root-level static type information incorrectly handled + with Maps (losing parameterization) + [1.7.7] + * Reported [JACKSON-572] Problems serializing generic non-static inner classes + [1.7.7] + * Suggested [JACKSON-726] Add java.util.UUID key deserializer + [1.9.3] + +Elliot Barlas: + * Reported [JACKSON-491]: Bug in NumberInput.inLongRange, causing false overflows + [1.6.6] + +Gili (cowwoc): + * Reported [JACKSON-495] NPE at JaxbAnnotationIntrospector, with @JsonCreator + annotations + [1.6.6] + +Jax Law: + * Reported [JACKSON-499] Problems serializing HashMap.keySet(), values() + [1.6.7] + +Ga�l Marziou: + * Contributed [JACKSON-351]: Add @JsonRawValue that allows injecting literal textual + value into JSON + [1.7.0] + +Patrick Leamon: + * Suggested [JACKSON-412] Add 'DeserializationConfig.Feature.FAIL_ON_NUMBERS_FOR_ENUMS' + to optionally prevent mapping JSON integers into Java Enum values + [1.7.0] + +Tauren Mills: + * Suggested [JACKSON-414] Add 'JsonNode.getValueAsBoolean()' (and 'JsonParser.getValueAsBoolean()') + [1.7.0] + +Chris Winters: + * Reported [JACKSON-457] Misspelled method in Module ("getSeserializationConfig") + [1.7.1] + * Suggested [JACKSON-459]: Add mapper-level configuration to set default serialization + order be alphabetic (by property name). + [1.8.0] + +Coda Hale: + * Reported [JACKSON-462]: Buffer overflow in Utf8Generator#writeFieldName(String) + [1.7.1] + * [JACKSON-557] CollectionLikeType#equals() casts parameter to CollectionType + [1.8.1] + +David Yu: + * Suggested [JACKSON-474]: Add ability to pass externally allocated buffer for Utf8Generator, SmileGenerator + [1.7.2] + * Reported [JACKSON-492], contributed unit test: problem encoding 1 byte length "raw" UTF8 Strings + [1.7.3] + +Christopher Berner: + * [JACKSON-508] Type information lost when serializing List<List<X>> + [1.7.4] + +Pascal Glinas: + * Suggested [JACKSON-541] with patch: Remove the need for @JsonCreator on + multi-arg constructor iff all parameters have @JsonProperty + [1.7.5] + * Reported [JACKSON-554] ObjectMapper.readValue(JsonNode) was not properly + passing itself as ObjectCodec, making secondary conversions fail + [1.7.7] + * Suggested [JACKSON-581] Add 'ObjectMapper.readTree(File)' + [1.9.0] + * Reported [JACKSON-687] Problems with PropertyNamingStrategy, property merging + [1.9.1] + * Reported [JACKSON-689] Deserialization of Iterable fails + [1.9.1] + * Reported [JACKSON-693] @JsonBackReference not used during deserialization + if it's annotated on a getter method. + [1.9.1] + +Maik Jorra: + * Reported [JACKSON-540] Side-effects with ObjectMapper.canSerialize(), + canDeserialize() + [1.7.5] + +Suchema Oyetey: + * Reported [JACKSON-530] Default SerializationInclusion value not properly + passed when "USE_ANNOTATION" set to false + [1.7.5] + +Michel Goldstein: + * Reported [JACKSON-545] UTF8Writer getting NPE if flush() called after close() + [1.7.5] + +Andrei Pozolotin: + * Reported [JACKSON-550] Registration of serializers was not completely + working with SimpleModule (interfaces implemented by superclasses skipped) + [1.7.6] + +Luis Neves: + * Reported [JACKSON-542] Base64 decoder couldn't handle escaped characters + +Xyn Wang: + * Reported [JACKSON-553] SerializationConfig.Feature.DEFAULT_VIEW_INCLUSION + did not work correctly + [1.7.7] + +Alex Porras: + * Reported [JACKSON-556] @XmlElement.name property ignored in some cases + [1.7.7] + +Gregor Ottman: + * Reported [JACKSON-569] ContextualSerializer not resolved for serializers + defined with @JsonSerialize annotation + [1.7.7] + +Bryce McKinlay: + * Suggested [JACKSON-358]: Allow parsing numbers with leading zeroes + [1.8.0] + +Sven Jacobs: + * Suggested [JACKSON-527]: Add 'HandlerInstantiator' abstraction, which can be implemented + and registered with ObjectMapper to get more control over how handlers (serializers, + deserializers, type id resolver) are constructed. + [1.8.0] + +Ruben Errejon Garcia: + * Reported [JACKSON-560] Mix-in annotations ignored when used with views + [1.8.0] + +Young Jin Park: + * Failure to serialize certain Unicode Strings + [1.8.1] + +Oleg Estekhin: + * Reported [JACKSON-563] JSON Schema uses "required" (not "optional") + [1.8.1] + +Jamie Reilly: + * Reported [JACKSON-570] Caching of MapSerializer not thread-safe + [1.8.1] + +Pierre-Alexandre Meyer: + * Reported [JACKSON-586]: Problems with @JsonValue, method visibility + [1.8.2] + +Chris Pruett: + * Reported [JACKSON-587] TextNode.getValueAsLong() failing with values + beyond int range. + [1.8.3] + +Tom Leccese: + * reported [JACKSON-591] JodaDeserializers not throwing wrongTokenException + [1.8.3] + +Lawrence Chang: + * Reported [JACKSON-627] WriterBasedGenerator failure for long Strings, + custom character escaping, unit test, suggested fix. + [1.8.4] + +Maxxan: + * Reported [JACKSON-629] Fix a buffer boundary problem with SmileParser, + 5-7 character names + [1.8.4] + +Tim Bond: + * Reported [JACKSON-631] Problems decoding Base64Variants.MODIFIED_FOR_URL + [1.8.4] + +Edward Alexandrov: + * Reported [JACKSON-632] Handling of UTF-8 BOM incorrect, causing + "Internal Error" + [1.8.4] + +Paul Marynchev: + * Reported [JACKSON-637] NumberSerializer was missing proper handling of + Integer, Long + [1.8.5] + +Ransom Briggs: + * Reported [JACKSON-668] Problems with 'JsonParser.getDecimalValue' + not clearing earlier state + [1.8.6] + +William Burns: + * Reported [JACKSON-677], suggested fix for: Inner generic type references + not working properly + [1.8.6] + +Tom Boettcher: + * Reported [JACKSON-709] Problems converting base64-encoded Strings + between JsonNode, POJOs + [1.8.7] + +Ryan Kennedy: + * Reported [JACKSON-462] (REGRESSION?) Buffer overflow in + Utf8Generator#writeFieldName(String) + [1.8.7] + +Jacques-Olivier Goussard: + * Reported [JACKSON-733] Smile-based mapper could not properly bind + byte[] values + [1.8.7] + +Alex Temnokhod: + * Reported [JACKSON-738] Parsing fails for Unicode 1Fxxx symbols when + skipping + [1.8.7] + +Lloyd Smith: + * Reported [JACKSON-701] ArrayIndexOutOfBoundsException when trying to serialize + non-static inner classes with annotations on last ctor param + [1.8.8] + +Erik Gorset: + * Reported [JACKSON-763] State of base64/byte[] decoding not reset when + using 'convertValue()' for list of byte[] values. + [1.8.9] + +Matt Schemmel: + * Reported [JACKSON-820] WriterBasedGenerator with CharacterEscapes produces + unescaped output for strings > 2k in length + [1.8.9] + +"Programmer Bruce": + * Suggested these for 1.8.x: + - [JACKSON-597] Make ClassDeserializer support primitive types [1.8.3] + * Suggested these for 1.9.0: + - [JACKSON-593] Add ObjectMapper.readTree(byte[]), (URL) variants + - [JACKSON-594] Allow deserializing non-static inner class valued properties + - [JACKSON-595] Terse Visibility Config (ObjectMapper.setVisibility, related) + - [JACKSON-598] Add set of standard naming-strategy implementations + - [JACKSON-599] Expose Settability Of SimpleModule Serializers/Deserializers + - [JACKSON-605] Handle deserialization of typed Class properties correctly + - [JACKSON-612] Add 'readValues()' methods to JsonParser, ObjectCodec + - [JACKSON-613] Add ArrayNode/ObjectNode methods for dealing with wrappers/unboxing/nulls + - [JACKSON-616] Better handling of primitive deserializers, to avoid NPEs + - [JACKSON-621] Add new fluent method, VisibilityChecker.with(Visibility) + +Anand Hatrwalne: + * Requested [JACKSON-558] Add 'DeserializationConfig.Feature.UNWRAP_ROOT_VALUE' as + matching counterpart for 'SerializationConfig.Feature.WRAP_ROOT_VALUE' + [1.9.0] + +Earl Baugh: + * Suggested [JACKSON-584] Serialize type info for non-static anonymous inner classes + as that of declared (static) type + [1.9.0] + +Matt Goldspink: + * Suggested [JACKSON-578] Allow use of @JsonView on JAX-RS resource, with JacksonJsonProvider + [1.9.0] + +Ed Anuff: + * Suggested [JACKSON-602] Add 'JsonSerialize.Inclusion.NON_EMPTY' option + [1.9.0] + + +Lukasz Strzelecki: + * Requested [JACKSON-630] Add @JsonRootName annotation for specifying name of root-level wrapper + [1.9.0] + +Simone Bordet: + * Requested [JACKSON-652] Add 'DeserializationConfig.Feature.USE_JAVA_ARRAY_FOR_JSON_ARRAY' to + allow mapping JSON Array to Object[] + [1.9.0] + +David Phillips: + * Requested [JACKSON-671] Add convenience constructor for 'MinimalPrettyPrinter' + [1.9.0] + +Kirill Sukhanov: + * Suggested [JACKSON-650] Allow dealing with missing filter ids, by adding + 'SimpleFilterProvider.setFailOnUnknownId()' to specify if exception is thrown or not. + [1.9.0] + +Ben Hale: + * Reported [JACKSON-700] Type problems with properties that have different + types for constructor property, setter and/or field + [1.9.1] + +Andreas Knoepfle, Tobias Schmid: + * Contributed implementation for [JACKSON-657], key deserializers for + java.util.Date and java.util.Calendar types + [1.9.3] + +Steve Loeppky: + * Reported [JACKSON-746] Problems with JsonTypeInfo.Id.NONE, default typing + [1.9.4] + +Sebastian Thelen: + * Reported [JACKSON-753] JsonParserDelegate missing delegation of getBooleanValue(), + getEmbeddedObject() + [1.9.4] + +Stephan Bailliez: + * Reported [JACKSON-757] Problems with Enum values, annotations on constructors + [1.9.4] + +Mika Mannermaa: + * Reported [JACKSON-756] Problems with enums, @JsonCreator, when used as keys + of EnumMap, regular Map, or contents of EnumSet + [1.9.4] + +Nathaniel Bauernfeind: + * Reported [JACKSON-774]: PropertyBasedCreator not using JsonDeserializer.getNullValue() + [1.9.5] + +Ittai Zeidman: + * Reported [JACKSON-775]: MissingNode.asText() should return "", not null + [1.9.5] + +Alexander Klauer: + * Reported [JACKSON-779]: Problems with multi-byte UTF-8 chars in JSON comments + [1.9.5] + +Vladimir Petrukhin: + * Reported [JACKSON-778], provided test case: Incorrect detection of generic + types with TypeReference + [1.9.5] + +Christopher Brown: + * Reported [JACKSON-796]: Problems with byte[] conversion to/from JsonNode. + [1.9.5] + +Harold Marger: + * Reported [JACKSON-806]: REQUIRE_SETTERS_FOR_GETTERS ignores explicitly annotated getters + [1.9.6] + +Adam Vandenberg: + * Reported [JACKSON-823] MissingNode does not return default value for + 'asXxx()' methods + [1.9.7] + +James Roper: + * Reported [JACKSON-829] Custom serializers not working for List<String> + properties, @JsonSerialize(contentUsing) + [1.9.7] + +Laurent Pireyn: + * Reported [JACKSON-831] External type id, explicit property do not work well together + [1.9.7] + +Jan Jan: + * Reported [JACKSON-832] (partial) Fix numeric range check for Longs (was not working) + [1.9.7] + +Klaus Reimer: + * [JACKSON-834] Could not use @JsonFactory with non-String argument with Enums + [1.9.7] + +Stuart Dootson: + * Reported [Issue-13] Runtime error passing multiple injected values to a constructor + [1.9.7] + +Lóránt Pintér: + * Reported [JACKSON-838]: Utf8StreamParser._reportInvalidToken() skips + letters from reported token name + [1.9.8] + +Scott Stanton: + * Reported [JACKSON-841] Data is doubled in SegmentedStringWriter output + [1.9.8] + +Sébastien R: + * Reported [JACKSON-842] ArrayIndexOutOfBoundsException when skipping C-style comments + [1.9.8] + +Duncan Bloem: + * Reported [JACKSON-867] missing Export-Package header for + "org.codehaus.jackson.map.ext" + [1.9.10]
diff --git a/1.9.10/release-notes/VERSION b/1.9.10/release-notes/VERSION new file mode 100644 index 0000000..00931ff --- /dev/null +++ b/1.9.10/release-notes/VERSION
@@ -0,0 +1,1782 @@ +Version: 1.9.10 + +Release date: + 23-Sep-2012 + +Description: + Another patch release for 1.9. + +Fixes: + * [JACKSON-855]: add StackOverflowError as root cause + * [JACKSON-867]: missing Export-Package header for "org.codehaus.jackson.map.ext" + (reported by Duncan B) + * [Issue#57]: Allow serialization of JDK proxy types + * [Issue#71]: java.util.concurrent.ConcurrentNavigableMap support was failing + +------------------------------------------------------------------------ +=== History: === +------------------------------------------------------------------------ + +1.9.9 (28-Jul-2012) + +Fixes: + * [Issue-21]: Improve handling of String hash code collisions for + symbol tables; exception for degenerate cases (attacks), improvements + for calculation otherwise + * [Issue-24]: ArrayIndexOutOfBoundsException with TextBuffer.append() + * [JACKSON-853]: JsonStringEncoder.quoteAsString() problem with buffer boundary + +Other: + * Improved multi-threader handling of byte-based symbol table; should + reduce lock contention for heavily multi-threaded cases, esp. when + parsing short documents. + + +1.9.8 (28-Jun-2012) + +Fixes: + + * [Issue-6]: element count for PrettyPrinter, endObject wrong + (reported by "thebluemountain") + * [JACKSON-838]: Utf8StreamParser._reportInvalidToken() skips letters + from reported token name + (reported by Lóránt Pintér) + * [JACKSON-841] Data is doubled in SegmentedStringWriter output + (reported by Scott S) + * [JACKSON-842] ArrayIndexOutOfBoundsException when skipping C-style comments + (reported by Sebastien R) + * [JACKSON-845] Problem with Object[][] deserialization, default typing + (reported by Pawel J) + +1.9.7 (02-May-2012) + + Fixes: + + * [Smile/Issue-2] SmileParser failed to decode surrogate-pair characters for + long Strings + (reported by Steven S) + * [Issue-11] JsonParser.getValueAsLong() returning int, not long + (reported by Daniel L) + * [Issue-13] Runtime error passing multiple injected values to a constructor + (reported by Stuart D) + * [Issue-14]: Annotations were not included from parent classes of + mix-in classes + (reported by @guillaup) + * [JACKSON-823] MissingNode does not return default value for 'asXxx()' + methods + (reported by Adam V) + * [JACKSON-829] Custom serializers not working for List<String> properties, + @JsonSerialize(contentUsing) + (reported by James R) + * [JACKSON-831] External type id, explicit property do not work well together + (reported by Laurent P) + * [JACKSON-832] (partial) Fix numeric range check for Longs (was not working) + (reported by Jan J) + * [JACKSON-834] Could not use @JsonFactory with non-String argument with Enums + (reported by Klaus R) + +1.9.6 [26-Mar-2012] + + Fixes: + + * [JACKSON-763] State of base64/byte[] decoding not reset when + using 'convertValue()' for list of byte[] values. + (reported by Erik G) + * [JACKSON-794]: JDK 7 has new property for Exceptions ("suppressable"), + needs to be ignored during deserialization + * [JACKSON-799]: JsonSerialize.as not working as class annotation, for root values + * [JACKSON-802]: Improvements to class loading to use both contextual + class loader and Class.forName, as necessary + * [JACKSON-803]: Problems with Smile, parsing of long names + (reported by D Lam) + * [JACKSON-804]: Allow byte range up to 255, for interoperability with unsigned bytes + * [JACKSON-806]: REQUIRE_SETTERS_FOR_GETTERS ignores explicitly annotated getters + (reported by Harold M) + * [JACKSON-812]: BigIntegerNode.equals(...) using '==' for equality + * [JACKSON-820]: WriterBasedGenerator with CharacterEscapes produces unescaped output + for strings > 2k in length + (reported by Matt S) + +1.9.5 [24-Feb-2012] + + Fixes: + + * [JACKSON-757]: further fixing (1.9.4 had partial fix) + * [JACKSON-773]: Bug in SimpleFilterProvider constructor + (reported by Kenny M) + * [JACKSON-774]: PropertyBasedCreator was not using JsonDeserializer.getNullValue() + (reported by Nathaniel B) + * [JACKSON-775]: MissingNode.asText() should return "", not null + (reported by Ittai Z) + * [JACKSON-778]: Incorrect detection of generic types with TypeReference + (reported by Vladimir P) + * [JACKSON-779]: Problems with multi-byte UTF-8 chars in JSON comments + (reported by Alexander K) + * [JACKSON-789]: Add support for 'java.nio.charset.Charset' + * [JACKSON-796]: Problems with byte[] conversion to/from JsonNode. + (reported by Christopher B) + +1.9.4 [20-Jan-2012] + + Fixes: + + * [JACKSON-712] Issue with @JsonCreator + DefaultImpl + (suggested by Eric T) + * [JACKSON-744] @JsonAnySetter problems with 1.9 + * [JACKSON-746] Problems with JsonTypeInfo.Id.NONE, default typing + (reported by Steve L) + (reported by Sebastian T) + * [JACKSON-756] Problems with enums, @JsonCreator, when used as keys + of EnumMap, regular Map, or contents of EnumSet + (reported by Mika M) + * [JACKSON-757] Problems with Enum values, annotations on constructors + -- but note, some issues remained for 1.9.5 to tackle + (reported by Stephan B) + + (all fixes up to 1.8.8) + +1.9.3 [16-Dec-2011] + + Improvements: + + * [JACKSON-657] Add Date/Calendar key deserializers + (contributed by Andreas K, Tobias S) + * [JACKSON-717] ObjectReader.updateValues(): use configured 'valueToUpdate' + * [JACKSON-726] Add java.util.UUID key deserializer + (suggested by Steven S) + * [JACKSON-729] Add 'ObjectMapper.readValues(byte[])' convenience method + + Fixes: + + (all fixes up to 1.8.7) + +1.9.2 [04-Nov-2011] + + Improvements: + + * [JACKSON-706] Joda support: add support for "org.joda.time.Period" + (suggested by Dain S) + + Fixes: + + * [JACKSON-700] Type problems with properties that have different types + for constructor property, setter and/or field + (reported by Ben H) + * [JACKSON-703] 'SerializationConfig.isEnabled(...)', + 'DeserializationConfig.isEnabled(...)' incompatible due to signature change + +1.9.1 [23-Oct-2011] + + Fixes: + + * [JACKSON-687] Problems with PropertyNamingStrategy, property merging + (reported by Pascal G) + * [JACKSON-689] Deserialization of Iterable fails + (reported by Pascal G) + * [JACKSON-693] @JsonBackReference not used during deserialization if it's annotated + on a getter method. + (reported by Pascal G) + +1.9.0 [04-Oct-2011] + + Fixes: + + * [JACKSON-539] Incorrect handling of combination of JAXB annotations + (@XmlTransient with property renaming) + (reported Ryan H) + * [JACKSON-605] Handle deserialization of typed Class properties correctly + (reported by Bruce P) + + Improvements: + + * [JACKSON-242] Rewrite property introspection part of framework to combine + getter/setter/field annotations + * [JACKSON-505] Handle missing type information gracefully by checking for + abstract type mapping to find default implementation, if no valid type + information found for @JsonTypeInfo + * [JACKSON-531] Comparing actual and default value (for JsonSerialize.Inclusion.NON_DEFAULT) + should check array contents + (suggested by Christoph S) + * [JACKSON-584] Serialize type info for non-static anonymous inner classes + as that of declared (static) type + (suggested by Earl B) + * [JACKSON-593] Add ObjectMapper.readTree(byte[]), (URL) variants + (suggested by Bruce P) + * [JACKSON-594] Allow deserializing non-static inner class valued properties + (suggested by Bruce P) + * [JACKSON-595] Terse Visibility Config (ObjectMapper.setVisibility, related) + (suggested by Bruce P) + * [JACKSON-598] Add set of standard naming-strategy implementations + (suggested by Bruce P) + * [JACKSON-599] Expose Settability Of SimpleModule Serializers/Deserializers + (suggested by Bruce P) + * [JACKSON-606] Add Built-in Support for Date Map Keys as Timestamps + (SerializationConfig.Feature#WRITE_DATE_KEYS_AS_TIMESTAMPS) + * [JACKSON-612] Expose 'readValues()' methods via ObjectCodec, JsonParser + (suggested by Bruce P) + * [JACKSON-613] Add ArrayNode/ObjectNode methods for dealing with wrapper + values, unboxing, nulls + (suggested by Bruce P) + * [JACKSON-615] Make JavaType serializable/deserializable + * [JACKSON-616] Better handling of primitive deserializers, to avoid NPEs + (suggested by Bruce P) + * [JACKSON-619] SmileParser.getCurrentLocation(), getTokenLocation() did not + report actual byte offsets. + (reported by Ray R) + * [JACKSON-620] Allow empty String to mean null Map, Collection, array, + if 'DeserializationConfig.Feature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT' enabled + * [JACKSON-621] Add new fluent method, VisibilityChecker.with(Visibility) + (suggested by Bruce P) + * [JACKSON-638] TypeFactory methods for constructing "raw" map or collection types + (suggested by Christopher C) + * [JACKSON-639] Change BasicClassIntrospector.forClassAnnotations to take + JavaType (not raw Class) + (requested by Chris C) + * [JACKSON-643] ObjectMapper.readValue() should check JsonDeserializer.getNullValue() + when encountering root-level JsonToken.VALUE_NULL + * [JACKSON-644] Add SimpleModule.setMixInAnnotations() + * [JACKSON-648] ObjectWriter: allow changing default serialization DateFormat + (ObjectMapper.writer(DateFormat), ObjectWriter.withDateFormat(DateFormat)) + * [JACKSON-650] Allow dealing with missing filter ids, by adding + 'SimpleFilterProvider.setFailOnUnknownId()' to specify if exception is thrown or not. + (suggested by Kirill S) + * [JACKSON-661] Add shorter 'JsonNode.asXxx' methods to replace 'JsonNode.getValueAsXxx' + * [JACKSON-662] Add 'ObjectMapper.enable()' and 'ObjectMapper.disable()' to allow + enabling/disabling multiple features with a single call. + * [JACKSON-665] Add 'AnnotatedWithParams.getIndex()' for accessing index of a + method or constructor parameter + (requested by Chistropher C) + * [JACKSON-671] Add convenience constructor for 'MinimalPrettyPrinter' + (requested by David P) + * [JACKSON-683] Mr Bean: Fail gracefully if attempt is made to materialize + non-public type (since impl class on different package than base class) + * [JACKSON-684] Add SerializationConfig.Feature.WRITE_ENUMS_USING_INDEX to serialize + Enums as int (index) + + New features: + + * [JACKSON-132] Support "unwrapped" properties, using @JsonUnwrapped. + * [JACKSON-254] Add 'SerializationConfig.Feature.WRITE_EMPTY_JSON_ARRAYS', + which can be used to suppress serialization of empty JSON arrays (unless + overridden by per-property annotations). + (suggested by Fabrice D) + * [JACKSON-406] Allow injecting of values (with @JacksonInject) during deserialization + * [JACKSON-453] Support "external type id" with new @JsonTypeInfo.As enum value, + EXTERNAL_PROPERTY + * [JACKSON-558] Add 'DeserializationConfig.Feature.UNWRAP_ROOT_VALUE' as + matching counterpart for 'SerializationConfig.Feature.WRAP_ROOT_VALUE' + (requested by Anand H) + * [JACKSON-578] Allow use of @JsonView on JAX-RS resource, with JacksonJsonProvider + (suggested by Matt G) + * [JACKSON-580] Allow registering instantiators (ValueInstantiator) for types (classes) + * [JACKSON-581] Add 'ObjectMapper.readTree(File)' + (suggested by Pascal G) + * [JACKSON-602] Add 'JsonSerialize.Inclusion.NON_EMPTY' option + (suggested by Ed A) + * [JACKSON-614] Add JsonTypeInfo.defaultImpl property to indicate type to use if type name missing + * [JACKSON-630] Add @JsonRootName annotation for specifying name of root-level wrapper + (requested by Lukasz Strzelecki) + * [JACKSON-633] Add @JsonValueInstantiator to allow annotating which ValueInstantiator + a type uses. + * [JACKSON-652] Add 'DeserializationConfig.Feature.USE_JAVA_ARRAY_FOR_JSON_ARRAY' to + allow mapping JSON Array to Object[] + (suggested by Simone B) + * [JACKSON-653] Add 'JsonParser.isNextTokenName()' for more efficient field name matching + * [JACKSON-666] Add 'Add SerializationConfig.Feature.REQUIRE_SETTERS_FOR_GETTERS' to allow + suppressing use of getters for which there is no matching mutator. + + Issues handled by new external projects: + + * [JACKSON-51]: Implement Just-In-Time code generation for serialization + created "jackson-module-afterburner" at [https://github.com/FasterXML/jackson-module-afterburner] + + Potential backwards compatibility issues (compared to 1.8.x): + + * Removed 'org.codehaus.jackson.annotate.JsonClass, JsonKeyClass and + JsonContentClass (deprecated since 1.1) + * Move TokenBufferDeserializer to separate class (from inside StdDeserializer) + +1.8.8 [20-Jan-2012] + + Fixes: + + * [JACKSON-701] ArrayIndexOutOfBoundsException when trying to serialize + non-static inner classes with annotations on last ctor param + (reported Lloyd S) + * [JACKSON-741] Add missing linkage from ObjectMapper to JsonFactory + by calling 'JsonFactory.setCodec()' from ObjectMapper constructor + * [JACKSON-753] JsonParserDelegate missing delegation of getBooleanValue(), + getEmbeddedObject() + (reported by Sebastian T) + * Partial fix for [JACSON-756]: EnumMap, EnumSet work with enums that use + @JsonCreator; regular Maps only with 1.9 + (reported by Mika M) + +1.8.7 [16-Dec-2011] + + Fixes: + + * [JACKSON-462] (REGRESSION?) Buffer overflow in Utf8Generator#writeFieldName(String) + (reported by Ryan K) + * [JACKSON-696] Problems accessing "any getter" that is not public + (reported by Brian M) + * [JACKSON-709] Problems converting base64-encoded Strings between + JsonNode, POJOs + (reported by Tom B) + * [JACKSON-733] Smile-based mapper could not properly bind byte[] values + (reported by Jacques-Olivier G) + * [JACKSON-738] Parsing fails for Unicode 1Fxxx symbols when skipping + (reported by Alex T) + +1.8.6 [04-Oct-2011] + + Fixes: + + * [JACKSON-288] Problems (de)serializing values with JAXB adapters + * [JACKSON-668] Problems with 'JsonParser.getDecimalValue' not + clearing earlier state + (reported by Ransom B) + * [JACKSON-677] Inner generic type references not working properly + (reported by William B) + +1.8.5 [04-Aug-2011] + + Fixes: + + * [JACKSON-401] Further fixes to ensure FLUSH_PASSED_TO_STREAM works + * [JACKSON-637] NumberSerializer was missing proper handling of Integer, Long + (reported by Paul M) + * [JACKSON-640] SmileParser.getTextCharacters() missing value in some + cases (value back-references) + * [JACKSON-647] ResolvableSerializer.resolve() not called after creating + contextual instance + +1.8.4 [25-Jul-2011] + + Fixes: + + * [JACKSON-605] Handle deserialization of Class<T> properties + * [JACKSON-627] WriterBasedGenerator failure for long Strings, + custom character escaping + (reported by Lawrence C) + * [JACKSON-629] Fix a buffer boundary problem with SmileParser, 5-7 + character names + (reported by Maxxan) + * [JACKSON-631] Problems decoding Base64Variants.MODIFIED_FOR_URL + (reported by Tim B) + * [JACKSON-632] Handling of UTF-8 BOM incorrect, causing "Internal Error" + (reported by Edward A) + +1.8.3 [08-Jul-2011] + + Fixes: + + * [JACKSON-587] TextNode.getValueAsLong() does not work properly + (reported by Chris P) + * [JACKSON-591] JodaDeserializers not throwing wrongTokenException + (reported by Tom L) + * [JACKSON-597] Make ClassDeserializer support primitive types + (suggested by Bruce P) + (plus all 1.7 fixes up to 1.7.8) + +1.8.2 [15-Jun-2011] + + Fixes: + + * Problem with FilteredBeanPropertyWriter: was not delegating call + to wrapped BeanPropertyWriter, causing problems with modules + +1.8.1 [17-May-2011] + + Fixes: + + * [JACKSON-557] CollectionLikeType#equals() casts parameter to CollectionType + (reported by Coda H) + * [JACKSON-560] Mix-in annotations ignored when used with views + (reported by Ruben E-G) + * [JACKSON-568] Package 'org.codehaus.jackson.util' missing from + core/lgpl jar + (reported by Christoph S) + * [JACKSON-570] Caching of MapSerializer not thread-safe + (reported by Jamie R) + * [JACKSON-573] Failure to serialize certain Unicode Strings + (reported by Young J-P) + (plus all 1.7 fixes up to 1.7.7) + +1.8.0 [20-Apr-2011] + + Another minor release. Main improvements are: + + - Proper configurability for key serializers, deserializers + - Ability to control details of low-level character escaping + - Pluggable format auto-detection (for JSON and Smile in core packages) + - Fully configurable type-defaulting (abstract-to-concrete) for deserialization + - Pass-through FormatSchema abstraction to help support schema-based formats + + New features: + + * [JACKSON-43]: Add "ObjectMapper.readValues()", "ObjectReader.readValues()" for + more convenient binding of arrays (and root-level sequences) of homogenous types + * [JACKSON-102]: Ability to force escaping of non-ASCII characters; using + JsonGenerator.Feature.ESCAPE_NON_ASCII and JsonGenerator.setHighestNonEscapedChar + * [JACKSON-106]: Add 'org.codehaus.jackson.io.CharacterEscapes' which can be + registered with JsonFactory, JsonGenerator, to add fully customized + character escaping handling + (suggested by Scott A) + * [JACKSON-142]: Add 'JsonParser.Feature.ALLOW_NON_NUMERIC_NUMBERS' to allow + non-standard use of 'NaN', '+INF'/'+Infinite', '-INF'/'-Infinite' as numbers + * [JACKSON-178]: Add support for custom property name strategies (with + PropertyNamingStrategy) + * [JACKSON-204]: Add DeserializationConfig.Feature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT + to allow binding empty JSON String as null for POJOs + * [JACKSON-358]: Add JsonParser.Feature.ALLOW_NUMERIC_LEADING_ZEROS, to allow + optional (and non-standard) support for numbers like 00006 + (suggested by Bryce M) + * [JACKSON-427]: Added "JsonNode.with()" which is similar to "JsonNode.path()" but + creates ObjectNode for property if no value exists (similar to "upsert" (update-or-insert)) + * [JACKSON-464]: Allow defining default mappings for abstract types, with + SimpleAbstractTypeResolver + * [JACKSON-494]: Add support for format auto-detection (via JsonFactory); add + support for basic JSON, Smile (and as many modules as possible) + * [JACKSON-512]: Allow wrapping InputStream/Reader, OutputStream/Writer when + constructing JsonParser, JsonGenerator; JsonFactory allows registering + InputDecorator, OutputDecorator instances. + * [JACKSON-513]: Add methods for registering key serializers, deserializers, + via Module API + * [JACKSON-520]: Add minimal FormatSchema abstraction, passed through by ObjectMapper + to JsonGenerator, JsonParser; needed for supporting schema-based formats. + * [JACKSON-521]: Add support for new 'MapLikeType' and 'CollectionLikeType', to + support Map/Collection types of languages like Scala + * [JACKSON-523]: Allow passing actual type for TypeSerializer to use, to + force specific super type to be used (instead of a concrete sub type) + * [JACKSON-526]: Add DeserializationConfig.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY + which allows implicit conversion from JSON scalars and Objects into single-element + collections/arrays (for interoperability with XML-to-JSON converers like Jettison) + * [JACKSON-527]: Add 'HandlerInstantiator' abstraction, which can be implemented and + registered with ObjectMapper to get more control over how handlers (serializers, + deserializers, type id resolver) are constructed. + (requested by Sven J) + * [JACKSON-555]: Add 'JsonParser.getInputSource()' and 'JsonGenerator.getOutputTarget()' + to give direct access to low-level stream/reader/writer instances + + Improvements: + + * [JACKSON-480]: Added missing @JsonSerialize properties: keyAs, keyUsing, + contentAs, contentUsing + * [JACKSON-502]: Convert mr Bean functionality to be basic Module + * [JACKSON-503]: Allow registering AbstractTypeResolvers via Module API + * [JACKSON-519]: Add support for contextual key serializers, deserializers + * [JACKSON-548]: enabling ALLOW_SINGLE_QUOTES should allow backslash-escaping + of apostrophes + (suggested by Tim W) + * [JACKSON-551]: Add new methods to 'Serializers' and 'Deserializers' interfaces to + support CollectionLikeType, MapLikeType. + + Fixes: + + * [JACKSON-459]: Add mapper-level configuration to set default serialization + order be alphabetic (by property name). + (suggested by Chris W) + * [JACKSON-487]: Block all annotation access if SerializationConfig.Feature.USE_ANNOTATIONS + (and ditto for DeserializationConfig) is disabled; to help with Android, missing JAXB annotations + * [JACKSON-498]: Fix issues with type names, abstract types, collections + (reported by John V) + * [JACKSON-509] @JsonSubTypes was not allowed for fields/methods/ctor-parameters (although + @JsonTypeInfo was, starting with 1.7) + * [JACKSON-510] Registered subtypes not used for @JsonTypeInfo used with properties + + Potential backwards compatibility issues (compared to 1.7.x): + + * [JACKSON-523]: Added method "idFromValueAndType()" in TypeIdResolver interface, + which is needed to properly handle types such as InetAddress, TimeZone -- unfortunately + this would break custom TypeIdResolver instances. + * [JACKSON-551]: Addition of new methods to 'Serializers' and 'Deserializers' interfaces + means that existing code (1.7 only) that directly implements interfaces will not compile + (i.e. source and binary incompatible change) + + Issues handled by new external projects: + + * [JACKSON-532]: Add support for org.json.JSONObject, org.json.JSONArray; + created "jackson-module-json-org" at [https://github.com/FasterXML/jackson-module-json-org] + +1.7.8 [08-Jul-2011] + + Fixes: + + * [JACKSON-586] Problems with @JsonValue, method access (failed on + non-public methods, or public method of non-public class) + (reported by Pierre-Alexander M) + * [JACKSON-587] TextNode.getValueAsLong() does not work properly + (reported by Chris P) + * [JACKSON-591] JodaDeserializers not throwing wrongTokenException + (reported by Tom L) + * [JACKSON-597] Make ClassDeserializer support primitive types + (suggested by Bruce P) + +1.7.7 [17-May-2011] + + Fixes: + + * [JACKSON-542] Base64 decoder couldn't handle escaped characters + (reported by Luis N) + * [JACKSON-543] Root-level static type information incorrectly handled + with Maps (losing parameterization) + (reported by Steven S) + * [JACKSON-553] SerializationConfig.Feature.DEFAULT_VIEW_INCLUSION + did not work correctly + (reported by Xun W) + * [JACKSON-554] ObjectMapper.readValue(JsonNode) was not properly passing + itself as ObjectCodec, making secondary conversions fail + (reported by Pascal G) + * [JACKSON-556] @XmlElement.name property ignored in some cases + (reported by Alex P) + * [JACKSON-562] Smile property name decoding issue + (reported by Jeffrey Damick, Shay Banon) + * [JACKSON-563] JSON Schema uses "required" (not "optional") + (reported by Oleg E) + * [JACKSON-569] ContextualSerializer not resolved for serializers + defined with @JsonSerialize annotation + (reported by Gregor O) + * [JACKSON-572] Problems serializing generic non-static inner classes + (reported by Steven S) + +1.7.6 [12-Apr-2011] + + Fixes: + + * [JACKSON-547] Problems relaying exceptions from creator methods + (reported by Gili) + * [JACKSON-550] Registration of serializers was not completely working + with SimpleModule (interfaces implemented by superclasses skipped) + (reported by Andrei P) + * [JACKSON-552] SmileParser not handling long field names properly, + failed with "this code path should never get executed" exception + (reported by Shay B) + +1.7.5 [01-Apr-2011] + + Fixes: + + * [JACKSON-530] Default SerializationInclusion value not properly + passed when "USE_ANNOTATION" set to false + (Suchema O) + * [JACKSON-533] Failed to serialize LinkedHashMap.value() + (reported by Linghu C) + * [JACKSON-540] Side-effects with ObjectMapper.canSerialize(), + canDeserialize() + (reported by Maik J) + * [JACKSON-541] Remove the need for @JsonCreator on multi-arg constructor + iff all parameters have @JsonProperty + (suggested by Pascal Glinas) + * [JACKSON-545] UTF8Writer.flush() should check against NPE + (reported by Michel G) + +1.7.4 [04-Mar-2011] + + Fixes: + + * [JACKSON-484]: improve serialization of InetAddress + (reported by Brian H) + * [JACKSON-506]: problems with type handling for java.util.Date + when using @JsonTypeInfo on field/method + (reported by Kirill S) + * [JACKSON-504]: FilterProvider registration directly via SerializationConfig + was not working + (reported by Kirill S) + * [JACKSON-508]: Type information lost when serializing List<List<X>> + (reported by Christopher B) + * [JACKSON-518]: Problems with JAX-RS, type variables + (reported by Kirill S) + * [JACKSON-522]: java.util.TimeZone was not correctly handled + * [JACKSON-525]: Problem with SmileGenerator, shared-names buffer recycling + (reported by Shay B) + +1.7.3 [14-Feb-2011] + + Fixes: + + * [JACKSON-483]: allow deserializing CharSequence (also: support + conversion from byte[] to char[], assuming base64 encoding) + * [JACKSON-492]: problem encoding 1 byte length "raw" UTF8 Strings + (reported by David Y) + + (plus all fixes up to and including 1.6.6) + +1.7.2 [02-Feb-2011] + + Fixes: + + * [JACKSON-476] ContextualDeserializer handling not completely working + (reported by Sean P) + * [JACKSON-481] OSGi headers must include 1.5 AND 1.6 + (reported by drozzy@gmail.com) + + (plus all fixes up to and including 1.6.5) + + Improvements: + + * [JACKSON-474] Add ability to pass externally allocated buffer + for Utf8Generator, SmileGenerator + (suggested by David Y) + +1.7.1 [12-Jan-2010] + + Fixes: + + * [JACKSON-456]: Type check issues with Jackson JAX-RS provider + (reported by Kirill S) + * [JACKSON-457]: Typo in Module method "getSeserializationConfig" ("bananana error"); renamed + as "getSerializationConfig" (version with old spelling retained as deprecated for compatibility) + (reported by Chris W) + * [JACKSON-458]: Problems with ObjectMapper.convertValue(), TokenBuffer, SerializedString + (reported by Larry Y) + * [JACKSON-462]: Buffer overflow in Utf8Generator#writeFieldName(String) + (reported by Coda H) + +1.7.0 [06-Jan-2010] + + Fixes: + + * [JACKSON-356]: Type information not written for nested-generics root types + (reported by Alex R on mailing list) + * [JACKSON-450] JAXB annotations chosen incorrectly from interface method + (instead of method definition in class), when serializing + (reported by Sean P) + + Improvements: + + * [JACKSON-280]: Allow use of @JsonTypeInfo for properties (fields, methods) + * [JACKSON-345]: Make BeanSerializer use SerializedString for even faster serialization + * [JACKSON-393]: Allow deserializing UUIDs from VALUE_EMBEDDED_OBJECT + * [JACKSON-399]: JAX-RS is not passing generic type information as root type + (reported by Kirill S) + * [JACKSON-409] Add SmileGenerator.writeRaw(byte) + * [JACKSON-414] Add 'JsonNode.getValueAsBoolean()' (and 'JsonParser.getValueAsBoolean()') + (suggested by Tauren M) + * [JACKSON-419]: Add explicit support for handling 'java.util.Locale' + (suggested by Brian R) + * [JACKSON-432]: Add 'ObjectMapper.enableDefaultTypingAsProperty()' to allow + specifying inclusion type 'As.PROPERTY' and property name to use + (suggested by Peter L) + * [JACKSON-434]: Add 'JsonGenerator.writeString(SerializableString)' + * [JACKSON-438]: Wrap exceptions thrown by Creator methods as JsonMappingException + (suggested by Tim W) + + New features: + + * [JACKSON-163] Add 'SerializationConfig.Feature.WRAP_ROOT_VALUE' which + allows wrapping of output within single-property JSON Object. + * [JACKSON-297] Add simple Module abstraction to allow pluggable support + tor third-party libraries, data types + * [JACKSON-312] Add ability to dynamically filter out serialized properties + * [JACKSON-351]: Add @JsonRawValue for injecting literal textual + value into JSON + (contributed by Ga�l Marziou) + * [JACKSON-369]: Allow registering custom Collection and Map deserializers + (implemented via 'org.codehaus.jackson.map.Deserializers') + * [JACKSON-385]: Support contextual serializers, deserializers; works by + implementing 'org.codehaus.jackson.map.ser.ContextualSerializer' or + 'org.codehaus.jackson.map.deser.ContextualDeserializer' + * [JACKSON-401] Add features 'SerializationConfig.FLUSH_AFTER_WRITE_VALUE' + and 'JsonGenerator.FLUSH_PASSED_TO_STREAM' to allow blocking of flush() + calls to underlying output stream or writer + * [JACKSON-405]: Add command-line tool for manual Smile encoding/decoding + * [JACKSON-407]: Add features (SerializationConfig.Feature.WRAP_EXCEPTIONS, + DeserializationConfig.Feature.WRAP_EXCEPTIONS) to disable exception wrapping + * [JACKSON-412] Add 'DeserializationConfig.Feature.FAIL_ON_NUMBERS_FOR_ENUMS' + to optionally prevent mapping JSON integers into Java Enum values + (suggested by Patrick L) + * [JACKSON-420] Add 'DeserializationConfig.Feature.FAIL_ON_NULL_FOR_PRIMITIVES' + to optionally prevent JSON null from mapping to default value + (suggested by Thomas D) + * [JACKSON-421] Add ability to register multiple sets of serializers + without extending SerializerFactory (related to [JACKSON-297]) + * [JACKSON-429] Add @JsonIgnoreType to allow ignoring any and all properties + of specified type; useful to exclude well-known proxy/facade/handler types + * [JACKSON-440] Add ability to process serializers, deserializers during their + construction (to allow adding, removing, modifying properties to handle) + * [JACKSON-448] Add 'JsonGenerator.writeString()' alternatives that accept + pre-encoded UTF-8 byte sequences (writeUTF8String() and writeRawUTF8String()) + (requested by Shay B) + + Issues handled by new external projects: + + * [JACKSON-317] Add support for Guava (ex-Google-collections); implemented + as a new module, see: https://github.com/FasterXML/jackson-module-guava + * [JACKSON-394] Add support for using data binding to/from XML (Stax) sources; + sort of "mini-JAXB". + + Potential backwards compatibility issues (compared to 1.6.x): + + * [JACKSON-419] (see above) 'java.util.Locale' now serialized as JSON String + (using Locale.toString()), instead of as bean-like JSON Object + * Added 'BeanProperty' argument for many methods in SerializerFactory / + DeserializerFactory, SerializerProvider / DeserializerProvider implementations. + * Related to [JACKSON-407], will wrap some previously unwrapped exceptions from + deserializer (to have symmetric handling; serializer already wrapped); new + features to allow disabling wrapping on serialization and/or deserialization. + +1.6.5 [01-Feb-2011] + + Fixes: + + * [JACKSON-454] JSON Schema generator was adding bogus "items" property + for JSON object types (only allowed for arrays) + * [JACKSON-461] ArrayIndexOutOfBoundsException when property is subclass of + Map with fewer type parameters + (reported by Tim W) + * [JACKSON-465] Deserialization with @JsonCreator that takes in a Map fails + (reported by Tim W) + * [JACKSON-468] Method-bound type variables (public <T> T getValue()) not handled + (reported by Christian N) + * [JACKSON-470] ArrayIndexOutOfBoundsException if @JsonCreator constructor + has @JsonParameter parameters with same name + (reported by Tim W) + * [JACKSON-472] Custom bean deserializers are not cached when using + JAXB annotation introspector + (reported by Seam P) + * [JACKSON-473] JsonMapping$Reference not Serializable + (reported by Steven S) + * [JACKSON-478] Improve support for 'java.sql.Timestamp' type by allowing + deserializing textual representations + (reported by John L) + +1.6.4 [21-Dec-2010] + + Fixes: + + * [JACKSON-364] @JsonTypeInfo not included properly for Collection types + when using JsonView functionality + * [JACKSON-428] Type information, Map key deserializer definitions don't + work together + (reported by Patrick R) + * [JACKSON-431] Deserialization fails with JSON array with beans with + @JsonCreator, unmapped properties before and after creator properties + (reported by Hannu L) + * [JACKSON-436] @XmlElementType not working correctly with Collection type + properties + (reported by Sean P) + +1.6.3 [04-Dec-2010] + + Fixes: + + * [JACKSON-228], [JACKSON-411] XmlJavaTypeAdapter, package-level annotations not + working + (reported by Claudio R, Raymond F) + * [JACKSON-387]: Deserialization fails for certain objects serialized with + enableDefaultTyping + (reported by Peter L) + * [JACKSON-415] XMLElement annotation ignored during schema generation + (reported by Sean P) + * [JACKSON-416] XmlElement.type() doesn't override type during serialization + (reported by Sean P) + * [JACKSON-417] Deserialization of "native" types (String, Integer, Boolean) + failed with abstract types + (reported by Joe J) + * [JACKSON-423] Incorrect serialization of BigDecimal, BigInteger, + when using TokenBuffer + (reported by Sean P) + * [JACKSON-424] ArrayIndexOutOfBounds with SmileGenerator, long Unicode + Strings + (reported by Shay B) + +1.6.2 [02-Nov-2010] + + Fixes: + + * [JACKSON-288] Problems with JAXB annotation handling for combination of + @XmlJavaTypeAdapter, @XmlElement + (reported by Kent R) + * [JACKSON-366] Type metadata not written for empty beans + (reported by Patrick R) + * [JACKSON-388] Deserialization of Throwable fails with Inclusion.NON_NULL + (reported by Kirill S) + * [JACKSON-391] ObjectReader.withValueUpdate() passing wrong object + (reported by Kurtis) + * [JACKSON-392] Beans with only @JsonAnyGetter fail on serialization + (reported by Kirill S) + * [JACKSON-395]: JsonParser.getCurrentName() not working with + JsonParser.nextValue() for nested JSON Arrays, Objects + * [JACKSON-397] Reverted most of [JACKSON-371] from 1.6 branch, since it caused + externally visible change in exception handling; behavior now back to 1.6.0 + (will change to catch and rethrow in 1.7.0) + (reported by Jon Berg) + * [JACKSON-398]: Root type information not correctly passed by + ObjectWriter when using JsonGenerator + (reported by Kirill S) + * [JACKSON-403]: XMLGregorianCalendar could not be deserialized from timestamp + (reported by Manual F) + * [JACKSON-404] Problem with XmlAdapter, generic types, deserialization + (reported by Davide) + +1.6.1 [06-Oct-2010] + + Fixes: + + * [JACKSON-359] TypeIdResolver.init() was not being called properly + (reported by Peter L) + * [JACKSON-372] handle missing primitive type values for @JsonCreator gracefully (with defaults) + * [JACKSON-376] writing binary data as object field value with Smile failed + (reported by Shay B) + * [JACKSON-371] Provide path of type error in ObjectMapper.convertValue() + (reported by Larry Y) + * [JACKSON-383] @JsonAnySetter gets called for ignorable properties if + FAIL_ON_UNKNOWN_PROPERTIES set to false (related to [JACKSON-313]) + (reported by Kirill S) + * [JACKSON-384] @JsonAnyGetter values were duplicated if method name was valid as a regular + getter name + (reported by Bruce R) + * all fixes from 1.5.x up to 1.5.7 + + Improvements: + + * [JACKSON-360] Convert empty String to null values for Joda + (suggested by Shilpa P) + * [JACKSON-386] Improve registration for optional/external types (javax.xml, joda) + +1.6.0 [06-Sep-2010] + + Fixes: + + * [JACKSON-265] Problems with generic wildcard type, type info + (reported by Fabrice D) + * [JACKSON-268] Property ordering for JAXB did not work with "raw" property + names (but just with renamed names like with Jackson annotations) + (reported by Valentin B) + * [JACKSON-303] JAXB annotation @XmlAccessorType(XmlAccessType.NONE) seems + to not work correctly during deserialisation process + (reported by David M) + * [JACKSON-313] Ignorable properties should not be passed to any-setter + * [JACKSON-336] Generics handling: Map type not handled if intermediate types + with just one generic parameter + + Improvements: + + * [JACKSON-193] @JsonCreator-annotated factory methods and @JsonValue annotated + output methods now work with enums, allowing more customizable enum ser/deser. + (requested by Paul B) + * [JACKSON-253] Support combination of @XmlAnyElement + @XmlElementRefs + * [JACKSON-261] @JsonView now implies that associated element (field, + getter/setter) is to be considered a property; similar to how + @JsonSerialize/@JsonDeserialize/@JsonProperty are used. + * [JACKSON-274] Un-deprecated @JsonGetter and @JsonSetter. + * [JACKSON-283] JDK atomic types (java.util.concurrent.atomic) supported + * [JACKSON-289] Added "SerializationConfig.Feature.WRITE_CHAR_ARRAYS_AS_JSON_ARRAYS" + to allow serializing char[]s as JSON Arrays with single-char-String values + (also fixed issues with deserializing the same on deserializer side) + (requested by Brian O) + * [JACKSON-290] @JsonWriteNullProperties can be used with fields too; + annotation itself is now deprecated (use JsonSerialize#include instead). + * [JACKSON-301] Allow JsonMappingException to return name of "bad" (unrecognized) + field + (requested by Rob O) + * [JACKSON-302] Add JsonNode.has(String/int) to allow for more convenient checking + of whether JSON Object/Array nodes have specified value. + * [JACKSON-308] Configurable date formatting support for XMLGregorianCalendar: + XMLGregorianCalendar now uses same Date/Calendar serialization as other date types. + (suggested by Igor K) + * [JACKSON-321] Allow passing JsonNodeFactory to use for ObjectMapper, ObjectReader, + to allow use of custom JsonNode types. + * [JACKSON-326] Add 'JsonParser.hasTextCharacters()' to make it easier to optimize + text access (esp. when copying events) + * [JACKSON-328] Precedence of "getters-as-setters" (for Maps, Collections) was + accidentally higher than that of property fields (public, @JsonProperty) + (reported by Thomas D) + * [JACKSON-333] Add JsonNode.getValueAsInt()/.getValueAsDouble() for more convenient + coercion; including parsing of JSON text values to numbers if necessary + * [JACKSON-339] Support Joda ReadableDateTime, ReadableInstant out of the box + * [JACKSON-349] Accept empty String as number (null for wrappers, 0 for primitives) + + New features: + + * [JACKSON-41] Add code generation to allow deserialization into arbitrary Bean interfaces. + * [JACKSON-210] Add method(s) in JsonNode for finding values of named property + * [JACKSON-212] Allow serializer/deserializing Enums using toString() method + instead name() + * [JACKSON-235] Handle bi-directional (parent/child, double-linked lists) references + * [JACKSON-257] Add ability to register sub-types for Polymetric Type Handling + * [JACKSON-264] Ability to "update" values; to read and bind JSON + content as properties of existing beans. This is done by using + "ObjectMapper.updatingReader()" (and "reader.readValue(source)") + * [JACKSON-267] Allow unquoted field names to start with '@' in + (when unquoted name support is enabled, to support polymorphic + typing (which defaults to property names like "@class"). + (requested by Michel G) + * [JACKSON-278] Allow access to version information (via new Versioned interface) + (requested by Andrei V) + * [JACKSON-282] Added SerializationConfig.Feature.CLOSE_CLOSEABLE + which when enabled forced a call to value.close() right after + serialization of a (root-level) value. + * [JACKSON-287] Add JsonParser.releaseBufferedContent() which can be called + to "push back" content read but not (yet) consumed by JsonParser + * [JACKSON-292] Add "any-getter" (using @JsonAnyGetter) to complement @JsonAnySetter, + more convenient mapping of miscellaneous extra properties. + * [JACKSON-295] Add 'jackson-all' jar + (suggested by Ant E) + * [JACKSON-299] Added 'org.codehaus.jackson.impl.MinimalPrettyPrinter' + to make it easier to add simple output customizations + (suggested by David P) + * [JACKSON-300] Add 'JsonParser.Feature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER + to allow non-standard character escapes like \'. + (requested by Ketan G) + * [JACKSON-314] (go Pi, go!) Add 'SerializationConfig.Feature.WRITE_NULL_MAP_VALUES' + to suppress writing of Map entries with null values. + * [JACKSON-316] Allow per-call enable/disable of pretty printing (added + methods in ObjectWriter; .withPrettyPrinter()) + * [JACKSON-325] Add new Jackson "internal" annotation (@JacksonStdCodec?) to allow + marking default/standard serializers, deserializers + * [JACKSON-337] Add "ObjectMapper.valueToTree()" + + Backwards incompatible changes + + * [JACKSON-328] (see above) fixes precedence of "getter-as-setter" (for Maps, Collections) + to be LOWER than that of fields; this is the original intended behavior. However, + versions 1.1 - 1.5 accidentally had fields at lower precedence. This fix can + change behavior of code. + * [JACKSON-308] (see above) Configurable date formatting support for XMLGregorianCalendar: + since default Date/Calendar formatting uses timestamp instead of textual serialization, + default XMLGregorianCalendar serialization is changing. + +1.5.7 [03-Oct-2010] + + Fixes: + + * [JACKSON-352] Polymorphic deserialization for Object always assumes + array-wrapper style + (reported by Henry L) + * [JACKSON-355] Handling of BigInteger with JsonNode not correct + (reported by Adam S) + * [JACKSON-363] CustomDeserializerFactory did not work for custom + array deserializers. + (reported by Lubomir K) + * [JACKSON-370] TreeTraversingParser.skipChildren() not working correctly + (reported by Dmitry L) + * [JACKSON-373] Interface inheritance not traversed when looking up + custom serializers + (reported by Lubomir K) + * [JACKSON-377] ThrowableDeserializer was not properly using information from + @JsonCreator or @JsonAnySetter + (reported by Kirill S) + * [JACKSON-380] Incorrect type information serialized for some Enums + +1.5.6 [17-Aug-2010] + + Fixes: + + * [JACKSON-329] type information was not properly serialized for + Iterator or Iterable serializers + (reported by Yuanchen Z) + * [JACKSON-330] ObjectMapper.convertValue(): base64 conversions + do not work as expected + * [JACKSON-334] Support ISO-8601 date without milliseconds + * [JACKSON-340] Meta annotations missing for @JsonTypeResolver + (reported by Yuanchen Z) + * [JACKSON-341] Issue with static typing, array and subtyping + (reported by Yuanchen Z) + +1.5.5 [25-Jul-2010] + + Fixes: + + * [JACKSON-309] Serialization of null properties not working correctly + when using JAXB annotation introspector + * [JACKSON-318] Deserializer missing support for java.util.Currency + (reported by Geoffrey A) + * [JACKSON-319] Issues when trying to deserialize polymorphic type + with no data (just type information) + (reported by Chris C) + * [JACKSON-324] JsonParserBase: call releaseBuffers() in finally + block (within close()) + (suggested by Steve C) + * [JACKSON-327] CustomSerializerFactory had a bug in handling of + interface registrations + (reported by Yuanchen Z) + + (and all fixes from 1.4.x branch up to 1.4.5) + +1.5.4 [25-Jun-2010] + + Fixes: + + * [JACKSON-296]: Add support for JAXB/@XmlElementRef(s), fix related + issues uncovered (wrt. handling of polymorphic collection fields) + (reported by Ryan H) + * [JACKSON-311]: Problems handling polymorphic type information for + 'untyped' (Object) bean properties, default typing + (reported by Eric S) + +1.5.3 [31-May-2010] + + Fixes: + + * [JACKSON-285]: Problem with @JsonCreator annotated constructor that + also uses @JsonDeserialize annotations + + Improvements: + + * [JACKSON-284]: Reduce scope of sync block in + SerializerCache.getReadOnlyLookupMap() + * Partial fix for [JACKSON-289]: allow JSON Array with single-character + Strings to be bound to char[] during deserialization + (suggested by Brian O) + +1.5.2 [25-Apr-2010] + + Fixes: + + * [JACKSON-273] Yet another OSGi issue, "org.codehaus.jackson.map.util" + not exported by mapper module, needed by jax-rs module. + (reported by Lukasz D) + * [JACKSON-281] JsonGenerator.writeObject() only supports subset of + wrapper types (when not specifying ObjectCodec) + (reported by Aron A) + + (and all fixes from 1.4.x branch up to 1.4.4) + +1.5.1 [09-Apr-2010] + + Fixes: + + * [JACKSON-265]: problems with generic type handling for serialization + (reported by Fabrice D) + * [JACKSON-269]: missing OSGi export by mapper (o.c.j.m.jsontype.impl), + needed by jackson-xc module + (reported by Raymond F) + + (and all fixes from 1.4.x branch up to 1.4.3) + + +1.5.0 [14-Mar-2010] + + Fixes: + + * [JACKSON-246] JAXB property name determination not working correctly. + (reported by Lars C) + + Improvements: + + * [JACKSON-160] Factory Creator methods now handle polymorphic + construction correctly, allowing manual polymorphic deserialization + * [JACKSON-218] Extended support for Joda date/time types like + LocalDate, LocalDateTime and DateMidnight + * [JACKSON-220] @JsonSerialize.using() was not working properly for + non-Bean types (Collections, Maps, wrappers) + * [JACKSON-236] Allow deserialization of timestamps-as-Strings (not + just timestamps as JSON integer numbers). + (requested by Chris C) + * [JACKSON-255] Allow setter override even with incompatible type + (as long as only one setter per class, so there is no ambiguity) + * [JACKSON-256] AnnotationIntrospector.findSerializationInclusion + was not combining values correctly for JAXB annotations. + (reported by John L) + + New features: + + * [JACKSON-91] Polymorphic Type Handling: automatic handling of + polymorphic types, based on annotations (@JsonTypeInfo) and/or + global settings (ObjectMapper.enableDefaultTyping()) + * [JACKSON-175] Add "org.codehaus.jackson.util.TokenBuffer", used for + much more efficient type conversions (and other internal buffering) + * [JACKSON-195] Add methods to ObjectMapper to allow specification of + root object serialization type. + * [JACKSON-221] Add 'ObjectMapper.writeValueAsBytes()' convenience + method to simplify a common usage pattern + * [JACKSON-229] TypeFactory should have methods to construct parametric + types programmatically (TypeFactory.parametricType()) + * [JACKSON-232] Add 'SerializationConfig.Feature.DEFAULT_VIEW_INCLUSION' + to disable inclusion of non-annotated properties with explicit views + (suggested by Andrei V) + * [JACKSON-234] Add support for JSONP, by adding JSONPObject wrapper + that serializes as expected. + * [JACKSON-241] Add a mechanism for adding new "untouchable" types for + JAX-RS JSON provider, to allow excluding types from being handled + (added method "JacksonJsonProvider.addUntouchable()") + * [JACKSON-244] Allow specifying specific minimum visibility levels for + auto-detecting getters, setters, fields and creators + (requested by Pierre-Yves R) + * [JACKSON-245] Add configuration setting in JAX-RS provider to allow + automatic JSONP wrapping (provider.setJSONPFunctionName()) + * [JACKSON-259] Add JsonParser.Feature to allow disabling field name + canonicalization (JsonParser.Feature.CANONICALIZE_FIELD_NAMES) + + Backwards incompatible changes: + + * Moved following serializers out of BasicSerializerFactory + JdkSerializers: ClassSerializer (into JdkSerializers), + NullSerializer (separate class) + * Add one parameter to StdDeserializer.handleUnknownProperty: + addition was required for handling polymorphic cases that + can use nested JsonParser instances. + * Fixed issues in generic type handling (was not resolving all named + types completely) + * Annotation changes: + * Moved "NoClass" into "org.codehaus.jackson.map.annotate" package + * Removed @JsonUseSerializer and @JsonUseDeserializer annotations + (which has been deprecated for 1.1; replaced by + @JsonSerialize.using and @JsonDeserialize.using, respectively) + * @JsonGetter and @JsonSetter are marked as deprecated, since + @JsonProperty can (and should) be used instead. + +1.4.4 [25-Apr-2010] + + Fixes: + + * [JACKSON-263] BooleanNode.asToken() incorrectly returns 'true' token + for all nodes (not just 'false' ones) + (reported by Gennadiy S) + * [JACKSON-266] Deserialization issues when binding data from JsonNode + (reported by Martin T) + +1.4.3 [18-Feb-2010] + + Fixes: + + * [JACKSON-237]: NPE in deserialization due to race condition + (reported by Benjamin D) + + +1.4.2 [31-Jan-2010] + + Fixes: + + * [JACKSON-238]: Fix to ensure custom serializers can override + default serializers (like DOM, Joda serializers) + (reported by Pablo L) + * other fixes from 1.3.4 release + +1.4.1 [10-Jan-2010] + + Fixes: + + fixes from 1.3.x branch up to 1.3.3. + +1.4.0 [19-Dec-2009] + + Improvements: + + * [JACKSON-38] Allow serializing/deserializing DOM trees (Node, Document) + (suggested by Scott D) + * [JACKSON-89] Make ignored field/creator-backed properties quietly + skippable during deserialization (that is, without having to explicitly + declare such properties as ignorable as per [JACKSON-77]) + * [JACKSON-161] Added basic support for Joda, ser/deser DateTime class + * [JACKSON-170] Serialize Creator properties before other properties + * [JACKSON-196] Schema generation does not respect the annotation + configured serializer on a bean property + (reported by Gil M) + * [JACKSON-208] Add feature (JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS) + to allow unquoted control characters (esp. tabs) in Strings and + field names + (requested by Mark S) + * [JACKSON-216] Jackson JAXB annotation handler does not use @XmlElement.type + property for figuring out actual type + (reported by Mike R) + + New features: + + * [JACKSON-77] Add class annotation @JsonIgnoreProperties to allow + for ignoring specific set of properties for serialization/deserialization + * [JACKSON-90] Added @JsonPropertyOrder, which allows for specifying + order in which properties are serialized. + * [JACKSON-138] Implement JsonView; ability to suppress subsets of + properties, based on view definition. Views are defined using @JsonView + annotation. + * [JACKSON-191] Add access to basic statistics on number of cached + serializers, deserializers (and methods to flush these caches) + * [JACKSON-192] Added basic delegate implementations (JsonParserDelegate, + JsonGeneratorDelegate) to make it easier to override core parser and + generate behavior + * [JACKSON-201] Allow serialization of "empty beans" (classes without + getters), if SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS is + disabled; or if class has recognized Jackson annotation + (suggested by Mike P) + + Other: + + * Removed "BasicSerializerFactory.StringLikeSerializer" that was + deprecated for 1.0, replaced by public "ToStringSerializer" + +1.3.4 [31-Jan-2010] + + Fixes: + + * [JACKSON-225], [JACKSON-227], missing null checks/conversions when + adding entries to ArrayNode and ObjectNode + (reported by Kenny M) + * [JACKSON-230]: wrong NumberType reported for big ints, longs + (reported by Henning S) + * [JACKSON-231]: ArrayDeserializer for byte[] should be able to + use VALUE_EMBEDDED_OBJECT (if Object is byte[]) + +1.3.3 [21-Dec-2009] + + Fixes: + + * [JACKSON-214] Enum types with sub-classes failed to serialize + (reported by Elliot S) + * [JACKSON-215] Add JAX-RS provider annotations on JacksonJaxbJsonProvider + (suggested by Matthew R) + * [JACKSON-220] JsonSerialize.using() not recognized for Collection and + Map types (and similarly for JsonDeserialize) + +1.3.2 [02-Dec-2009] + + Fixes: + + * [JACKSON-103] (additional work) Groovy setMetaClass() setter caused + problems when deserializing (although serialization was fixed earlier) + (reported by Stephen F) + * [JACKSON-187] Issues with GAE security model, Class.getEnclosingMethod() + * [JACKSON-188] Jackson not working on Google App Engine (GAE) due to + unintended dependency from JacksonJsonProvider to JAXB API classes + (reported by Jeff S) + * [JACKSON-206] Support parsing dates of form "1984-11-13T00:00:00" + +1.3.1 [23-Nov-2009] + + Fixes: + + * [JACKSON-190] Problems deserializing certain nested generic types + (reported by Nathan C) + * [JACKSON-194] ObjectMapper class loading issues on Android + (reported by Martin L) + * [JACKSON-197] Remove 2 debug messages that print out to System.err + (reported by Edward T) + * [JACKSON-200] java.sql.Date deserialization not working well + (reported by Steve L) + * [JACKSON-202] Non-public fields not deserialized properly with + JAXB annotations + (reported by Mike P) + * [JACKSON-203] Date deserializers should map empty String to null + (reported by Steve L) + +1.3.0 [30-Oct-2009] + + Fixes: + + * [JACKSON-150] Some JAXB-required core types (XMLGregorianCalendar, + Duration, QName, DataHandler) were not completely supported + * [JACKSON-155] Failed to serialize java.io.File (with infinite + recursion) + (reported by Gabe S) + * [JACKSON-167] Map and Collection sub-classes seem to lose generic + information for deserialization + * [JACKSON-177] Problems with Hibernate, repackaged cglib + (reported by Ted B) + * [JACKSON-179] Single-long-arg factory Creators were not working + (reported by Brian M) + * [JACKSON-183] Root-level 'JsonDeserialize' annotation was not handled + completely; 'as' setting was not taking effect + (reported by Nick P) + + Improvements: + + * [JACKSON-152] Add "ObjectMapper.writeValueAsString()" convenience + method to simplify serializing JSON into String. + * [JACKSON-153] Allow use of @JsonCreator with Map types too + * [JACKSON-158] Bean serializer now checks for direct self-references + (partial, trivial cycle detection) + * [JACKSON-164] Improve null handling for JsonGenerator.writeStringValue + (suggested by Benjamin Darfler) + * [JACKSON-165] Add JsonParser.getBooleanValue() convenience method + (suggested by Benjamin Darfler) + * [JACKSON-166] Add ability to control auto-detection of + "is getters" (boolean isXxx()) methods separate from regular getters + * [JACKSON-168] Make JsonLocation serializable (and deserializable) + (suggested by Shay B) + * [JACKSON-182] Improved handling of SerializationConfig.AUTO_DETECT_GETTERS + with JAXB annotations (uses Jackson-specified default, not JAXB defaults) + + New features: + + * [JACKSON-129] Allow constructing JsonParser to read from JsonNode + (tree representation) + * [JACKSON-154] Added JsonDeserialize.keyUsing and .contentUsing, + to allow for overriding key and content/value deserializers for + properties of structured (array, Collection, Map) types + * [JACKSON-159] Added 'org.codehaus.jackson.jaxrs.JacksonJaxbJsonProvider' + to improve use of Jackson as JSON converter for JAX-RS services. + * [JACKSON-173] Add "JsonParser.Feature.ALLOW_SINGLE_QUOTES" to + handle some more invalid JSON content + (requested by Brian M) + * [JACKSON-174] Add "ObjectMapper.convertValue()" convenience method + for simple Object-to-Object conversions, using Jackson's data binding + functionality + * [JACKSON-176] Added 'JsonGenerator.Feature.WRITE_NUMBER_AS_STRINGS' + as a work-around for Javascript problems with big longs (due to + always representing numbers as 64-bit doubles internally) + (requested by Doug D) + * [JACKSON-180] Added 'JsonParser.Feature.INTERN_FIELD_NAMES' to allow + disabling field name intern()ing. + (suggested by Jeff Y) + * [JACKSON-181] Added convenience methods in TypeFactory to allow + dynamically constructed fully typed structured types (map, collection + array types), similar to using TypeReference but without inner classes + * Added method in AnnotationIntrospector to find declared namespace + for JAXB annotations, needed for XML compatibility (future features) + + Other: + + * Removed obsolete class 'org.codehaus.jackson.map.type.TypeReference' + (obsoleted by 'org.codehaus.jackson.type.TypeReference) -- was supposed + to have been removed by 1.0 but had not been. + * Added support to handle 'java.util.regex.Pattern' + +1.2.1 [03-Oct-2009] + + Problems fixed: + + * [JACKSON-162] OSGi packaging problems for xc package. + (reported by Troy Waldrep) + * [JACKSON-171] Self-referential types cause infinite recursion when + using only JAXB annotation introspector + (reported by Randy L) + +1.2.0 [02-Aug-2009] + + Improvements: + + * Added "-use" flag for generating javadocs + (suggested by Dain S) + * [JACKSON-136] JsonParser and JsonGenerator should implement + java.io.Closeable (since they already have close() method) + (suggested by Dain S) + * [JACKSON-148] Changed configuration methods to allow chaining, + by returning 'this' (instead of 'void') + + New features: + + * [JACKSON-33] Allow use of "non-default constructors" and + multiple-argument factory methods for constructing beans to + deserialize + * [JACKSON-69] Support parsing non-standard JSON where Object keys are not quoted + * [JACKSON-76] Mix-in annotations: allow dynamic attachment of + annotations to existing classes, for purposes of configuring + serialization/deserialization behavior + * [JACKSON-92] Allow use of @JsonCreator for constructors and + static methods that take a single deserializable type as argument + (so-called delegating creators) + * [JACKSON-114] Add feature and annotations to make serialization use + static (declared) type over concrete (actual/runtime) type + * [JACKSON-131] Allow constructing and passing of non-shared + SerializationConfig/DeserializationConfig instances to ObjectMapper + * [JACKSON-135] Add basic JsonNode construction support in ObjectMapper + * [JACKSON-147] Add global deserialization feature for suppressing error + reporting for unknown properties + * [JACKSON-149] Add ser/deser features + (DeserializationConfig.Feature.USE_ANNOTATIONS, + SerializationConfig.Feature.USE_ANNOTATIONS) to allow disabling + use of annotations for serialization and/or deserialization config + +1.1.2 [31-Jul-2009] + + Fixes: + + * [JACKSON-143] NPE on ArrayNode.equals() when comparing empty array + node to non-empty array node + (reported by Gregory G) + * [JACKSON-144] Static "getter-like" methods mistaken for getters (for + serialization) + (reported by Dan S) + +1.1.1 [18-Jul-2009] + + Fixes: + + * [JACKSON-139] Non-numeric double values (NaN, Infinity) are serialized + as invalid JSON tokens + (reported by Peter H) + * Core jar incorrectly included much of "mapper" classes (in addition + to core classes) + * Now compiles again using JDK 1.5 javac (1.1.0 didn't) + +1.1.0 [22-Jun-2009] + + Fixes: + + * [JACKSON-109] Allow deserializing into generics Bean classes + (like Wrapper<Bean>) not just generic Maps and Collections + * [JACKSON-121] Problems deserializing Date values of some ISO-8601 + variants (like one using 'Z' to indicate GMT timezone) + * [JACKSON-122] Annotated serializers and deserializers had to + be public classes with public default constructor; not any more. + + Improvements: + + * [JACKSON-111] Added "jackson-xc" jar to contains XML Compatibility + extensions. + + New features: + + * [JACKSON-70] Add support for generating JSON Schema + * [JACKSON-98] Allow serializing/deserializing field-accessible properties, + in addition to method-accessible ones. + * [JACKSON-105] Allow suppressing output of "default values"; which + means value of a property when bean is constructed using the default + no-arg constructor + (requested by Christoph S) + * [JACKSON-119] Add (optional) support for using JAXB annotations + (by using JaxbAnnotationIntrospector) + (requested by Ryan H) + * [JACKSON-120] Add annotations @JsonSerialize, @JsonDeserialize, + to streamline annotation by replacing host of existing annotations. + * [JACKSON-123] Add "chaining" AnnotationIntrospector (implemented + as inner class, AnnotationIntrospector.Pair) that allows combining + functionality of 2 introspectors. + +1.0.1 [04-Jun-2009] + + Fixes: + + * [JACKSON-104] Build fails on JDK 1.5, assorted other minor issues + (reported by Oleksander A) + * [JACKSON-121] Problems deserializing Date values of some ISO-8601 + variants (like one using 'Z' to indicate GMT timezone) + +1.0.0 [09-May-2009] + + Fixes: + + * [JACKSON-103] Serializing Groovy objects; need to exclude getter method + "getMetaClass" from serialization to prevent infinite recursion + (reported by Ray T) + + Improvements: + + * Removed JAX-RS META-INF/services - based auto-registration for + JAX-RS MessageBodyReader/MessageBodyWriter, because it could + conflict with other application/json content handlers. + +0.9.9-6 [27-Apr-2009] + + Improvements: + + * Improved jax-rs provider integration with jersey; now properly + auto-registers as handler for json media type(s), and allows + for defining custom ObjectMapper to be injected. + +0.9.9-5 [20-Apr-2009] + + New features: + + * [JACKSON-88]: Support for "Setter-less" collection (and Map) types + + Improvements: + + * [JACKSON-100]: Allow specifying that BigInteger should be used instead + of Integer or Long for "generic" integral numeric types (Object, Number) + (DeserializationConfig.Feature.USE_BIG_INTEGER_FOR_INTS) + * [JACKSON-101]: Allow disabling of access modifier overrides + (SerializationgConfig.Feature.CAN_OVERRIDE_ACCESS_MODIFIERS) + to support more security-constrainted running environments. + +0.9.9-4 [14-Apr-2009] + + Fixes: + + * [JACKSON-94] Added missing "JsonParser.readValueAsTree()" method. + * JacksonJsonProvider was using strict equality comparison against + JSON type; instead needs to use "isCompatible". There were other + similar problems + (reported by Stephen D) + * [JACKSON-97] Generic types (with bound wildcards) caused problems + when Class introspector could not figure out that a concrete method + was overriding/implementing generic method; as well as having + problems with synthetic bridge methods. + + Improvements: + + * [JACKSON-95] Added support for deserializing simple exceptions + (Throwable and its sub-classes): anything with a String constructor + (assumed to take "message") should work to some degree. + * [JACKSON-99] IOExceptions should not be wrapped during object + mapping. + (reported by Eldar A) + + New features: + + * [JACKSON-85]: Make Date deserialization (more) configurable (add + DeserializationConfig.setDateFormat()) + * [JACKSON-93]: Allow overriding the default ClassIntrospector. + * [JACKSON-96]: Allow enabling pretty-printing with data binding, + through SerializationConfig object. + +0.9.9-3 [03-Apr-2009] + + Fixes: + + * [JACKSON-79]: Primitive value deserialization fragile wrt nulls + * [JACKSON-81]: Data binding code could lead to unnecessary blocking + because it tried to advance parser (and stream) after binding + (reported by Eldar A) + + New features: + + * [JACKSON-61]: Allow suppressing writing of bean properties with null values + (requested by Justin F) + * [JACKSON-63]: Create CustomDeserializerFactory to allow for adding + custom deserializers for non-structured/generic types. + * [JACKSON-75]: Add "any setter" method; ability to catch otherwise + unknown (unmapped) properties and call a method with name+value. + * [JACKSON-80]: Add @JsonValue annotation, to specify that a Bean value + is to be serialized as value returned by annotated method: can for + example annotate "toString()" method. + * [JACKSON-84]: Added JsonGenerator.writeRawValue methods to augment + existing JsonGenerator.writeRaw() method + (requested by Scott A) + * [JACKSON-86]: Added JsonParser.isClosed() and JsonGenerator.isClosed() + methods. + * [JACKSON-87]: Added ability to customized Date/Calendar serialization, + both by toggling between timestamp (number) and textual (ISO-8601), + and by specifying alternate DateFormat to use. + +0.9.9-2 [19-Mar-2009]: + + Fixes: + + * [JACKSON-75]: Didn't have Deserializer for Number.class. + + Improvements: + + * [JACKSON-68]: Add DeserializationProblemListener, and + DeserializationConfig.addHandler to add instances to ObjectMapper. + * [JACKSON-71]: Add support ser/deser of Class.class. + * [JACKSON-72]: Allow specifying that BigDecimal should be used instead + of Double for "generic" numeric types (Object, Number) + (DeserializationConfig.Feature.USE_BIG_DECIMAL_FOR_FLOATS) + * [JACKSON-73]: Refactored ser/deser configuration settings into + separate configuration classes. + * [JACKSON-78]: Should be able to deserialize ints into Booleans (0 == false) + + New features: + + * [JACKSON-45]: Add convenience methods to help writing custom + serializers + (requested by Scott A) + +0.9.9 [02-Mar-2009]: + + Fixes: + + * [JACKSON-59]: NPE with String[] serializer + (reported by Kevin G) + * [JACKSON-62]: NPE with JsonMappingException if source exception used + null message. + (reported by Justin F) + * [JACKSON-64]: Handling of property name (with @JsonGetter, @JsonSetter) + made bit more intuitive; uses bean naming convention if no explicit + name given. + + Improvements: + + * [JACKSON-60]: Method annotations did not follow intuitive expectations + of inheritability; now do. + * [JACKSON-65]: Need to support typing using "java.lang.reflect.Type", to + help integration with frameworks. + * [JACKSON-66]: ObjectMapper now has "canSerialize" and "canDeserialize" + methods to help frameworks figure out what is supported. + + New features: + + * [JACKSON-52]: Allow disabling name-based auto-detection of + getter methods + (requested by Justin F) + * [JACKSON-58]: Allow defining custom global Enum serializer + (to, for example, make Enums be serialized using Enum.toString(), + or lower-case name or such) + * [JACKSON-67]: Add JAX-RS provider based on Jackson that can handle + JSON content type; initially as a separate jar. + + Other: + + * [JACKSON-22]: all contributors now have submitted contributor + agreement, stored under 'DEV/agreements-received' in svn trunk. + +0.9.8 [18-Feb-2009]: + + Fixes: + + * [JACKSON-49]: Incorrect bounds check for Float values resulted in + exception when trying to serializer 0.0f. + + New features: + + * [JACKSON-32]: add annotations to configure serialization process + (@JsonClass/@JsonContentClass/@JsonKeyClass; @JsonUseSerializer, + @JsonUseDeserializer, @JsonIgnore) + * [JACKSON-36]: add annotations to define property names that differ + from bean naming convention (@JsonGetter/@JsonSetter) + + Improvements: + + * [JACKSON-47]: Change DeserializerProvider.findValueDeserializer to + take "referrer" information. This is needed to be able to give + contextual mappings where a given type may be deserialized differently + (by different deserializer, and possibly to a different java class) + depending on where the reference is from. + * [JACKSON-48]: Integrate ObjectMapper with JsonGenerator, JsonParser; + add MappingJsonFactory. + (suggested by Scott A) + * [JACKSON-50]: JsonNode.getElements() and .iterator() now work for + ObjectNodes too, not just ArrayNodes. Also added convenience factory + methods to allow constructing child nodes directly from container + nodes. + * [JACKSON-53]: iBatis proxied value classes didn't work; fixed by + prevent CGLib-generated "getCallbacks" from getting called. + (reportd by Justin F) + * [JACKSON-55]: Added support for reference-path-tracking in + JsonMappingException, made serializers populate it: this to make + it easier to trouble-shoot nested serialization problems + * [JACKSON-56]: Added support for RFC-1123 date format, along with + simpler "standard" format; and can add more as need be. + +0.9.7 [04-Feb-2009]: + + Improvements: + + * [JACKSON-34]: Improved packaging by adding an intermediate directory + in source tarball, to not mess up the current directory (and to indicate + version number as well) + * [JACKSON-37]: Make Jackson run on Android, by ensuring that there are + no hard linkages to classes that Android SDK doesn't have (the only + reference that was there, to XMLGregorianCalendar, was changed to + soft linkage) + * [JACKSON-42]: Add new JsonNode sub-class, BinaryNode, to represent + base64 encoded binary content. + + New features: + + * [JACKSON-6]: Implement JsonParser.getBinaryValue() so that one can + now also read Base64-encoded binary, not just write. + * [JACKSON-40]: Add JsonParser.nextValue() for more convenient + iteration. + * [JACKSON-46]: Allow disabling quoting of field names by disabling + feature 'JsonGenerator.feature.QUOTE_FIELD_NAMES' + (requested by Scott Anderson) + +0.9.6 [14-Jan-2009]: + + Bug fixes: + + * Serialization of some core types (boolean/java.lang.Boolean, + long/java.lang.Long) was not working due to incorrectly mapped + serializers. + + New features: + + * [JACKSON-31]: Complete rewrite of ObjectMapper's deserialization: + now supports Beans, typed (generics-aware) Lists/Maps/arrays. + + Improvements: + + * [JACKSON-24]: Add efficient byte-array - based parser factory + method to JsonFactory (has maybe 5% improvement over wrapping + in ByteArrayInputStream). + * [JACKSON-29]: Split classes in 2 jars: core that has parser and + generator APIs and implementations; and mapper jar that has object + and tree mapper code. + * [JACKSON-30]: Renamed "JavaTypeMapper" as "ObjectMapper", and + "JsonTypeMapper" as "TreeMapper"; new names should be more intuitive + to indicate their purpose. Will leave simple implementations of + old classes to allow for gradual migration of existing code. + +0.9.5 [10-Dec-2008]: + + Bug fixes: + + * [JACKSON-25]: Problems with Maven pom for lgpl version + (report by Ray R) + note: backported to 0.9.4 Codehaus Maven repo + + Improvements: + + * [JACKSON-13]: JavaTypeMapper can now take JsonFactory argument, and + thus is able to construct JsonParser/JsonGenerator instances as necessary + * [JACKSON-17]: Handling of unknown types now configurable with + JavaTypeMapper serialization (see JsonSerializerProvider for methods) + * [JACKSON-20]: Handling of nulls (key, value) configurable with + JavaTypeMapper serialization (see JsonSerializerProvider for methods) + * [JACKSON-26]: Add convenience JsonGenerator.writeXxxField() methods + to simplify json generation. + + New features: + + * [JACKSON-27]: Allow automatic closing of incomplete START_ARRAY and + START_OBJECT events, when JsonGenerator.close() is called. + +0.9.4 [26-Nov-2008]: + + Bug fixes: + + * [JACKSON-16]: JavaDocs regarding whether Jackson is to close underlying + streams, readers and writers, were incorrect. Additionally added + parser/generator features to allow specifying whether automatic closing + is to be done by Jackson: feature is enabled by default, both for + backwards compatibility, and because it seems like the right setting. + * [JACKSON-18]: ArrayIndexOutOfBounds on IntNode, due to off-by-one + problem with comparisons + (reported by Michael D) + * Fixed a problem with CR (\r) handling; was sometimes skipping + characters (problematic if there's no indentation). + * Multiple UTF-8 decoding fixes: was specifically not working for + names. + + Improvements: + + * More complete JavaDoc comments for core public classes. + * Internal cleanup of core parsing, to unify handling of Object and + Array entries + +0.8.0 - 0.9.3 [between 17-Oct-2007 and 05-Sep-2008]: + + Changes: + + * [JACKSON-5]: Symbol table construction was not thread-safe for + utf-8 encoded content (new bug with 0.9.2, not present with earlier) + (reported by Tudor B) + * [JACKSON-8]: Serialization of BigDecimal broken with JavaTypeMapper + (reported by Johannes L) + * [JACKSON-9]: Add support for (non-standard) Json comments. + (requested by Mike G) + * [JACKSON-11]: Implement base64/binary methods for json generator. + * [JACKSON-14]: Problems with generic collections, serializer + method signatures (due to lack of covariance wrt collection types) + * [JACKSON-15]: Add copy-through methods to JsonGenerator for + pass-through copying of content (copyCurrentEvent, copyCurrentStructure) + * [JACKSON-23]: Add OSGi manifest headers for jars (to run on OSGi container). + * Added generic "feature" mechanism to parsers, writers; features are + togglable (on/off) things with well-defined default values, implemented + as Enums. + + * [JACKSON-1]: JsonNode now implements Iterable<JsonNode> so that + it is possible use Java 5 foreach loop over array/object nodes. + (suggested by Michael M) + * [JACKSON-4] Added JsonParser.skipChildren() method. + * UTF-16/32 handling was not completely correct, was erroneously + skipping first 2/4 bytes in some cases (even when no BOM included). + Also, related unit tests added/fixed. + * JsonGenerator.useDefaultPrettyPrinter()/.setPrettyPrinter() + allow for pretty printing (indentation). + (thanks to Ziad M for suggestion, sample code) + + * Implicit conversions for numbers could sometimes lose accuracy, + if floating-point number was first accessed as int/long, and then + as a BigDecimal. + * One Nasty NPE fixed from NameCanonicalizer (which was added in 0.9.2) + + * Java type mapper had a bug in Collection mapping (mismatched + calls between writeStartArray and writeEndObject!) + (reported by Mike E) + * Java type mapper had a bug which prevented custom mappers (as + well as slower interface-based introspection) from working. + (reported by Mike E) + * Numeric value parsing had some problems + * JavaTypeMapper and JsonTypeMapper had a bug which resulted + in NullPointerException when stream ends, instead of returning + null to indicate it. + (reported by Augusto C) + * JavaTypeMapper did not implicitly flush generator after mapping + objects: it should, and now will (note: JsonTypeMapper not directly + affected, flushing still needed) + (suggested by Maciej P)
diff --git a/1.9.10/release-notes/asl/ASL2.0 b/1.9.10/release-notes/asl/ASL2.0 new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/1.9.10/release-notes/asl/ASL2.0
@@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed 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.
diff --git a/1.9.10/release-notes/asl/LICENSE b/1.9.10/release-notes/asl/LICENSE new file mode 100644 index 0000000..3eaf591 --- /dev/null +++ b/1.9.10/release-notes/asl/LICENSE
@@ -0,0 +1,13 @@ +This copy of Jackson JSON processor is licensed under the +Apache (Software) License, version 2.0 ("the License"). +See the License for details about distribution rights, and the +specific rights regarding derivate works. + +You may obtain a copy of the License at: + +http://www.apache.org/licenses/ + +A copy is also included with both the the downloadable source code package +and jar that contains class bytecodes, as file "ASL 2.0". In both cases, +that file should be located next to this file: in source distribution +the location should be "release-notes/asl"; and in jar "META-INF/"
diff --git a/1.9.10/release-notes/asl/NOTICE b/1.9.10/release-notes/asl/NOTICE new file mode 100644 index 0000000..0cae638 --- /dev/null +++ b/1.9.10/release-notes/asl/NOTICE
@@ -0,0 +1,7 @@ +This product currently only contains code developed by authors +of specific components, as identified by the source code files; +if such notes are missing files have been created by +Tatu Saloranta. + +For additional credits (generally to people who reported problems) +see CREDITS file.
diff --git a/1.9.10/release-notes/lgpl/LGPL2.1 b/1.9.10/release-notes/lgpl/LGPL2.1 new file mode 100644 index 0000000..b1e3f5a --- /dev/null +++ b/1.9.10/release-notes/lgpl/LGPL2.1
@@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + <one line to give the library's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + <signature of Ty Coon>, 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + +
diff --git a/1.9.10/release-notes/lgpl/LICENSE b/1.9.10/release-notes/lgpl/LICENSE new file mode 100644 index 0000000..b5420ca --- /dev/null +++ b/1.9.10/release-notes/lgpl/LICENSE
@@ -0,0 +1,13 @@ +This copy of Jackson JSON processor is licensed under the +Lesser General Public License (LGPL), version 2.1 ("the License"). +See the License for details about distribution rights, and the +specific rights regarding derivate works. + +You may obtain a copy of the License at: + +http://www.gnu.org/licenses/licenses.html + +A copy is also included with both the the downloadable source code package +and jar that contains class bytecodes, as file "LGPL 2.1". In both cases, +that file should be located next to this file: in source distribution +the location should be "release-notes/lgpl"; and in jar "META-INF/"
diff --git a/1.9.10/release-notes/lgpl/NOTICE b/1.9.10/release-notes/lgpl/NOTICE new file mode 100644 index 0000000..0cae638 --- /dev/null +++ b/1.9.10/release-notes/lgpl/NOTICE
@@ -0,0 +1,7 @@ +This product currently only contains code developed by authors +of specific components, as identified by the source code files; +if such notes are missing files have been created by +Tatu Saloranta. + +For additional credits (generally to people who reported problems) +see CREDITS file.
diff --git a/1.9.10/run.sh b/1.9.10/run.sh new file mode 100755 index 0000000..62d1b05 --- /dev/null +++ b/1.9.10/run.sh
@@ -0,0 +1,9 @@ +#!/bin/sh + +java -Xmx128m -server\ + -XX:-PrintGC -XX:-PrintGCDetails \ + -cp lib/junit/junit-3.8.1.jar\ +:lib/repackaged/\*:lib/xml/\*\ +:build/classes/core:build/classes/mapper:build/classes/xc:build/classes/extra\ +:build/classes/perf:build/classes/smile \ + $*
diff --git a/1.9.10/samples-nondist/twitter-search-mod-entry.json b/1.9.10/samples-nondist/twitter-search-mod-entry.json new file mode 100644 index 0000000..669476b --- /dev/null +++ b/1.9.10/samples-nondist/twitter-search-mod-entry.json
@@ -0,0 +1,7 @@ +{ + "id":1125687077, + "text":"@stroughtonsmith You need to add a \"Favourites\" tab to TC/iPhone. Like what TwitterFon did. I can't WAIT for your Twitter App!! :) Any ETA?", + "fromUserId":855523, + "toUserId":815309, + "languageCode":"en" +}
diff --git a/1.9.10/samples-nondist/twitter-search.jsn b/1.9.10/samples-nondist/twitter-search.jsn new file mode 100644 index 0000000..d81b044 --- /dev/null +++ b/1.9.10/samples-nondist/twitter-search.jsn
@@ -0,0 +1 @@ +{"results":[{"text":"@stroughtonsmith You need to add a "Favourites" tab to TC\/iPhone. Like what TwitterFon did. I can't WAIT for your Twitter App!! :) Any ETA?","to_user_id":815309,"to_user":"stroughtonsmith","from_user":"Shaun_R","id":1125687077,"from_user_id":855523,"iso_language_code":"en","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/68778135\/Safari_Dude_normal.jpg","created_at":"Sat, 17 Jan 2009 06:14:13 +0000"},{"text":"Beginning to understand the Twitter world...and liking it.","to_user_id":null,"from_user":"AWheeler15","id":1125687050,"from_user_id":3694831,"iso_language_code":"en","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/71564236\/Photo_2_normal.jpg","created_at":"Sat, 17 Jan 2009 06:14:11 +0000"},{"text":"@genar hehe, she cant twitter from work, hasnt got it set up on the phone, and on our workout nights generally the computer is untouched too","to_user_id":1089113,"to_user":"genar","from_user":"donro","id":1125687042,"from_user_id":1907789,"iso_language_code":"en","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/68316085\/stef_and_don_normal.jpg","created_at":"Sat, 17 Jan 2009 06:14:11 +0000"},{"text":"My morning routine: mail, flickr, google reader, friendfeed, twitter replies http:\/\/ff.im\/-DMrn","to_user_id":null,"from_user":"hakandahlstrom","id":1125686913,"from_user_id":213116,"iso_language_code":"en","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/67707376\/squarelg_normal.jpg","created_at":"Sat, 17 Jan 2009 06:14:04 +0000"},{"text":"@LeeCollins If you have not seen Lee's Website..Check it out ..Perfect layout. Also.. Twitter Photo tool","to_user_id":381690,"to_user":"leecollins","from_user":"MichaelGPerry","id":1125686877,"from_user_id":2765433,"iso_language_code":"en","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/70614206\/MG_Perry_normal.JPG","created_at":"Sat, 17 Jan 2009 06:14:02 +0000"},{"text":"Just Buzzed My Blog:: New Friend @AlohaArlene Gets Twooted From Twitter http:\/\/tinyurl.com\/8hd7qy","to_user_id":null,"from_user":"BabyBloggerBrie","id":1125686854,"from_user_id":3593267,"iso_language_code":"nl","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/70969980\/brie_normal.jpg","created_at":"Sat, 17 Jan 2009 06:14:02 +0000"},{"text":"Current will air the inauguration while streaming tweets from the twitter audience on the TV as we watch. Check it - http:\/\/ub0.cc\/7C\/2d","to_user_id":null,"from_user":"my3rdeye","id":1125686843,"from_user_id":2553098,"iso_language_code":"en","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/67353656\/Charlie_Boognish_normal.jpg","created_at":"Sat, 17 Jan 2009 06:14:01 +0000"},{"text":"milestone: Twitter Grader has now graded 1,000,000 unique twitter accounts. Woo hoo! (via @grader)","to_user_id":null,"from_user":"christyitamoto","id":1125686812,"from_user_id":1549031,"iso_language_code":"en","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/60294809\/MyPicture_normal.jpg","created_at":"Sat, 17 Jan 2009 06:13:59 +0000"},{"text":"Twitter-Yahoo Mashup Yields Impressive News Search Engine http:\/\/twurl.nl\/pg8sxs","to_user_id":null,"from_user":"synectic","id":1125686791,"from_user_id":2563073,"iso_language_code":"en","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/67483750\/8yplOv7l.kokopelli_trans_normal.png","created_at":"Sat, 17 Jan 2009 06:13:58 +0000"},{"text":"RT: @sarahamrin You really know how to work Twitter. *scribbles another mark for Sarah on the International T.. http:\/\/tinyurl.com\/7xt8hb","to_user_id":null,"from_user":"howtotweets","id":1125686790,"from_user_id":3437258,"iso_language_code":"en","profile_image_url":"http:\/\/static.twitter.com\/images\/default_profile_normal.png","created_at":"Sat, 17 Jan 2009 06:13:58 +0000"},{"text":"IPhone App Reviews - Breaking News in the 09s: iPhone and Twitter: Breaking News in the 09s: iPhone and Twitter .. http:\/\/tinyurl.com\/922qcl","to_user_id":null,"from_user":"ifones","id":1125686749,"from_user_id":1412337,"iso_language_code":"en","profile_image_url":"http:\/\/static.twitter.com\/images\/default_profile_normal.png","created_at":"Sat, 17 Jan 2009 06:13:56 +0000"},{"text":"RT: @davidall's book about how to use twitter RULES!! You can get it here: http:\/\/tinyurl.com\/495nm2 http:\/\/tinyurl.com\/8kuva5","to_user_id":null,"from_user":"howtotweets","id":1125686716,"from_user_id":3437258,"iso_language_code":"en","profile_image_url":"http:\/\/static.twitter.com\/images\/default_profile_normal.png","created_at":"Sat, 17 Jan 2009 06:13:54 +0000"},{"text":"@ev new 2 twitter & already hooked, thx 4 the welcome. It's rough being a newbie","to_user_id":5621,"to_user":"ev","from_user":"jgordo","id":1125686687,"from_user_id":3696186,"iso_language_code":"en","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/68508879\/Img00020_normal.jpg","created_at":"Sat, 17 Jan 2009 06:13:53 +0000"},{"text":"Twitter applicatie TweetDeck heeft een investering v $500k binnengehaald: http:\/\/twurl.nl\/gfei3i","to_user_id":null,"from_user":"gvenkdaily","id":1125686526,"from_user_id":230616,"iso_language_code":"nl","profile_image_url":"http:\/\/s3.amazonaws.com\/twitter_production\/profile_images\/55316327\/gvenkdaily-logo-vierkant_normal.png","created_at":"Sat, 17 Jan 2009 06:13:46 +0000"},{"text":"We are like Twitter Retards.. HA ha ha. I thought I was going to be gay, but I totally changed my mind after being chewed on the other night","to_user_id":null,"from_user":"Aroyal88","id":1125686475,"from_user_id":3219428,"iso_language_code":"en","profile_image_url":"http:\/\/static.twitter.com\/images\/default_profile_normal.png","created_at":"Sat, 17 Jan 2009 06:13:43 +0000"}],"since_id":0,"max_id":1125687077,"refresh_url":"?since_id=1125687077&q=twitter","results_per_page":15,"next_page":"?page=2&max_id=1125687077&q=twitter","completed_in":0.01338,"page":1,"query":"twitter"} \ No newline at end of file
diff --git a/1.9.10/samples-smile/db100.xml.smile b/1.9.10/samples-smile/db100.xml.smile new file mode 100644 index 0000000..0ead767 --- /dev/null +++ b/1.9.10/samples-smile/db100.xml.smile
@@ -0,0 +1,2 @@ +:) +útableúrowøúidú$C0000ûfirstnameúCAAlûlastnameúCEAranowû streetúCH1 Any St.ûcityúCFAnytownûstateúCAALûzipúCD22000ûûúBúCC0001ûDúCBBobûEúCûFúCH2 Any St.ûGúCûHúCûIúCûûúBúCC0002ûDúCFCharlesûEúCûFúCH3 Any St.ûGúCûHúCûIúCûûúBúCC0003ûDúCDDavidûEúCûFúCH4 Any St.ûGúCûHúCûIúCûûúBúCC0004ûDúCCEgonûEúCûFúCH5 Any St.ûGúCûHúCûIúCûûúBúCC0005ûDúCFFarboodûEúCûFúCH6 Any St.ûGúCûHúCûIúCûûúBúCC0006ûDúCEGeorgeûEúCûFúCH7 Any St.ûGúCûHúCûIúCûûúBúCC0007ûDúCCHankûEúCûFúCH8 Any St.ûGúCûHúCûIúCûûúBúCC0008ûDúCCInkiûEúCûFúCH9 Any St.ûGúCûHúCûIúCûûúBúCC0009ûDúCDJamesûEúCûFúCI10 Any St.ûGúCûHúCûIúCûûúBúCC0010ûDúCûEúCEBarkerûFúCI11 Any St.ûGúCûHúCûIúCûûúBúCC0011ûDúC ûEúCì#ûFúCI12 Any St.ûGúCûHúCûIúCûûúBúCC0012ûDúCûEúCì#ûFúCI13 Any St.ûGúCûHúCûIúCûûúBúCC0013ûDúCûEúCì#ûFúCI14 Any St.ûGúCûHúCûIúCûûúBúCC0014ûDúCûEúCì#ûFúCI15 Any St.ûGúCûHúCûIúCûûúBúCC0015ûDúCûEúCì#ûFúCI16 Any St.ûGúCûHúCûIúCûûúBúCC0016ûDúCûEúCì#ûFúCI17 Any St.ûGúCûHúCûIúCûûúBúCC0017ûDúCûEúCì#ûFúCI18 Any St.ûGúCûHúCûIúCûûúBúCC0018ûDúCûEúCì#ûFúCI19 Any St.ûGúCûHúCûIúCûûúBúCC0019ûDúCì ûEúCì#ûFúCI20 Any St.ûGúCûHúCûIúCûûúBúCC0020ûDúCûEúCGCorsettiûFúCI21 Any St.ûGúCûHúCûIúCûûúBúCC0021ûDúC ûEúCì8ûFúCI22 Any St.ûGúCûHúCûIúCûûúBúCC0022ûDúCûEúCì8ûFúCI23 Any St.ûGúCûHúCûIúCûûúBúCC0023ûDúCûEúCì8ûFúCI24 Any St.ûGúCûHúCûIúCûûúBúCC0024ûDúCCEgonûEúCì8ûFúCI25 Any St.ûGúCûHúCûIúCûûúBúCC0025ûDúCFFarboodûEúCì8ûFúCI26 Any St.ûGúCûHúCûIúCûûúBúCC0026ûDúCEGeorgeûEúCì8ûFúCI27 Any St.ûGúCûHúCûIúCûûúBúCC0027ûDúCûEúCì8ûFúCI28 Any St.ûGúCûHúCûIúCûûúBúCC0028ûDúCCInkiûEúCì8ûFúCI29 Any St.ûGúCûHúCûIúCûûúBúCC0029ûDúCDJamesûEúCì8ûFúCI30 Any St.ûGúCûHúCûIúCûûúBúCC0030ûDúCAAlûEúCIDershowitzûFúCI31 Any St.ûGúCûHúCûIúCûûúBúCC0031ûDúC ûEúCìSûFúCI32 Any St.ûGúCûHúCûIúCûûúBúCC0032ûDúCFCharlesûEúCìSûFúCI33 Any St.ûGúCûHúCûIúCûûúBúCC0033ûDúCûEúCìSûFúCI34 Any St.ûGúCûHúCûIúCûûúBúCC0034ûDúCìAûEúCìSûFúCI35 Any St.ûGúCûHúCûIúCûûúBúCC0035ûDúCìDûEúCìSûFúCI36 Any St.ûGúCûHúCûIúCûûúBúCC0036ûDúCìGûEúCìSûFúCI37 Any St.ûGúCûHúCûIúCûûúBúCC0037ûDúCûEúCìSûFúCI38 Any St.ûGúCûHúCûIúCûûúBúCC0038ûDúCìLûEúCìSûFúCI39 Any St.ûGúCûHúCûIúCûûúBúCC0039ûDúCìOûEúCìSûFúCI40 Any St.ûGúCûHúCûIúCûûúBúCC0040ûDúCìRûEúCGEnglemanûFúCI41 Any St.ûGúCûHúCûIúCûûúBúCC0041ûDúC ûEúCìiûFúCI42 Any St.ûGúCûHúCûIúCûûúBúCC0042ûDúCìXûEúCìiûFúCI43 Any St.ûGúCûHúCûIúCûûúBúCC0043ûDúCûEúCìiûFúCI44 Any St.ûGúCûHúCûIúCûûúBúCC0044ûDúCìAûEúCìiûFúCI45 Any St.ûGúCûHúCûIúCûûúBúCC0045ûDúCìDûEúCìiûFúCI46 Any St.ûGúCûHúCûIúCûûúBúCC0046ûDúCìGûEúCìiûFúCI47 Any St.ûGúCûHúCûIúCûûúBúCC0047ûDúCûEúCìiûFúCI48 Any St.ûGúCûHúCûIúCûûúBúCC0048ûDúCìLûEúCìiûFúCI49 Any St.ûGúCûHúCûIúCûûúBúCC0049ûDúCìOûEúCìiûFúCI50 Any St.ûGúCûHúCûIúCûûúBúCC0050ûDúCìRûEúCGFranklinûFúCI51 Any St.ûGúCûHúCûIúCûûúBúCC0051ûDúC ûEúCì~ûFúCI52 Any St.ûGúCûHúCûIúCûûúBúCC0052ûDúCìXûEúCì~ûFúCI53 Any St.ûGúCûHúCûIúCûûúBúCC0053ûDúCûEúCì~ûFúCI54 Any St.ûGúCûHúCûIúCûûúBúCC0054ûDúCìAûEúCì~ûFúCI55 Any St.ûGúCûHúCûIúCûûúBúCC0055ûDúCìDûEúCì~ûFúCI56 Any St.ûGúCûHúCûIúCûûúBúCC0056ûDúCìGûEúCì~ûFúCI57 Any St.ûGúCûHúCûIúCûûúBúCC0057ûDúCûEúCì~ûFúCI58 Any St.ûGúCûHúCûIúCûûúBúCC0058ûDúCìLûEúCì~ûFúCI59 Any St.ûGúCûHúCûIúCûûúBúCC0059ûDúCìOûEúCì~ûFúCI60 Any St.ûGúCûHúCûIúCûûúBúCC0060ûDúCìRûEúCDGriceûFúCI61 Any St.ûGúCûHúCûIúCûûúBúCC0061ûDúC ûEúCìûFúCI62 Any St.ûGúCûHúCûIúCûûúBúCC0062ûDúCìXûEúCìûFúCI63 Any St.ûGúCûHúCûIúCûûúBúCC0063ûDúCûEúCìûFúCI64 Any St.ûGúCûHúCûIúCûûúBúCC0064ûDúCìAûEúCìûFúCI65 Any St.ûGúCûHúCûIúCûûúBúCC0065ûDúCìDûEúCìûFúCI66 Any St.ûGúCûHúCûIúCûûúBúCC0066ûDúCìGûEúCìûFúCI67 Any St.ûGúCûHúCûIúCûûúBúCC0067ûDúCûEúCìûFúCI68 Any St.ûGúCûHúCûIúCûûúBúCC0068ûDúCìLûEúCìûFúCI69 Any St.ûGúCûHúCûIúCûûúBúCC0069ûDúCìOûEúCìûFúCI70 Any St.ûGúCûHúCûIúCûûúBúCC0070ûDúCìRûEúCHHaverfordûFúCI71 Any St.ûGúCûHúCûIúCûûúBúCC0071ûDúC ûEúCì¨ûFúCI72 Any St.ûGúCûHúCûIúCûûúBúCC0072ûDúCìXûEúCì¨ûFúCI73 Any St.ûGúCûHúCûIúCûûúBúCC0073ûDúCûEúCì¨ûFúCI74 Any St.ûGúCûHúCûIúCûûúBúCC0074ûDúCìAûEúCì¨ûFúCI75 Any St.ûGúCûHúCûIúCûûúBúCC0075ûDúCìDûEúCì¨ûFúCI76 Any St.ûGúCûHúCûIúCûûúBúCC0076ûDúCìGûEúCì¨ûFúCI77 Any St.ûGúCûHúCûIúCûûúBúCC0077ûDúCûEúCì¨ûFúCI78 Any St.ûGúCûHúCûIúCûûúBúCC0078ûDúCìLûEúCì¨ûFúCI79 Any St.ûGúCûHúCûIúCûûúBúCC0079ûDúCìOûEúCì¨ûFúCI80 Any St.ûGúCûHúCûIúCûûúBúCC0080ûDúCìRûEúCGIlvedsonûFúCI81 Any St.ûGúCûHúCûIúCûûúBúCC0081ûDúC ûEúCì½ûFúCI82 Any St.ûGúCûHúCûIúCûûúBúCC0082ûDúCìXûEúCì½ûFúCI83 Any St.ûGúCûHúCûIúCûûúBúCC0083ûDúCûEúCì½ûFúCI84 Any St.ûGúCûHúCûIúCûûúBúCC0084ûDúCìAûEúCì½ûFúCI85 Any St.ûGúCûHúCûIúCûûúBúCC0085ûDúCìDûEúCì½ûFúCI86 Any St.ûGúCûHúCûIúCûûúBúCC0086ûDúCìGûEúCì½ûFúCI87 Any St.ûGúCûHúCûIúCûûúBúCC0087ûDúCûEúCì½ûFúCI88 Any St.ûGúCûHúCûIúCûûúBúCC0088ûDúCìLûEúCì½ûFúCI89 Any St.ûGúCûHúCûIúCûûúBúCC0089ûDúCìOûEúCì½ûFúCI90 Any St.ûGúCûHúCûIúCûûúBúCC0090ûDúCìRûEúCDJonesûFúCI91 Any St.ûGúCûHúCûIúCûûúBúCC0091ûDúC ûEúCìÒûFúCI92 Any St.ûGúCûHúCûIúCûûúBúCC0092ûDúCìXûEúCìÒûFúCI93 Any St.ûGúCûHúCûIúCûûúBúCC0093ûDúCûEúCìÒûFúCI94 Any St.ûGúCûHúCûIúCûûúBúCC0094ûDúCìAûEúCìÒûFúCI95 Any St.ûGúCûHúCûIúCûûúBúCC0095ûDúCìDûEúCìÒûFúCI96 Any St.ûGúCûHúCûIúCûûúBúCC0096ûDúCìGûEúCìÒûFúCI97 Any St.ûGúCûHúCûIúCûûúBúCC0097ûDúCûEúCìÒûFúCI98 Any St.ûGúCûHúCûIúCûûúBúCC0098ûDúCìLûEúCìÒûFúCI99 Any St.ûGúCûHúCûIúCûûúBúCC0099ûDúCìOûEúCìÒûFúCJ100 Any St.ûGúCûHúCûIúCûûùûû \ No newline at end of file
diff --git a/1.9.10/samples-smile/json-org-sample1.smile b/1.9.10/samples-smile/json-org-sample1.smile new file mode 100644 index 0000000..b3d2f57 --- /dev/null +++ b/1.9.10/samples-smile/json-org-sample1.smile
@@ -0,0 +1,2 @@ +:) +úglossaryútitleOexample glossaryGlossDivúA@SGlossListúGlossEntryúIDCSGML SortAsGlossTermcStandard Generalized Markup LanguageAcronym AbbrevLISO 8879:1986GlossDefúparaàA meta-markup language, used to create markup languages such as DocBook.üGlossSeeAlsoøBGMLBXMLùûGlossSeeEmarkupûûûûû \ No newline at end of file
diff --git a/1.9.10/samples-smile/json-org-sample2.smile b/1.9.10/samples-smile/json-org-sample2.smile new file mode 100644 index 0000000..778d834 --- /dev/null +++ b/1.9.10/samples-smile/json-org-sample2.smile
@@ -0,0 +1,2 @@ +:) +úmenuúidCfilevalueCFilepopupúmenuitemøúBBNewonclickMCreateNewDoc()ûúBCOpenEHOpenDoc()ûúBDCloseEICloseDoc()ûùûûû \ No newline at end of file
diff --git a/1.9.10/samples-smile/json-org-sample3.smile b/1.9.10/samples-smile/json-org-sample3.smile new file mode 100644 index 0000000..a4af3cc --- /dev/null +++ b/1.9.10/samples-smile/json-org-sample3.smile
@@ -0,0 +1,2 @@ +:) +ú widgetúdebugAon windowútitleYSample Konfabulator WidgetnameJmain_windowwidth$¨ height$¨ûimageúsrcMImages/Sun.pngDCsun1hOffset$´vOffset$´alignmentEcenterûtextúdataIClick Heresize$styleCboldDDtext1I$´J$KonMouseUphsun1.opacity = (sun1.opacity / 100) * 90;ûûû \ No newline at end of file
diff --git a/1.9.10/samples-smile/json-org-sample4.smile b/1.9.10/samples-smile/json-org-sample4.smile new file mode 100644 index 0000000..f37686e --- /dev/null +++ b/1.9.10/samples-smile/json-org-sample4.smile
@@ -0,0 +1,2 @@ +:) +úweb-appúservletøúservlet-nameGcofaxCDSservlet-classWorg.cofax.cds.CDSServletinit-paramúconfigGlossary:installationAtOPhiladelphia, PAconfigGlossary:adminEmailLksm@pobox.comconfigGlossary:poweredByDCofaxconfigGlossary:poweredByIconP/images/cofax.gifconfigGlossary:staticPathN/content/statictemplateProcessorClassXorg.cofax.WysiwygTemplatetemplateLoaderClass\org.cofax.FilesTemplateLoadertemplatePathHtemplatestemplateOverridePath defaultListTemplateOlistTemplate.htmdefaultFileTemplateRarticleTemplate.htm useJSP"jspListTemplateOlistTemplate.jspjspFileTemplateRarticleTemplate.jspcachePackageTagsTrack$cachePackageTagsStore$cachePackageTagsRefresh$¸cacheTemplatesTrack$cacheTemplatesStore$¤cacheTemplatesRefreshÞcachePagesTrack$cachePagesStore$cachePagesRefreshÔcachePagesDirtyReadÔsearchEngineListTemplateWforSearchEnginesList.htmsearchEngineFileTemplateSforSearchEngines.htmsearchEngineRobotsDbPWEB-INF/robots.dbuseDataStore#dataStoreClassUorg.cofax.SqlDataStoreredirectionClassWorg.cofax.SqlRedirectiondataStoreNameDcofaxdataStoreDriverkcom.microsoft.jdbc.sqlserver.SQLServerDriverdataStoreUrlzjdbc:microsoft:sqlserver://LOCALHOST:1433;DatabaseName=goondataStoreUserAsadataStorePasswordQdataStoreTestQuerydataStoreTestQueryaSET NOCOUNT ON;select test='test';dataStoreLogFilec/usr/local/tomcat/logs/datastore.logdataStoreInitConnsÔdataStoreMaxConns$dataStoreConnUsageLimit$dataStoreLogLevelDdebugmaxUrlLength$¨ûûúBIcofaxEmailCYorg.cofax.cds.EmailServletDúmailHostDmail1mailHostOverrideDmail2ûûúBIcofaxAdminCYorg.cofax.cds.AdminServletûúBJfileServletCXorg.cofax.cds.FileServletûúBIcofaxToolsC^org.cofax.cms.CofaxToolsServletDúLNtoolstemplates/logÂlogLocationd/usr/local/tomcat/logs/CofaxTools.loglogMaxSize dataLogÂdataLogLocationa/usr/local/tomcat/logs/dataLog.logdataLogMaxSize removePageCached/content/admin/remove?cache=pages&id=removeTemplateCacheh/content/admin/remove?cache=templates&id=fileTransferFolders/usr/local/tomcat/webapps/content/fileTransferFolderlookInContextÂadminGroupIDÈbetaServer#ûûùservlet-mappingúcofaxCDS@/cofaxEmailR/cofaxutil/aemail/*cofaxAdminG/admin/*fileServletH/static/*cofaxToolsG/tools/*û taglibútaglib-uriHcofax.tldtaglib-locationV/WEB-INF/tlds/cofax.tldûûû \ No newline at end of file
diff --git a/1.9.10/samples-smile/json-org-sample5.smile b/1.9.10/samples-smile/json-org-sample5.smile new file mode 100644 index 0000000..aa5c4fc --- /dev/null +++ b/1.9.10/samples-smile/json-org-sample5.smile
@@ -0,0 +1,2 @@ +:) +úmenuú headerISVG VieweritemsøúidCOpenûúCFOpenNewlabelGOpen Newû!úCEZoomInDFZoom InûúCFZoomOutDGZoom OutûúCKOriginalViewDLOriginal Viewû!úCFQualityûúCDPauseûúCCMuteû!úCCFindDFFind...ûúCHFindAgainDIFind AgainûúCCCopyûúCHCopyAgainDICopy AgainûúCFCopySVGDGCopy SVGûúCFViewSVGDGView SVGûúCIViewSourceDJView SourceûúCESaveAsDFSave Asû!úCCHelpûúCDAboutDXAbout Adobe CVG Viewer...ûùûû \ No newline at end of file
diff --git a/1.9.10/samples-smile/map-spam.xml.smile b/1.9.10/samples-smile/map-spam.xml.smile new file mode 100644 index 0000000..6c96a71 --- /dev/null +++ b/1.9.10/samples-smile/map-spam.xml.smile
@@ -0,0 +1,89 @@ +:) +úsvgú@údefsúfontøúfont-faceú@idESymbol@font-variantEnormal@font-weightB400 @xmlnsúxlink[http://www.w3.org/1999/xlink$Yhttp://www.w3.org/2000/svgûûmissing-glyphú@horiz-adv-xB500@diM63 0V800H438V0H63ZM125 63H375V738H125V63ZGúHIûûglyphúpathúLàM51 3688l0 5 -40 20 40 19 0 5 -48 -23 0 -3 48 -23zm-48 55l48 0 0 5 -48 0 0 -5züGúHIûû@unicodeB163GúHIûûDFFontID5KC1000GúHIûûúCúDNHumnst777_Lt_BTE@font-styleEitalicFGúHIûûJúKLGúHIûûMøúNúL\M5 3698l41 0 -2 9 -41 0 2 -9zGúHIûûOA45GúHIûûúNúLàM15 3632l54 0 0 10 -43 -1 0 42 41 0 0 10 -41 0 0 55 -11 0 0 -116züGúHIûûOA70GúHIûûúNúLàM15 3632l17 0 39 95c0,2 1,3 1,5 1,2 1,4 1,6 1,-2 1,-4 1,-5 1,-2 1,-3 2,-5l41 -96 16 0 0 116 -10 0 0 -98c0,0 -1,0 -1,-1 0,-1 0,-1 0,-2 0,-1 0,-2 1,-3 0,-1 0,-2 0,-4 -1,3 -2,6 -3,8 0,1 0,1 0,1l-42 99 -10 0 -41 -99c0,-1 -1,-3 -2,-6 0,-1 0,-2 0,-3 0,2 0,4 0,7 0,2 0,3 0,3l0 98 -10 0 0 -116züGúHIûûOA77GúHIûûúNúLàM101 3677c0,-12 -3,-21 -9,-28 -6,-6 -14,-10 -24,-10 -6,0 -12,2 -18,5 -6,2 -11,7 -15,12 -5,6 -9,13 -11,21 -3,8 -5,17 -5,25 0,12 3,21 9,28 6,7 14,10 24,10 7,0 13,-1 19,-4 6,-3 11,-8 16,-15 4,-5 8,-12 10,-20 3,-8 4,-16 4,-24zm-32 -47c13,0 24,4 32,13 8,8 11,19 11,33 0,8 -1,16 -3,24 -2,8 -5,15 -9,21 -6,9 -13,17 -21,22 -8,5 -17,7 -27,7 -14,0 -24,-4 -32,-13 -8,-9 -12,-20 -12,-35 0,-10 2,-20 5,-30 4,-10 10,-18 16,-25 5,-5 11,-9 18,-12 7,-3 14,-5 22,-5züGúHIûûOA79GúHIûûúNúLàM68 3642l-39 65 50 0 -11 -65zm-4 -10l12 0 23 116 -11 0 -7 -31 -58 0 -19 31 -12 0 72 -116züGúHIûûOA65GúHIûûúNúLàM26 3642l0 47 12 0c9,0 16,-2 21,-7 6,-4 8,-10 8,-17 0,-7 -2,-13 -7,-17 -5,-4 -11,-6 -19,-6l-15 0zm-11 -10l25 0c12,0 22,3 29,9 6,5 10,13 10,24 0,10 -4,19 -11,25 -7,5 -17,8 -30,8l-12 0 0 50 -11 0 0 -116züGúHIûûOA80GúHIûûúNúLàM44 3672c-8,0 -13,3 -18,9 -4,6 -6,14 -6,24 0,11 2,19 6,25 5,6 11,9 18,9 8,0 14,-3 18,-9 5,-6 7,-14 7,-24 0,-11 -2,-19 -7,-25 -4,-6 -10,-9 -18,-9zm26 9l0 -16 10 0 0 74c0,15 -3,27 -10,34 -6,8 -15,12 -28,12 -4,0 -9,-1 -14,-2 -4,0 -8,-2 -12,-3l1 -11c4,2 8,4 12,5 4,1 9,1 13,1 9,0 16,-3 21,-9 5,-6 7,-14 7,-25l0 -11c-3,6 -7,11 -12,14 -4,3 -10,4 -16,4 -10,0 -18,-4 -24,-11 -6,-8 -9,-18 -9,-31 0,-13 3,-24 9,-31 6,-8 14,-12 25,-12 6,0 11,2 16,5 5,3 9,7 11,13züGúHIûûOB103GúHIûûúNúLàM15 3624l10 0 0 73 37 -32 13 0 -40 35 45 48 -14 0 -41 -44 0 44 -10 0 0 -124züGúHIûûOB107GúHIûûúNúLàM46 3672c-8,0 -14,3 -19,9 -5,7 -8,15 -8,25 0,11 3,19 8,25 5,7 11,10 19,10 9,0 15,-3 20,-10 5,-6 8,-14 8,-25 0,-10 -3,-18 -8,-25 -4,-6 -11,-9 -20,-9zm0 -9c12,0 22,4 29,12 6,8 10,18 10,31 0,14 -4,24 -10,32 -7,8 -17,12 -29,12 -11,0 -21,-4 -28,-12 -7,-8 -10,-18 -10,-31 0,-14 3,-24 10,-32 7,-8 17,-12 28,-12züGúHIûûOB111GúHIûûúNúLàM67 3698c0,-8 -2,-14 -6,-18 -4,-5 -9,-8 -16,-8 -3,1 -6,1 -9,2 -3,2 -6,4 -8,6 -4,4 -7,10 -10,16 -2,7 -4,14 -4,21 0,7 2,13 6,18 4,4 9,6 15,6 5,0 9,-1 13,-4 4,-3 8,-7 11,-12 3,-3 4,-8 6,-12 1,-5 2,-10 2,-15zm17 -74l10 0 -26 124 -9 0 2 -14c-4,5 -8,9 -13,12 -5,3 -10,4 -15,4 -9,0 -17,-3 -22,-9 -5,-6 -8,-14 -8,-25 0,-5 1,-11 3,-17 1,-6 4,-11 7,-16 4,-7 8,-11 14,-15 5,-3 11,-5 17,-5 7,0 13,2 18,5 4,3 8,8 10,14l12 -58züGúHIûûOB100GúHIûûúNúLàM77 3702l0 6 -59 0c0,11 3,19 8,25 6,5 13,8 22,8 4,0 8,-1 11,-2 4,-1 8,-2 11,-4l0 10c-3,2 -7,3 -11,4 -4,1 -8,1 -12,1 -12,0 -22,-4 -29,-12 -7,-7 -10,-18 -10,-32 0,-13 3,-23 10,-31 7,-8 16,-12 27,-12 9,0 17,4 23,11 6,7 9,16 9,28zm-10 -1c-1,-10 -3,-17 -7,-22 -4,-5 -10,-7 -17,-7 -6,0 -12,2 -17,8 -4,5 -7,12 -8,21l49 0züGúHIûûOB101GúHIûûúNúLàM15 3624l10 0 0 55c3,-5 7,-9 11,-12 5,-2 10,-4 17,-4 9,0 15,3 20,9 5,6 7,14 7,25l0 51 -10 0 0 -48c0,-10 -2,-16 -5,-21 -3,-4 -8,-6 -15,-6 -8,0 -14,2 -18,8 -5,6 -7,14 -7,24l0 43 -10 0 0 -124züGúHIûûOB104GúHIûûúNúLàM69 3668l-1 10c-2,-1 -5,-3 -8,-3 -3,-1 -7,-1 -10,-1 -9,0 -17,3 -22,9 -6,6 -9,14 -9,23 0,11 3,19 8,24 6,6 13,9 22,9 3,0 6,0 9,-1 4,-1 7,-2 11,-3l1 10c-4,1 -7,2 -11,3 -3,1 -7,1 -11,1 -12,0 -22,-4 -29,-12 -7,-7 -11,-18 -11,-31 0,-12 4,-22 12,-30 7,-8 18,-12 30,-12 4,0 7,1 10,1 3,1 6,1 9,3züGúHIûûOA99GúHIûûúNúL|M14 3665l10 0 0 83 -10 0 0 -83zm-1 -39l12 0 0 14 -12 0 0 -14zGúHIûûOB105GúHIûûúNúLàM80 3697l0 51 -10 0 0 -48c0,-10 -2,-16 -5,-21 -3,-4 -8,-6 -15,-6 -8,0 -14,2 -18,8 -5,6 -7,14 -7,24l0 43 -10 0 0 -83 9 0 0 16c3,-6 7,-11 12,-13 5,-3 10,-5 17,-5 9,0 15,3 20,9 5,6 7,14 7,25züGúHIûûOB110GúHIûûúNúLàM48 3706c-10,0 -17,1 -22,5 -6,3 -8,8 -8,14 0,4 1,8 4,11 3,3 8,5 13,5 7,0 13,-3 18,-8 5,-5 7,-11 7,-20l0 -7 -12 0zm22 -11l0 53 -9 0 0 -14c-3,5 -7,9 -12,11 -4,3 -10,4 -16,4 -8,0 -14,-2 -19,-6 -5,-5 -7,-10 -7,-18 0,-9 4,-15 11,-20 7,-5 18,-8 31,-8l11 0c0,0 0,0 0,-1 0,-1 0,-1 0,-1 0,-7 -2,-13 -5,-17 -4,-4 -8,-6 -14,-6 -5,0 -9,1 -13,2 -4,1 -7,3 -11,5l0 -10c4,-2 8,-3 12,-4 4,-1 9,-2 13,-2 9,0 16,3 21,8 5,5 7,13 7,24züGúHIûûOA97GúHIûûúNúL`M14 3624l10 0 0 124 -10 0 0 -124zGúHIûûOB108GúHIûûúNúLàM13 3665l10 0 0 48c0,9 2,16 5,20 3,5 8,7 15,7 8,0 14,-3 18,-9 5,-6 7,-15 7,-27l0 -39 10 0 0 83 -9 0 0 -16c-4,5 -7,10 -12,13 -5,3 -10,4 -17,4 -9,0 -16,-3 -20,-9 -5,-5 -7,-14 -7,-25l0 -50züGúHIûûOB117GúHIûûúNúLàM14 3665l61 0 -2 9 -64 66 51 0 -2 8 -64 0 2 -10 65 -65 -48 0 1 -8züGúHIûûOB122GúHIûûúNúLàM53 3664l0 11c-1,0 -2,0 -3,-1 -1,0 -2,0 -3,0 -7,0 -12,3 -16,8 -4,5 -6,13 -6,22l0 44 -10 0 0 -83 9 0 0 18c2,-6 5,-11 10,-14 4,-3 9,-5 14,-5 1,0 2,0 2,0 1,0 2,0 3,0züGúHIûûOB114GúHIûûúNúLàM61 3667l-3 10c-3,-2 -6,-3 -9,-4 -3,-1 -6,-1 -10,-1 -5,0 -10,1 -13,3 -4,2 -6,5 -6,9 0,4 5,9 14,15 3,2 5,4 6,5 5,3 8,6 10,10 2,3 3,7 3,11 0,8 -3,14 -9,18 -6,5 -14,7 -25,7 -4,0 -8,0 -12,-1 -4,-1 -8,-2 -12,-4l4 -10c3,2 7,3 10,4 4,1 8,2 12,2 6,0 11,-2 15,-4 4,-3 5,-7 5,-12 0,-3 0,-5 -2,-8 -2,-2 -5,-5 -11,-9 -1,-1 -1,-1 -1,-1 -12,-8 -17,-15 -17,-21 0,-7 3,-13 8,-17 5,-4 13,-6 22,-6 4,0 7,0 10,1 4,1 7,2 11,3züGúHIûûOB115GúHIûûúNúLàM32 3640l-1 25 20 0 0 9 -20 0 0 48c0,7 1,11 3,14 2,3 5,4 9,4 2,0 3,0 5,0 1,-1 2,-1 4,-2l0 10c-2,0 -4,1 -5,1 -2,0 -4,0 -6,0 -7,0 -12,-2 -15,-6 -3,-3 -5,-10 -5,-19l0 -50 -17 0 0 -9 17 0 0 -21 11 -4züGúHIûûOB116GúHIûûúNúLàM58 3705c-1,0 -2,0 -3,0 -1,0 -3,0 -6,0 -13,0 -23,2 -29,5 -6,3 -9,9 -9,16 0,4 2,8 5,10 3,3 6,5 11,5 9,0 16,-4 21,-10 5,-6 9,-15 10,-26zm11 -5l-5 26c-1,7 -2,12 -3,14 0,3 -1,6 -1,8l-9 0 2 -13c-4,5 -8,8 -13,11 -4,2 -9,3 -15,3 -7,0 -13,-2 -18,-6 -5,-4 -7,-10 -7,-17 0,-9 4,-17 12,-22 8,-5 19,-8 33,-8 2,0 4,0 6,1 2,0 5,0 8,0 1,-2 1,-4 1,-5 0,-1 0,-2 0,-3 0,-5 -1,-10 -4,-13 -3,-3 -8,-4 -14,-4 -3,0 -6,0 -10,1 -5,1 -9,3 -15,5l1 -11c6,-1 10,-3 14,-3 4,-1 8,-1 11,-1 9,0 15,2 20,6 5,5 7,11 7,19 0,1 0,3 0,5 0,2 -1,4 -1,7zm-13 -66l12 0 -3 14 -12 0 3 -14zm-26 0l11 0 -2 14 -12 0 3 -14züGúHIûûOB228GúHIûûùDFFontID1K +GúHIûûúCúDKHumnst777_BTEPFF400,700GúHIûûJúKLGúHIûûMøúNúLàM56 3723c-2,0 -4,1 -5,3 -1,1 -2,4 -2,7 0,4 1,6 2,8 1,2 3,3 5,3 2,0 4,-1 5,-3 2,-2 2,-4 2,-8 0,-3 0,-6 -2,-7 -1,-2 -3,-3 -5,-3zm0 -5c4,0 8,1 10,4 2,3 4,7 4,11 0,5 -2,9 -4,12 -2,3 -6,4 -10,4 -4,0 -7,-1 -10,-4 -2,-3 -3,-7 -3,-12 0,-4 1,-8 3,-11 3,-3 6,-4 10,-4zm-39 -24c-2,0 -4,1 -5,3 -2,2 -2,4 -2,8 0,3 0,6 2,7 1,2 3,3 5,3 2,0 3,-1 5,-3 1,-1 1,-4 1,-7 0,-4 0,-6 -1,-8 -2,-2 -3,-3 -5,-3zm32 -5l6 0 -31 60 -6 0 31 -60zm-32 0c4,0 7,1 9,4 3,3 4,7 4,12 0,4 -1,8 -4,11 -2,3 -5,4 -9,4 -4,0 -8,-1 -10,-4 -3,-3 -4,-6 -4,-11 0,-5 1,-9 4,-12 2,-3 6,-4 10,-4züGúHIûûOA37GúHIûûúNúL_M16 3699l5 0 -20 55 -5 0 20 -55zGúHIûûOA47GúHIûûúNúL[M4 3722l21 0 0 6 -21 0 0 -6zGúHIûûOGúHIûûúNúLàM2 3685l6 0c5,7 8,13 10,19 2,6 3,12 3,18 0,6 -1,12 -3,18 -2,6 -5,13 -10,19l-6 0c4,-7 7,-13 9,-19 2,-6 3,-12 3,-18 0,-6 -1,-12 -3,-18 -2,-6 -5,-12 -9,-19züGúHIûûOA41GúHIûûúNúLàM19 3685l6 0c-4,7 -7,13 -9,19 -2,6 -3,12 -3,18 0,6 1,12 3,18 2,6 5,12 9,19l-6 0c-5,-6 -8,-13 -10,-19 -2,-6 -3,-12 -3,-18 0,-6 1,-12 3,-18 2,-6 5,-13 10,-19züGúHIûûOA40GúHIûûúNúL\M9 3739l9 0 -7 19 -7 0 5 -19zGúHIûûOA44GúHIûûúNúLYM8 3739l8 0 0 9 -8 0 0 -9zGúHIûûOA46GúHIûûúNúLàM8 3690l32 0 0 6 -24 0 -1 16c2,0 3,0 4,0 2,0 3,-1 4,-1 6,0 11,2 14,5 4,3 5,8 5,13 0,6 -2,11 -6,14 -4,4 -9,6 -16,6 -3,0 -5,-1 -7,-1 -2,0 -4,-1 -6,-2l0 -7c2,1 4,2 6,2 2,1 4,1 7,1 4,0 8,-1 10,-3 3,-3 4,-6 4,-10 0,-3 -1,-6 -4,-8 -2,-2 -5,-3 -10,-3 -1,0 -3,0 -5,0 -2,0 -5,1 -7,2l0 -30züGúHIûûOA53GúHIûûúNúLnM5 3690l36 0 0 7 -22 51 -9 0 23 -51 -28 0 0 -7zGúHIûûOA55GúHIûûúNúLàM35 3708c0,-4 -1,-7 -3,-9 -2,-3 -5,-4 -8,-4 -3,0 -6,2 -8,4 -2,2 -3,6 -3,9 0,4 1,7 3,9 2,2 4,3 8,3 3,0 6,-1 8,-3 2,-2 3,-6 3,-9zm-28 39l1 -7c1,1 3,1 4,2 2,0 4,0 6,0 6,0 10,-2 13,-6 3,-3 5,-9 5,-17 -1,3 -3,5 -6,6 -2,1 -5,2 -8,2 -5,0 -9,-2 -12,-5 -4,-4 -5,-8 -5,-13 0,-6 2,-11 5,-14 4,-4 8,-6 14,-6 6,0 11,2 14,7 4,5 6,12 6,20 0,11 -3,19 -7,24 -4,6 -10,9 -18,9 -2,0 -4,0 -6,-1 -2,0 -4,-1 -6,-1züGúHIûûOA57GúHIûûúNúLrM8 3739l8 0 0 9 -8 0 0 -9zm0 -33l8 0 0 9 -8 0 0 -9zGúHIûûOA58GúHIûûúNúLàM28 3718c4,0 7,2 10,4 2,3 3,6 3,9 0,5 -2,10 -6,13 -4,3 -10,4 -17,4 -2,0 -5,0 -7,0 -3,0 -5,-1 -7,-2l1 -7c2,1 4,2 6,2 2,1 4,1 6,1 5,0 8,-1 11,-3 3,-2 4,-5 4,-8 0,-3 -1,-6 -3,-7 -2,-2 -6,-3 -10,-3l-6 0 0 -6 6 0c4,0 7,-1 10,-3 2,-2 3,-4 3,-7 0,-2 -1,-5 -3,-6 -3,-2 -6,-3 -9,-3 -2,0 -4,0 -6,1 -3,0 -5,1 -7,2l0 -7c2,-1 5,-1 7,-2 3,0 5,0 7,0 6,0 11,1 14,4 4,3 5,6 5,11 0,3 -1,6 -3,8 -2,2 -5,4 -9,5züGúHIûûOA51GúHIûûúNúLàM12 3743l22 0 0 5 -30 0 0 -6c9,-8 15,-15 18,-19 3,-4 4,-8 4,-11 0,-2 -1,-4 -2,-5 -2,-1 -4,-2 -7,-2 -2,0 -3,0 -5,1 -2,0 -4,1 -6,2l0 -6c2,-1 4,-2 6,-2 3,-1 5,-1 7,-1 4,0 7,1 10,4 3,2 4,5 4,9 0,4 -2,8 -5,12 -3,5 -8,11 -16,19züGúHIûûOA50GúHIûûúNúLàM30 3697l-21 32 21 0 0 -32zm-2 -7l9 0 0 39 9 0 0 6 -9 0 0 13 -7 0 0 -13 -28 0 0 -7 26 -38züGúHIûûOA52GúHIûûúNúLàM25 3718c-3,0 -6,1 -8,3 -2,3 -3,6 -3,9 0,4 1,7 3,9 2,3 5,4 8,4 3,0 6,-1 8,-4 2,-2 3,-5 3,-9 0,-4 -1,-7 -3,-9 -2,-2 -5,-3 -8,-3zm17 -27l-1 7c-1,-1 -3,-1 -4,-2 -2,0 -4,0 -6,0 -6,0 -10,2 -13,6 -3,4 -5,9 -5,17 1,-3 3,-4 6,-6 2,-1 5,-2 8,-2 5,0 9,2 12,5 4,4 5,8 5,13 0,6 -2,11 -5,14 -4,4 -8,6 -14,6 -6,0 -11,-2 -15,-7 -3,-5 -5,-11 -5,-20 0,-11 2,-18 7,-24 4,-6 10,-9 18,-9 2,0 4,1 6,1 2,0 4,1 6,1züGúHIûûOA54GúHIûûúNúLàM24 3715c4,-1 6,-3 8,-5 1,-2 2,-4 2,-7 0,-2 -1,-4 -2,-6 -2,-1 -5,-2 -7,-2 -4,0 -6,1 -8,2 -2,2 -3,4 -3,7 0,2 1,4 2,6 2,2 5,4 8,5zm-1 6c-4,1 -6,3 -8,5 -2,2 -3,4 -3,6 0,3 1,6 3,8 3,2 5,3 9,3 3,0 6,-1 8,-3 2,-2 4,-4 4,-7 0,-3 -1,-5 -3,-7 -2,-2 -6,-4 -10,-5zm8 -3c4,1 7,3 10,6 2,2 3,5 3,9 0,5 -2,9 -6,12 -3,3 -8,4 -14,4 -6,0 -11,-2 -15,-5 -3,-3 -5,-6 -5,-11 0,-4 1,-7 3,-9 3,-3 6,-5 10,-6 -3,-2 -6,-4 -8,-6 -2,-3 -3,-6 -3,-9 0,-4 2,-7 5,-10 4,-3 8,-4 14,-4 5,0 9,1 12,4 3,2 5,6 5,10 0,3 -1,6 -3,8 -2,3 -5,5 -8,7züGúHIûûOA56GúHIûûúNúLàM24 3695c-4,0 -7,2 -9,6 -2,4 -3,10 -3,18 0,8 1,14 3,18 2,4 5,6 9,6 4,0 7,-2 8,-6 2,-4 3,-10 3,-18 0,-8 -1,-14 -2,-18 -2,-4 -5,-6 -9,-6zm0 -6c6,0 11,3 15,8 3,5 5,12 5,22 0,10 -2,17 -5,22 -4,6 -9,8 -15,8 -6,0 -11,-2 -15,-8 -3,-5 -5,-12 -5,-22 0,-10 2,-17 5,-22 4,-5 9,-8 15,-8züGúHIûûOA48GúHIûûúNúLnM23 3690l7 0 0 58 -8 0 0 -49 -9 8 -4 -5 14 -12zGúHIûûOA49GúH[http://www.w3.org/1999/xlinkIûûúNúLàM7 3690l8 0 0 25 27 0 0 -25 8 0 0 58 -8 0 0 -27 -27 0 0 27 -8 0 0 -58züGúHìAIûûOA72GúHìAIûûúNúLàM6 3700l8 0 21 37c1,1 1,2 1,3 1,1 1,2 2,4 -1,-2 -1,-4 -1,-5 0,-1 0,-3 0,-4l0 -35 6 0 0 48 -8 0 -22 -38c0,0 0,-1 -1,-2 0,-1 0,-3 -1,-4 1,2 1,4 1,6 0,1 0,2 0,3l0 35 -6 0 0 -48züGúHìAIûûOA78GúHìAIûûúNúLàM13 3705l0 37 5 0c6,0 11,-1 14,-5 4,-3 5,-7 5,-13 0,-6 -1,-11 -5,-14 -3,-3 -7,-5 -14,-5l-5 0zm-7 -5l11 0c9,0 16,2 21,6 4,4 6,10 6,18 0,8 -2,14 -7,18 -4,4 -11,6 -20,6l-11 0 0 -48züGúHìAIûûOA68GúHìAIûûúNúLàM10 3671l41 0 0 8 -31 0 0 25 30 0 0 8 -30 0 0 27 32 0 0 9 -42 0 0 -77züGúHìAIûûOA69GúHìAIûûúNúLàM28 3697l-11 30 22 0 -11 -30zm-5 -7l10 0 23 58 -9 0 -5 -15 -28 0 -5 15 -9 0 23 -58züGúHìAIûûOA65GúHìAIûûúNúLàM41 3702l-1 5c-2,0 -3,-1 -5,-1 -2,-1 -4,-1 -6,-1 -5,0 -10,2 -13,5 -4,4 -5,8 -5,14 0,6 1,10 5,14 3,3 8,5 14,5 1,0 3,-1 5,-1 2,0 3,-1 5,-2l0 6c-1,1 -3,1 -5,2 -2,0 -4,0 -6,0 -8,0 -14,-2 -19,-6 -4,-5 -7,-10 -7,-18 0,-7 3,-13 7,-18 5,-4 11,-6 19,-6 2,0 4,0 6,0 2,0 4,1 6,2züGúHìAIûûOA67GúHìAIûûúNúL[M6 3700l7 0 0 48 -7 0 0 -48zGúHìAIûûOA73GúHìAIûûúNúLàM29 3705l0 29 11 0c6,0 11,-1 15,-4 3,-2 5,-6 5,-11 0,-4 -2,-8 -5,-10 -3,-3 -8,-4 -14,-4l-12 0zm0 -40l0 27 9 0c7,0 11,-1 15,-4 3,-2 5,-5 5,-9 0,-5 -2,-8 -5,-10 -3,-3 -8,-4 -13,-4l-11 0zm-18 -13l32 0c11,0 19,2 25,6 6,4 9,10 9,19 0,5 -2,9 -5,13 -3,4 -8,6 -13,8 6,1 11,4 15,8 3,4 5,9 5,15 0,9 -3,16 -9,20 -7,5 -16,7 -28,7l-31 0 0 -96züGúHìAIûûOA66GúHìAIûûúNúLeM7 3690l8 0 0 51 23 0 0 7 -31 0 0 -58zGúHìAIûûOA76GúHìAIûûúNúLàM6 3700l7 0 0 21 20 -21 8 0 -22 22 24 26 -9 0 -21 -24 0 24 -7 0 0 -48züGúHìAIûûOA75GúHìAIûûúNúLàM7 3690l12 0 18 45c0,1 0,2 0,3 1,2 1,3 1,4 0,-1 0,-3 1,-4 0,-2 0,-2 0,-3l18 -45 12 0 0 58 -8 0 0 -45c0,-2 0,-3 0,-5 1,-1 1,-3 1,-4 0,1 -1,3 -1,4 -1,1 -1,2 -1,4l-19 46 -7 0 -18 -47c-1,-1 -1,-2 -1,-3 0,-1 -1,-3 -1,-4 0,2 0,4 0,6 0,1 0,2 0,3l0 45 -7 0 0 -58züGúHìAIûûOA77GúHìAIûûúNúLàM51 3693l-1 7c-2,-2 -4,-2 -7,-3 -2,0 -5,-1 -7,-1 -7,0 -13,2 -17,7 -4,4 -6,9 -6,16 0,7 2,13 6,17 4,4 10,6 17,6 2,0 3,0 5,-1 1,0 3,0 4,-1l0 -17 -12 0 0 -7 20 0 0 29c-3,1 -5,2 -8,2 -3,1 -6,1 -10,1 -9,0 -17,-2 -22,-8 -6,-5 -9,-12 -9,-21 0,-9 3,-16 9,-21 5,-5 13,-8 22,-8 3,0 6,0 9,1 2,0 5,1 7,2züGúHìAIûûOA71GúHìAIûûúNúLàM42 3747l12 12 -9 0 -11 -10c-1,0 -1,0 -2,0 0,0 -1,0 -1,0 -8,0 -15,-3 -20,-8 -4,-5 -7,-13 -7,-22 0,-9 3,-17 7,-22 5,-5 11,-8 20,-8 8,0 14,3 19,8 4,5 7,13 7,22 0,7 -2,13 -4,17 -3,5 -6,8 -11,11zm-11 -51c-6,0 -10,2 -13,6 -4,4 -5,10 -5,17 0,7 1,13 5,17 3,4 7,6 13,6 5,0 9,-2 12,-6 4,-4 5,-10 5,-17 0,-7 -1,-13 -5,-17 -3,-4 -7,-6 -12,-6züGúHìAIûûOA81GúHìAIûûúNúLàM1 3700l7 0 9 38c0,1 1,1 1,2 0,1 0,3 0,4 0,-1 0,-2 0,-3 1,-1 1,-2 1,-2l10 -39 9 0 9 39c1,0 1,1 1,2 0,1 0,2 0,3 0,-1 0,-2 1,-3 0,-1 0,-2 0,-2l10 -39 6 0 -13 48 -8 0 -10 -39c-1,-1 -1,-2 -1,-3 0,-1 0,-2 0,-3 0,2 0,4 -1,4 0,1 0,2 0,2l-10 39 -8 0 -13 -48züGúHìAIûûOA87GúHìAIûûúNúLàM6 3700l6 0 0 28c0,5 1,9 3,12 2,2 5,3 9,3 4,0 6,-1 8,-4 2,-2 3,-6 3,-11l0 -28 7 0 0 28c0,7 -2,12 -5,16 -3,3 -7,5 -14,5 -5,0 -10,-2 -13,-5 -3,-4 -4,-9 -4,-16l0 -28züGúHìAIûûOA85GúHìAIûûúNúLàM13 3705l0 16 5 0c3,0 6,0 8,-2 2,-1 3,-3 3,-6 0,-3 -1,-5 -3,-6 -2,-1 -5,-2 -8,-2l-5 0zm-7 -5l13 0c5,0 10,1 12,3 3,2 5,5 5,9 0,3 -1,6 -3,8 -2,2 -5,3 -8,4 1,0 3,1 4,2 0,1 1,2 2,5l8 17 -8 0 -6 -16c-1,-2 -2,-3 -3,-4 -1,-1 -3,-1 -5,-1l-4 0 0 21 -7 0 0 -48züGúHìAIûûOA82GúHìAIûûúNúLqM1 3690l40 0 0 7 -16 0 0 51 -8 0 0 -51 -16 0 0 -7zGúHìAIûûOA84GúHìAIûûúNúLàM15 3696l0 22 6 0c4,0 7,-1 9,-3 3,-2 4,-4 4,-8 0,-3 -1,-6 -3,-8 -2,-2 -5,-3 -9,-3l-7 0zm-8 -6l15 0c6,0 12,2 15,4 4,3 5,8 5,13 0,6 -2,10 -5,13 -4,3 -9,4 -16,4l-6 0 0 24 -8 0 0 -58züGúHìAIûûOA80GúHìAIûûúNúLàM37 3692l-1 7c-2,-1 -3,-2 -5,-2 -2,-1 -4,-1 -6,-1 -4,0 -6,1 -8,2 -2,1 -3,3 -3,5 0,2 0,4 2,5 1,2 4,4 8,6 6,3 10,6 12,9 2,2 3,5 3,9 0,5 -2,9 -5,12 -4,3 -8,4 -14,4 -3,0 -5,0 -8,0 -2,-1 -5,-1 -7,-2l1 -8c2,1 5,2 7,3 2,0 4,1 6,1 4,0 7,-1 9,-3 2,-1 3,-3 3,-6 0,-3 -4,-8 -12,-12 -2,-1 -3,-2 -4,-2 -3,-2 -5,-4 -7,-7 -2,-2 -2,-5 -2,-8 0,-4 1,-8 5,-10 3,-3 8,-4 14,-4 2,0 4,0 6,0 2,1 4,1 6,2züGúHìAIûûOA83GúHìAIûûúNúLpM1 3690l9 0 17 50 17 -50 8 0 -21 58 -9 0 -21 -58zGúHìAIûûOA86GúHìAIûûúNúL}M4 3690l37 0 0 7 -30 44 31 0 0 7 -39 0 0 -8 30 -43 -29 0 0 -7zGúHìAIûûOA90GúHìAIûûúNúLàM27 3711c-4,0 -7,2 -9,4 -2,3 -3,7 -3,12 0,5 1,8 3,11 2,3 5,4 8,4 4,0 6,-1 8,-4 3,-2 4,-6 4,-11 0,-5 -1,-9 -3,-12 -2,-2 -5,-4 -8,-4zm-20 -25l8 0 0 27c1,-3 3,-5 5,-6 3,-1 5,-2 8,-2 6,0 10,2 13,6 3,4 5,9 5,15 0,7 -2,12 -5,16 -3,5 -7,7 -13,7 -3,0 -6,-1 -8,-3 -2,-1 -4,-3 -6,-7l0 9 -7 0 0 -62züGúHìAIûûOA98GúHìAIûûúNúLàM40 3714c2,-3 4,-5 6,-6 3,-2 5,-3 8,-3 5,0 8,2 10,5 3,3 4,7 4,13l0 25 -8 0 0 -24c0,-4 -1,-7 -2,-9 -1,-2 -3,-3 -6,-3 -3,0 -6,1 -8,4 -2,3 -3,6 -3,11l0 21 -8 0 0 -24c0,-4 0,-7 -2,-9 -1,-2 -3,-3 -6,-3 -3,0 -6,1 -7,4 -2,3 -3,6 -3,11l0 21 -8 0 0 -42 7 0 0 8c2,-3 3,-5 6,-7 2,-1 5,-2 8,-2 3,0 5,1 7,3 3,1 4,3 5,6züGúHìAIûûOB109GúHìAIûûúNúLàM26 3727c-5,0 -9,1 -11,3 -3,1 -4,3 -4,6 0,2 1,4 2,5 2,1 3,2 6,2 3,0 6,-1 8,-3 2,-3 3,-6 3,-10l0 -3 -4 0zm12 -4l0 25 -7 0 0 -7c-2,3 -4,4 -6,6 -2,1 -5,2 -8,2 -4,0 -8,-2 -10,-4 -2,-2 -4,-5 -4,-9 0,-4 2,-8 6,-10 4,-3 9,-4 16,-4l5 0 0 -1c0,-3 0,-5 -2,-7 -2,-2 -5,-3 -8,-3 -2,0 -4,0 -6,1 -2,0 -4,1 -6,3l0 -7c2,-1 5,-2 7,-2 2,-1 5,-1 7,-1 6,0 9,2 12,5 3,2 4,7 4,13züGúHìAIûûOA97GúHìAIûûúNúLàM6 3696l6 0 0 31 14 -14 8 0 -16 15 17 20 -8 0 -15 -18 0 18 -6 0 0 -52züGúHìAIûûOB107GúHìAIûûúNúLàM7 3706l7 0 0 44c0,6 -1,10 -3,12 -1,3 -4,4 -9,4 0,0 -1,0 -2,0 -1,0 -2,-1 -3,-1l1 -5c0,0 1,0 1,0 1,0 1,0 2,0 2,0 3,-1 4,-2 1,-2 2,-4 2,-8l0 -44zm0 -19l7 0 0 8 -7 0 0 -8züGúHìAIûûOB106GúHìAIûûúNúLàM23 3711c-3,0 -6,2 -8,4 -2,3 -3,7 -3,12 0,4 1,8 3,11 2,2 5,4 8,4 4,0 7,-2 9,-4 2,-3 3,-7 3,-11 0,-5 -1,-9 -3,-12 -2,-2 -5,-4 -9,-4zm13 3l0 -8 7 0 0 37c0,8 -2,14 -5,18 -4,3 -9,5 -16,5 -2,0 -5,0 -7,0 -3,-1 -5,-1 -7,-2l1 -7c2,1 4,2 6,2 2,1 4,1 6,1 5,0 8,-1 11,-4 2,-3 3,-6 3,-11l0 -5c-1,2 -3,4 -6,6 -2,1 -5,2 -8,2 -5,0 -9,-2 -12,-6 -3,-4 -5,-9 -5,-15 0,-7 2,-12 5,-16 3,-4 7,-6 13,-6 3,0 6,1 8,2 2,2 4,4 6,7züGúHìAIûûOGúHìAIûûúNúLàM39 3665l0 8c-2,0 -3,0 -4,-1 0,0 -1,0 -2,0 -3,0 -5,1 -6,3 -2,2 -2,5 -2,9l0 8 13 0 0 8 -13 0 0 48 -11 0 0 -48 -11 0 0 -8 11 0 0 -9c0,-6 2,-11 5,-14 3,-3 7,-5 13,-5 1,0 2,0 3,0 1,0 3,1 4,1züGúHìAIûûOB102GúHìAIûûúNúLàM23 3711c-3,0 -6,2 -8,4 -2,3 -3,7 -3,12 0,5 1,8 3,11 2,3 5,4 8,4 4,0 7,-1 9,-4 2,-3 3,-6 3,-11 0,-5 -1,-9 -3,-12 -2,-2 -5,-4 -9,-4zm12 -25l8 0 0 62 -7 0 0 -9c-2,4 -4,6 -6,7 -3,2 -6,3 -9,3 -5,0 -9,-2 -12,-7 -3,-4 -5,-9 -5,-16 0,-6 1,-11 5,-15 3,-4 7,-6 12,-6 3,0 6,1 8,2 3,1 4,3 6,6l0 -27züGúHìAIûûOB100GúHìAIûûúNúLàM25 3711c-4,0 -7,2 -10,4 -2,3 -3,7 -3,12 0,5 1,9 3,11 3,3 6,5 10,5 3,0 6,-2 9,-4 2,-3 3,-7 3,-12 0,-5 -1,-9 -3,-12 -3,-2 -6,-4 -9,-4zm-1 -6c7,0 12,2 16,6 3,4 5,9 5,16 0,7 -2,12 -5,16 -4,4 -9,6 -16,6 -6,0 -11,-2 -15,-6 -3,-4 -5,-9 -5,-16 0,-7 2,-12 5,-16 4,-4 9,-6 15,-6züGúHìAIûûOGúHìAIûûúNúLàM7 3686l8 0 0 27c1,-3 3,-5 5,-6 3,-1 5,-2 9,-2 4,0 8,2 10,5 3,3 4,7 4,13l0 25 -8 0 0 -24c0,-4 -1,-7 -2,-9 -2,-2 -4,-3 -7,-3 -4,0 -6,1 -8,4 -2,2 -3,6 -3,11l0 21 -8 0 0 -62züGúHìAIûûOGúHìAIûûúNúLàM36 3708l-1 6c-1,0 -2,-1 -4,-1 -1,-1 -3,-1 -5,-1 -4,0 -7,1 -10,4 -3,3 -4,7 -4,11 0,5 1,8 4,11 2,3 6,4 10,4 2,0 3,0 5,-1 2,0 3,0 5,-1l0 7c-2,0 -3,1 -5,1 -2,0 -4,0 -6,0 -6,0 -12,-1 -15,-5 -4,-4 -6,-9 -6,-16 0,-6 2,-11 6,-15 4,-4 9,-6 16,-6 2,0 3,0 5,0 2,1 3,1 5,2züGúHìAIûûOA99GúHìAIûûúNúLtM7 3706l7 0 0 42 -7 0 0 -42zm0 -19l7 0 0 8 -7 0 0 -8zGúHìAIûûOGúHìAIûûúNúLàM43 3723l0 25 -8 0 0 -24c0,-4 -1,-7 -2,-9 -2,-2 -4,-3 -7,-3 -4,0 -6,1 -8,4 -2,2 -3,6 -3,11l0 21 -8 0 0 -42 7 0 0 8c2,-3 4,-5 6,-7 2,-1 5,-2 9,-2 4,0 8,2 10,5 3,3 4,7 4,13züGúHìAIûûOGúHìAIûûúNúL[M7 3686l7 0 0 62 -7 0 0 -62zGúHìAIûûOìGúHìAIûûúNúLàM41 3726l0 3 -30 0c1,4 2,8 5,10 2,3 6,4 10,4 2,0 4,0 6,-1 2,0 4,-1 6,-2l0 7c-2,0 -4,1 -7,1 -2,1 -4,1 -7,1 -6,0 -11,-2 -15,-6 -3,-4 -5,-9 -5,-16 0,-7 2,-12 5,-16 4,-4 8,-6 14,-6 6,0 10,2 13,6 3,3 5,8 5,15zm-7 -2c-1,-4 -2,-8 -4,-10 -1,-2 -4,-3 -7,-3 -3,0 -6,1 -8,3 -2,3 -3,6 -4,10l23 0züGúHìAIûûOGúHìAIûûúNúLàM1 3706l8 0 12 35 11 -35 8 0 -17 46c-2,5 -4,9 -6,11 -2,2 -5,3 -9,3 0,0 -1,0 -2,0 -1,0 -2,0 -3,0l1 -7c1,0 1,0 2,1 0,0 1,0 2,0 1,0 3,-1 5,-3 1,-1 2,-4 4,-7l-16 -44züGúHìAIûûOB121GúHìAIûûúNúLàM2 3706l9 0 9 15 9 -15 9 0 -13 20 14 22 -9 0 -10 -17 -11 17 -8 0 14 -22 -13 -20züGúHìAIûûOB120GúHìAIûûúNúLàM34 3723c0,-3 -1,-6 -2,-8 -2,-2 -5,-3 -8,-3 -3,0 -7,1 -10,5 -2,4 -4,9 -4,15 0,3 1,6 3,8 1,2 4,3 7,3 4,0 7,-2 10,-6 3,-4 4,-8 4,-14zm4 -17l8 0 -13 59 -7 0 5 -23c-2,3 -4,4 -6,5 -3,1 -5,2 -8,2 -5,0 -8,-2 -11,-5 -3,-3 -4,-7 -4,-13 0,-4 1,-7 2,-11 1,-3 3,-6 5,-9 2,-2 4,-3 7,-4 2,-1 4,-2 7,-2 4,0 6,1 9,3 2,1 4,4 4,7l2 -9züGúHìAIûûOB113GúHìAIûûúNúLàM6 3706l8 0 0 23c0,5 0,8 2,10 1,2 4,3 7,3 4,0 6,-2 8,-4 2,-3 3,-7 3,-13l0 -19 8 0 0 42 -7 0 0 -8c-2,3 -4,5 -6,6 -2,2 -5,3 -9,3 -4,0 -8,-2 -10,-5 -3,-3 -4,-7 -4,-13l0 -25züGúHìAIûûOì GúHìAIûûúNúLàM15 3741l0 24 -8 0 0 -59 7 0 0 8c2,-3 4,-5 6,-7 3,-1 6,-2 9,-2 5,0 9,2 12,6 3,4 5,9 5,15 0,7 -2,13 -5,17 -3,4 -7,6 -13,6 -3,0 -5,-1 -8,-2 -2,-1 -4,-3 -5,-6zm23 -14c0,-5 -1,-9 -3,-12 -2,-2 -5,-4 -8,-4 -4,0 -7,2 -9,5 -2,2 -3,6 -3,11 0,5 1,9 3,11 2,3 5,5 8,5 4,0 7,-2 9,-5 2,-3 3,-6 3,-11züGúHìAIûûOB112GúHìAIûûúNúL}M4 3706l31 0 0 7 -23 29 23 0 0 6 -32 0 0 -7 24 -29 -23 0 0 -6zGúHìAIûûOì!GúHìAIûûúNúLàM29 3706l0 7c-1,0 -1,0 -2,0 0,0 -1,0 -1,0 -4,0 -7,1 -8,3 -2,3 -3,6 -3,11l0 21 -8 0 0 -42 7 0 0 9c1,-3 3,-6 5,-7 2,-2 4,-3 7,-3 0,0 1,0 2,0 0,1 1,1 1,1züGúHìAIûûOì"GúHìAIûûúNúLpM1 3706l8 0 11 35 12 -35 7 0 -14 42 -9 0 -15 -42zGúHìAIûûOB118GúHìAIûûúNúLàM18 3693l0 13 10 0 0 6 -10 0 0 22c0,3 0,5 1,7 1,1 3,2 5,2 1,0 1,0 2,0 1,-1 1,-1 2,-1l0 6c-1,0 -2,0 -3,1 -1,0 -2,0 -3,0 -4,0 -7,-1 -9,-4 -2,-2 -3,-5 -3,-11l0 -22 -8 0 0 -6 9 0 0 -10 7 -3züGúHìAIûûOì$GúHìAIûûúNúLàM30 3707l0 7c-2,-1 -4,-2 -5,-2 -2,-1 -4,-1 -6,-1 -2,0 -4,1 -5,1 -1,1 -2,2 -2,4 0,1 1,2 2,3 1,1 3,3 6,4 5,2 8,4 9,6 2,2 3,4 3,7 0,4 -2,7 -5,9 -3,2 -7,3 -12,3 -2,0 -4,0 -6,0 -2,0 -3,-1 -5,-2l0 -6c2,1 4,2 6,2 2,1 4,1 5,1 3,0 5,-1 6,-2 2,-1 3,-2 3,-4 0,-2 -1,-3 -2,-4 -1,-1 -3,-2 -6,-4 -4,-2 -7,-4 -9,-6 -2,-2 -2,-4 -2,-6 0,-4 1,-6 4,-8 2,-2 6,-3 11,-3 1,0 3,0 5,0 2,0 3,1 5,1züGúHìAIûûOB115GúHìAIûûúNúLàM2 3692l11 0 12 43c0,0 0,1 0,2 0,2 1,3 1,5 0,-3 0,-4 1,-5 0,-1 0,-2 0,-2l12 -43 13 0 13 43c0,0 0,1 0,2 0,1 1,3 1,5 0,-2 0,-3 0,-5 1,-1 1,-2 1,-2l12 -43 11 0 -19 56 -11 0 -14 -44c0,-1 0,-2 0,-3 0,-1 0,-2 -1,-4 0,2 0,3 0,4 0,1 0,2 -1,3l-13 44 -12 0 -17 -56züGúHìAIûûOB119GúHìAIûûúNúLàM18 3708c0,-1 -1,-3 -2,-4 -1,-2 -3,-2 -5,-2 -1,0 -3,0 -4,2 -2,1 -2,3 -2,4 0,2 0,4 2,5 1,1 3,2 4,2 2,0 4,-1 5,-2 1,-1 2,-3 2,-5zm-7 -9c3,0 5,1 7,2 2,2 3,5 3,7 0,3 -1,5 -3,7 -2,2 -4,3 -7,3 -2,0 -5,-1 -7,-3 -1,-2 -2,-4 -2,-7 0,-2 1,-5 3,-7 1,-1 4,-2 6,-2züGúHìAIûûOB176GúHìAIûûúNúLàM34 3720c-6,0 -11,1 -14,3 -4,2 -5,5 -5,9 0,3 1,5 3,7 1,1 4,2 7,2 5,0 8,-1 11,-4 3,-3 5,-7 5,-12l0 -5 -7 0zm17 -6l0 34 -10 0 0 -9c-2,3 -5,6 -8,7 -3,2 -7,3 -11,3 -5,0 -9,-2 -13,-5 -3,-3 -5,-7 -5,-12 0,-6 3,-10 8,-14 5,-3 12,-4 21,-4l8 0 0 -2c0,-4 -2,-7 -4,-10 -3,-2 -6,-3 -10,-3 -3,0 -5,0 -8,1 -2,1 -5,2 -8,3l0 -8c3,-1 6,-2 9,-3 3,-1 6,-1 10,-1 7,0 12,2 15,6 4,4 6,9 6,17zm-17 -43l9 0 0 10 -9 0 0 -10zm-18 0l9 0 0 10 -9 0 0 -10züGúHìAIûûOì%GúHìAIûûúNúLàM8 3692l10 0 0 31c0,6 1,10 3,13 2,3 5,4 10,4 4,0 8,-2 11,-6 2,-3 4,-9 4,-16l0 -26 10 0 0 56 -10 0 0 -11c-2,4 -4,7 -7,9 -4,2 -7,3 -12,3 -6,0 -11,-2 -14,-6 -3,-4 -5,-10 -5,-18l0 -33zm29 -21l9 0 0 10 -9 0 0 -10zm-18 0l9 0 0 10 -9 0 0 -10züGúHìAIûûOB252GúHìAIûûúNúLàM43 3689c-5,0 -10,2 -13,6 -4,5 -5,10 -5,18 0,7 1,12 5,17 3,4 8,6 13,6 6,0 10,-2 14,-6 3,-5 5,-10 5,-17 0,-8 -2,-13 -5,-18 -4,-4 -8,-6 -14,-6zm0 -13c12,0 21,3 28,10 6,6 10,15 10,27 0,11 -4,20 -10,27 -7,7 -16,10 -28,10 -11,0 -21,-3 -27,-10 -7,-7 -10,-16 -10,-27 0,-12 3,-21 10,-27 6,-7 16,-10 27,-10zm5 -27l14 0 0 15 -14 0 0 -15zm-24 0l14 0 0 15 -14 0 0 -15züGúHìAIûûOB246GúHìAIûûùDFFontID0KC1000GúHìAIûûùstyleúIä + .str18 {stroke:#1F1A17;stroke-width:3} + .str7 {stroke:#0093DD;stroke-width:4;stroke-linejoin:round} + .str2 {stroke:#0093DD;stroke-width:4;stroke-linejoin:round} + .str11 {stroke:#1F1A17;stroke-width:4} + .str15 {stroke:#1F1A17;stroke-width:4;stroke-linejoin:round} + .str16 {stroke:#131516;stroke-width:4;stroke-linejoin:round} + .str13 {stroke:#1F1A17;stroke-width:4;stroke-linejoin:round} + .str6 {stroke:#0093DD;stroke-width:6;stroke-linejoin:round} + .str17 {stroke:#1F1A17;stroke-width:6} + .str9 {stroke:#131516;stroke-width:6;stroke-linejoin:round} + .str0 {stroke:#4E4B4A;stroke-width:6;stroke-linejoin:round} + .str5 {stroke:#0093DD;stroke-width:8;stroke-linejoin:round} + .str12 {stroke:#1F1A17;stroke-width:8} + .str14 {stroke:#131516;stroke-width:8;stroke-linejoin:round} + .str8 {stroke:#449285;stroke-width:8;stroke-linejoin:round} + .str4 {stroke:#0093DD;stroke-width:10;stroke-linejoin:round} + .str3 {stroke:#0093DD;stroke-width:12;stroke-linejoin:round} + .str10 {stroke:#131516;stroke-width:12;stroke-linejoin:round} + .str1 {stroke:#4E4B4A;stroke-width:12;stroke-linejoin:round} + .fil7 {fill:none} + .fil19 {fill:#0093DD} + .fil8 {fill:#1F1A17} + .fil20 {fill:#FFFFFF} + .fil9 {fill:#DA251D} + .fil18 {fill:#F1A400} + .fil16 {fill:#0096D4} + .fil13 {fill:#96C7EB} + .fil5 {fill:#C4E1F6} + .fil15 {fill:#E1553F} + .fil17 {fill:#E57A51} + .fil10 {fill:#EDF5D4} + .fil11 {fill:#EEA45C} + .fil14 {fill:#EFB289} + .fil12 {fill:#F5E0A0} + .fil6 {fill:#C3C3C2;fill-opacity:0.501961} + .fil4 {fill:#DA251D;fill-opacity:0.501961} + .fil3 {fill:#EC914F;fill-opacity:0.501961} + .fil1 {fill:#EECB97;fill-opacity:0.501961} + .fil2 {fill:#F4B770;fill-opacity:0.501961} + .fil0 {fill:#FFFEE3;fill-opacity:0.501961} + .fnt0 {font-weight:normal;font-size:69;font-family:FontID0, 'Humnst777 BT'} + .fnt42 {font-weight:normal;font-size:69;font-family:FontID34, 'Humnst777 BT'} + .fnt8 {font-weight:normal;font-size:69;font-family:FontID4, 'Humnst777 BT'} + .fnt41 {font-weight:normal;font-size:83;font-family:FontID34, 'Humnst777 BT'} + .fnt5 {font-weight:normal;font-size:83;font-family:FontID4, 'Humnst777 BT'} + .fnt17 {font-weight:normal;font-size:97;font-family:FontID10, 'Humnst777 BT'} + .fnt19 {font-weight:normal;font-size:97;font-family:FontID12, 'Humnst777 BT'} + .fnt21 {font-weight:normal;font-size:97;font-family:FontID14, 'Humnst777 BT'} + .fnt23 {font-weight:normal;font-size:97;font-family:FontID16, 'Humnst777 BT'} + .fnt25 {font-weight:normal;font-size:97;font-family:FontID18, 'Humnst777 BT'} + .fnt27 {font-weight:normal;font-size:97;font-family:FontID20, 'Humnst777 BT'} + .fnt29 {font-weight:normal;font-size:97;font-family:FontID22, 'Humnst777 BT'} + .fnt31 {font-weight:normal;font-size:97;font-family:FontID24, 'Humnst777 BT'} + .fnt33 {font-weight:normal;font-size:97;font-family:FontID26, 'Humnst777 BT'} + .fnt35 {font-weight:normal;font-size:97;font-family:FontID28, 'Humnst777 BT'} + .fnt37 {font-weight:normal;font-size:97;font-family:FontID30, 'Humnst777 BT'} + .fnt39 {font-weight:normal;font-size:97;font-family:FontID32, 'Humnst777 BT'} + .fnt13 {font-weight:normal;font-size:97;font-family:FontID6, 'Humnst777 BT'} + .fnt15 {font-weight:normal;font-size:97;font-family:FontID8, 'Humnst777 BT'} + .fnt18 {font-weight:normal;font-size:97;font-family:FontID11, Symbol} + .fnt20 {font-weight:normal;font-size:97;font-family:FontID13, Symbol} + .fnt22 {font-weight:normal;font-size:97;font-family:FontID15, Symbol} + .fnt24 {font-weight:normal;font-size:97;font-family:FontID17, Symbol} + .fnt26 {font-weight:normal;font-size:97;font-family:FontID19, Symbol} + .fnt28 {font-weight:normal;font-size:97;font-family:FontID21, Symbol} + .fnt30 {font-weight:normal;font-size:97;font-family:FontID23, Symbol} + .fnt32 {font-weight:normal;font-size:97;font-family:FontID25, Symbol} + .fnt34 {font-weight:normal;font-size:97;font-family:FontID27, Symbol} + .fnt36 {font-weight:normal;font-size:97;font-family:FontID29, Symbol} + .fnt38 {font-weight:normal;font-size:97;font-family:FontID31, Symbol} + .fnt40 {font-weight:normal;font-size:97;font-family:FontID33, Symbol} + .fnt12 {font-weight:normal;font-size:97;font-family:FontID5, Symbol} + .fnt14 {font-weight:normal;font-size:97;font-family:FontID7, Symbol} + .fnt16 {font-weight:normal;font-size:97;font-family:FontID9, Symbol} + .fnt3 {font-weight:normal;font-size:111;font-family:FontID2, 'Humnst777 BT'} + .fnt7 {font-weight:normal;font-size:111;font-family:FontID4, 'Humnst777 BT'} + .fnt2 {font-weight:normal;font-size:130;font-family:FontID2, 'Humnst777 BT'} + .fnt9 {font-weight:normal;font-size:130;font-family:FontID4, 'Humnst777 BT'} + .fnt11 {font-weight:bold;font-size:130;font-family:FontID4, 'Humnst777 BT'} + .fnt4 {font-weight:normal;font-size:167;font-family:FontID3, 'Humnst777 Lt BT'} + .fnt10 {font-weight:bold;font-size:222;font-family:FontID4, 'Humnst777 BT'} + .fnt6 {font-style:italic;font-weight:normal;font-size:83;font-family:FontID4, 'Humnst777 BT'} + .fnt1 {font-style:italic;font-weight:normal;font-size:167;font-family:FontID1, 'Humnst777 Lt BT'} + ü@typeGtext/cssGúHìAIûûGúHìAIûûgøúimageú@transformlmatrix(0.555102 0 0 0.555268 -5368.74 5205.7)@x@0@yD-8696 @widthD15792@heightD12444@xlink:hrefetests/resources/images/spainRelief.pngGúHìAIûûDEreliefGúHìAIûûúNøú @classCfil0LàM-1948 1100l87 -3 57 -27 23 7 33 53 60 13 10 77 14 7 30 -17 3 20 -30 17 57 36 -10 20 -20 -13 -80 50 13 43 -17 47 24 50 -4 23 -33 7 -13 20 10 33 26 0 44 184 46 3 24 20 -17 17 7 26 46 0 7 10 -13 27 13 17 53 -17 -3 20 -43 23 -10 27 -50 17 -4 26 27 47 -30 -3 -17 -24 -60 -3 -36 27 -47 -14 -20 20 -23 0 -17 -13 10 -27 -13 -13 -37 13 -33 -46 -27 -4 -33 34 -30 -7 -40 -63 -60 10 -10 -20 53 -107 -13 -43 -50 -10 16 -90 20 -4 10 -23 0 -13 -16 3 3 -23 37 -14 -10 -33 16 -67 -13 -13 23 -117 -33 -26 23 -30 0 -57 20 -7 37 -83 33 -20züGúHìAIûûú[ì|LàM199 1140l0 20 53 23 37 54 20 -7 10 -27 60 17 47 -37 60 40 23 -3 27 47 53 26 100 -40 43 10 24 30 33 -36 40 23 113 -10 17 -23 -20 -24 10 -63 23 -13 70 20 -73 103 7 47 36 16 -16 74 -20 10 30 60 6 63 -20 143 -30 97 -40 43 24 44 -144 153 20 53 44 4 10 33 -24 40 -30 10 0 50 -6 3 -50 -10 -7 14 -7 -4 -3 -3 -7 -3 -6 0 -4 0 -6 3 -7 0 -3 3 -7 4 -3 3 -4 7 -3 3 -7 3 -3 4 -3 6 -4 4 0 6 -3 7 0 7 -37 0 -6 -14 -7 0 0 14 -27 -10 -66 -164 -24 -3 -20 17 -63 -40 -10 -37 -73 -27 -7 -80 -77 -80 -60 0 -60 -30 30 -66 17 26 13 -10 -6 -130 16 -40 -6 -50 -7 -3 -10 10 0 17 -17 46 -33 -6 -13 26 -17 -6 53 -104 -46 -23 3 -60 -23 -3 16 -27 -16 -17 13 -20 -7 -36 17 -24 -17 -16 4 -27 30 -27 -4 -46 17 -47 50 -10züGúHìAIûûú[ì|LäM-3064 1633l40 34 36 -7 84 30 93 -13 53 43 97 -3 43 23 37 -17 20 27 43 -20 24 17 33 -17 43 67 34 -37 13 30 13 30 -10 23 20 7 10 -30 37 -17 47 47 -27 27 17 20 -14 63 7 3 -3 20 -30 24 0 23 23 37 0 50 30 10 -10 26 17 14 -4 23 -40 23 -3 4 17 43 -17 37 23 83 -26 47 26 6 -3 34 -20 13 -33 -17 -10 -36 -30 6 -7 24 -43 -54 -24 7 -26 -27 -67 17 -70 -17 -30 57 -10 3 -3 -10 -17 7 -10 -7 0 -30 -43 -3 -7 -7 -3 -3 -4 0 -6 7 -4 3 -6 0 -4 -3 -3 -4 -3 -6 -4 -7 0 -3 -6 -7 -4 -3 -3 -4 -7 0 -6 0 -4 -3 -3 -3 0 -7 0 -7 0 -6 0 -7 0 -3 -7 -7 -3 -3 -7 0 -3 3 -3 7 -4 3 -3 7 -7 3 -3 3 -7 4 -3 0 -7 0 -3 -4 -7 -3 -6 0 -4 0 -6 0 -7 -3 -7 0 -3 0 -7 0 -6 0 -7 0 -10 0 7 -7 3 -3 7 -4 3 -3 7 -3 3 -4 7 -3 3 -3 3 -7 4 -3 3 -7 0 -3 3 -7 4 -3 3 -7 3 0 7 0 7 0 6 -3 4 -4 3 -3 0 -7 0 -6 3 -7 0 -3 4 -7 3 -3 3 -7 4 -3 3 -7 3 -3 0 -7 4 -3 3 -7 3 -3 4 -7 3 -3 3 -7 4 -3 3 -7 3 -3 4 -4 3 -6 7 -4 10 -16 -84 -67 -50 -7 -36 17 -24 -20 -6 -47 30 -86 -30 -14 10 -40 -17 -20 -20 20 -53 0 -30 -26 -10 -14 -27 30 -50 0 -30 -20 13 -46 -20 -17 0 -23 30 -27 10 -33 40 -34 34 10 10 -30m530 317l-4 7 -3 3 -3 7 -4 3 -6 0 -4 0 -3 7 -3 3 0 7 0 6 3 7 3 3 4 7 0 3 0 7 0 7 -4 6 -3 4 -3 3 -4 3 -6 4 -4 6 -3 4 -3 6 0 4 -7 3 -3 7 -7 0 -3 0 -4 3 -3 7 0 6 0 7 0 7 -3 3 -7 3 -3 0 -7 4 -7 3 -3 3 -7 0 -6 0 -4 0 0 7 0 7 7 3 3 3 0 7 0 7 4 3 0 7 3 6 3 -3 7 -3 3 -4 0 -6 -3 -4 0 -6 3 -7 0 -3 4 -7 6 -3 7 0 3 0 7 -4 3 -3 0 -7 0 -6 4 -4 0 -6 3 -7 3 -3 7 0 3 -4 7 4 7 0 6 -4 0 -3 -3 -7 -3 -6 -4 -4 4 -6 0 -7 6 0 7 0 3 0 7 0 7 -3 6 -4 0 -3 0 -7 -3 -6 0 -7 -3 -3 -4 -7 -3 -3 -3 -7 0 -7 0 -3 0 -7 3 -3 3 -7 4 -3 3 -7 0 -6 -3 -7züGúHìAIûûú[ì|LàM-964 1820l23 10 33 -23 7 -47 27 -13 16 23 -20 53 90 14 37 -50 0 -20 10 -14 7 4 33 -24 67 -3 20 40 40 -17 33 7 -13 37 26 23 4 47 76 23 57 -30 27 77 -24 43 40 57 -16 40 -24 0 -36 43 -20 -7 -17 10 13 30 -6 44 26 60 -50 23 -6 -37 -37 -6 -10 50 -23 36 16 100 50 24 -3 50 -7 0 -26 -20 -17 0 -13 20 -34 -4 -46 24 -20 -17 -30 20 -27 -17 -37 -56 -23 6 -7 -6 4 -14 -24 -10 14 -16 -4 -4 -13 4 -10 -20 -37 -4 -3 -13 -10 -3 -27 16 -30 -10 -26 -33 -20 0 -17 13 -57 14 -80 -20 -80 -64 7 -50 -47 -13 -16 -40 -20 10 -20 -13 -10 -30 3 -24 43 17 7 -20 20 -43 23 -14 4 -30 36 -23 0 -53 20 -10 50 40 30 -44 -3 -16 47 -7 10 -30 20 -3 3 -37 27 -30züGúHìAIûûú[ì|LàM-1304 2147l10 30 20 13 20 -10 16 40 47 13 -7 50 80 64 -26 33 -77 -3 -17 13 4 27 -74 33 -43 13 -90 110 -63 24 -27 43 -17 87 -53 0 -47 70 -63 6 7 10 -10 10 -20 0 -24 4 -30 -10 -6 -54 -27 -30 -7 -43 -30 -3 0 -4 10 -16 -16 -14 -4 -50 -50 -66 -36 -14 0 -66 20 -24 20 7 6 -3 -6 -30 43 -37 -10 -27 7 -6 33 10 17 -24 -17 -50 90 -30 133 -23 64 -30 10 -43 43 20 43 53 17 -27 10 4 0 26 7 7 10 0 6 -40 27 -27 77 -16züGúHìAIûûú[ì|LàM766 2463l6 24 27 10 13 36 -23 57 17 53 -24 37 -33 20 3 10 -73 33 -13 -30 -47 10 -63 -43 -20 27 -10 46 -37 20 -13 -13 -27 13 3 37 47 3 -3 70 23 24 -43 30 36 46 -60 57 -10 37 -50 16 -26 -10 0 40 -37 87 -30 23 -40 0 -10 30 -30 17 -3 43 26 30 -53 20 -23 -76 -44 -14 -80 10 -13 -30 47 -20 0 -20 -40 -36 -54 0 -16 -30 -14 -27 -13 0 -3 40 -67 -3 0 -37 -60 7 -73 -77 -4 3 -13 -13 3 -3 -3 -4 -7 -6 -3 -4 -3 -3 -7 -3 -3 -7 -4 -3 -3 -4 -3 -6 -4 -4 -3 -3 -7 -3 -3 -4 -7 -3 30 -47 30 -13 10 -80 47 17 27 -20 3 -64 -17 -36 14 -54 -47 -56 -3 -47 83 -7 13 -26 -10 -20 54 -54 16 24 24 3 23 -17 -7 -33 27 -17 33 7 27 -27 43 20 24 -6 -10 36 30 14 33 -50 17 26 30 0 23 -46 43 33 34 -60 -30 -23 20 -14 0 -43 23 -3 0 3 3 -3 4 -30 46 3 44 53 36 17 14 -13 50 46 120 47 33 53 17 -23 80 3züGúHìAIûûú[ì|LàM-1118 2347l80 20 57 -14 17 -13 20 0 26 33 30 10 27 -16 10 3 3 13 37 4 10 20 13 -4 4 4 -14 16 24 10 -4 14 7 6 23 -6 37 56 27 17 30 -20 20 17 46 -24 34 4 13 -20 17 0 26 20 7 0 3 -50 54 -20 16 23 70 37 104 103 3 47 47 56 -14 54 17 36 -3 64 -27 20 -47 -17 -10 80 -30 13 -30 47 -6 -3 -4 -4 -3 0 -3 -3 0 -3 -4 -7 -3 -3 -3 -7 -4 -3 -6 -4 0 -6 -4 -7 0 -3 0 -7 -3 -7 0 -3 -3 -7 0 -6 0 -7 -4 -3 -3 -7 0 -7 -3 -3 0 -7 -4 -6 0 -4 -3 -6 -3 -10 -20 -10 -7 16 -27 -3 -40 -37 -33 -10 -23 30 -54 -6 4 36 -17 10 -50 -30 -10 20 23 27 -10 17 -63 10 -10 16 17 30 -7 14 -7 0 -3 -4 -3 -3 -4 -7 0 -3 -3 -7 -7 0 -6 0 -4 0 -6 4 -7 0 -3 3 -7 0 -7 3 -3 0 -7 0 -6 0 -7 0 -3 0 -7 4 -3 3 -7 0 -7 3 -3 4 -7 3 -3 3 -3 4 -7 -7 -17 7 -13 46 13 67 -13 43 -47 34 -53 -34 -10 37 -30 0 0 -3 -17 -84 -40 27 -10 -7 34 -106 -14 -24 -26 -13 0 -50 -30 -20 -20 7 0 -24 -24 -23 10 -37 -26 4 -14 -34 -10 14 -33 -14 13 -50 -33 -26 57 -147 -24 -37 4 -23 -34 -10 -30 -50 74 -33 -4 -27 17 -13 77 3 26 -33m314 456l-7 0 -3 0 -7 0 -7 4 -6 0 -4 3 -3 7 -3 3 0 7 -4 6 -3 4 -3 6 0 4 -4 6 0 7 -3 3 -3 7 0 7 3 3 3 7 4 3 0 7 -4 3 0 7 -3 6 0 7 0 3 -3 7 6 7 4 0 3 -7 3 -3 4 -7 0 -3 0 -7 3 -7 3 -3 4 -3 3 -7 3 -3 -3 -7 -3 -3 -7 -4 -3 -3 0 -7 0 -6 0 -7 3 -3 0 -7 3 -3 4 -7 6 -3 4 -4 3 -3 7 0 6 -3 4 -4 0 -10züGúHìAIûûú[ì|LàM-1954 2457l0 66 36 14 50 66 4 50 16 14 -10 16 0 4 30 3 7 43 27 30 6 54 30 10 24 -4 20 0 10 -10 -7 -10 63 -6 -6 50 -40 13 -17 -13 -7 6 4 24 -24 26 0 97 -56 7 -24 60 -30 -14 -10 7 4 27 -24 56 -50 10 -23 -63 -57 10 -3 33 -90 80 -20 0 -10 -36 -77 53 -93 -23 -20 -47 10 -40 -20 -13 -23 3 -24 30 -36 10 -107 -77 30 -30 -3 -56 33 -34 37 -10 -7 24 30 16 3 -30 27 0 17 -53 -10 -17 -37 10 3 -33 30 7 27 -14 27 -33 -7 -23 73 -40 50 -57 37 -127 -7 -26 -23 -17 13 -63 74 -17 80 47 26 -30 44 -10züGúHìAIûûú[ì|LäM-731 2977l7 -14 -17 -30 10 -16 63 -10 10 -17 -23 -27 10 -20 50 30 17 -10 -4 -36 54 6 23 -30 33 10 40 37 27 3 7 -16 20 10 3 10 3 6 0 4 4 6 0 7 3 3 0 7 3 7 4 3 0 7 0 6 3 7 0 3 3 7 0 7 0 3 4 7 0 6 6 4 4 3 3 7 3 3 4 7 0 3 3 3 3 0 4 4 6 3 7 3 3 4 7 3 3 3 4 4 3 6 3 4 4 3 3 7 7 3 3 3 3 4 7 6 3 4 -3 3 13 13 4 -3 73 77 60 -7 0 37 40 96 43 7 37 7 40 -14 13 30 -36 17 3 17 3 46 -36 87 3 43 -27 14 -36 -10 -64 86 -13 87 13 20 -133 77 -27 30 -60 -17 -53 7 -20 -44 -37 -3 0 10 4 3 0 7 0 7 3 3 0 7 3 6 0 4 4 6 3 7 0 3 3 7 -70 -10 -56 40 -30 -40 -30 33 -74 -73 -80 10 -6 0 -7 3 -3 0 -7 0 -7 4 -6 0 -4 0 -10 0 -13 -37 -20 -7 -20 24 -3 3 -30 -7 13 -23 -33 -57 6 -130 -46 -50 -44 -100 -30 -16 17 -80 -33 -7 -7 -53 57 -17 -20 -40 13 -10 30 0 10 -37 53 34 47 -34 13 -43 -13 -67 13 -46 17 -7 7 7 -4 6 -6 4 -4 6 0 4 7 3 3 3 7 4 3 3 4 7 0 6 0 4 0 6 0 7 3 7 0 3 3 7 4 3 3 3 7 0 6 0 4 0 3 -6 0 -7 3 -7 0 -3 0 -7 -3 -6 -3 -4 -4 -3 -3 -7 -3 -3 -4 -7 0 -3 0 -7 0 -6 4 -4 3 -6 3 -4 4 -3 6 -3 7 0 3 -4 7 0 7 0 6 0 4 0 6 0 7 0 7 4 3 0 7 3 3 3 7 0 3 4 7 3 6 0 4 3 6 0 7 0 3 -6 0 -4 -3 -3 -7 -3 -6 0 -7 0m247 626l-4 -6 -3 -4 -3 -6 -4 -4 0 -6 0 -4 -3 -6 -7 -4 -6 0 -7 0 -3 0 -7 -3 -3 -3 -4 -7 -6 -3 -4 -4 -3 -6 0 -4 -3 -6 0 -7 3 -3 3 -7 0 -3 -6 -7 -4 0 -6 0 -7 0 -7 -3 -3 -4 -3 -6 0 -4 -4 -6 -3 -4 -7 -3 -3 -3 -3 -4 -4 7 0 7 0 6 4 4 0 6 3 7 0 3 7 4 3 3 3 3 4 7 3 7 3 3 4 3 3 7 7 3 3 4 3 3 4 7 3 3 0 7 0 6 3 4 7 3 3 3 7 0 7 0 6 0 4 4 3 3 3 7 4 3 6 3 4 4 6 0 4 -4züGúHìAIûûú[ì|LäM-2521 3073l107 77 36 -10 24 -30 23 -3 20 13 -10 40 20 47 -23 16 3 60 -27 97 44 -7 23 14 -20 70 7 6 3 4 3 3 7 0 7 3 3 0 7 0 3 -3 3 -7 4 -3 6 -7 4 0 6 -3 4 -3 6 0 7 0 3 0 7 0 -3 30 16 26 -36 90 133 134 -7 0 -6 0 -4 3 -6 0 -4 3 -6 4 -4 6 -3 4 -3 10 -7 0 -27 -17 -13 40 -57 23 -43 -20 -23 14 -7 53 -23 47 -37 3 -30 -33 -33 0 -20 16 16 24 -10 30 -43 20 -77 -44 -13 24 -53 16 -14 -20 -33 34 -7 -34 -20 -3 -53 53 -50 -40 -40 -10 -10 -46 -20 -4 -13 7 -87 -17 -7 20 -40 -30 -43 10 -43 -10 -17 -40 33 -53 -26 -17 -4 -33 -46 -3 -90 -37 -10 17 26 20 -26 46 -17 7 -7 -33 17 -17 -30 -7 -27 24 -6 16 10 4 -24 36 -20 -3 -43 -50 13 -90 -46 -23 -4 -24 -66 -60 -10 -43 6 0 4 0 6 0 7 0 7 0 3 3 7 0 6 4 4 0 6 3 7 0 3 0 7 3 7 0 6 0 4 4 6 0 7 3 7 0 3 -3 7 0 3 -4 7 -3 6 -3 4 0 6 -4 7 0 3 0 7 0 7 4 6 0 4 0 6 0 7 3 3 0 7 0 7 0 6 0 4 0 6 3 7 0 7 -3 3 0 7 0 6 0 7 -3 10 0 7 0 3 -4 7 0 20 -96 43 -40 30 -107 -33 -67 -44 -20 -10 -46 17 -27 77 -27 20 20 36 7 24 -17 16 14 67 -20 10 -40 190 -107 83 60 -3 7 -10 3 -3 7 -4 3 -3 3 -3 7 -4 3 -3 4 -7 3 -3 3 -7 7 -3 0 -7 -3 -6 0 -4 -4 -6 4 -4 6 -3 7 0 3 7 0 6 -3 7 0 7 -3 3 3 7 0 3 3 3 7 0 7 0 3 0 7 -6 3 -4 7 -3 3 -3 3 -4 7 0 7 -3 3 0 7 3 3 7 3 3 4 7 0 7 -4 6 0 7 0 3 -3 7 -3 3 -4 4 -3 3 -3 0 -7 0 -7 0 -6 -7 -4 -3 0 -7 -3 -3 -3 -7 -4 0 -6 -3 -7 0 -3 0 -7 0 -7 3 -6 4 -4 3 -3 7 -3 40 13 20 27 43 16 13 -30 50 -20 0 44 37 -4m-150 324l7 3 6 0 4 -3 3 -4 7 -3 3 -3 7 -4 6 -3 0 -3 0 -7 4 -7 0 -3 3 -7 0 -6 -3 -4 -7 0 -3 4 -4 6 0 7 0 3 -3 7 -3 7 -4 3 -3 3 -7 0 -6 4 -4 3 -3 7m207 56l6 0 4 0 6 -3 4 -3 6 -4 4 -3 6 0 7 -3 3 0 7 0 7 0 6 0 4 0 6 0 7 3 3 7 7 0 3 -4 7 -3 3 0 7 -3 7 0 6 -4 4 4 6 3 4 3 3 4 10 0 -7 -4 -3 -3 -3 -7 0 -6 0 -7 3 -3 0 -7 3 -7 0 -3 0 -7 -3 -6 -7 0 -6 0 0 3 -4 7 0 6 -3 7 -3 3 -7 4 -3 3 -7 0 -7 0 -3 3 -7 -3 -6 3 -7 0 -3 0 -7 0 -7 0 -6 0 -4 0 -6 0 -7 4 -3 0 -7 0 -7 3 -3 3 -7 4 -3 3 -3 3 0 10m-204 -46l7 3 3 3 7 4 3 3 7 0 3 3 4 7 3 7 3 0 7 3 7 0 6 0 4 0 6 0 7 3 3 4 4 6 3 4 3 3 4 3 6 0 7 0 7 0 3 0 7 -3 6 0 4 -3 6 0 7 0 3 -4 7 -3 -3 -3 3 -7 3 -3 4 -4 6 -3 0 -7 -3 -3 -7 0 -3 3 -3 4 -4 6 -3 4 -3 3 -7 3 -7 4 -3 3 -3 3 -7 0 -7 0 -6 0 -4 -3 -6 0 -4 -3 -3 -7 -7 -3 -3 -4 -7 -3 -3 0 -7 0 -6 -3 -4 0 -3 -7 -3 -7 -4 -3 -3 -3 -7 3 -6 0 -7 -3 -3 0 -14 0m-510 60l4 3 6 0 7 0 3 -3 7 -4 3 -3 4 -3 6 -4 4 -3 6 0 7 0 7 -3 3 0 7 3 6 0 4 0 6 0 7 0 7 0 3 0 7 0 6 0 7 0 3 0 7 -3 3 0 7 0 7 3 3 0 7 7 3 3 7 3 3 4 7 3 3 3 7 0 3 4 7 3 3 3 7 4 0 6 0 4 -4 6 4 7 6 0 4 0 6 0 4 3 3 7 3 3 4 7 3 3 3 7 0 7 4 3 3 7 3 3 4 7 3 3 3 3 7 4 3 3 7 3 3 4 7 0 7 0 6 0 4 0 6 0 7 0 7 0 3 0 7 3 6 0 4 3 6 4 7 0 3 3 7 3 3 4 4 3 6 3 4 4 6 3 4 3 6 0 7 0 3 0 7 -3 0 -7 -3 -3 -7 -3 -3 0 -7 -4 -7 0 -3 -3 -7 -3 -3 -4 -7 -3 -3 -3 -7 -4 -3 -3 -7 -3 -3 -4 -3 -3 -7 -3 -7 0 -3 0 -7 0 -6 3 -7 0 -3 0 -7 0 -7 0 -6 -3 -4 -4 -6 0 -4 -6 -3 -4 -3 -3 -4 -7 -3 -3 -3 -3 -4 -7 -6 -3 -4 -7 -3 -3 -3 -4 0 -6 -4 -7 -3 -3 3 -7 4 -3 6 -4 7 0 3 -3 7 0 7 -3 3 0 7 0 6 -4 7 0 3 0 7 -3 7 0 3 -3 7 0 6 0 7 0 3 0 7 0 7 0 3 -4 7 0 6 -3 4 -3 6 0 7 -4 3 -3 7 -3 3 0 7 -4 7 -3 3 0 7 -3 6 0 4 0 6 0 4 -4 3 -6 7 -4 3 -3 3 -3 10 -7 -3 -7 0 -6 0 -7 -3 0 -7 7 0 3 0 7 -7 6 -3 4 -3 3 -7 3 -3 0 -7 0 -7 4 -3 3 -7 0 -6 3 -4 4 -6 0 -7 3 -3 0 -7 3 -3 4 -7 0 -7 3 -3 0 -7 3 -6 0 -7 0 -3 0 -7 4 -7 0 -6 0 -4 0 -6 0 -7 3 -3 0 -7 0 -7 3 -3 4 -7 3 -3 3 -7 0 -3 0 -7 -3 0 -7 0 -3 -6 -3 -7 0 -3 -4 -7 0 -7 4 -3 6 0 4 -7 3 -6 -3 -7 0 -3 -4 -4 -3 -6 -3 -4 -4 -6 -3 -4 -3 -3 -4 -3 -6 -4 -7 -3 -3 -3 -4 -7 4 -7 0 -6 0 -4 3 -3 3 -7 4 -6 0 -7 0 -3 -4 0 -6 6 -4 4 -3 -4 -7 -3 0 -7 4 -3 3 -3 3 -7 4 -3 0 -7 3 -7 0 -6 0 -4 3 -6 4 -7 0 -3 3 -7 3 -3 0 -7 4 -3 3 -7 3 -3 -3 -4 -3 7 -7 3 -3 4 -4 3 -6 3 -4 4 -6 3 -4 3 -6 4 -4 0 -6 3 -4 3 -6 0 -7 4 -3 3 -7 0 -3 3 -7 7 0 7 -3 6 0 4 -4 6 0 7 0 3 -3 4 -7 6 -3 4 -3 3 -4 7 -3 3 -3 7 -4 3 0 7 -3 6 0 4 0 6 -3 7 -4 3 -3 7 0 7 0 0 -3 -4 -7 -6 0 -7 0 -7 3 -3 0 -7 4 -3 3 -7 3 -3 0 -7 4 -6 3 -4 3 -3 4 -7 3 -3 3 -7 0 -3 -3 0 -7 3 -6 -3 -4 -7 -3 -3 7 0 6 0 4 0 6 0 7 -7 3 -3 0 -7 4 -3 3 -7 3 -3 4 -7 3 -3 3 -3 7 -4 3 0 7 -3 3 -3 7 -4 3 0 7 -3 3 -3 7 -4 7 0 3 -3 7 -3 3 -4 7 -3 3 -3 7 -4 3 -3 7 0 3 3 7züGúHìAIûûú[ì|LàM-901 3767l20 -24 20 7 13 37 14 40 -64 93 17 70 -43 73 63 34 23 73 57 40 -17 60 -33 27 -17 -7 0 70 -73 53 -17 -10 -63 17 -20 -23 -40 26 -113 -23 -20 7 -14 33 -40 20 -40 -7 -16 -30 -24 37 -110 -20 -53 43 -213 -23 -10 37 -104 -30 -46 -57 -44 -17 -56 -60 -84 -30 -6 -50 -54 0 -40 -33 30 -7 27 -90 23 -20 30 4 7 -30 -50 -27 -23 -63 46 13 27 -10 -23 -37 16 -50 20 -26 50 3 7 -13 -27 -70 27 -14 23 -60 -10 -26 37 -4 7 -26 60 -47 20 50 23 -30 107 33 26 -16 20 -50 60 -4 10 40 -16 7 -4 40 -23 0 -17 67 24 16 16 -16 54 10 6 43 60 27 44 -24 33 17 43 -20 64 -7 66 -70 60 4 10 -57 54 0 23 -17 83 37 44 -17 33 57 -13 23 30 7 3 -3züGúHìAIûûú[ì|LàM-2094 3723l13 -13 23 -73 24 -17 53 40 -3 60 -57 30 -3 0 6 -3 -3 -7 0 -7 -7 -3 -3 -3 -7 0 -6 -4 -4 -3 -6 0 -7 0 -3 3 -10 0züGúHìAIûûú[ì|LàM-798 3780l80 -10 74 73 30 -33 30 40 56 -40 70 10 -3 -7 0 -3 -3 -7 -4 -6 0 -4 -3 -6 0 -7 -3 -3 0 -7 0 -7 -4 -3 0 -10 37 3 20 44 53 -7 60 17 27 -30 133 -77 34 40 26 -10 34 27 100 20 -10 76 0 4 -40 106 73 84 103 -10 24 43 0 67 -20 16 33 64 -67 23 -50 -37 -6 -26 -30 -10 -47 16 -47 40 -16 -13 -20 7 -27 26 -3 57 -27 30 17 113 -44 44 -53 10 -23 -40 -37 -7 -3 3 -87 64 -47 13 -33 -20 -30 47 -63 36 -67 124 -120 -40 60 -87 7 -53 -10 -7 -24 -13 0 -70 -50 -14 -13 -70 -53 10 -44 -23 0 -70 17 7 33 -27 17 -60 -57 -40 -23 -73 -63 -34 43 -73 -17 -70 64 -93 -14 -40 10 0 4 0 6 0 7 -4 7 0 3 0 7 -3 6 0züGúHìAIûûú[Cfil1LàM-3514 537l36 -4 10 37 10 7 20 -34 44 4 -4 13 54 20 36 63 34 24 103 10 -3 50 -30 40 -37 0 -3 30 20 6 3 34 33 30 4 46 46 27 0 47 44 -24 26 20 -23 37 -40 10 -30 40 13 23 24 -13 40 20 10 50 -20 27 0 53 -30 37 -27 0 -43 36 16 44 -23 16 7 27 -20 57 -50 83 -7 -3 -7 0 -3 -4 -7 -3 -3 -3 -3 -7 -4 -7 0 -3 -3 -7 0 -6 -3 -4 -7 -3 -3 -3 -7 -4 -3 -3 -7 0 -7 0 -6 0 -4 0 -6 0 -7 0 -7 0 -3 0 -7 3 -6 0 -4 4 -6 0 -4 3 -6 7 -4 3 -3 3 -7 4 -3 3 -7 3 -3 0 -7 4 -6 0 -4 3 -6 0 -7 0 -7 0 -3 -3 -7 0 -6 0 -4 0 -6 0 -7 3 -3 0 -7 0 -7 -3 -6 0 -4 -4 -6 0 -4 -3 -6 -3 -4 -4 -6 -3 -4 -3 -6 -4 -4 -3 -3 -3 -10 -7 3 0 -20 -13 10 -10 -3 -7 -73 -10 10 -33 -17 -20 37 -100 -57 -47 7 -53 -14 -4 50 -80 -16 -66 16 -34 -23 -70 23 -46 -6 -20 30 -37 0 -47 33 0 30 -50 27 -110 20 -16 -10 -27 10 -33m-54 810l7 -7 3 -3 0 -7 0 -7 0 -6 0 -4 0 -6 4 -7 0 -3 6 -4 4 -3 6 -3 0 -7 0 -7 4 -3 3 -7 3 -3 0 -7 4 -3 3 -7 3 -3 4 -7 3 -3 0 -7 3 -3 7 -3 7 -4 3 -3 3 -3 4 -7 3 -3 3 -7 4 -3 -7 -4 -7 4 -6 0 -4 3 -3 7 -7 3 -3 3 -3 7 -4 3 0 7 -3 3 -3 7 -4 3 -3 4 -7 6 -3 4 -3 3 0 7 -4 6 0 4 -3 6 -3 4 -4 3 -6 3 -4 7 -3 3 0 7 -3 7 0 3 0 7 0 6 0 7 3 3 3 7 0 7züGúHìAIûûú[ì}LàM-2001 973l-3 57 36 20 20 50 -33 20 -37 83 -20 7 0 57 -23 30 33 26 -23 117 13 13 -16 67 10 33 -37 14 -3 23 16 -3 0 13 -10 23 -20 4 -23 -7 -3 13 -14 0 -6 -6 -14 -17 -36 33 -27 -6 -13 23 6 7 -6 6 -20 -3 -10 20 -20 -10 -20 20 0 33 3 70 -37 17 -10 30 -20 -7 10 -23 -13 -30 -13 -30 -34 37 -43 -67 -33 17 -24 -17 -43 20 -20 -27 -37 17 -43 -23 -97 3 -53 -43 -93 13 -84 -30 -36 7 -40 -34 30 -63 -57 -50 17 -50 -17 -10 -50 -23 -23 20 -50 -10 20 -57 -7 -27 23 -16 -16 -44 43 -36 27 0 30 -37 0 -53 20 -27 33 20 33 -27 77 10 63 -16 4 -17 -10 -7 6 -13 14 0 30 -47 73 37 10 -27 50 17 17 -30 33 10 20 -10 17 40 36 23 60 10 27 -36 43 -14 54 17 30 -3 10 -24 40 4 16 -30 80 6 37 -23 17 13 26 -56 37 0 47 -40 26 6 17 30züGúHìAIûûú[ì}LàM-1251 1010l83 -47 67 27 -17 27 24 16 -4 47 -16 13 60 7 43 57 -67 23 -60 -33 -33 56 33 34 10 -27 24 0 10 -10 6 7 -10 66 10 10 10 -3 7 0 3 0 7 0 7 0 6 0 4 3 3 7 3 3 4 4 6 6 4 4 3 3 7 3 3 4 7 3 3 0 7 3 6 0 4 4 6 0 7 3 3 3 4 4 6 3 4 3 3 7 3 3 0 7 4 7 0 3 -27 13 -27 -13 -50 3 -6 14 3 20 -23 26 0 10 16 4 -6 36 23 27 -3 43 -7 4 -10 -24 -10 10 20 30 -30 14 17 60 -20 46 53 84 57 0 10 43 -27 30 -3 37 -20 3 -10 30 -47 7 3 16 -30 44 -50 -40 -20 10 0 53 -36 23 -4 30 -23 14 -20 43 -7 20 -43 -17 -3 24 -77 16 -27 27 -6 40 -10 0 -7 -7 0 -26 -10 -4 -17 27 -43 -53 -43 -20 -17 -27 0 -3 -17 6 7 -56 -30 -27 20 -30 -27 -47 4 -26 50 -17 10 -27 43 -23 3 -20 -53 17 -13 -17 13 -27 -7 -10 -46 0 -7 -26 17 -17 -24 -20 -46 -3 -44 -184 -26 0 -10 -33 13 -20 33 -7 4 -23 -24 -50 17 -47 -13 -43 80 -50 20 13 10 -20 76 4 27 -30 40 0 -3 -27 -4 -27 -33 20 -10 -23 43 -27 -10 -20 -53 30 -20 -16 17 -50 10 0 6 0 4 0 6 0 7 3 3 0 7 3 3 -6 4 -4 0 -6 0 -7 -4 -3 -3 -7 -3 -3 23 -14 7 -26 43 -7 50 -60 77 30 43 0züGúHìAIûûú[ì}LàM1042 1167l50 23 14 -10 70 10 46 53 30 -13 67 3 53 80 -10 44 30 16 -26 20 20 37 53 0 23 -27 30 0 7 -26 30 -7 3 10 0 40 44 13 -4 34 0 3 30 -3 -3 43 -87 23 14 34 -7 26 27 7 6 17 -20 23 14 37 -24 26 14 20 -24 17 20 7 -3 6 -17 7 0 33 -36 37 30 10 -17 67 -27 16 -23 -20 -13 14 -4 -24 -26 7 3 50 -17 17 37 43 -43 20 20 27 -4 16 -93 -3 -27 27 7 36 -30 14 -27 -10 -10 6 10 20 -63 74 -43 10 -20 -14 -14 24 -30 0 -76 36 -20 -16 -74 10 -10 23 -23 0 -20 -37 13 -20 -33 -23 7 -17 6 -3 0 -50 30 -10 24 -40 -10 -33 -44 -4 -20 -53 144 -153 -24 -44 40 -43 30 -97 20 -143 -6 -63 -30 -60 20 -10 16 -74 -36 -16 -7 -47 73 -103züGúHìAIûûú[ì}LàM-921 1257l123 20 7 16 -17 30 20 17 7 3 10 -6 10 0 3 16 -10 7 -53 0 -23 -20 -44 10 -53 -50 20 -43züGúHìAIûûú[ì}LàM-2841 2347l3 3 7 7 3 3 4 3 3 7 -3 7 0 6 -4 4 -3 6 3 7 0 3 7 4 3 -4 7 -3 3 -7 4 -3 0 -7 3 -3 7 0 3 7 3 3 7 3 7 0 3 4 7 3 3 7 3 0 7 0 7 0 3 3 3 7 4 3 0 7 0 6 0 4 3 6 3 4 4 0 0 -7 3 -3 7 0 6 0 7 0 3 3 4 3 3 7 0 7 3 3 0 7 4 6 3 4 7 3 3 3 3 4 7 -7 0 -3 0 -7 -3 -7 0 -3 -4 -7 -3 -3 -3 -7 -4 -3 -3 -7 -3 -3 -7 -3 -3 -7 -4 -3 -3 -4 -3 -6 -4 -4 -6 -3 43 3 0 30 10 7 17 -7 3 10 10 -3 30 -57 70 17 67 -17 26 27 24 -7 43 54 7 -24 30 -6 10 36 33 17 20 -13 3 -34 7 -13 20 3 13 24 20 -4 30 24 -13 63 23 17 7 26 -37 127 -50 57 -73 40 7 23 -27 33 -27 14 -30 -7 -3 33 37 -10 10 17 -17 53 -27 0 -3 30 -30 -16 7 -24 -37 10 -33 34 3 56 -30 30 -37 4 0 -44 -50 20 -13 30 -43 -16 -20 -27 -40 -13 3 -4 3 -6 4 -4 3 -3 3 -7 -3 -6 3 -7 -83 -60 -190 107 -10 40 -67 20 -16 -14 -24 17 -36 -7 -20 -20 46 -60 -33 -66 33 -54 -26 -36 23 -64 -13 -73 6 -60 14 -10 -50 -93 6 -37 7 0 7 0 6 0 4 0 6 -3 7 -4 3 -3 7 -3 3 -4 4 -3 3 -7 3 -3 0 -7 4 -6 0 -4 3 -6 3 -4 0 -6 4 -7 3 -3 3 -7 4 -3 3 -7 3 -3 4 -7 0 -3 3 -7 3 -3 7 -4 3 -3 4 -7 3 -3 7 -3 3 -4 3 -6 7 -4 3 0 7 -3 7 0 3 0 7 0 6 -3 7 0 3 0 7 0 3 -4 7 -6 3 -4 4 -3 6 -3 7 0 3 -4 4 -3 3 -3 10 0 7 0 6 0 7 0 3 0 7 0 7 3 6 0 4 0 6 0 7 3 3 4 7 0züGúHìAIûûú[ì}LàM-2301 3207l93 23 77 -53 10 36 20 0 90 -80 3 -33 57 -10 23 63 50 -10 27 14 47 -30 30 -44 16 4 7 26 30 27 30 -40 30 -13 30 36 43 -16 34 36 110 30 23 27 20 -7 57 20 6 24 -13 23 -7 0 -3 3 -7 4 -3 3 -3 3 -7 4 -3 6 -4 4 -6 3 -4 3 -3 4 -3 6 -4 4 0 6 -6 4 -4 0 -6 0 -7 0 -7 3 -3 3 -7 4 -3 0 -7 3 -3 3 -7 4 -3 3 -7 3 -3 4 -3 3 23 27 7 3 50 -47 50 -10 0 -20 60 -20 13 -20 27 0 6 0 7 0 7 0 3 0 7 0 6 0 10 0 7 0 7 0 6 0 4 0 6 0 7 0 3 -3 4 0 26 0 40 -30 7 17 7 53 33 7 -17 80 30 16 44 100 46 50 -6 130 -44 17 -83 -37 -23 17 -54 0 -10 57 -60 -4 -66 70 -64 7 -43 20 -33 -17 -44 24 -60 -27 -6 -43 -54 -10 -16 16 -24 -16 17 -67 23 0 4 -40 16 -7 -10 -40 -60 4 -20 50 -26 16 -107 -33 -23 30 -20 -50 -60 47 -7 26 -37 4 -36 23 3 -60 -53 -40 -24 17 -23 73 -13 13 -7 4 -133 -134 36 -90 -16 -26 3 -30 -7 0 -3 0 -7 0 -6 0 -4 3 -6 3 -4 0 -6 7 -4 3 -3 7 -3 3 -7 0 -3 0 -7 -3 -7 0 -3 -3 -3 -4 -7 -6 20 -70 -23 -14 -44 7 27 -97 -3 -60 23 -16züGúHìAIûûú[ì}LäM-1984 3720l36 -23 10 26 -23 60 -27 14 27 70 -7 13 -50 -3 -20 26 -16 50 23 37 -27 10 -46 -13 23 63 50 27 -7 30 -30 -4 -23 20 -27 90 -30 7 -63 0 -13 10 6 23 -13 10 -43 24 -30 36 -40 0 -20 50 -90 57 -4 70 27 50 3 43 -10 34 -30 20 -26 -4 -50 40 -14 -30 30 -20 -10 -20 -26 -10 -47 10 -50 47 3 33 -20 40 -96 20 -44 30 -96 -46 -4 -24 -30 -20 -23 4 -13 33 -60 -13 -10 -44 -120 -23 10 -50 -80 -27 -90 24 -30 -74 -70 -110 -20 -13 3 -3 3 -7 4 -3 3 -7 3 -3 0 -7 -3 -7 0 -6 0 -4 0 -6 0 -7 0 -3 0 -7 3 -7 0 -6 4 -4 3 -6 3 -4 4 -3 3 -7 3 -3 4 -3 3 -7 3 -7 0 -3 4 -7 0 -6 -4 -4 0 -6 -3 -7 -7 -3 0 -7 0 -7 0 -6 0 -7 0 -3 0 -7 4 -7 3 -3 3 -3 7 -4 3 -6 4 -4 6 -3 4 -3 3 -4 7 -3 3 -3 7 -4 3 -3 7 -3 3 -4 3 -3 7 -3 3 -4 7 -3 3 -3 4 -4 6 -6 4 -4 3 -3 7 -3 3 -4 3 -3 7 -7 3 -3 -3 -30 53 -80 -6 -40 -27 -30 -73 0 6 -43 -56 -30 6 -47 20 3 24 -36 -10 -4 6 -16 27 -24 30 7 -17 17 7 33 17 -7 26 -46 -26 -20 10 -17 90 37 46 3 4 33 26 17 -33 53 17 40 43 10 43 -10 40 30 7 -20 87 17 13 -7 20 4 10 46 40 10 50 40 53 -53 20 3 7 34 33 -34 14 20 53 -16 13 -24 77 44 43 -20 10 -30 -16 -24 20 -16 33 0 30 33 37 -3 23 -47 7 -53 23 -14 43 20 57 -23 13 -40 27 17 7 0 0 3 -4 7 0 6 0 4 0 6 -3 7 0 7 0 3 -3 7 -4 6 -3 4 -3 6 -4 4 -3 3 -7 3 -3 4 -7 3 -3 3 -7 0 -3 -3 -3 -7 -4 -3 0 -7 -6 0 -4 4 0 3 0 7 0 6 0 7 0 3 -3 7 0 7 -3 3 0 7 -4 6 0 7 0 3 4 10 3 4 7 -4 -4 -6 0 -4 0 -6 0 -7 0 -7 4 -3 6 -3 4 -4 6 -3 4 -3 6 0 4 -4 6 -3 4 -3 6 -4 4 -3 6 -3 4 -4 3 -6 3 -4 4 -6 3 -4 3 -6 0 -4 4 -6 3 -7 0 -3 3 -7 0 -7 4 -3 3 -7 0 -3 7 -3 3 -4 7 -3 6 0 7 3 3 4 4 6 3 4 3 6 4 4 3 3 3 7 7 3 3 0 7 3 3 7 0 3 4 7 3 7 0 3 3 7 4 3 6 3 10 0 -3 -3 0 -7 -3 -6 -4 -4 -3 -6 -3 -4 3 -6 3 -7 -3 -3 -3 -4 -4 -3 -6 -3 -4 -4 -6 -3 -4 -3 -6 -4 -4 -3 0 -7 7 -3 3 3 7 0 7 -3 3 0 57 -30m-437 303l0 4 7 0 6 0 4 -4 6 -3 4 -3 6 -4 4 -3 6 0 7 -3 3 0 7 -4 7 -3 3 -3 7 -4 3 -3 3 -3 7 -4 3 -3 4 -3 3 -7 10 -7 -7 0 -6 0 -7 0 -3 4 -7 3 -3 3 -7 4 -3 3 0 7 -7 3 -3 3 -7 0 -7 4 -3 3 -7 0 -6 3 -4 0 -6 4 -7 0 -3 3 -4 7 -3 6m30 60l3 -3 7 0 7 0 6 3 4 0 6 0 7 4 3 0 7 3 7 0 6 0 4 0 6 -3 7 0 3 -7 7 0 3 0 7 -3 7 0 6 0 4 0 6 0 7 0 7 0 3 3 7 3 3 4 0 6 3 7 4 3 3 4 7 3 3 3 7 4 3 3 3 3 7 4 3 3 7 3 7 0 3 -6 0 -7 -3 -3 -4 -7 -3 -3 -7 0 -6 -4 -4 -3 -6 0 -4 -3 -6 -7 -4 -3 -3 -4 -3 -6 3 -7 0 -3 3 -7 0 -7 -3 -3 -7 0 -6 0 -4 3 -6 4 -4 3 -6 3 -7 0 -3 0 -7 0 -7 0 -6 0 -4 0 -6 0 -7 0 -3 4 -7 3 -3 3 -7 0 -7 4 -6 0 -4 0 -6 -4 -7 0 -3 -3 -7 -3 -3 -4 -7 0 -7 4 -3 3 0 7 0 6züGúHìAIûûú[ì}LàM-2818 4783l4 17 26 7 -20 33 20 27 -36 20 -7 40 -17 3 -20 -20 -116 23 -44 60 7 17 80 10 0 33 47 90 -30 17 6 37 -23 13 27 37 -14 40 4 86 -27 30 17 64 -14 40 27 30 -17 50 -13 6 -20 -10 -23 -56 -57 -70 -217 -140 10 -27 -6 -3 -30 16 6 14 -10 6 -80 -33 -113 13 -27 14 -10 -7 -20 -37 -6 -13 -4 -7 0 -6 0 -7 0 -7 0 -3 0 -7 0 -6 0 -4 -3 -6 0 -7 0 -7 0 -3 0 -7 0 -6 0 -7 0 -3 -3 -7 0 -7 0 -6 0 -4 0 -6 0 -7 0 -7 0 -3 0 -7 0 -6 -4 -7 0 -7 0 -3 -3 -7 0 -3 -3 -7 -4 -3 -6 -7 -4 -3 -3 -3 -3 -7 -7 -7 47 -73 16 -73 77 -64 30 -106 70 -7 13 -30 57 13 47 -130 80 27 -10 50 120 23 10 44 60 13 13 -33 23 -4 30 20 4 24 96 46züGúHìAIûûú[Cfil2LàM-348 880l47 -10 20 40 30 -30 83 17 7 50 -20 53 -27 27 27 33 43 7 4 -50 16 -10 10 6 -6 20 20 20 30 -6 146 70 60 3 44 -13 13 33 -50 10 -17 47 4 46 -30 27 -67 37 -7 40 -56 0 -27 70 -27 -7 -16 23 10 37 -37 37 -7 33 14 23 -30 37 -17 63 17 70 50 54 -50 86 -4 14 -46 -10 -30 13 -60 -40 -24 10 -40 -30 -43 -3 -27 -20 0 -34 44 -56 53 3 13 -20 -3 -13 -7 -4 -3 -3 -7 -3 -3 -4 -7 0 -3 -3 -7 -3 -6 -4 -4 -3 -6 0 -4 -3 -6 -4 -7 0 -3 -3 -7 0 -7 -3 -3 -4 -3 -3 0 -7 0 -6 -4 -7 -6 -7 -4 -3 -6 -7 -4 -3 -3 -3 -3 -4 -7 -3 -3 -7 -4 -3 -6 -3 -4 -4 -3 -3 -13 -3 -7 -4 -7 0 -3 0 -7 0 -6 0 -7 0 -3 0 -4 -3 -6 -7 -4 -3 -3 -7 -3 -3 -4 -3 -3 -4 -7 -3 -3 0 -7 0 -6 0 -7 0 -3 0 -7 -3 -7 0 -3 -4 -7 -3 -3 -3 -7 -4 -3 -3 -7 0 -3 -3 -7 -4 -6 0 -4 -3 -6 0 -7 0 -7 0 -3 -3 -7 0 -6 0 -7 -4 -3 0 -7 -3 -7 0 -3 0 -7 -3 -6 0 -4 -4 -6 0 -7 0 -7 -3 37 -7 13 -50 -13 -26 -23 20 -24 -30 47 -37 27 20 36 -17 -20 -56 27 -14 -3 -36 23 -34 -10 -36 23 -44 40 10 20 -26 27 -7 13 -60 60 -47 -6 -60 43 -10 23 -46 30 -7züGúHìAIûûú[ì~LàM-391 1827l43 3 40 30 24 -10 60 40 30 -13 46 10 4 -14 50 -86 -50 -54 -17 -70 17 -63 30 -37 -14 -23 7 -33 37 -37 -10 -37 16 -23 27 7 27 -70 56 0 7 -40 67 -37 -4 27 17 16 -17 24 7 36 -13 20 16 17 -16 27 23 3 -3 60 46 23 -53 104 17 6 13 -26 33 6 17 -46 0 -17 10 -10 7 3 6 50 -16 40 6 130 -13 10 -17 -26 -30 66 60 30 60 0 77 80 7 80 73 27 10 37 63 40 20 -17 24 3 66 164 27 10 0 -14 7 0 6 14 37 0 -3 6 -4 4 -3 3 -7 3 -6 0 -4 0 -6 0 -7 0 -3 4 -7 3 0 7 0 6 -3 4 0 6 0 7 -7 0 -7 0 -3 0 -7 -3 -6 -4 -4 0 -6 0 -7 0 -3 4 -7 3 0 10 3 3 7 0 7 0 6 4 4 0 6 0 7 3 3 3 7 0 7 0 3 0 7 -3 3 -7 3 -3 0 -7 4 -6 3 -4 3 -6 4 -4 6 0 4 -3 6 0 7 -3 3 -4 4 -3 3 -7 3 -3 4 -7 3 -3 3 -7 0 -6 4 -4 0 -6 0 -7 3 -3 3 -4 7 -3 7 -3 6 0 4 0 6 0 7 0 3 3 7 3 3 7 4 3 3 4 7 3 6 0 10 0 -3 -7 -3 -3 -4 -7 -3 -3 -3 -3 -7 -4 -3 -3 -7 -3 7 -14 50 10 -7 17 33 23 -13 20 20 37 -3 23 0 4 -34 23 -6 37 -47 26 7 40 -80 -3 -17 23 -33 -53 -120 -47 -50 -46 -14 13 -36 -17 -44 -53 -46 -3 -4 30 -3 3 0 -3 -23 3 0 43 -20 14 30 23 -34 60 -43 -33 -23 46 -30 0 -17 -26 -33 50 -30 -14 10 -36 -24 6 -43 -20 -27 27 -33 -7 -27 17 7 33 -23 17 -24 -3 -16 -24 -54 54 10 20 -13 26 -83 7 -104 -103 -70 -37 -16 -23 -54 20 -50 -24 -16 -100 23 -36 10 -50 37 6 6 37 50 -23 -26 -60 6 -44 -13 -30 17 -10 20 7 36 -43 24 0 16 -40 -40 -57 24 -43 -27 -77 0 -33züGúHìAIûûú[ì~LàM-914 1427l33 -47 33 27 -10 53 10 3 7 0 3 4 4 3 3 7 3 3 7 0 7 3 6 0 4 0 6 0 7 -3 3 -3 7 0 7 0 3 -4 7 0 6 0 7 0 3 4 7 0 3 3 7 3 7 0 6 0 4 4 6 0 7 3 3 0 7 0 7 3 3 0 7 4 6 0 7 0 3 3 7 0 7 0 6 0 4 3 6 0 7 4 3 3 7 0 3 3 7 4 3 3 7 3 3 4 7 0 7 3 3 0 7 0 6 0 7 0 3 0 7 3 3 4 4 3 3 3 3 7 4 3 6 7 4 3 3 0 7 0 6 0 7 0 3 0 7 0 7 4 13 3 3 3 4 4 6 3 4 3 3 7 7 3 3 4 3 3 4 3 6 7 4 3 6 7 4 7 0 6 0 7 3 3 3 4 7 3 7 0 3 3 7 0 6 4 4 3 6 0 4 3 6 4 7 3 3 3 7 0 3 4 7 3 3 3 7 4 3 13 -13 20 -53 -3 -44 56 0 34 27 20 0 33 -57 30 -76 -23 -4 -47 -26 -23 13 -37 -33 -7 -40 17 -20 -40 -67 3 -33 24 -7 -4 -10 14 0 20 -37 50 -90 -14 20 -53 -16 -23 -27 13 -7 47 -33 23 -23 -10 -10 -43 -57 0 -53 -84 20 -46 -17 -60 30 -14 -20 -30 10 -10 10 24 7 -4 3 -43 -23 -27 6 -36 -16 -4 0 -10 23 -26 -3 -20 6 -14 50 -3 27 13 27 -13 3 10 0 7 3 3 4 7 3 3 3 7 4 3 3 7 3 3 4 7züGúHìAIûûú[ì~LàM-3671 1377l17 20 -10 33 73 10 3 7 -10 10 20 13 -3 0 10 7 3 3 4 3 6 4 4 3 6 3 4 4 6 3 4 3 6 0 4 4 6 0 7 3 7 0 3 0 7 -3 6 0 4 0 6 0 7 0 3 3 7 0 7 0 6 0 4 -3 6 0 7 -4 3 0 7 -3 3 -3 7 -4 3 -3 4 -3 6 -7 4 -3 6 0 4 -4 6 0 7 -3 3 0 7 0 7 0 6 0 4 0 6 0 7 0 7 0 3 3 7 4 3 3 7 3 3 4 0 6 3 7 0 3 4 7 3 7 3 3 7 3 3 4 7 0 7 3 50 -83 50 10 23 -20 50 23 17 10 -17 50 57 50 -30 63 -10 30 -34 -10 -40 34 -10 33 -30 27 0 23 20 17 -13 46 -30 17 -43 -33 -34 6 -10 70 -70 27 -26 -3 -27 23 -17 -37 -6 0 -17 -6 -13 23 -47 3 7 -33 -57 -23 -73 13 -20 17 -7 0 -3 -34 -14 0 -6 20 -27 0 -43 40 -44 7 -20 -10 4 -33 -24 -10 -6 -27 36 -50 40 -23 4 -27 -24 -20 -30 10 -6 -70 3 0 3 -7 4 -3 3 -7 0 -3 0 -7 0 -6 0 -7 -3 -3 3 -7 0 -7 -27 7 -16 -13 3 -40 -37 -37 -6 -100 93 -50 87 17 53 -20züGúHìAIûûú[ì~LàM-2098 1627l-16 90 50 10 13 43 -53 107 10 20 60 -10 40 63 30 7 33 -34 27 4 33 46 37 -13 13 13 -10 27 17 13 23 0 20 -20 47 14 36 -27 60 3 17 24 30 3 -20 30 30 27 -7 56 17 -6 0 3 17 27 -10 43 -64 30 -133 23 -90 30 17 50 -17 24 -33 -10 -7 6 10 27 -43 37 6 30 -6 3 -20 -7 -20 24 -44 10 -26 30 -80 -47 -74 17 -30 -24 -20 4 -13 -24 -20 -3 -7 13 -26 -6 26 -47 -23 -83 17 -37 -17 -43 3 -4 40 -23 4 -23 -17 -14 10 -26 -30 -10 0 -50 -23 -37 0 -23 30 -24 3 -20 -7 -3 14 -63 -17 -20 27 -27 -47 -47 -3 -70 0 -33 20 -20 20 10 10 -20 20 3 6 -6 -6 -7 13 -23 27 6 36 -33 14 17 6 6 14 0 3 -13 23 7züGúHìAIûûú[ì~LàM752 2710l24 0 13 20 33 10 -6 37 70 20 23 36 43 17 -83 170 -90 103 -17 60 -56 40 -20 80 -57 70 -43 80 -47 -16 -17 -30 -36 -7 -24 40 -43 33 -23 -33 -67 3 -10 -63 -20 -7 -20 27 -37 -47 -26 -30 3 -43 30 -17 10 -30 40 0 30 -23 37 -87 0 -40 26 10 50 -16 10 -37 60 -57 -36 -46 43 -30 -23 -24 3 -70 -47 -3 -3 -37 27 -13 13 13 37 -20 10 -46 20 -27 63 43 47 -10 13 30 73 -33züGúHìAIûûú[ì~LàM-2148 4220l40 33 54 0 6 50 84 30 56 60 44 17 46 57 104 30 20 6 16 34 -3 36 30 64 -60 113 -3 3 -7 147 43 13 -20 40 40 27 -26 47 30 10 60 76 -7 14 43 63 -53 -7 -37 44 -43 6 -13 80 -40 34 -34 -27 -10 -43 -36 6 -17 37 -27 10 -33 0 -10 -30 -23 -3 -27 -70 -50 16 -17 -16 -10 -60 -30 -7 -30 -50 4 -67 -4 -6 -16 3 -4 -3 10 -27 -30 -47 -43 7 0 17 -7 0 -10 -14 -3 17 -10 3 -33 -6 -97 66 -30 -33 0 -33 3 -4 7 0 7 -3 3 -3 7 0 3 -4 7 -3 3 -3 7 0 6 -4 7 -3 -7 -47 -16 -13 -4 -40 -36 -23 0 -54 -37 -30 0 -33 -57 -73 30 -20 10 -34 -3 -43 -27 -50 4 -70 90 -57 20 -50 40 0 30 -36 43 -24 13 -10 -6 -23 13 -10 63 0züGúHìAIûûú[ì~LàM-1714 4497l10 -37 213 23 53 -43 110 20 24 -37 16 30 40 7 40 -20 14 -33 20 -7 113 23 40 -26 20 23 63 -17 17 10 73 -53 44 23 53 -10 13 70 50 14 0 70 24 13 10 7 -7 53 -60 87 -27 13 -10 57 -26 16 -27 -6 -47 40 -63 123 7 53 -47 30 -10 27 -33 -10 -30 13 -50 -33 -27 0 -40 40 -47 20 -80 -40 -60 63 -80 37 -23 -3 -27 70 -56 10 -34 -17 -43 -63 7 -14 -60 -76 -30 -10 26 -47 -40 -27 20 -40 -43 -13 7 -147 3 -3 60 -113 -30 -64 3 -36 -16 -34 -20 -6m846 186l7 -3 7 -3 3 -4 3 -6 4 -4 0 -6 -4 -4 -3 -6 -3 -7 0 -3 0 -7 3 -3 3 -7 7 -3 3 -4 4 -6 3 -4 3 -3 0 -7 0 -3 -6 0 -4 7 -3 3 -3 7 -4 3 -3 3 -3 7 -7 3 3 4 0 6 0 7 -3 7 0 3 0 7 -3 6 -4 4 0 6 -3 7 3 3züGúHìAIûûú[ì~LàM-721 4687l120 40 77 76 -47 37 -3 50 13 20 -27 67 7 40 -33 -4 -4 14 10 50 -10 16 -40 10 -3 14 -50 23 -53 47 -14 120 -13 10 -47 -14 -13 -20 -37 -10 -56 130 -30 -3 -10 10 26 90 -53 47 27 50 -67 40 3 26 -120 7 -23 23 -40 14 -93 -40 -74 16 -30 -10 7 -43 -33 -40 -127 -37 -33 -33 -64 -27 -6 -23 -30 -3 -10 -77 -20 -43 40 -34 13 -80 43 -6 37 -44 53 7 34 17 56 -10 27 -70 23 3 80 -37 60 -63 80 40 47 -20 40 -40 27 0 50 33 30 -13 33 10 10 -27 47 -30 -7 -53 63 -123 47 -40 27 6 26 -16 10 -57 27 -13züGúHìAIûûú[ì~LàM-524 4803l23 20 23 -10 24 17 43 0 17 23 -10 40 3 104 103 146 54 0 63 47 -77 97 -16 -7 0 3 10 7 -64 220 -56 40 0 33 -34 24 -3 26 -37 30 -36 14 -57 -74 -43 -13 -37 20 -33 -10 -47 10 -43 80 -50 23 -34 -3 -23 -17 -27 7 -40 -40 -120 3 -3 -26 67 -40 -27 -50 53 -47 -26 -90 10 -10 30 3 56 -130 37 10 13 20 47 14 13 -10 14 -120 53 -47 50 -23 3 -14 40 -10 10 -16 -10 -50 4 -14 33 4 -7 -40 27 -67 -13 -20 3 -50 47 -37züGúHìAIûûú[Cfil3LàM-3514 537l-10 33 10 27 -20 16 -27 110 -30 50 -33 0 0 47 -30 37 6 20 -23 46 23 70 -16 34 16 66 -50 80 -33 7 -17 -13 -53 -7 -17 7 4 16 -27 -6 -10 13 -20 -17 -10 10 -7 24 -30 0 -10 26 -73 -10 -97 40 -10 34 -23 10 -37 -20 -3 26 -7 4 -6 -14 -17 4 -10 33 -47 37 -10 -7 0 -27 -16 -3 -4 -17 30 -73 40 -27 -13 -23 -43 -7 -14 34 -30 -44 24 -20 -20 -30 6 -33 -3 -3 -23 -10 0 6 -24 -13 -16 27 -20 -27 20 -30 -7 -50 20 -37 47 -16 0 -14 -20 10 0 -26 40 -27 36 13 30 -33 20 3 7 -13 -10 -27 73 -36 70 40 57 -20 33 6 60 -43 30 17 14 -4 0 -23 16 -10 30 33 30 -6 7 -30 -27 0 -46 -34 10 -43 16 -7 -6 -10 16 -13 17 0 37 -47 13 10 30 -26 20 3 7 -43 40 0 46 -37 20 0 0 33 -3 7 7 10 13 3 7 -23 66 -37 14 7 -20 27züGúHìAIûûú[ìLàM-3174 727l20 -27 -4 -27 40 -10 80 20 20 -10 17 17 47 -13 70 16 90 -6 56 -17 64 20 46 -23 30 10 34 -34 36 -13 70 57 7 20 150 -4 67 20 36 37 47 -10 30 17 290 56 -17 30 14 30 -7 24 -40 -17 -13 20 -47 7 -7 53 -53 3 -17 -30 -26 -6 -47 40 -37 0 -26 56 -17 -13 -37 23 -80 -6 -16 30 -40 -4 -10 24 -30 3 -54 -17 -43 14 -27 36 -60 -10 -36 -23 -17 -40 -20 10 -33 -10 -17 30 -50 -17 -10 27 -73 -37 -30 47 -14 0 -6 13 10 7 -4 17 -63 16 -77 -10 -33 27 -33 -20 -10 -50 -40 -20 -24 13 -13 -23 30 -40 40 -10 23 -37 -26 -20 -44 24 0 -47 -46 -27 -4 -46 -33 -30 -3 -34 -20 -6 3 -30 37 0 30 -40züGúHìAIûûú[ìLàM-1831 823l157 0 220 -73 20 20 -34 17 4 16 13 4 40 -37 80 -30 77 33 0 14 -14 3 17 20 50 -3 7 10 46 3 44 33 0 27 -17 13 -77 -3 -63 47 10 73 -43 0 -77 -30 -50 60 -43 7 -7 26 -23 14 -7 0 -7 -4 -6 0 -4 0 -6 -3 -7 0 -3 3 -7 4 -3 3 -4 7 -3 3 -3 3 -7 4 -3 3 -7 0 -7 -3 -3 0 -7 -4 -6 0 -7 0 -3 4 -7 0 -3 3 -4 7 4 6 3 4 3 3 7 3 7 -3 6 0 7 0 7 -3 6 0 7 0 3 0 7 -4 7 -3 3 0 7 -3 -17 50 20 16 53 -30 10 20 -43 27 10 23 33 -20 4 27 3 27 -40 0 -27 30 -76 -4 -57 -36 30 -17 -3 -20 -30 17 -14 -7 -10 -77 -60 -13 -33 -53 -23 -7 -57 27 -87 3 -20 -50 -36 -20 3 -57 53 -3 7 -53 47 -7 13 -20 40 17 7 -24 -14 -30 17 -30züGúHìAIûûú[ìLàM-778 1040l10 30 -40 27 4 23 26 13 77 0 80 44 10 36 -23 34 3 36 -27 14 20 56 -36 17 -27 -20 -47 37 24 30 23 -20 13 26 -13 50 -37 7 -3 -3 -7 0 -3 -4 -7 0 -6 0 -7 0 -3 4 -7 0 -7 0 -3 3 -7 3 -6 0 -4 0 -6 0 -7 -3 -7 0 -3 -3 -3 -7 -4 -3 -3 -4 -7 0 -10 -3 10 -53 -33 -27 -33 47 -4 -7 -3 -3 -3 -7 -4 -3 -3 -7 -3 -3 -4 -7 -3 -3 0 -7 -3 -10 0 -3 -4 -7 0 -7 -3 -3 -3 -7 -4 -3 -6 -3 -4 -4 -3 -3 -7 -3 -6 0 -4 -4 -6 0 -7 -3 -3 0 -7 -3 -3 -4 -7 -3 -3 -3 -4 -4 -6 -6 -4 -4 -3 -3 -3 -7 -4 -3 -6 0 -7 0 -7 0 -3 0 -7 0 -10 3 -10 -10 10 -66 -6 -7 -10 10 -24 0 -10 27 -33 -34 33 -56 60 33 67 -23 -43 -57 -60 -7 16 -13 4 -47 -24 -16 17 -27 57 3 3 -36 30 3 20 40 -13 40 93 43 83 7 -10 -40 60 -10m-143 217l-20 43 53 50 44 -10 23 20 53 0 10 -7 -3 -16 -10 0 -10 6 -7 -3 -20 -17 17 -30 -7 -16 -123 -20züGúHìAIûûú[ìLàM1532 1380l114 27 3 6 20 47 23 13 40 -10 27 -43 67 -17 93 27 20 30 30 10 23 -23 40 6 20 -43 57 -10 80 -53 50 0 30 30 43 -10 0 56 20 14 37 -7 20 20 -10 40 -37 23 -26 -20 -24 37 10 63 34 14 20 30 -10 33 23 40 -10 50 -53 40 -24 43 -53 54 -60 23 -23 30 -14 -60 -56 -3 -60 26 -44 -46 -73 -14 -7 -43 4 -7 20 4 50 -30 -4 -17 -26 -20 26 -10 10 -37 -10 -30 -36 4 -34 -37 -33 10 -20 -27 -73 30 -64 -23 -16 -20 3 -13 23 0 0 -14 -10 -13 17 -47 -77 -13 -43 10 3 -43 -30 3 0 -3 4 -34 -44 -13 0 -40züGúHìAIûûú[ìLàM1396 2057l26 6 4 20 -27 20 47 30 3 54 57 26 -10 14 16 33 24 -3 -7 30 -20 3 3 7 30 10 0 23 -230 77 -23 40 -30 -10 -77 30 -140 176 24 27 33 -3 57 36 -4 4 -63 46 -50 64 -33 0 -7 -14 43 -10 -3 -30 -47 17 -40 70 -43 -17 -23 -36 -70 -20 6 -37 -33 -10 -13 -20 -24 0 -3 -10 33 -20 24 -37 -17 -53 23 -57 -13 -36 -27 -10 -6 -24 -7 -40 47 -26 6 -37 34 -23 0 -4 3 -23 23 0 10 -23 74 -10 20 16 76 -36 30 0 14 -24 20 14 43 -10 63 -74 -10 -20 10 -6 27 10 30 -14 -7 -36 27 -27 93 3 4 -16züGúHìAIûûú[ìLàM-601 4727l67 -124 63 -36 30 -47 33 20 47 -13 87 -64 3 -3 37 7 23 40 53 -10 44 -44 -17 -113 27 -30 3 -57 27 -26 20 -7 16 13 47 -40 47 -16 30 10 6 26 50 37 10 113 -43 60 7 50 50 14 16 33 -6 57 -30 56 6 34 7 10 67 103 43 40 43 13 7 27 -7 10 -10 -7 -13 7 -30 60 33 40 40 13 7 -3 -3 -17 3 0 20 24 -20 23 -113 40 -37 -23 -50 6 -27 17 4 10 -10 3 -54 -26 -20 16 -43 0 -70 54 -17 50 -23 0 -60 33 -63 -47 -54 0 -103 -146 -3 -104 10 -40 -17 -23 -43 0 -24 -17 -23 10 -23 -20 -77 -76züGúHìAIûûú[ìLàM-2468 4647l57 73 0 33 37 30 0 54 36 23 4 40 16 13 7 47 -7 3 -6 4 -7 0 -3 3 -7 3 -3 4 -7 0 -3 3 -7 3 -7 0 -3 4 0 33 30 33 97 -66 33 6 10 -3 3 -17 10 14 7 0 0 -17 43 -7 30 47 -10 27 4 3 16 -3 4 6 -4 67 30 50 30 7 10 60 17 16 50 -16 27 70 -44 3 7 37 -40 30 -23 -34 -30 30 -24 -6 -6 6 16 17 -6 20 -60 43 -70 17 -7 17 -43 36 -20 -3 -24 -37 -26 -3 -57 50 -10 -3 -10 -24 23 -20 0 -26 -33 -7 -17 10 17 30 -3 17 -30 33 -17 0 -13 -17 -24 -10 -33 4 -13 20 -84 13 -26 43 -100 -3 -64 -33 -43 -4 0 -3 -20 -13 -30 10 -27 -30 14 -40 -17 -64 27 -30 -4 -86 14 -40 -27 -37 23 -13 -6 -37 30 -17 -47 -90 0 -33 -80 -10 -7 -17 44 -60 116 -23 20 20 17 -3 7 -40 36 -20 -20 -27 20 -33 -26 -7 -4 -17 44 -30 96 -20 20 -40 -3 -33 50 -47 47 -10 26 10 10 20 -30 20 14 30 50 -40 26 4züGúHìAIûûú[ìLàM-2871 5540l0 3 43 4 64 33 100 3 26 -43 84 -13 13 -20 33 -4 24 10 13 17 17 0 30 -33 3 -17 -17 -30 17 -10 33 7 0 26 -23 20 10 24 10 3 57 -50 26 3 24 37 20 3 43 -36 23 30 7 40 -27 50 -33 10 -37 -30 -26 -4 -30 30 30 44 -24 66 -36 34 -37 10 -40 63 -47 -10 -6 3 3 20 43 10 20 -23 17 -3 30 3 43 80 10 60 10 7 17 -7 20 20 -43 60 -14 53 -6 0 -14 -13 -30 -3 -6 3 0 77 -90 43 -17 -3 -40 -37 -73 -17 -54 -66 -16 -7 -57 -3 -17 -14 -36 -63 -27 -17 -90 -170 17 0 26 47 7 3 20 -26 -3 -7 -17 3 -7 -13 0 -37 -36 -30 -44 -3 -33 -73 10 -24 53 -30 14 -60 13 -13 30 0züGúHìAIûûú[Cfil4LàM-1104 853l26 -10 37 20 -3 -30 46 -23 4 -20 73 3 23 -20 34 34 100 23 50 40 -10 23 10 17 -37 47 -3 63 -24 20 -60 10 10 40 -83 -7 -93 -43 13 -40 -20 -40 -30 -3 -3 36 -57 -3 -67 -27 -83 47 -10 -73 63 -47 77 3 17 -13 0 -27züGúHìAIûûú[ìLàM-378 833l30 47 -30 7 -23 46 -43 10 6 60 -60 47 -13 60 -27 7 -20 26 -40 -10 -23 44 -80 -44 -77 0 -26 -13 -4 -23 40 -27 -10 -30 24 -20 3 -63 37 -47 -10 -17 10 -23 50 17 63 -14 40 17 127 -40 46 -37 10 20züGúHìAIûûú[ìLàM-4108 1297l10 -34 97 -40 73 10 10 -26 30 0 7 -24 10 -10 20 17 10 -13 27 6 -4 -16 17 -7 53 7 17 13 33 -7 14 4 -7 53 57 47 -37 100 -53 20 -87 -17 -93 50 6 100 37 37 -3 40 16 13 27 -7 0 7 -3 7 3 3 0 7 0 6 0 7 0 3 -3 7 -4 3 -3 7 -3 0 -7 3 -3 4 -7 3 -7 0 -3 3 -7 0 -6 4 -4 3 -6 3 -4 4 -3 3 -7 3 -3 4 -7 3 -3 3 -7 0 -6 4 -4 0 -6 3 -7 0 -7 0 -3 0 -7 0 -6 0 -7 0 -3 0 -7 -3 -7 0 -3 0 -7 0 -6 0 -7 3 -3 3 -4 4 -6 3 -4 3 -6 4 -4 0 -6 0 -7 -4 -7 0 -3 4 -7 3 -3 0 -7 3 -3 4 -7 3 -3 3 -3 7 -4 3 -3 7 -3 3 -4 4 -3 6 -7 4 -3 3 -3 3 -4 4 -6 6 -4 4 -3 3 -73 40 0 -160 23 -13 7 3 6 -10 -6 -13 43 -47 83 -43 7 -40 -7 -7 -30 50 -70 13 0 -53 20 -3 54 -64 -7 -10 -40 30 -43 0 -17 -46 -27 -7 4 -10 26 -17 10 14 -3 10 10 10 13 -4 -3 -20 13 -3 -13 -53 33 -17 20 -43züGúHìAIûûú[ìLàM1599 1510l43 -10 77 13 -17 47 10 13 0 14 -23 0 -3 13 16 20 64 23 73 -30 20 27 33 -10 34 37 36 -4 10 30 -10 37 -26 10 26 20 4 17 -50 30 -20 -4 -4 7 7 43 73 14 44 46 60 -26 56 3 14 60 -274 167 -70 126 -260 87 0 -23 -30 -10 -3 -7 20 -3 7 -30 -24 3 -16 -33 10 -14 -57 -26 -3 -54 -47 -30 27 -20 -4 -20 -26 -6 -20 -27 43 -20 -37 -43 17 -17 -3 -50 26 -7 4 24 13 -14 23 20 27 -16 17 -67 -30 -10 36 -37 0 -33 17 -7 3 -6 -20 -7 24 -17 -14 -20 24 -26 -14 -37 20 -23 -6 -17 -27 -7 7 -26 -14 -34 87 -23züGúHìAIûûú[ìLàM-1308 2450l30 50 34 10 -4 23 24 37 -57 147 33 26 -13 50 33 14 10 -14 14 34 26 -4 -10 37 24 23 0 24 20 -7 30 20 0 50 26 13 14 24 -34 106 10 7 40 -27 17 84 0 3 -13 10 20 40 -57 17 -7 -17 -40 30 -26 0 -4 0 -3 3 -7 0 -6 0 -4 0 -6 0 -7 0 -7 0 -10 0 -6 0 -7 0 -3 0 -7 0 -7 0 -6 0 -27 0 -13 20 -60 20 0 20 -50 10 -50 47 -7 -3 -23 -27 3 -3 3 -4 7 -3 3 -3 7 -4 3 -3 7 -3 3 0 7 -4 3 -3 7 -3 7 0 6 0 4 0 6 -4 0 -6 4 -4 3 -6 3 -4 4 -3 6 -3 4 -4 3 -6 7 -4 3 -3 3 -3 7 -4 3 -3 7 0 13 -23 -6 -24 -57 -20 -20 7 -23 -27 -110 -30 -34 -36 -43 16 -30 -36 -30 13 -30 40 -30 -27 -7 -26 -16 -4 -30 44 -47 30 -27 -14 24 -56 -4 -27 10 -7 30 14 24 -60 56 -7 0 -97 24 -26 -4 -24 7 -6 17 13 40 -13 6 -50 47 -70 53 0 17 -87 27 -43 63 -24 90 -110 43 -13züGúHìAIûûú[ìLàM3082 3223l-163 -76 -83 16 -10 -6 0 -47 -24 -17 20 -30 124 -10 16 -10 0 -10 14 24 16 -7 0 -3 4 -7 13 0 23 43 37 4 13 53 24 23 0 7 -20 -7 0 7 16 20 -20 33züGúHìAIûûú[ìLàM-131 3167l67 3 3 -40 13 0 14 27 16 30 54 0 40 36 0 20 -47 20 -40 14 -37 -7 -43 -7 -40 -96züGúHìAIûûú[ìLàM2509 3607l-7 10 -3 0 -60 53 -13 0 -54 -60 -73 10 -30 -10 -33 -70 13 -27 -47 -36 -73 30 -10 46 -7 0 -30 -43 -50 0 -13 -30 7 -27 113 -80 107 -113 36 -10 54 -47 66 -6 57 -37 17 3 3 4 -63 40 13 30 43 -20 7 3 -7 30 -33 7 10 36 70 34 53 -47 60 23 10 20 -13 64 -23 6 6 34 -53 60 -13 66 -7 14 -27 36 -3 4züGúHìAIûûú[ìLàM242 3353l37 47 20 -27 20 7 10 63 67 -3 23 33 43 -33 24 -40 36 7 17 30 47 16 -7 47 -63 113 -7 57 0 7 27 83 46 83 -6 24 -4 6 37 84 90 103 0 23 -23 -23 -40 23 -14 -16 -30 23 -53 -20 -83 60 -67 3 0 24 40 3 7 13 -67 47 -17 -37 -50 -16 -46 23 -20 -27 -27 0 -13 -16 0 -67 -24 -43 -103 10 -73 -84 40 -106 0 -4 10 -76 -100 -20 -34 -27 -26 10 -34 -40 -13 -20 13 -87 64 -86 36 10 27 -14 -3 -43 36 -87 -3 -46 -3 -17 36 -17 80 -10 44 14 23 76 53 -20züGúHìAIûûú[ìLgM2382 3780l-23 -20 3 -3 24 -4 3 7 -7 20zGúHìAIûûú[ìLàM1499 4057l-13 -27 -7 0 -57 0 -10 -3 -6 -54 3 -6 40 -10 3 -10 -6 -34 36 -30 94 -43 43 17 -7 20 17 20 0 10 -40 33 -23 43 -40 20 -4 47 -23 7züGúHìAIûûú[ìLàM699 4060l130 50 0 17 27 33 -70 50 -14 30 -60 13 -33 67 -33 -3 -117 63 -23 30 -10 50 -20 -7 -30 20 0 94 -64 33 -3 33 -7 94 -26 13 -34 93 -43 -13 -43 -40 -67 -103 -7 -10 -6 -34 30 -56 6 -57 -16 -33 -50 -14 -7 -50 43 -60 -10 -113 67 -23 -33 -64 20 -16 13 16 27 0 20 27 46 -23 50 16 17 37 67 -47 -7 -13 -40 -3 0 -24 67 -3 83 -60 53 20 30 -23 14 16 40 -23 23 23 0 -23züGúHìAIûûú[ìLàM1519 4193l-10 -56 27 -30 6 0 34 46 23 10 20 -10 3 0 4 7 -4 7 -23 13 -33 -17 -14 0 -33 30züGúHìAIûûú[ìLàM-1934 5297l23 3 10 30 33 0 27 -10 17 -37 36 -6 10 43 34 27 20 43 10 77 30 3 6 23 64 27 33 33 127 37 33 40 -7 43 -33 -13 -77 23 -66 -20 -34 27 -156 -7 -64 94 -53 20 -20 43 -57 17 -126 -7 -134 57 -43 73 -20 -20 -17 7 -10 -7 -10 -60 -43 -80 -30 -3 -17 3 -20 23 -43 -10 -3 -20 6 -3 47 10 40 -63 37 -10 36 -34 24 -66 -30 -44 30 -30 26 4 37 30 33 -10 27 -50 -7 -40 -23 -30 7 -17 70 -17 60 -43 6 -20 -16 -17 6 -6 24 6 30 -30 23 34 40 -30 -7 -37 44 -3züGúHìAIûûú[Cfil5LäM-3514 537l20 -27 -14 -7 -66 37 -7 23 -13 -3 -7 -10 3 -7 0 -33 -20 0 -46 37 -40 0 -7 43 -20 -3 -30 26 -13 -10 -37 47 -17 0 -16 13 6 10 -16 7 -10 43 46 34 27 0 -7 30 -30 6 -30 -33 -16 10 0 23 -14 4 -30 -17 -60 43 -33 -6 -57 20 -70 -40 -73 36 10 27 -7 13 -20 -3 -30 33 -36 -13 -40 27 0 26 20 -10 0 14 -47 16 -20 37 7 50 -20 30 20 27 16 -27 24 13 0 -6 23 10 3 3 -6 33 20 30 -24 20 30 44 14 -34 43 7 13 23 -40 27 -30 73 4 17 16 3 0 27 10 7 47 -37 10 -33 17 -4 6 14 7 -4 3 -26 37 20 23 -10 -20 43 -33 17 13 53 -13 3 3 20 -13 4 -10 -10 3 -10 -10 -14 -26 17 -4 10 27 7 17 46 43 0 40 -30 7 10 -54 64 -20 3 0 53 70 -13 30 -50 7 7 -7 40 -83 43 -43 47 6 13 -6 10 -7 -3 -23 13 0 160 73 -40 3 -3 -73 60 -10 83 23 47 24 156 -10 40 23 64 10 103 20 33 7 7 6 87 -66 250 3 0 23 -34 20 -80 10 0 7 10 0 7 -20 20 -3 10 0 20 23 10 0 3 -17 4 -20 50 -33 0 -10 26 -60 214 -37 83 27 40 0 3 -123 287 -20 103 -94 117 -73 33 -7 30 10 24 0 43 -53 113 0 94 -57 120 14 26 -7 20 7 14 80 23 100 -17 20 -13 30 -83 36 -50 14 0 3 50 27 50 -4 13 -70 33 4 17 36 -3 0 3 -16 7 -4 13 -3 0 -17 -10 -20 7 7 30 0 3 -10 -13 -23 -4 -4 -3 7 -3 -10 -24 -13 0 -44 14 -6 13 33 83 -20 74 7 6 16 -10 57 0 110 -53 63 33 10 -36 10 0 10 6 4 10 -20 37 16 17 -3 6 -53 -16 0 10 -7 0 -17 -17 -3 0 30 50 10 127 -33 123 -37 57 43 30 -10 126 20 14 0 6 -10 7 -20 70 10 107 -53 103 7 37 -37 53 3 30 -50 97 24 16 70 -43 93 -10 33 -37 44 17 3 -13 7 3 3 17 27 16 56 -10 54 27 60 -13 113 66 110 -3 127 -87 60 -20 20 4 13 -10 -3 -47 6 13 20 37 10 7 27 -14 113 -13 80 33 10 -6 -6 -14 30 -16 6 3 -10 27 217 140 57 70 23 56 20 10 13 -6 17 -50 30 -10 20 13 -30 0 -13 13 -14 60 -53 30 -10 24 33 73 44 3 36 30 0 37 7 13 17 -3 3 7 -20 26 -7 -3 -26 -47 -17 0 90 170 27 17 36 63 17 14 57 3 16 7 54 66 73 17 40 37 17 3 90 -43 0 -77 6 -3 30 3 14 13 0 24 6 -24 14 -53 43 -60 43 -73 134 -57 126 7 57 -17 20 -43 53 -20 64 -94 156 7 34 -27 66 20 77 -23 33 13 30 10 74 -16 93 40 40 -14 23 -23 120 -7 120 -3 40 40 27 -7 23 17 34 3 50 -23 43 -80 47 -10 33 10 37 -20 43 13 57 74 36 -14 37 -30 3 -26 34 -24 0 -33 56 -40 64 -220 -10 -7 0 -3 16 7 77 -97 60 -33 23 0 17 -50 70 -54 43 0 20 -16 54 26 10 -3 -4 -10 27 -17 50 -6 37 23 113 -40 20 -23 -20 -24 -3 0 3 17 -7 3 -40 -13 -33 -40 30 -60 13 -7 10 7 7 -10 -7 -27 34 -93 26 -13 7 -94 3 -33 64 -33 0 -94 30 -20 20 7 10 -50 23 -30 117 -63 33 3 33 -67 60 -13 14 -30 70 -50 -27 -33 0 -17 -130 -50 -90 -103 -37 -84 4 -6 6 -24 -46 -83 -27 -83 0 -7 7 -57 63 -113 7 -47 43 -80 57 -70 20 -80 56 -40 17 -60 90 -103 83 -170 40 -70 47 -17 3 30 -43 10 7 14 33 0 50 -64 63 -46 4 -4 -57 -36 -33 3 -24 -27 140 -176 77 -30 30 10 23 -40 230 -77 260 -87 70 -126 274 -167 23 -30 60 -23 53 -54 24 -43 53 -40 10 -50 -23 -40 10 -33 -20 -30 -34 -14 -10 -63 24 -37 26 20 37 -23 10 -40 -20 -20 -37 7 -20 -14 0 -56 -26 -34 3 -23 -50 -23 -17 -220 -3 0 -10 43 -23 -3 -10 -24 20 -43 20 -7 0 -16 -20 -14 3 -6 13 0 17 -67 -17 -10 0 -7 17 4 23 -60 80 -90 64 -30 43 6 70 -90 190 -140 47 0 10 40 30 20 40 0 3 -6 -13 -10 20 -17 16 7 7 23 37 -3 60 -7 40 0 36 23 34 14 16 0 37 6 0 -3 3 -20 24 -3 23 23 17 20 43 3 33 -3 34 0 20 -17 -20 -10 13 -10 53 0 24 -3 16 -7 0 4750 -36 -6 -277 40 -37 -17 -86 30 -50 53 -90 44 -100 0 -50 -20 -10 43 -40 17 -30 -7 -40 -40 -70 13 -57 84 -123 80 -100 6 -10 -20 -34 -6 -183 66 -93 0 -220 47 -77 -10 -50 30 -50 0 -67 23 -66 30 -44 54 -66 36 -64 10 -106 80 -67 20 -23 44 -50 23 -47 47 -3 10 -40 120 -87 70 -110 -24 -3 -3 -7 -30 -40 -23 -67 20 -23 76 -30 10 -30 37 -37 0 -16 -20 -64 -17 -26 40 -37 -3 -60 33 -70 80 -20 0 -40 130 -27 37 -43 33 -53 4 -37 20 -140 120 -23 -4 -87 40 -57 4 -63 -20 -40 10 -67 -27 -50 -20 -53 40 -100 -3 -57 -24 -66 -66 20 36 53 44 -20 6 -67 -33 -10 -83 -20 -40 -13 -34 10 -40 -17 -6 -53 110 -33 0 -34 36 -83 34 -140 -17 -73 -50 -37 10 -13 40 -30 13 -50 -10 -20 -33 -34 20 -36 -7 -60 34 -67 6 -43 27 -220 -43 -217 -147 -67 -97 -43 -23 -17 -80 -26 -13 -14 -107 30 -30 -3 -13 -53 -10 -47 3 -70 60 -60 -7 -47 37 -70 -13 -26 10 -60 213 -170 433 -144 284 -2296 0 0 -6920 5206 0 -33 183 3 73 -43 80 -33 70 -44 40 -43 4 -17 16 -10 -20 -46 37 -127 40 -40 -17 -63 14 -50 -17 -50 -40 -100 -23 -34 -34 -23 20 -73 -3 -4 20 -46 23 3 30 -37 -20 -26 10 -44 -33 -46 -3 -7 -10 -50 3 -17 -20 14 -3 0 -14 -77 -33 -80 30 -40 37 -13 -4 -4 -16 34 -17 -20 -20 -220 73 -157 0 -290 -56 -30 -17 -47 10 -36 -37 -67 -20 -150 4 -7 -20 -70 -57 -36 13 -34 34 -30 -10 -46 23 -64 -20 -56 17 -90 6 -70 -16 -47 13 -17 -17 -20 10 -80 -20 -40 10 4 27 -20 27 3 -50 -103 -10 -34 -24 -36 -63 -54 -20 4 -13 -44 -4 -20 34 -10 -7 -10 -37 -36 4m6596 2686l20 -33 -16 -20 0 -7 20 7 0 -7 -24 -23 -13 -53 -37 -4 -23 -43 -13 0 -4 7 0 3 -16 7 -14 -24 0 10 -16 10 -124 10 -20 30 24 17 0 47 10 6 83 -16 163 76m-573 384l3 -4 27 -36 7 -14 13 -66 53 -60 -6 -34 23 -6 13 -64 -10 -20 -60 -23 -53 47 -70 -34 -10 -36 33 -7 7 -30 -7 -3 -43 20 -13 -30 63 -40 -3 -4 -17 -3 -57 37 -66 6 -54 47 -36 10 -107 113 -113 80 -7 27 13 30 50 0 30 43 7 0 10 -46 73 -30 47 36 -13 27 33 70 30 10 73 -10 54 60 13 0 60 -53 3 0 7 -10m-127 173l7 -20 -3 -7 -24 4 -3 3 23 20m-883 277l23 -7 4 -47 40 -20 23 -43 40 -33 0 -10 -17 -20 7 -20 -43 -17 -94 43 -36 30 6 34 -3 10 -40 10 -3 6 6 54 10 3 57 0 7 0 13 27m20 136l33 -30 14 0 33 17 23 -13 4 -7 -4 -7 -3 0 -20 10 -23 -10 -34 -46 -6 0 -27 30 10 56züGúHìAIûûú[ìLàM-1494 1087l3 3 3 7 4 3 0 7 0 6 -4 4 -3 6 -7 -3 -3 0 -7 -3 -6 0 -4 0 -6 0 -10 0 -7 3 -3 0 -7 3 -7 4 -3 0 -7 0 -6 0 -7 3 -7 0 -6 0 -7 3 -7 -3 -3 -3 -3 -4 -4 -6 4 -7 3 -3 7 0 3 -4 7 0 6 0 7 4 3 0 7 3 7 0 3 -3 7 -4 3 -3 3 -3 4 -7 3 -3 7 -4 3 -3 7 0 6 3 4 0 6 0 7 4 7 0züGúHìAIûûú[ìLàM-3568 1347l0 -7 -3 -7 -3 -3 0 -7 0 -6 0 -7 0 -3 3 -7 0 -7 3 -3 4 -7 6 -3 4 -3 3 -4 3 -6 0 -4 4 -6 0 -7 3 -3 3 -4 7 -6 3 -4 4 -3 3 -7 3 -3 0 -7 4 -3 3 -7 3 -3 7 -3 3 -7 4 -3 6 0 7 -4 7 4 -4 3 -3 7 -3 3 -4 7 -3 3 -3 3 -7 4 -7 3 -3 3 0 7 -3 3 -4 7 -3 3 -3 7 -4 3 0 7 -3 3 -3 7 -4 3 0 7 0 7 -6 3 -4 3 -6 4 0 3 -4 7 0 6 0 4 0 6 0 7 0 7 -3 3 -7 7züGúHìAIûûú[ìLàM-2534 1950l3 7 0 6 -3 7 -4 3 -3 7 -3 3 0 7 0 3 0 7 3 7 3 3 4 7 3 3 0 7 3 6 0 7 0 3 -6 4 -7 3 -7 0 -3 0 -7 0 -6 0 0 7 -4 6 4 4 3 6 3 7 0 3 -6 4 -7 0 -7 -4 -3 4 -7 0 -3 3 -3 7 0 6 -4 4 0 6 0 7 -3 3 -7 4 -3 0 -7 0 -6 3 -4 7 0 3 -3 7 0 6 3 4 0 6 -3 4 -7 3 -3 3 -3 -6 0 -7 -4 -3 0 -7 0 -7 -3 -3 -7 -3 0 -7 0 -7 4 0 6 0 7 0 3 -3 7 -3 7 -4 3 0 7 -3 3 -3 0 -7 0 -7 0 -6 3 -7 4 -3 3 0 7 0 3 -7 7 -3 0 -4 3 -6 3 -4 4 -6 6 -4 4 -3 3 -3 3 -4 4 -6 0 -7 0 -7 0 -3 -4 -7 -3 -3 -3 -7 0 -6 0 -7 3 -3 3 -7 4 0 6 0 4 -3 3 -7 3 -3 4 -7züGúHìAIûûú[ìLàM759 2217l7 3 3 3 7 4 3 3 3 3 4 7 3 3 3 7 -10 0 -6 0 -7 -3 -3 -4 -4 -3 -3 -7 -7 -3 -3 -3 -7 0 -6 0 -4 0 -6 0 -7 3 -7 3 -3 4 -3 3 0 7 0 6 -4 4 0 6 -3 7 -3 3 -4 7 -3 3 -3 7 -4 3 -3 4 -7 3 -6 0 -4 3 -6 0 -4 4 -3 6 -3 4 -4 6 0 7 -3 3 -3 7 -7 3 -3 0 -7 0 -7 0 -3 -3 -7 -3 -6 0 -4 0 -6 -4 -7 0 -7 0 -3 -3 0 -10 7 -3 3 -4 7 0 6 0 4 0 6 4 7 3 3 0 7 0 7 0 0 -7 0 -6 3 -4 0 -6 0 -7 7 -3 3 -4 7 0 6 0 4 0 6 0 7 -3 3 -3 4 -4 3 -6 0 -7 3 -7 0 -6 4 -4 3 -6 3 -4 7 -3 3 -3 4 -7 3 -3 7 -4 3 -3 7 0 6 -3 4 0 6 0 7 3 3 3 7 4züGúHìAIûûú[ìLàM-2838 2350l-3 -3 3 0 7 -4 3 -3 7 -3 3 -7 4 -3 3 -7 3 -3 7 0 3 3 7 7 0 3 0 7 0 6 0 7 0 7 3 3 4 3 6 0 7 0 3 4 4 3 6 7 0 3 4 7 3 6 3 4 4 3 6 0 4 -3 6 -7 4 0 3 3 7 7 6 3 4 4 3 6 3 4 4 3 3 7 7 3 3 3 3 7 4 3 3 7 3 3 4 7 0 3 3 7 0 7 0 3 -7 7 -3 -4 -3 -3 -7 -3 -3 -4 -4 -6 0 -7 -3 -3 0 -7 -3 -7 -4 -3 -3 -3 -7 0 -6 0 -7 0 -3 3 0 7 -4 0 -3 -4 -3 -6 0 -4 0 -6 0 -7 -4 -3 -3 -7 -3 -3 -7 0 -7 0 -3 0 -3 -7 -7 -3 -3 -4 -7 0 -7 -3 -3 -3 -3 -7 -7 0 -3 3 0 7 -4 3 -3 7 -7 3 -3 4 -7 -4 0 -3 -3 -7 3 -6 4 -4 0 -6 3 -7 -3 -7 -4 -3 -3 -3 -7 -7züGúHìAIûûú[ìLàM-804 2803l0 10 -4 4 -6 3 -7 0 -3 3 -4 4 -6 3 -4 7 -3 3 0 7 -3 3 0 7 0 6 0 7 3 3 7 4 3 3 3 7 -3 3 -3 7 -4 3 -3 3 -3 7 0 7 0 3 -4 7 -3 3 -3 7 -4 0 -6 -7 3 -7 0 -3 0 -7 3 -6 0 -7 4 -3 0 -7 -4 -3 -3 -7 -3 -3 0 -7 3 -7 3 -3 0 -7 4 -6 0 -4 3 -6 3 -4 4 -6 0 -7 3 -3 3 -7 4 -3 6 0 7 -4 7 0 3 0 7 0züGúHìAIûûú[ìLàM-731 2977l7 0 6 0 7 3 3 3 0 4 -3 6 -7 0 -6 0 -4 -3 -6 0 -7 -3 -3 -4 -7 0 -3 -3 -7 -3 -3 0 -7 -4 -7 0 -6 0 -4 0 -6 0 -7 0 -7 0 -3 4 -7 0 -6 3 -4 3 -3 4 -3 6 -4 4 0 6 0 7 0 3 4 7 3 3 3 7 4 3 3 4 3 6 0 7 0 3 -3 7 0 7 -3 6 -4 0 -6 0 -7 0 -3 -3 -4 -3 -3 -7 0 -3 -3 -7 0 -7 0 -6 0 -4 0 -6 -4 -7 -3 -3 -7 -4 -3 -3 -7 -3 0 -4 4 -6 6 -4 4 -6 3 -4 3 -3 7 -3 3 -4 7 -3 7 0 3 -3 7 -4 3 0 7 0 6 0 7 0 3 0 7 -3 7 0 3 -3 7 0 6 -4 4 0 6 0 7 0 3 7 0 3 4 7 3 3 3 4 7 0züGúHìAIûûú[ìLàM-2711 2997l3 6 -3 7 -3 3 -4 4 -3 6 -3 4 -7 3 -3 3 -4 4 -3 6 0 7 0 7 0 3 3 7 0 6 7 4 3 3 7 3 3 0 7 4 0 6 0 7 0 7 -3 3 -4 3 -3 4 -7 3 -3 3 -7 0 -6 0 -7 4 -7 0 -3 -4 -7 -3 -3 -3 0 -7 3 -3 0 -7 4 -7 3 -3 3 -3 4 -7 6 -3 0 -7 0 -3 0 -7 -3 -7 -3 -3 -7 0 -3 -3 -7 3 -7 0 -6 3 -7 0 0 -3 3 -7 4 -6 6 -4 4 4 6 0 7 3 3 0 7 -7 3 -3 7 -3 3 -4 4 -3 3 -7 3 -3 4 -3 3 -7 10 -3züGúHìAIûûú[ìLäM-3178 3467l-3 -7 0 -3 3 -7 4 -3 3 -7 3 -3 4 -7 3 -3 3 -7 0 -3 4 -7 3 -7 3 -3 0 -7 4 -3 3 -7 3 -3 0 -7 4 -3 3 -7 3 -3 7 -3 3 -4 7 -3 3 -3 7 -4 3 0 7 -3 0 -7 0 -6 0 -4 0 -6 3 -7 7 3 3 4 -3 6 0 7 3 3 7 0 3 -3 7 -3 3 -4 4 -3 6 -3 7 -4 3 0 7 -3 3 -3 7 -4 3 0 7 -3 7 0 6 0 4 7 0 3 -7 0 -7 0 -3 3 -7 4 -6 3 -4 0 -6 0 -7 3 -3 0 -7 4 -3 3 -7 3 -3 4 -4 3 -6 3 -4 7 -3 3 -7 0 -6 0 -4 4 -6 0 -7 3 -7 0 -3 7 0 3 -3 7 -4 3 0 7 -3 6 -3 4 0 6 -4 4 -3 6 -3 4 -4 6 -3 4 -3 6 -4 4 -3 3 -7 7 4 3 3 3 7 -3 3 -3 7 -4 3 0 7 -3 3 -3 7 0 6 -4 4 -3 6 0 7 0 7 -3 3 0 7 -4 3 -3 3 -3 7 -4 3 0 4 7 -4 3 -6 4 0 6 3 4 7 0 6 0 7 -4 3 -3 4 -3 6 0 7 0 7 -4 3 4 3 3 4 7 3 6 3 4 4 3 6 3 4 4 6 3 4 3 3 4 7 0 6 3 7 -3 0 -4 3 -6 7 -4 7 0 3 4 7 0 6 3 0 3 0 7 7 3 3 0 7 0 3 -3 7 -3 3 -4 7 -3 7 0 3 0 7 -3 6 0 4 0 6 0 7 0 7 -4 3 0 7 0 6 0 7 -3 3 0 7 -3 7 0 3 -4 7 -3 3 0 7 -3 6 0 4 -4 6 -3 7 0 3 -3 7 -4 7 0 3 0 7 -3 3 -3 3 -4 7 -6 0 -7 0 -3 7 -7 3 0 0 7 0 6 3 7 -10 7 -3 3 -3 3 -7 4 -3 6 -4 4 -6 0 -4 0 -6 0 -7 3 -3 0 -7 3 -7 4 -3 0 -7 3 -3 3 -7 4 -6 0 -4 3 -6 3 -7 0 -3 4 -7 0 -7 0 -3 0 -7 0 -6 0 -7 0 -3 3 -7 0 -7 3 -3 0 -7 0 -6 4 -7 0 -3 0 -7 3 -7 0 -3 3 -7 0 -6 4 -4 3 -3 7 3 3 4 7 0 6 3 4 3 3 4 7 6 3 4 7 3 3 3 3 4 7 3 3 3 4 4 6 6 0 4 4 6 3 7 0 7 0 3 0 7 0 6 -3 7 0 3 0 7 0 7 3 3 3 3 4 7 3 3 3 7 4 3 3 7 3 3 4 7 3 3 3 7 0 7 4 3 0 7 3 3 3 0 7 -7 3 -3 0 -7 0 -6 0 -4 -3 -6 -3 -4 -4 -6 -3 -4 -3 -3 -4 -7 -3 -3 -3 -7 0 -6 -4 -4 -3 -6 0 -7 -3 -3 0 -7 0 -7 0 -6 0 -4 0 -6 0 -7 0 -7 0 -3 -4 -7 -3 -3 -3 -7 -4 -3 -3 -3 -3 -4 -7 -3 -3 -3 -7 -4 -3 0 -7 -3 -7 -3 -3 -4 -7 -3 -3 -3 -7 -4 -3 -6 0 -4 0 -6 0 -4 -7 4 -6 0 -4 0 -6 -7 -4 -3 -3 -7 -3 -3 -4 -7 0 -3 -3 -7 -3 -3 -4 -7 -3 -3 -3 -7 -7 -3 0 -7 -3 -7 0 -3 0 -7 3 -3 0 -7 0 -6 0 -7 0 -3 0 -7 0 -7 0 -6 0 -4 0 -6 0 -7 -3 -3 0 -7 3 -7 0 -6 0 -4 3 -6 4 -4 3 -3 3 -7 4 -3 3 -7 0 -6 0 -4 -3züGúHìAIûûú[ìLàM-2671 3397l3 -7 4 -3 6 -4 7 0 3 -3 4 -3 3 -7 3 -7 0 -3 0 -7 4 -6 3 -4 7 0 3 4 0 6 -3 7 0 3 -4 7 0 7 0 3 -6 3 -7 4 -3 3 -7 3 -3 4 -4 3 -6 0 -7 -3züGúHìAIûûú[ìLàM-2464 3453l0 -10 3 -3 3 -3 7 -4 3 -3 7 -3 7 0 3 0 7 -4 6 0 4 0 6 0 7 0 7 0 3 0 7 0 6 -3 7 3 3 -3 7 0 7 0 3 -3 7 -4 3 -3 3 -7 0 -6 4 -7 0 -3 6 0 7 0 3 6 0 7 0 3 -3 7 0 7 -3 3 0 7 0 6 3 7 3 3 7 4 -10 0 -3 -4 -4 -3 -6 -3 -4 -4 -6 4 -7 0 -7 3 -3 0 -7 3 -3 4 -7 0 -3 -7 -7 -3 -6 0 -4 0 -6 0 -7 0 -7 0 -3 0 -7 3 -6 0 -4 3 -6 4 -4 3 -6 3 -4 0 -6 0züGúHìAIûûú[ìLàM-3991 3567l0 -7 0 -7 3 -6 4 -4 6 0 7 4 3 -4 7 -3 3 -3 0 -7 -3 -3 -7 -4 0 -6 0 -7 4 -3 3 -7 3 -3 4 -7 3 -3 3 -4 4 -6 3 -4 0 -6 0 -7 0 -7 0 -3 0 -7 0 -6 0 -7 3 -3 0 -7 -3 -3 -3 -7 -4 -3 0 -7 4 0 6 0 7 3 7 0 3 4 3 6 -3 7 0 7 -3 3 0 7 -4 6 0 4 0 6 0 7 0 7 0 3 -3 7 0 6 0 7 0 3 7 4 6 0 4 3 3 3 -3 4 -7 0 -7 0 -3 0 -7 0 -3 6 0 4 3 6 0 7 0 7 -3 0 -3 3 -7 3 -3 7 -4 3 -3 7 -3 3 -4 4 -6 3 -7 0 -3 -3 -7 0züGúHìAIûûú[ìLàM-2668 3407l14 0 3 0 7 3 6 0 7 -3 3 3 4 3 3 7 3 7 4 0 6 3 7 0 3 0 7 3 3 4 7 3 3 7 4 3 6 0 4 3 6 0 7 0 7 0 3 -3 3 -3 7 -4 7 -3 3 -3 3 -4 4 -6 3 -4 3 -3 7 0 3 3 0 7 -6 3 -4 4 -3 3 -3 7 3 3 -7 3 -3 4 -7 0 -6 0 -4 3 -6 0 -7 3 -3 0 -7 0 -7 0 -6 0 -4 -3 -3 -3 -3 -4 -4 -6 -3 -4 -7 -3 -6 0 -4 0 -6 0 -7 0 -7 -3 -3 0 -3 -7 -4 -7 -3 -3 -7 0 -3 -3 -7 -4 -3 -3 -7 -3züGúHìAIûûú[ìLàM-484 3603l-4 4 -6 0 -4 -4 -6 -3 -4 -3 -3 -7 -3 -3 -4 -4 -6 0 -7 0 -7 0 -3 -3 -7 -3 -3 -4 0 -6 0 -7 -3 -3 -4 -7 -3 -3 -3 -4 -7 -3 -3 -7 -4 -3 -3 -3 -3 -7 -4 -7 -3 -3 -3 -3 -7 -4 0 -3 -3 -7 0 -6 -4 -4 0 -6 0 -7 4 -7 3 4 3 3 7 3 3 4 4 6 0 4 3 6 3 4 7 3 7 0 6 0 4 0 6 7 0 3 -3 7 -3 3 0 7 3 6 0 4 3 6 4 4 6 3 4 7 3 3 7 3 3 0 7 0 6 0 7 4 3 6 0 4 0 6 4 4 3 6 3 4 4 6züGúHìAIûûú[ìLàM-2094 3723l10 0 3 -3 7 0 6 0 4 3 6 4 7 0 3 3 7 3 0 7 3 7 -6 3 -7 3 -7 0 -3 -3 -7 3 0 7 4 3 6 4 4 3 6 3 4 4 6 3 4 3 3 4 3 3 -3 7 -3 6 3 4 3 6 4 4 3 6 0 7 3 3 -10 0 -6 -3 -4 -3 -3 -7 0 -3 -3 -7 -4 -7 0 -3 -3 -7 -7 -3 -3 0 -7 -3 -3 -7 -3 -3 -4 -4 -3 -6 -3 -4 -4 -6 -3 -4 -7 -3 -6 0 -7 3 -3 4 -7 3 0 3 -3 7 -4 3 0 7 -3 7 0 3 -3 7 -4 6 0 4 -3 6 -3 4 -4 6 -3 4 -3 6 -4 4 -6 3 -4 3 -6 4 -4 3 -6 3 -4 4 -6 0 -4 3 -6 3 -4 4 -6 3 -4 3 0 7 0 7 0 6 0 4 4 6 -7 4 -3 -4 -4 -10 0 -3 0 -7 4 -6 0 -7 3 -3 0 -7 3 -7 0 -3 0 -7 0 -6 0 -7 0 -3 4 -4 6 0 0 7 4 3 3 7 3 3 7 0 3 -3 7 -3 3 -4 7 -3 3 -3 4 -4 3 -6 3 -4 4 -6 3 -7 0 -3 0 -7 3 -7 0 -6 0 -4 0 -6 4 -7 0 -3 3 -10 3 -4 4 -6 6 -4 4 -3 6 0 4 -3 6 0 7 0 7 -4züGúHìAIûûú[ìLàM-2421 4023l3 -6 4 -7 3 -3 7 0 6 -4 4 0 6 -3 7 0 3 -3 7 -4 7 0 3 -3 7 -3 0 -7 3 -3 7 -4 3 -3 7 -3 3 -4 7 0 6 0 7 0 -10 7 -3 7 -4 3 -3 3 -7 4 -3 3 -3 3 -7 4 -3 3 -7 3 -7 4 -3 0 -7 3 -6 0 -4 3 -6 4 -4 3 -6 3 -4 4 -6 0 -7 0 0 -4züGúHìAIûûú[ìLàM-2391 4083l0 -6 0 -7 3 -3 7 -4 7 0 3 4 7 3 3 3 7 0 6 4 4 0 6 0 7 -4 7 0 3 -3 7 -3 3 -4 7 0 6 0 4 0 6 0 7 0 7 0 3 0 7 0 6 -3 4 -3 6 -4 4 -3 6 0 7 0 3 3 0 7 -3 7 0 3 -3 7 3 6 3 4 4 3 6 7 4 3 6 0 4 3 6 4 7 0 3 3 4 7 3 3 0 7 -3 6 -7 0 -7 -3 -3 -3 -7 -4 -3 -3 -3 -3 -7 -4 -3 -3 -7 -3 -3 -4 -4 -3 -3 -7 0 -6 -3 -4 -7 -3 -3 -3 -7 0 -7 0 -6 0 -4 0 -6 0 -7 0 -7 3 -3 0 -7 0 -3 7 -7 0 -6 3 -4 0 -6 0 -7 0 -7 -3 -3 0 -7 -4 -6 0 -4 0 -6 -3 -7 0 -7 0 -3 3züGúHìAIûûú[ìLàM-3454 4400l-7 7 -3 3 -4 3 -3 7 -3 3 -4 7 -3 3 -3 7 -4 3 -3 7 -3 3 -4 4 -3 6 -3 4 -4 6 -3 4 0 6 0 7 3 3 7 4 3 0 7 0 7 0 3 -4 7 0 6 -3 4 0 6 -3 7 0 3 -4 7 0 7 0 6 -3 4 0 6 0 7 3 7 0 3 4 7 0 3 6 0 7 0 7 -3 3 -4 0 -6 0 -7 0 -3 -3 -7 0 -7 0 -6 -4 -7 0 -3 0 -7 0 -7 0 -3 0 -7 0 -6 4 -4 3 -3 7 0 3 0 7 -3 6 -4 4 -3 6 -7 0 -3 4 -7 0 -6 0 -7 3 -3 0 -7 3 -3 4 -7 3 -3 3 -7 4 -3 3 0 7 -4 3 -3 7 -3 3 -7 3 -7 -6 0 -7 -3 -7 0 -3 0 -7 3 -6 0 -4 0 -6 0 -7 0 -7 -3 -3 0 -7 -3 -3 -7 -3 -3 -4 -7 -3 -7 0 -3 -7 3 -6 0 -4 -3 -6 0 -7 -3 -3 0 -7 0 -7 3 -3 7 -3 3 -4 3 4 4 6 0 7 0 7 3 3 3 7 4 3 3 7 3 3 4 3 3 7 3 3 4 7 3 3 0 7 3 7 4 0 3 -4 3 -6 4 -7 0 -3 3 -7 3 -7 0 -3 4 -7 0 -6 3 -4 0 -6 0 -7 0 -3 3 -7 4 -7 0 -6 -4 -4 -3 -6 -3 -4 0 -6 0 -4 3 -3 7 -3 6 0 7 0 7 3 6 0 4 -3 3 -4 3 -6 0 -7 4 -3 3 -7 0 -7 3 -3 4 -7 3 -3 3 -7 4 -3 0 -7 3 -3 0 -7 0 -6 0 -7 3 -3 0 -7 0 -7 -3 -6 -3 -4 -4 -3 -3 -7 0 -6 3 -4 7 4 7 3 6 0 4 0 6 -3 4 -7 0 -3 3 -7 0 -7 -3 -6 3 -4 0 -6 3 -4 7 -6 3 0 7 3 3 7 0 6 4 4 0 6 -4 7 0 3 -3 7 -3 7 -4 3 -3 3 -3 7 -4 3 -3 4 -3 6 -4 4 0 6 -3 7 0 7 0 3 0 7 0 6 0 4 0 6 3 7 0 7 -3 3 -3 7 -4 3 -3 7 -3 3züGúHìAIûûú[ìLàM-868 4683l-3 -3 3 -7 0 -6 4 -4 3 -6 0 -7 0 -3 3 -7 0 -7 0 -6 -3 -4 7 -3 3 -7 3 -3 4 -3 3 -7 3 -3 4 -7 6 0 0 3 0 7 -3 3 -3 4 -4 6 -3 4 -7 3 -3 7 -3 3 0 7 0 3 3 7 3 6 4 4 0 6 -4 4 -3 6 -3 4 -7 3 -7 3züGúHìAIûûú[ìLàM3402 6413l-6 -6 -4 0 -6 0 -7 0 -7 0 -3 -4 -7 -3 0 -7 0 -6 4 -4 0 -6 0 -7 0 -7 0 -6 0 -7 3 -3 3 0 7 3 7 0 6 3 7 0 3 4 0 56züGúHìAIûûú[ìLàM366 6487l6 -4 7 0 3 -3 7 0 7 -3 3 -4 7 0 6 -3 4 0 6 -3 7 -4 3 0 7 -3 7 0 3 0 7 3 6 4 4 3 0 7 0 3 0 7 -4 6 -3 4 -3 6 -4 4 -3 3 -7 3 -6 4 -4 0 -6 0 -7 0 -7 3 -3 0 -7 0 -6 0 -7 0 -3 3 -7 0 -7 0 -3 4 -7 3 -3 0 -7 7 -3 3 -3 3 -7 4 -3 3 -7 3 -3 4 -7 0 -7 0 -3 -4 -7 0 -6 -3 -7 0 -3 0 -7 0 -7 3 -3 0 -7 0 -6 4 -7 0 -3 0 -7 0 -7 0 -3 -4 -3 -6 3 -7 3 -3 7 -4 7 -3 3 0 3 -7 7 -3 3 -3 4 -4 6 -3 4 -3 6 -4 4 0 6 -3 7 -3 7 0 3 0 7 -4 6 4 4 3 6 3 4 0 6 -3 4 -3 6 -4 7 -3 7 -3züGúHìAIûûú[ìLàM2859 6683l0 -3 3 -7 0 -6 4 -4 0 -6 3 -7 3 -3 0 -7 4 -3 3 -7 3 -3 4 -7 3 -3 3 -7 4 -3 3 -7 3 -3 4 -7 3 -3 0 -7 3 -3 4 -7 3 -7 3 -3 4 -3 3 -7 7 -3 3 0 7 -4 3 -3 7 0 6 0 7 -3 3 0 7 -4 7 -3 3 -3 3 -4 4 -3 6 -3 4 -4 6 -3 7 0 3 -3 7 -4 7 -3 3 0 7 -3 6 0 4 3 3 7 3 3 4 7 0 6 0 7 0 3 -4 7 -3 3 -7 4 -3 0 -7 3 -6 -3 -7 3 -3 0 -7 0 -7 3 -3 4 -7 3 0 7 -3 3 -3 7 -4 6 0 4 -6 3 -4 7 -3 3 -7 3 -3 4 -7 3 -3 0 -7 0 -6 3 -4 4 -3 3 -7 3 -3 4 -3 6 -7 4 -3 3 -4 3 -6 4 -4 6 -3 4 -3 3 -4 7 -3 3 -3 3 -7 7 -3 3 -7 0 -10 0züGúHìAIûûú[ìLàM2599 6813l-3 7 -4 3 -3 7 0 3 -7 7 -3 3 -3 4 -7 0 -7 0 -6 0 -4 0 -6 3 -4 3 0 7 -6 3 -4 4 -6 3 -4 3 -6 0 -7 0 -7 0 -3 -3 -7 0 -6 0 -4 0 -6 0 -7 0 -7 0 -3 0 -7 0 -6 -3 -4 -4 -6 -3 -4 -3 -6 -4 -4 -3 0 -7 0 -6 7 -4 7 0 6 0 4 0 6 0 7 4 3 3 7 3 3 0 4 -6 3 -4 0 -6 3 -7 4 -3 3 -7 3 -3 7 -4 3 -3 7 0 7 3 3 0 7 -3 6 0 7 -3 3 0 7 -4 3 -3 4 -7 3 -3 3 -3 7 -4 7 0 6 0 4 -3 6 0 7 0 7 0 3 0 7 -3 6 0 7 3 3 3 0 7 -3 3 -3 7 -4 3 -6 4 -4 6 -3 4 -7 3 -3 3züGúHìAIûûú[ìLàM1512 7287l-220 0 7 -4 7 -3 3 -3 7 0 3 -4 7 0 6 -3 4 -3 6 -4 4 -3 3 -7 7 0 3 -3 7 3 6 0 7 0 7 0 3 -6 3 -4 0 -6 4 -7 0 -3 -4 -7 -3 -3 -3 -7 -4 -3 -6 -7 0 -3 0 -7 0 -3 3 -7 3 -7 4 -3 3 -3 3 -7 7 -3 3 -4 7 -3 3 0 7 -3 3 3 4 7 -4 3 0 7 0 6 0 7 0 7 4 3 3 3 7 4 6 0 7 0 3 -4 7 0 7 0 6 -3 4 0 6 -3 7 0 3 -4 7 -3 3 0 7 -3 3 -4 7 -3 0 -7 3 -6 4 -4 3 -6 3 -4 4 -6 3 -4 3 -3 7 -7 3 -3 7 0 3 3 4 7 0 7 3 6 0 4 3 6 -3 7 0 3 -3 7 -4 3 -6 4 -4 3 -6 3 -4 7 -3 3 -3 4 -7 3 -3 7 -4 3 -3 7 -3 3 -4 3 -3 7 0 7 0 3 0 7 0 6 0 7 0 3 0 7 0 7 3 6 0 4züGúHìAIûûú[Cfil6LàM2996 367l3 0 403 0 0 206 -16 7 -24 3 -53 0 -13 10 20 10 -20 17 -34 0 -33 3 -43 -3 -17 -20 -23 -23 -24 3 -3 20 0 3 -37 -6 -16 0 -34 -14 -36 -23 -40 0 -60 7 -37 3 -7 -23 -16 -7 -20 17 13 10 -3 6 -40 0 -30 -20 -10 -40 -47 0 -190 140 -70 90 -43 -6 -64 30 -80 90 -23 60 -17 -4 0 7 17 10 -17 67 -13 0 -3 6 20 14 0 16 -20 7 -20 43 10 24 23 3 10 -43 3 0 17 220 50 23 -3 23 26 34 -43 10 -30 -30 -50 0 -80 53 -57 10 -20 43 -40 -6 -23 23 -30 -10 -20 -30 -93 -27 -67 17 -27 43 -40 10 -23 -13 -20 -47 -3 -6 -114 -27 -3 -10 3 -37 24 -13 -27 -10 -3 -20 -130 -17 -7 37 -17 3 -53 -80 -67 -3 -30 13 -46 -53 -70 -10 -14 10 -50 -23 -70 -20 -23 13 -10 63 20 24 -17 23 -113 10 -40 -23 -33 36 -24 -30 -43 -10 -100 40 -53 -26 -27 -47 -23 3 -60 -40 -47 37 -60 -17 -10 27 -20 7 -37 -54 -53 -23 0 -20 -13 -33 -44 13 -60 -3 -146 -70 -30 6 -20 -20 6 -20 -10 -6 -16 10 -4 50 -43 -7 -27 -33 27 -27 20 -53 -7 -50 -83 -17 -30 30 -20 -40 -47 10 -30 -47 17 -16 43 -4 44 -40 33 -70 43 -80 -3 -73 33 -183 3164 0züGúHìAIûûú[ìLàM1372 1313l17 -3 7 -37 130 17 3 20 27 10 -24 13 -3 37 -30 7 -7 26 -30 0 -23 27 -53 0 -20 -37 26 -20 -30 -16 10 -44züGúHìAIûûú[ìLäM-3834 1670l6 70 30 -10 24 20 -4 27 -40 23 -36 50 6 27 24 10 -4 33 20 10 44 -7 43 -40 27 0 6 -20 14 0 3 34 7 0 20 -17 73 -13 57 23 -7 33 47 -3 13 -23 17 6 6 0 17 37 27 -23 26 3 70 -27 10 -70 34 -6 43 33 30 -17 30 20 50 0 27 -30 10 14 30 26 53 0 20 -20 17 20 -10 40 30 14 -30 86 6 47 24 20 36 -17 50 7 84 67 -10 16 -7 4 -3 6 -4 4 -3 3 -3 7 -4 3 -3 7 -3 3 -4 7 -3 3 -3 7 -4 3 0 7 -3 3 -3 7 -4 3 -3 7 -3 3 -4 7 0 3 -3 7 0 6 0 7 -3 3 -4 4 -6 3 -7 0 -7 0 -3 0 -3 7 -4 3 -3 7 0 3 -3 7 -4 3 -3 7 -3 3 -7 3 -3 4 -7 3 -3 3 -7 4 -3 3 -7 7 -3 3 -4 3 -3 4 -7 0 -6 3 -4 3 -3 4 -7 6 -3 4 -7 0 -3 0 -7 0 -6 3 -7 0 -3 0 -7 0 -7 3 -3 0 -7 4 -3 6 -3 4 -7 3 -3 3 -4 7 -3 3 -7 4 -3 3 -3 7 0 3 -4 7 -3 3 -3 7 -4 3 -3 7 -3 3 -4 7 0 6 -3 4 -3 6 0 4 -4 6 0 7 -3 3 -3 7 -4 3 -3 4 -7 3 -3 3 -7 4 -6 3 -4 0 -6 0 -7 0 -7 0 -6 37 50 93 -14 10 -6 60 13 73 -23 64 26 36 -33 54 33 66 -46 60 -77 27 -17 27 10 46 44 20 33 67 -30 107 -43 40 -20 96 -7 0 -3 4 -7 0 -10 0 -7 3 -6 0 -7 0 -3 0 -7 3 -7 0 -6 -3 -4 0 -6 0 -7 0 -7 0 -3 0 -7 -3 -6 0 -4 0 -6 0 -7 -4 -7 0 -3 0 -7 0 -6 4 -4 0 -6 3 -7 3 -3 4 -7 0 -3 3 -7 0 -7 -3 -6 0 -4 -4 -6 0 -7 0 -7 -3 -3 0 -7 0 -6 -3 -4 0 -6 -4 -7 0 -3 -3 -7 0 -7 0 -6 0 -4 0 -6 0 10 43 66 60 4 24 46 23 -13 90 43 50 -6 47 56 30 -6 43 73 0 27 30 6 40 -53 80 3 30 -3 3 -7 7 -3 3 -3 4 -7 3 -3 3 -4 4 -6 6 -4 4 -3 3 -7 3 -3 4 -7 3 -3 3 -3 4 -7 3 -3 3 -7 4 -3 3 -7 3 -3 4 -4 3 -6 3 -4 4 -3 6 -7 4 -3 3 -3 3 -4 7 0 7 0 3 0 7 0 6 0 7 0 7 -3 0 -7 6 -3 4 0 6 -3 4 3 6 0 7 -3 7 0 3 -4 7 -6 3 -4 0 -6 0 -7 -3 -7 -4 -3 4 0 6 3 7 4 3 3 4 3 6 0 7 0 7 -3 3 0 7 0 6 0 7 -3 3 0 7 -4 3 -3 7 -3 3 -4 7 -3 3 0 7 -3 7 -4 3 0 7 -3 6 -3 4 -4 3 -6 0 -7 -3 -7 0 -6 0 -7 3 -3 3 0 4 0 6 3 4 3 6 4 4 0 6 -4 7 -3 7 0 3 0 7 0 6 -3 4 0 6 -4 7 0 3 -3 7 -3 7 0 3 -4 7 -3 6 -3 4 -4 0 -3 -7 0 -7 -3 -3 -4 -7 -3 -3 -3 -7 -4 -3 -3 -3 -3 -7 -4 -3 -3 -7 -3 -3 0 -7 0 -7 -4 -6 -3 -4 -3 4 -7 3 -3 3 0 7 0 7 3 3 0 7 3 6 0 4 -3 6 3 7 7 0 7 3 3 4 7 3 3 3 0 7 3 3 0 7 0 7 0 6 0 4 -3 6 0 7 0 3 3 7 0 7 7 6 7 -3 3 -3 3 -7 4 -3 0 -7 3 -3 7 -4 3 -3 7 -3 3 -4 7 -3 3 0 7 -3 6 0 7 0 3 -4 7 0 3 -6 4 -4 3 -6 0 -7 0 -3 3 -7 4 -3 6 -4 7 0 3 0 7 0 7 0 3 0 7 0 6 4 7 0 7 0 3 3 7 0 6 0 4 0 3 -3 0 -7 0 -7 -3 -6 -7 0 -3 -4 -7 0 -7 -3 -6 0 -4 0 -6 3 -7 0 -7 0 -3 4 -7 0 -6 3 -4 0 -6 3 -7 0 -3 4 -7 0 -7 0 -3 0 -7 -4 -3 -3 0 -7 0 -6 3 -4 4 -6 3 -4 3 -6 4 -4 3 -3 3 -7 4 -3 3 -7 3 -3 4 -7 3 -3 3 -7 4 -3 3 -3 7 -7 20 13 70 110 30 74 90 -24 -47 130 -57 -13 -13 30 -70 7 -30 106 -77 64 -16 73 -47 73 7 7 3 7 3 3 4 3 6 7 4 3 3 7 0 3 3 7 0 3 0 7 4 7 0 6 0 7 0 3 0 7 0 7 0 6 0 4 0 6 0 7 3 7 0 3 0 7 0 6 0 7 0 3 0 7 0 7 3 6 0 4 0 6 0 7 0 3 0 7 0 7 0 6 4 7 3 47 -13 10 -20 -4 -60 20 -127 87 -110 3 -113 -66 -60 13 -54 -27 -56 10 -27 -16 -3 -17 -7 -3 -3 13 -44 -17 -33 37 -93 10 -70 43 -24 -16 50 -97 -3 -30 37 -53 -7 -37 53 -103 -10 -107 20 -70 10 -7 0 -6 -20 -14 10 -126 -43 -30 37 -57 33 -123 -10 -127 -30 -50 3 0 17 17 7 0 0 -10 53 16 3 -6 -16 -17 20 -37 -4 -10 -10 -6 -10 0 -10 36 -63 -33 -110 53 -57 0 -16 10 -7 -6 20 -74 -33 -83 6 -13 44 -14 13 0 10 24 -7 3 4 3 23 4 10 13 0 -3 -7 -30 20 -7 17 10 3 0 4 -13 16 -7 0 -3 -36 3 -4 -17 70 -33 4 -13 -27 -50 -3 -50 -14 0 -36 50 -30 83 -20 13 -100 17 -80 -23 -7 -14 7 -20 -14 -26 57 -120 0 -94 53 -113 0 -43 -10 -24 7 -30 73 -33 94 -117 20 -103 123 -287 0 -3 -27 -40 37 -83 60 -214 10 -26 33 0 20 -50 17 -4 0 -3 -23 -10 0 -20 3 -10 20 -20 0 -7 -7 -10 -10 0 -20 80 -23 34 -3 0 66 -250 -6 -87 -7 -7 -20 -33 -10 -103 -23 -64 10 -40 -24 -156 -23 -47 10 -83 73 -60 4 -4 6 -6 4 -4 3 -3 3 -3 7 -4 3 -6 4 -4 3 -3 3 -7 4 -3 3 -7 3 -3 7 -3 3 -4 7 -3 3 0 7 -3 3 -4 7 0 7 4 6 0 4 0 6 -4 4 -3 6 -3 4 -4 3 -3 7 -3 6 0 7 0 3 0 7 0 7 3 3 0 7 0 6 0 7 0 3 0 7 0 7 0 6 -3 4 0 6 -4 7 0 3 -3 7 -3 3 -4 7 -3 3 -3 4 -4 6 -3 4 -3 6 -4 7 0 3 -3 7 0 7 -3 3 -4 7 -3m-157 1897l7 0 3 3 7 0 6 -3 4 -4 3 -3 3 -7 4 -3 3 -7 7 -3 3 -3 3 0 0 -7 0 -7 -3 -6 0 -4 3 -6 7 0 3 0 7 0 7 0 3 -4 -3 -3 -4 -3 -6 0 -7 -4 0 -3 0 -7 0 -6 3 -7 0 -3 0 -7 0 -7 0 -6 0 -4 4 -6 0 -7 3 -3 0 -7 3 -7 -3 -6 -3 -4 -7 0 -7 -3 -6 0 -4 0 0 7 4 3 3 7 3 3 0 7 -3 3 0 7 0 6 0 7 0 3 0 7 0 7 0 6 -3 4 -4 6 -3 4 -3 3 -4 7 -3 3 -3 7 -4 3 0 7 0 6 7 4 3 3 0 7 -3 3 -7 3 -3 4 -7 -4 -6 0 -4 4 -3 6 0 7 0 7züGúHìAIûûú[ìLäM3402 6357l-3 -4 -7 0 -6 -3 -7 0 -7 -3 -3 0 -3 3 0 7 0 6 0 7 0 7 0 6 -4 4 0 6 0 7 7 3 3 4 7 0 7 0 6 0 4 0 6 6 0 874 -1890 0 0 -4 -3 -6 0 -7 0 -7 0 -3 0 -7 0 -6 0 -7 0 -3 0 -7 3 -7 4 -3 3 -3 3 -7 4 -3 3 -7 7 -3 3 -4 3 -3 4 -7 6 -3 4 -3 6 -4 4 -3 3 -7 0 -3 3 -7 -3 -6 0 -4 -3 -6 0 -7 -4 -7 -3 -3 -7 0 -3 3 -7 7 -3 3 -3 4 -4 6 -3 4 -3 6 -4 4 -3 6 0 7 -7 3 -3 4 -7 3 -3 0 -7 3 -3 4 -7 0 -6 3 -4 0 -6 3 -7 0 -7 0 -3 4 -7 0 -6 0 -7 -4 -3 -3 -4 -3 0 -7 0 -7 0 -6 0 -7 4 -3 -4 -7 -3 -3 -7 3 -3 0 -7 3 -3 4 -7 3 -3 7 -3 3 -4 3 -3 7 -3 7 0 3 0 7 0 3 6 7 4 3 3 7 3 3 4 7 0 3 -4 7 0 6 -3 4 -3 6 -7 0 -7 0 -6 0 -7 -3 -3 3 -7 0 -3 7 -4 3 -6 4 -4 3 -6 3 -7 0 -3 4 -7 0 -3 3 -7 3 -7 4 -1633 0 -57 -94 0 -46 34 -57 -34 -63 -40 -84 -30 -23 -23 -53 40 -10 63 20 57 -4 87 -40 23 4 140 -120 37 -20 53 -4 43 -33 27 -37 40 -130 20 0 70 -80 60 -33 37 3 26 -40 64 17 16 20 37 0 30 -37 30 -10 23 -76 67 -20 40 23 7 30 3 3 110 24 87 -70 40 -120 3 -10 47 -47 50 -23 23 -44 67 -20 106 -80 64 -10 66 -36 44 -54 66 -30 67 -23 50 0 50 -30 77 10 220 -47 93 0 183 -66 34 6 10 20 100 -6 123 -80 57 -84 70 -13 40 40 30 7 40 -17 10 -43 50 20 100 0 90 -44 50 -53 86 -30 37 17 277 -40 36 6 0 1034m-3036 130l-7 3 -7 3 -6 4 -4 3 -6 3 -4 0 -6 -3 -4 -3 -6 -4 -7 4 -3 0 -7 0 -7 3 -6 3 -4 0 -6 4 -4 3 -6 3 -4 4 -3 3 -7 3 -3 7 -3 0 -7 3 -7 4 -3 3 -3 7 3 6 3 4 7 0 7 0 3 0 7 0 6 -4 7 0 3 0 7 -3 7 0 3 0 7 0 6 3 7 0 3 4 7 0 7 0 3 -4 7 -3 3 -3 7 -4 3 -3 3 -3 7 -7 3 0 7 -3 3 -4 7 0 7 0 3 -3 7 0 6 0 7 0 3 0 7 -3 7 0 6 0 4 0 6 -4 7 -3 3 -3 4 -4 3 -6 3 -4 4 -6 0 -7 0 -3 0 -7 -4 -3 -6 -4 -7 -3 -3 0 -7 0 -7 3 -3 0 -7 4 -6 3 -4 0 -6 3 -7 0 -3 4 -7 3 -7 0 -3 3 -7 0 -6 4m2493 196l10 0 7 0 3 -3 7 -7 3 -3 3 -3 4 -7 3 -3 3 -4 4 -6 6 -4 4 -3 3 -3 7 -4 3 -6 3 -4 7 -3 3 -3 4 -4 6 -3 7 0 3 0 7 -3 3 -4 7 -3 3 -3 4 -7 6 -3 0 -4 4 -6 3 -7 3 -3 0 -7 7 -3 3 -4 7 -3 7 0 3 0 7 -3 6 3 7 -3 3 0 7 -4 3 -3 4 -7 0 -3 0 -7 0 -6 -4 -7 -3 -3 -3 -7 -4 -3 -6 0 -7 3 -3 0 -7 3 -7 4 -3 3 -7 0 -6 3 -4 4 -6 3 -4 3 -3 4 -3 3 -7 3 -7 4 -3 0 -7 3 -6 0 -7 0 -3 3 -7 4 -3 0 -7 3 -3 7 -4 3 -3 3 -3 7 -4 7 -3 3 0 7 -3 3 -4 7 -3 3 -3 7 -4 3 -3 7 -3 3 -4 7 -3 3 -3 7 -4 3 0 7 -3 3 -3 7 0 6 -4 4 0 6 -3 7 0 3m-260 130l3 -3 7 -3 3 -4 4 -6 6 -4 4 -3 3 -7 3 -3 0 -7 -3 -3 -7 -3 -6 0 -7 3 -3 0 -7 0 -7 0 -6 0 -4 3 -6 0 -7 0 -7 4 -3 3 -3 3 -4 7 -3 3 -7 4 -3 0 -7 3 -6 0 -7 3 -3 0 -7 -3 -7 0 -3 3 -7 4 -3 3 -3 7 -4 3 -3 7 0 6 -3 4 -4 6 -3 0 -7 -3 -3 -3 -7 -4 -6 0 -4 0 -6 0 -7 0 -7 4 0 6 0 7 4 3 6 4 4 3 6 3 4 4 6 3 7 0 3 0 7 0 7 0 6 0 4 0 6 0 7 0 3 3 7 0 7 0 6 0 4 -3 6 -3 4 -4 6 -3 0 -7 4 -3 6 -3 4 0 6 0 7 0 7 0 3 -4 3 -3 7 -7 0 -3 3 -7 4 -3 3 -7züGúHìAIûûú[ìL[M-2354 6093l6 0 -6 24 0 -24zGúHìAIûûú[ìLàM-2358 6320l14 107 26 13 17 80 43 23 67 97 217 147 220 43 43 -27 67 -6 60 -34 36 7 34 -20 20 33 50 10 30 -13 13 -40 37 -10 73 50 140 17 83 -34 34 -36 33 0 53 -110 17 6 -10 40 13 34 -10 36 30 4 10 83 67 33 20 -6 -53 -44 -20 -36 66 66 57 24 100 3 53 -40 50 20 67 27 23 53 30 23 40 84 34 63 -34 57 0 46 57 94 -2737 0 144 -284 170 -433 60 -213 26 -10 70 13 47 -37 60 7 70 -60 47 -3 26 53züGúHìAIûûú[ìLeM-2358 6320l-26 -53 53 10 3 13 -30 30zGúHìAIûûú[ìLbM-928 6697l0 0 -10 36 30 4 -20 -40zGúHìAIûûùDLareas_densityGúHìAIûûúSøúNøú[Hfil7 str0LMM3001 367l-3 0GúHìAIûûú[ìL}M-1830 821l-15 32 14 28 -8 26 -41 -18 -13 22 -47 6 -6 51 -54 3GúHìAIûûú[ìLWM-1248 1007l83 -46 67 27GúHìAIûûú[ìLiM-1104 851l2 29 -16 12 -78 -4 -63 48 11 71GúHìAIûûú[ìLiM-712 867l-11 25 10 16 -37 47 -2 65 -25 18GúHìAIûûú[ìLpM-1493 1087l24 -16 6 -26 43 -7 52 -59 76 29 44 -1GúHìAIûûú[ìLàM-777 1038l-60 13 11 38 -83 -7 -94 -45 14 -37 -20 -40 -29 -5 -5 36 -55 -3üGúHìAIûûú[ìL[M-2000 971l-1 57 34 20 22 50GúHìAIûûú[ìLàM-3173 725l-30 42 -37 0 -4 28 21 8 3 33 33 28 5 49 45 27 2 46 43 -23 27 19 -25 35 -41 10 -27 41 12 23 23 -12 39 20 12 50üGúHìAIûûú[ìLàM-2000 971l-15 -29 -28 -7 -47 41 -35 -2 -27 59 -18 -13 -37 21 -77 -6 -17 30 -43 -1 -8 20 -30 6 -53 -18 -45 12 -25 38 -61 -8 -37 -26 -15 -38 -20 10 -34 -12 -17 32 -50 -16 -8 24 -74 -36 -31 45 -12 1 -7 14 9 8 -3 16 -64 18 -76 -11 -36 26 -31 -20üGúHìAIûûú[ìLàM-3511 537l-13 33 10 24 -19 18 -25 110 -31 51 -32 -2 -3 48 -30 36 10 20 -24 48 21 71 -17 31 18 66 -50 80üGúHìAIûûú[ìLàM-346 877l-29 9 -25 46 -43 12 7 59 -60 46 -12 59 -28 8 -21 26 -40 -11 -22 44üGúHìAIûûú[ìLlM-777 1038l11 32 -39 25 3 23 28 13 77 0 78 44GúHìAIûûú[ìLbM200 1138l-48 12 -19 45 3 46 -28 29GúHìAIûûú[ìLàM-1098 988l-19 28 23 16 -2 46 -16 13 58 9 46 57 -67 20 -62 -33 -34 59 36 32 11 -25 23 -2 7 -9 8 7 -10 65 12 10üGúHìAIûûú[ìLàM-1945 1098l88 -3 54 -25 24 7 35 52 58 13 10 77 14 7 31 -16 2 19 -28 17 55 38üGúHìAIûûú[ìLàM-1602 1284l75 1 27 -28 42 -3 -3 -24 -5 -29 -32 21 -12 -25 44 -24 -10 -22 -53 31 -20 -15 17 -50üGúHìAIûûú[ìLàM-4107 1294l13 -32 95 -41 72 10 12 -25 28 0 8 -25 12 -8 18 17 11 -15 25 7 -4 -15 18 -7 54 5 15 15 34 -9üGúHìAIûûú[ìLàM-920 1257l123 19 9 17 -17 28 18 19 7 1 10 -7 10 2 3 17 -10 7 -52 -3 -22 -17 -46 9 -53 -51 20 -41üGúHìAIûûú[ìLcM-3696 1171l14 4 -8 53 58 46 -36 101GúHìAIûûú[ìLàM-3212 1444l19 -54 -6 -27 24 -16 -16 -45 42 -37 25 1 30 -36 1 -54 21 -27üGúHìAIûûú[ìL]M-914 1424l34 -44 34 27 -10 51GúHìAIûûú[ìLmM-3668 1375l16 22 -10 31 71 12 6 6 -9 11 17 12GúHìAIûûú[ìLàM-619 1175l10 37 -22 33 3 38 -28 12 21 56 -37 19 -26 -21 -46 37 22 30 23 -22 12 28 -13 50 -34 6üGúHìAIûûú[ìLkM1535 1379l-1 39 45 14 -3 34 0 2 30 -3 -4 44GúHìAIûûú[ìLQM-3264 1528l52 -84GúHìAIûûú[ìL}M-3668 1375l-54 21 -87 -19 -93 53 6 99 35 35 -2 40 18 15 27 -6GúHìAIûûú[ìLàM-1945 1098l-33 21 -38 85 -20 6 0 55 -23 30 32 29 -23 114 15 14 -16 66 7 35 -35 13 -4 23 18 -2 1 13 -13 24 -20 1üGúHìAIûûú[ìLvM-3212 1444l49 11 25 -19 48 24 18 8 -17 51 57 49 -31 64GúHìAIûûú[ìLàM-2097 1625l-21 -7 -4 13 -15 2 -5 -7 -13 -17 -38 34 -25 -8 -13 22 4 8 -6 7 -20 -4 -10 21 -19 -9 -21 18 1 35 2 69üGúHìAIûûú[ìLàM-941 1370l-28 13 -27 -15 -48 3 -9 14 5 20 -24 26 1 11 16 2 -8 38 23 27 -3 44 -5 2 -12 -23 -10 9 20 30 -28 14 17 62 -21 45 55 83 53 1 10 43üGúHìAIûûú[ìLnM-310 1686l4 13 -14 20 -54 -3 -41 55 0 35 26 19GúHìAIûûú[ìLàM-3063 1632l-10 31 -32 -12 -41 35 -11 32 -30 28 0 24 21 14 -12 48üGúHìAIûûú[ìLàM-3063 1632l41 34 35 -5 83 29 95 -14 53 42 97 -1 42 23 38 -17 21 26 44 -19 21 17 35 -18 43 65 33 -34 14 30 12 28 -11 23 20 9 11 -31 36 -17üGúHìAIûûú[ìLOM-389 1825l-2 34GúHìAIûûú[ìLàM108 1270l-68 34 -6 40 -55 0 -29 71 -25 -5 -16 24 8 35 -36 37 -6 35 13 22 -31 35 -15 65 15 69 50 52 -48 90 -6 11 -45 -8 -31 11 -58 -39 -26 10 -40 -30 -42 -4üGúHìAIûûú[ìLàM-964 1819l24 9 35 -21 6 -47 26 -14 17 24 -21 53 93 14 34 -52 2 -19 11 -12 6 2 32 -25 68 -3 20 40 38 -17 35 7 -13 36 25 26 3 44 78 25 54 -30üGúHìAIûûú[ìLàM1602 1509l42 -11 78 15 -18 46 11 15 -1 13 -22 -1 -5 13 17 20 64 22 74 -28 18 27 36 -11 33 38 35 -6 12 30 -10 38 -28 10 28 20 1 18 -48 29 -20 -5 -6 8 10 44 70 14 43 47 60 -27 58 3 13 60üGúHìAIûûú[ìLàM-1602 1284l-11 19 -21 -13 -78 49 13 42 -18 48 24 50 -4 24 -31 6 -13 19 9 33 27 1 43 183 45 5 24 19 -17 16 9 28 45 0 8 9 -14 28 13 15 52 -16 0 21 -45 21 -9 30 -52 14 -3 27 26 47üGúHìAIûûú[ìLàM-2097 1625l-15 92 50 8 14 43 -55 107 11 22 61 -11 39 64 28 5 35 -32 25 3 35 45 36 -11 13 11 -8 28 14 13 25 0 18 -19 48 14 36 -29 62 6 17 22 28 3üGúHìAIûûú[ìLàM1602 1509l-88 24 15 33 -7 25 26 7 5 17 -18 23 14 39 -24 24 14 20 -25 19 19 4 -1 9 -16 5 -2 35 -37 34 31 13 -17 66 -28 18 -23 -22 -12 13 -2 -22 -29 5 4 50 -16 17 37 45 -43 18 17 28üGúHìAIûûú[ìLmM-1580 2009l-18 28 30 30 -6 56 15 -6 1 1 15 27GúHìAIûûú[ìLàM-964 1819l-26 30 -3 37 -21 4 -10 29 -46 7 4 16 -31 45 -48 -43 -20 11 0 55 -39 22 -1 31 -23 12 -20 44 -8 19 -43 -16 -4 24üGúHìAIûûú[ìLàM1043 1166l-73 104 9 47 35 14 -16 75 -20 9 30 61 5 64 -18 142 -30 97 -40 43 24 45 -144 151 18 55 44 2 9 35 -22 38 -29 10 -2 50üGúHìAIûûú[ìLTM760 2215l8 -11 49 10GúHìAIûûú[ìLàM-1303 2146l-76 17 -26 27 -6 37 -12 2 -7 -6 0 -28 -8 -3 -18 27 -44 -54 -43 -20üGúHìAIûûú[ìLàM108 1270l-4 27 19 15 -20 25 8 34 -15 23 20 15 -17 28 20 2 0 61 44 24 -51 101 15 7 13 -28 33 9 20 -46 -4 -18 12 -11 8 4 4 49 -14 42 5 131 -14 7 -17 -26 -29 66 61 33 59 -1 78 79 6 80 73 28 11 35 61 41 21 -17 25 4 64 164 29 9 -2 -13 8 -1 7 12 35 1üGúHìAIûûú[ìLàM1396 2056l-3 17 -91 -3 -29 26 7 35 -30 14 -26 -10 -10 9 10 17 -63 75 -43 11 -22 -14 -12 24 -30 -1 -77 36 -19 -15 -75 10 -7 22 -27 0üGúHìAIûûú[ìL[M812 2230l31 21 -12 21 18 37GúHìAIûûú[ìLàM1396 2056l30 6 1 19 -27 20 49 30 3 55 55 25 -9 14 15 35 24 -5 -7 31 -18 3 3 5 30 10 -1 25üGúHìAIûûú[ìLtM-1303 2146l11 31 20 12 19 -9 18 39 45 14 -5 51 79 63GúHìAIûûú[ìLàM-2300 1802l49 48 -26 27 15 18 -15 63 8 4 -3 20 -31 23 -1 25 25 35 1 50 28 10 -8 26 16 15 -2 21 -42 26 -3 2 17 45 -17 36 22 82 -26 47 28 6üGúHìAIûûú[ìLàM-391 1859l27 75 -20 46 38 56 -15 39 -25 1 -35 43 -21 -8 -16 12 12 28 -6 46 25 59 -49 21 -7 -34 -37 -9 -7 52 -26 35 16 101 53 25üGúHìAIûûú[ìLkM-1116 2347l-28 32 -74 -5 -17 16 4 26 -75 34GúHìAIûûú[ìLàM-1543 2145l-9 43 -65 32 -133 21 -88 30 14 50 -14 25 -35 -9 -7 6 11 25 -44 39 7 27 -6 6 -20 -7 -21 24üGúHìAIûûú[ìLlM849 2309l-2 24 -1 3 -31 22 -6 38 -48 26 6 40GúHìAIûûú[ìLgM-2265 2431l4 -13 22 3 12 23 21 -1 29 24GúHìAIûûú[ìLàM-2265 2431l-4 34 -19 13 -33 -16 -12 -35 -30 4 -6 23 -44 -53 -22 8 -29 -27 -66 16 -69 -15 -29 57 -10 3 -6 -11 -15 6 -9 -7 -1 -28 -43 -3üGúHìAIûûú[ìLgM-1953 2457l-43 10 -26 29 -82 -47 -73 18GúHìAIûûú[ìLàM-484 2447l-4 48 -8 2 -25 -21 -16 0 -17 19 -32 -3 -46 24 -20 -18 -29 19 -29 -15 -36 -58 -23 9 -6 -6 4 -15 -23 -10 13 -17 -3 -4 -14 4 -12 -19 -35 -4 -6 -14 -9 -2 -24 15 -33 -8 -24 -33 -22 -2 -16 15 -56 13 -81 -19üGúHìAIûûú[ìLàM767 2462l-78 -4 -19 24 -32 -52 -121 -48 -49 -45 -12 13 -38 -18 -44 -52 -45 -6 -3 32 -6 2 -1 -2 -22 1 2 46 -21 12 31 24 -36 59 -43 -33 -22 47 -29 0 -18 -27 -34 50 -29 -14 9 -37 -24 9 -41 -21 -26 28 -34 -9 -28 19 6 32 -22 18 -25 -3 -14 -24 -55 52 12 21 -14 26 -85 8üGúHìAIûûú[ìLdM-484 2447l52 -20 17 24 70 34 102 105GúHìAIûûú[ìLxM767 2462l8 23 28 9 12 39 -25 56 19 52 -24 38 -36 20 6 11GúHìAIûûú[ìL{M-1306 2450l-42 14 -91 109 -63 23 -28 43 -16 85 -52 2 -47 70GúHìAIûûú[ìLàM-1645 2796l-64 6 6 11 -9 9 -21 2 -22 3 -32 -10 -4 -55 -27 -31 -6 -43 -30 -3 -3 -4 10 -15 -15 -15 -4 -49 -50 -65 -35 -14 -2 -66üGúHìAIûûú[ìLrM755 2710l23 -1 12 21 33 10 -7 36 71 19 23 36 44 17GúHìAIûûú[ìLàM-728 2977l5 -16 -15 -29 8 -18 63 -7 12 -19 -23 -25 9 -21 51 29 14 -10 -2 -34 53 7 24 -33 35 12 37 36 28 4 5 -16 22 9üGúHìAIûûú[ìLàM-243 2590l3 46 48 56 -13 53 17 37 -6 64 -26 20 -46 -17 -9 81 -29 11 -32 48üGúHìAIûûú[ìLàM-2177 2467l-13 62 26 17 4 28 -36 124 -51 57 -72 41 7 22 -28 35 -26 14 -29 -7 -4 32 36 -9 12 15 -17 53 -29 1 -2 30 -30 -15 6 -26 -36 11 -32 34 3 55 -31 32üGúHìAIûûú[ìL|M-2519 3073l-37 2 0 -42 -49 20 -14 30 -43 -17 -19 -27 -42 -13GúHìAIûûú[ìLàM-2710 2997l5 -9 -86 -59 -187 105 -12 43 -65 17 -19 -12 -22 16 -37 -5 -19 -20üGúHìAIûûú[ìLàM-1645 2796l-7 50 -40 13 -18 -12 -7 5 3 24 -22 26 2 96 -59 7 -22 61 -32 -14 -8 6 4 27 -24 56üGúHìAIûûú[ìLkM-276 3045l-1 3 12 14 3 -2 74 75 58 -5 -1 37GúHìAIûûú[ìLàM-1306 2450l31 49 32 10 -4 23 24 37 -56 147 32 25 -12 52 33 13 11 -15 13 34 28 -3 -11 37 24 23 -2 25 21 -9 29 20 0 51 29 12 11 24 -32 106 11 8 38 -27 17 83 1 4üGúHìAIûûú[ìLàM-1038 3179l28 2 12 -39 54 35 46 -33 13 -44 -13 -69 14 -44 14 -9 7 9üGúHìAIûûú[ìLvM-2519 3073l107 75 35 -8 26 -32 24 -3 17 15 -9 39 21 48GúHìAIûûú[ìLàM-2298 3207l91 22 76 -53 11 35 22 0 87 -80 5 -30 55 -11 24 61 52 -10üGúHìAIûûú[ìL`M-1088 3246l55 -19 -18 -38 13 -10GúHìAIûûú[ìL_M-1164 3258l0 1 28 1 41 -30 7 16GúHìAIûûú[ìLàM-1875 3141l25 14 48 -28 30 -44 15 3 8 25 29 27 31 -39 31 -14 28 36 45 -16 33 37 108 32 26 26 18 -7 58 21 5 22 -12 24üGúHìAIûûú[ìL~M-131 3167l70 3 1 -40 15 -2 14 27 16 31 51 0 43 36 -2 19 -45 22GúHìAIûûú[ìL`M-131 3167l42 97 44 6 35 6 42 -13GúHìAIûûú[ìLMM32 3263l11 28GúHìAIûûú[ìLàM755 2710l-75 32 -12 -28 -46 7 -63 -41 -23 24 -9 50 -35 20 -15 -14 -26 13 4 36 48 4 -4 70 20 21 -41 32 37 47 -61 55 -9 39 -51 14 -25 -8 0 39 -37 87 -33 22 -40 2 -6 30 -34 16 0 44 25 30üGúHìAIûûú[ìLeM244 3353l-53 21 -22 -79 -43 -13 -83 9GúHìAIûûú[ìLwM-1483 3350l23 27 8 1 50 -46 49 -10 -1 -20 61 -20 15 -21GúHìAIûûú[ìLpM-2298 3207l-23 15 3 60 -26 96 42 -7 22 15 -19 70GúHìAIûûú[ìLàM588 3454l-46 -18 -18 -32 -36 -7 -23 43 -45 31 -22 -31 -67 4 -11 -65 -18 -7 -23 27 -35 -46üGúHìAIûûú[ìLtM-1088 3246l7 54 30 6 -16 81 32 15 44 99 46 52 -8 129GúHìAIûûú[ìLàM43 3291l-36 17 3 17 6 46 -39 90 5 41 -26 13 -40 -8 -63 85 -11 87 13 19üGúHìAIûûú[ìLQM-1981 3718l34 -22GúHìAIûûú[ìLkM-2092 3722l15 -13 22 -73 23 -16 53 40 -2 58GúHìAIûûú[ìLeM-2208 3444l-6 32 18 25 -36 91 132 132GúHìAIûûú[ìLWM-1981 3718l-58 31 -2 -1GúHìAIûûú[ìL[M-953 3682l35 56 -14 24 28 5GúHìAIûûú[ìL[M-901 3767l24 -24 17 6 13 36GúHìAIûûú[ìLoM-477 3749l37 5 20 43 53 -9 63 19 25 -31 134 -78GúHìAIûûú[ìLàM-1947 3696l40 -4 4 -25 61 -47 20 49 22 -29 108 31 25 -15 21 -51 59 -2 11 38 -15 7 -5 42 -24 0 -17 66 24 17 18 -17 54 9 6 43 59 29 42 -24 34 17 45 -22 61 -5 67 -70 61 1 12 -54 50 -2 24 -16 85 38 42 -18üGúHìAIûûú[ìLoM-797 3779l82 -10 74 74 29 -35 31 42 55 -40 69 9GúHìAIûûú[ìLàM-2142 3754l-7 3 -26 -19 -16 40 -56 23 -44 -18 -21 11 -7 55 -24 47 -36 4 -31 -33 -34 -2 -20 18 19 21 -10 32 -43 21 -79 -46 -13 24 -53 17 -12 -19 -33 33 -7 -34 -20 -2 -54 53 -49 -39 -41 -12 -9 -46 -21 -5 -12 7 -89 -15 -5 18 -42 -29 -41 10 -44 -11 -18 -37 34 -54 -25 -18 -6 -35 -47 0 -87 -39 -12 17 26 22 -26 47 -17 3 -7 -33 17 -15 -30 -7 -25 23 -7 17 11 5 -25 34 -20 -1üGúHìAIûûú[ìLàM-145 3698l34 41 24 -11 33 26 103 22 -10 78 -1 2 -42 105 74 85 104 -9 24 42 0 67üGúHìAIûûú[ìLàM701 4059l0 23 -22 -22 -42 22 -12 -16 -32 22 -51 -19 -85 60 -66 2 1 24 38 5 7 13 -67 45 -15 -35 -51 -19 -47 23 -19 -25 -28 0 -12 -16üGúHìAIûûú[ìLàM-2147 4219l30 -7 28 -91 25 -18 27 3 9 -31 -51 -25 -22 -64 47 14 27 -11 -24 -37 14 -51 21 -24 49 2 10 -12 -1 -1 -29 -72 29 -13 22 -57 -11 -28üGúHìAIûûú[ìL\M198 4146l-20 17 34 63 -68 22GúHìAIûûú[ìLàM-844 4360l-1 -70 16 4 35 -24 15 -61 -57 -41 -22 -71 -63 -35 43 -75 -19 -67 64 -96 -14 -39 0 0üGúHìAIûûú[ìLàM-1714 4497l10 -39 214 23 55 -41 111 20 23 -39 17 30 39 7 40 -19 12 -35 19 -6 114 26 42 -28 19 23 64 -17 16 10 75 -52üGúHìAIûûú[ìLyM-2147 4219l41 32 54 0 7 51 81 30 60 61 43 17 45 55 102 32GúHìAIûûú[ìLàM-2147 4219l-61 1 -15 8 6 23 -10 12 -46 22 -28 38 -40 -1 -22 49 -89 56 -4 73 28 48 3 43 -12 34 -28 21üGúHìAIûûú[ìL~M-844 4360l41 23 55 -10 12 70 50 11 2 71 21 15 9 7 -6 53 -60 87GúHìAIûûú[ìLàM-599 4725l66 -122 65 -39 29 -44 35 17 45 -10 87 -65 3 -3 35 6 25 42 55 -10 42 -46 -16 -112 26 -30 3 -56 26 -28 21 -7 18 15 47 -42 45 -15 31 11 7 26 48 35üGúHìAIûûú[ìLPM-720 4687l121 38GúHìAIûûú[ìLàM-2465 4646l-28 -4 -49 40 -15 -28 31 -23 -11 -20 -27 -10 -45 11 -51 48 5 33 -21 41 -95 17 -44 31üGúHìAIûûú[ìLàM-2815 4782l-97 -45 -5 -23 -29 -22 -22 4 -15 31 -58 -10 -11 -46 -119 -23 8 -49 -78 -26üGúHìAIûûú[ìLOM-599 4725l76 79GúHìAIûûú[ìLàM144 4248l9 116 -41 59 6 50 50 13 17 34 -7 56 -30 57 6 31 8 12 66 102 44 42 42 11üGúHìAIûûú[ìLvM-2465 4646l55 73 0 34 37 29 0 54 38 23 3 38 18 17 4 45GúHìAIûûú[ìLàM-523 4804l25 18 21 -11 25 18 43 1 17 23 -10 40 4 102 103 147 53 1 62 45üGúHìAIûûú[ìLàM-1554 5190l-45 -64 5 -15 -60 -75 -29 -9 29 -48 -41 -27 20 -40 -45 -14 9 -145 3 -5 60 -111 -30 -65 2 -36 -17 -34 -21 -5üGúHìAIûûú[ìLàM-720 4687l-26 11 -11 58 -26 15 -24 -6 -49 40 -64 125 8 53 -46 29 -12 27 -31 -9 -33 12 -48 -32 -28 0 -38 40 -49 20 -80 -40 -57 62 -81 38 -23 -4 -26 71 -57 8 -33 -15üGúHìAIûûú[ìLàM-2370 4984l0 33 32 34 96 -67 34 9 10 -4 1 -17 2 -1 9 15 7 -2 0 -14 42 -6 32 46 -10 26 3 4 15 -4 5 7 -3 68 30 47 28 8 10 59 19 17 48 -16 28 69üGúHìAIûûú[ìLlM-1554 5190l-55 -6 -37 43 -42 5 -15 79 -40 34GúHìAIûûú[ìLyM-1932 5295l23 3 10 32 34 0 25 -10 19 -39 37 -4 9 41 32 27GúHìAIûûú[ìLàM-2219 5475l7 -15 68 -19 62 -42 5 -19 -15 -19 5 -6 24 8 29 -31 24 34 42 -31 -7 -37 43 -3üGúHìAIûûú[ìLàM-2920 5534l-26 -28 15 -41 -16 -62 24 -31 -4 -87 15 -40 -26 -36 21 -12 -5 -36 30 -19 -48 -89 0 -36 -80 -9 -4 -15 40 -60 118 -26 21 23 17 -5 6 -40 37 -19 -21 -26 22 -33 -28 -8 -3 -17üGúHìAIûûú[ìLàM-2870 5540l1 1 45 4 62 35 100 4 25 -46 86 -11 13 -23 33 -1 21 9 14 16 16 -1 32 -32 3 -16 -16 -30 17 -10 32 8 -1 25 -23 19 12 26 11 1 55 -50 26 4 23 36 20 3 44 -36üGúHìAIûûú[ìLàM-523 4804l-47 34 -3 51 14 21 -26 64 6 42 -35 -3 -3 13 12 49 -11 19 -38 7 -4 16 -52 21 -53 47 -11 119 -16 10 -47 -10 -13 -22 -37 -9 -56 130 -29 -5 -11 12 26 90 -52 46 26 50 -66 38 3 29üGúHìAIûûú[ìLM-1743 5345l22 43 10 79 28 1 7 23 62 27 35 35 128 37 32 38 -8 43GúHìAIûûú[ìLàM-2219 5475l25 31 4 41 -26 50 -33 10 -36 -32 -28 -3 -28 32 28 41 -24 69 -35 33 -39 7 -39 65 -45 -10 -7 4 2 18 43 10 22 -22 15 -4 29 6 44 77 12 62 10 4 17 -4 18 18üGúHìAIûûùGúHìAIûûúNøú[Hfil7 str1LNM-374 834l28 43GúHìAIûûú[ìÄLàM-346 877l49 -8 18 40 31 -29 81 17 9 48 -20 54 -27 28 27 34 42 3 2 -49 17 -8 10 6 -7 18 22 21 28 -5 149 70 61 3 40 -16 14 34üGúHìAIûûú[ìÄLàM200 1138l0 21 54 25 38 51 18 -5 11 -26 61 16 46 -39 60 42 24 -6 25 48 55 28 97 -41 45 9 24 31 32 -37 39 25 116 -10 15 -23 -18 -24 9 -64 25 -12 67 19üGúHìAIûûú[ìÄLtM1043 1166l50 24 14 -10 72 10 45 52 30 -14 66 3 56 81GúHìAIûûú[ìÄLtM1376 1312l15 -5 7 -34 128 14 4 22 29 10 -24 13 -6 37GúHìAIûûú[ìÄLNM1529 1369l6 10GúHìAIûûú[ìÄLàM1376 1312l-11 44 28 18 -24 19 19 35 52 -1 25 -24 29 -1 8 -27 27 -6üGúHìAIûûú[ìÄLàM1535 1379l114 25 3 7 20 47 22 14 39 -9 29 -45 67 -16 91 27 21 29 31 11 22 -22 42 6 17 -45 57 -9 81 -55 50 0 29 30 46 -8üGúHìAIûûú[ìÄLàM-3834 1670l7 69 31 -9 25 18 -5 27 -41 23 -34 51 6 27 22 11 -1 31 17 10 46 -7 42 -38 27 -2 8 -18 10 0 5 31 8 2 20 -17 72 -12 58 22 -9 34 46 -6 15 -22 18 6 4 2 17 37 27 -26 26 5 70 -27 11 -68 33 -9 44 33 31 -16üGúHìAIûûú[ìÄLàM-3178 1832l30 20 49 2 25 -32 13 12 29 30 54 -2 19 -18 18 20 -13 38 32 14 -31 87 6 47 25 20 35 -19 50 9 84 66 -10 17üGúHìAIûûú[ìÄLàM-3146 2517l-8 38 50 93 -13 10 -5 61 14 74 -24 62 26 37 -34 55 36 64 -48 62üGúHìAIûûú[ìÄLM-3152 3073l-77 25 -16 28 8 47 44 21 34 64 -30 108 -43 41 -20 95GúHìAIûûú[ìÄLnM-3544 3500l13 43 64 58 3 24 50 24 -14 90 42 51GúHìAIûûú[ìÄLxM-3386 3790l-6 46 56 30 -6 42 73 3 27 29 8 40 -56 79 4 32GúHìAIûûú[ìÄLdM-3453 4399l21 15 70 108 30 72 91 -21GúHìAIûûú[ìÄLàM-3241 4573l-47 129 -57 -14 -14 31 -71 8 -30 107 -76 62 -17 72 -46 73 7 9üGúHìAIûûú[ìÄLNM-2352 6093l7 0GúHìAIûûú[ìÄLRM-2355 6320l-29 -55GúHìAIûûú[ìÄLWM-906 6736l-31 -4 11 -36GúHìAIûûú[ìÄLsM-489 6865l22 54 30 23 40 83 33 65 -33 57 2 44 56 96GúHìAIûûùGúHìAIûûùDFbordersGúHìAIûûúSøúNøú[Hfil7 str2LwM-1532 1117l-6 2 -5 1 -6 2 -6 2 -5 1 -6 1 -6 1 -6 1 -9 2GúHìAIûûú[ìÒLàM-1587 1130l-6 1 -6 0 -5 -1 -6 -3 -3 -5 -1 -6 1 -6 4 -3 5 -3 6 -1 6 0 6 1 6 1 5 1 6 1 6 1 5 -2 6 -3 4 -3 4 -5 2 -5 4 -5 4 -4 6 -1 5 0 6 1 6 1 6 1 6 2 6 2üGúHìAIûûú[ìÒLàM-3565 1344l-2 -5 -2 -6 -2 -5 -1 -6 0 -6 0 -6 1 -6 1 -5 2 -6 2 -5 4 -5 5 -3 4 -3 4 -5 3 -5 2 -5 1 -6 2 -6 3 -4 4 -5 4 -4 4 -4 3 -5 3 -5 3 -5 3 -5 3 -5 3 -5 4 -5 4 -4 4 -4 5 -3 5 -2 7 -1 5 1 -1 4 -4 6 -3 5 -4 5 -3 4 -5 4 -5 2 -6 3 -3 4 -2 6 -1 5 -3 5 -4 5 -4 4 -2 6 -3 5 -3 5 -4 4 0 6 -1 6 -2 6 -4 4 -5 2 -5 3 -3 5 -1 6 -1 6 0 6 0 6 0 6 0 6 -3 4 -6 5üGúHìAIûûú[ìÒLàM-2635 2170l6 -3 2 -4 0 -6 -1 -6 -1 -6 2 -6 3 -5 3 -5 4 -4 6 0 7 0 5 -1 3 -5 1 -6 1 -6 0 -6 1 -6 3 -5 4 -3 6 -3 6 -1 6 1 6 1 5 -2 1 -5 -2 -7 -4 -4 -3 -5 1 -6 3 -5 5 -3 6 1 6 0 6 -1 6 -3 5 -3 1 -4 0 -6 -2 -6 -2 -6 -2 -6 -3 -5 -4 -4 -2 -5 -1 -6 0 -6 0 -6 3 -5 4 -4 3 -5 2 -6 2 -5 -4 -8üGúHìAIûûú[ìÒLàM-2532 1949l-3 6 -3 5 -3 5 -4 3 -6 1 -5 1 -4 5 -1 6 -1 5 1 6 1 6 3 5 3 5 2 6 0 6 0 5 -2 6 -4 5 -4 3 -5 4 -4 4 -4 4 -4 4 -2 6 -3 5 -4 4 -4 4 -6 1 -5 1 -3 4 -2 6 -2 6 1 6 0 6 -4 4 -5 3 -6 2 -5 3 -5 3 -5 2 -6 1 -7 0 -5 2 0 6 3 4 5 4 3 5 1 5 1 6 1 6 2 6 1 5 5 -1üGúHìAIûûú[ìÒLàM680 2265l-2 6 -3 5 -5 3 -5 2 -6 2 -6 0 -5 -2 -6 2 -5 3 -4 4 -3 5 -1 6 0 6 0 7 -2 4 -5 2 -7 0 -6 -1 -5 -3 -5 -3 -6 -2 -5 0 -6 2 -6 3 -3 3 -1 9üGúHìAIûûú[ìÒLàM-2723 3026l-5 3 -5 4 -4 4 -2 6 -1 5 0 6 2 6 2 6 2 5 3 4 5 3 6 3 5 2 5 3 1 6 -1 6 1 6 -2 5 -4 4 -5 4 -5 3 -5 2 -6 1 -6 1 -6 1üGúHìAIûûú[ìÒLàM-2668 3397l6 1 5 0 5 -3 5 -4 4 -3 6 -3 5 -2 5 -3 2 -5 1 -6 0 -6 3 -5 2 -5 0 -6 -5 -4 -5 -1 -3 4 -3 6 -1 6 -1 6 -1 5 -3 5 -5 4 -4 3 -6 3 -6 1 -3 4 -3 8üGúHìAIûûú[ìÒLàM-2311 3446l-4 -4 -3 -5 -3 -5 -1 -6 0 -5 2 -6 2 -6 1 -5 1 -6 -1 -6 -3 -5 -5 -2 -6 1 -3 5 0 6 -2 6 -3 5 -4 4 -4 3 -6 3 -6 1 -5 2 -6 0 -6 -1 -6 1 -5 1 -6 1 -6 0 -6 0 -6 0 -6 0 -5 1 -6 0 -6 1 -6 2 -5 1 -5 3 -5 3 -4 5 -3 5 -1 8üGúHìAIûûú[ìÒLàM-2463 3452l6 1 5 -1 6 -3 5 -2 5 -3 5 -3 5 -3 6 -2 5 0 6 0 6 1 6 0 6 0 6 0 5 3 4 4 5 1 6 -2 5 -3 6 -2 5 -2 6 -1 6 -1 6 0 4 5 4 4 5 2 7 1üGúHìAIûûú[ìÒLàM-2509 3450l-3 -5 2 -5 4 -4 5 -4 4 -4 2 -6 -4 -3 -6 0 -4 3 -4 5 -3 5 -3 5 -5 3 -5 3 -5 2 -5 4 -4 3 -6 1 -6 0 -6 -1 -6 -1 -5 -3 -4 -4 -4 -4 -4 -4 -5 -4 -5 -2 -6 -1 -6 -1 -6 -1 -5 -3 -3 -5 -2 -5 -3 -5 -5 -3 -6 2 -6 -1 -6 -1 -5 -1 -12 1üGúHìAIûûú[ìÒLàM-2665 3406l5 4 5 3 4 3 6 3 6 1 3 4 3 5 3 5 5 3 6 1 6 1 6 -1 6 1 5 0 5 3 5 4 4 5 2 5 3 4 6 1 6 1 6 1 5 0 6 0 6 -3 5 -2 5 -3 6 -1 6 0 5 -2 6 -2üGúHìAIûûú[ìÒLàM-2994 3305l-3 -5 -5 0 -6 0 -6 1 -6 2 -4 4 -5 2 -6 2 -5 2 -6 3 -5 3 -5 2 -4 4 -5 4 -5 3 -6 0 -3 -4 0 -6 2 -6 -3 -4 -6 -2 -3 5 -1 6 1 6 1 6 -1 5 -5 3 -6 2 -5 3 -6 2 -5 3 -5 3 -4 4 -4 4 -3 5 -2 6 -2 5 -2 6 -4 4 -3 5 -2 6 -3 5 -2 5 -2 6 -3 5 -3 5 -3 5 -3 5 -3 5 -3 5 -2 5 -4 5 -2 5 4 7üGúHìAIûûú[ìÒLàM-2707 3409l-1 -6 -1 -6 -1 -6 -3 -1 -5 5 -2 6 -1 5 -3 5 -5 4 -4 4 -5 3 -5 1 -6 1 -6 2 -5 2 -6 2 -5 2 -5 2 -6 2 -5 2 -6 2 -5 2 -6 2 -5 2 -6 2 -5 2 -6 1 -6 1 -6 1 -5 0 -6 1 -6 1 -6 -1 -6 0 -5 1 -6 2 -6 2 -5 1 -6 2 -5 2 -5 4 -4 4 -6 1 -6 0 -3 -5 -1 -6 -1 -4 -5 -2 -6 -2 -6 0 -7 0 -4 2 -4 6 -3 5 -5 1 -6 -1 -5 -3 -5 -2 -5 -4 -5 -3 -5 -3 -5 -3 -4 -4 -5 -4 -2 -5 -1 -6 -4 -4 -6 -3 -5 2 -6 1 -6 1 -5 2 -4 4 -6 3 -6 0 -6 -1 -3 -3 0 -7 5 -3 3 -5 -1 -6 -5 0 -6 3 -4 4 -4 4 -6 3 -5 2 -6 2 -5 0 -6 1 -6 2 -5 2 -5 2 -6 3 -5 2 -6 2 -5 3 -5 4 -5 2 -5 -2 0 -5 4 -5 3 -5 5 -4 3 -4 4 -5 3 -5 3 -5 3 -5 3 -5 2 -5 2 -6 2 -5 2 -6 2 -5 2 -6 3 -5 4 -4 5 -2 6 -2 6 -1 5 -1 6 -1 6 -2 5 -3 4 -4 4 -4 4 -4 5 -4 4 -3 5 -4 5 -2 6 -2 6 -1 6 0 5 -2 5 -3 6 -2 5 -3 6 -1 6 0 -1 -4üGúHìAIûûú[ìÒLàM-3947 3399l2 5 2 6 3 5 4 4 1 6 -3 5 -1 6 0 6 -1 6 0 5 1 6 0 6 0 6 -2 5 -3 5 -4 5 -4 4 -3 5 -4 5 -3 5 -2 5 -2 6 1 6 5 4 4 4 -1 5 -3 5 -5 4 -5 0 -6 -2 -6 1 -5 3 -2 6 0 6 0 7üGúHìAIûûú[ìÒLàM-3989 3565l5 2 6 2 6 -1 5 -2 5 -3 4 -5 2 -5 4 -5 4 -4 4 -4 6 -3 4 -3 -1 -5 -2 -6 -1 -6 0 -6 3 -5 5 -1 6 2 6 0 7 -1 3 -2 -3 -6 -6 -3 -6 -1 -5 -1 -2 -5 2 -6 0 -6 1 -6 0 -6 0 -6 0 -6 0 -5 2 -6 2 -6 1 -5 2 -6 2 -5 1 -6 -2 -6 -5 -4 -5 -1 -6 -2 -6 0 -6 -1üGúHìAIûûú[ìÒLàM-604 3461l5 3 5 4 4 4 4 4 3 5 2 6 3 5 4 4 5 3 6 2 6 -2 5 1 5 4 0 5 -4 5 -1 6 0 6 1 5 3 6 3 5 4 4 4 5 4 3 5 4 5 3 6 1 6 0 5 2 5 3 5 4 1 5 -1 6 3 5 3 4 4 5 5 6üGúHìAIûûú[ìÒLàM-481 3602l-5 3 -6 0 -4 -2 -5 -5 -4 -4 -4 -5 -3 -5 -4 -2 -6 0 -7 0 -5 0 -6 -2 -5 -3 -2 -5 -2 -6 -2 -6 -1 -6 -3 -5 -4 -4 -4 -4 -5 -3 -4 -5 -4 -4 -3 -5 -2 -5 -3 -5 -5 -4 -5 -3 -4 -4 -2 -5 -2 -6 -1 -6 -1 -5 -1 -6 0 -6 1 -8üGúHìAIûûú[ìÒLàM-3176 3467l4 3 6 0 6 -1 5 -2 5 -3 4 -4 4 -5 5 -2 6 -3 5 -1 6 -2 6 0 6 0 5 2 6 1 6 0 6 0 5 0 6 0 6 0 6 0 6 0 6 0 5 -2 5 -3 6 0 6 1 6 2 5 2 4 4 5 4 5 3 4 3 5 4 5 3 5 3 5 3 5 3 5 3 5 3 3 5 -1 6 -2 6 1 4 6 3 6 0 6 -1 4 4 3 5 3 5 3 6 2 5 3 5 2 5 3 5 3 5 3 6 3 4 4 5 4 4 5 3 5 3 5 3 6 2 5 1 6 0 6 0 6 1 6 0 6 0 6 0 5 0 6 2 6 2 5 2 5 2 6 3 5 2 5 4 4 3 5 4 4 4 5 3 5 3 5 2 6 2 6 0 6 -1 4 -5 1 -6 -4 -4 -5 -3 -6 -1 -6 0 -5 -3 -5 -2 -5 -4 -5 -3 -5 -3 -5 -3 -5 -3 -5 -3 -4 -4 -5 -3 -5 -4 -5 -3 -6 0 -5 0 -6 1 -6 1 -6 1 -6 1 -5 -1 -6 -1 -6 -2 -5 -2 -5 -3 -5 -4 -4 -4 -4 -4 -3 -5 -3 -5 -4 -5 -3 -4 -4 -5 -3 -5 -4 -4 -3 -5 -3 -5 -2 -6 -1 -6 1 -5 5 -4 5 -2 6 -2 6 -1 5 -1 6 -2 5 -2 6 -1 6 -1 5 -1 6 -1 6 -2 5 -1 6 -1 6 0 6 0 6 0 5 -1 6 -1 6 -1 6 -1 5 -2 6 -2 5 -2 5 -2 6 -3 5 -2 5 -3 5 -3 6 -2 5 -3 5 -2 6 -1 6 0 6 1 5 -2 5 -3 3 -5 4 -4 5 -4 4 -4 8 -6üGúHìAIûûú[ìÒLàM-2017 3833l-1 -6 -2 -5 -3 -5 -3 -5 -3 -5 -2 -5 1 -6 3 -6 -1 -5 -4 -4 -5 -4 -5 -3 -5 -3 -5 -3 -5 -3 -5 -3 -4 -4 1 -6 5 -2 6 1 6 1 7 -4üGúHìAIûûú[ìÒLàM-2142 3754l-1 6 -1 6 -1 5 -1 6 -1 6 -1 6 -1 5 -2 6 -2 5 -2 6 -3 5 -3 5 -4 4 -5 4 -5 3 -5 3 -5 4 -5 3 -5 0 -5 -3 -4 -5 -2 -6 -1 -6 -4 -1 -6 4 0 5 2 6 -1 6 0 6 -1 6 -1 5 -2 6 -2 5 -1 6 -2 6 -1 5 -1 6 3 10üGúHìAIûûú[ìÒLàM-2224 3903l5 2 5 -3 0 -5 -1 -6 -2 -6 0 -6 2 -5 3 -5 5 -4 4 -4 6 -2 5 -2 6 -3 5 -3 5 -3 5 -3 4 -3 5 -3 5 -4 4 -4 4 -5 3 -4 3 -5 3 -5 3 -6 2 -5 3 -5 2 -6 2 -5 2 -6 2 -5 2 -6 2 -5 2 -5 5 -4 5 -2 6 -2 6 1 6 1 4 4 3 5 3 5 3 5 4 5 3 5 5 3 5 3 5 3 4 4 4 4 3 5 2 6 2 5 2 6 3 5 4 5 5 2 9 1üGúHìAIûûú[ìÒLàM-2310 3962l-6 1 -6 0 -6 1 -5 1 -6 2 -5 4 -4 4 -3 5 -3 5 -4 4 -5 3 -6 2 -5 2 -6 2 -5 1 -6 2 -6 1 -5 2 -5 3 -5 3 -3 5 -5 7üGúHìAIûûú[ìÒLàM-2420 4022l2 3 6 1 6 -1 5 -3 5 -3 5 -3 5 -3 5 -3 6 -2 5 -2 6 -2 5 -2 5 -3 5 -3 5 -3 5 -3 5 -4 4 -3 5 -4 4 -4 4 -5 7 -8üGúHìAIûûú[ìÒLàM-2391 4081l1 -7 1 -5 4 -3 6 -2 6 -1 6 1 4 5 5 3 5 2 6 1 6 0 6 0 6 -1 5 -2 6 -3 4 -3 5 -3 6 0 6 0 6 0 6 0 6 0 5 0 6 -1 6 -1 5 -2 6 -2 5 -4 4 -3 6 -2 6 2 4 3 0 5 -3 6 -1 6 -1 6 2 5 4 5 4 4 4 4 5 4 5 2 6 3 5 1 6 2 4 4 4 5 3 6 0 5 -5 5 -5 0 -5 -2 -5 -3 -6 -3 -4 -3 -5 -5 -4 -4 -5 -2 -6 -2 -3 -5 -3 -5 -3 -5 -2 -5 -4 -5 -4 -4 -6 -2 -5 -1 -6 0 -6 1 -6 0 -6 1 -6 0 -5 1 -6 1 -6 1 -4 4 -5 3 -6 1 -6 0 -6 0 -6 0 -5 -1 -6 -2 -6 -2 -5 -1 -6 -1 -6 -1 -6 0 -5 1 -7 0üGúHìAIûûú[ìÒLàM-858 4621l4 -3 5 -4 4 -4 4 -5 3 -5 3 -5 3 -5 5 -3 3 5 -1 6 -4 4 -4 4 -4 5 -4 4 -4 4 -3 5 -3 5 -1 6 1 5 3 6 2 5 3 6 0 5 -3 5 -4 5 -4 4 -4 4 -9 3üGúHìAIûûú[ìÒLàM-867 4683l-1 -5 1 -6 2 -6 2 -5 2 -5 2 -6 1 -5 1 -6 1 -6 -1 -6 -1 -6üGúHìAIûûú[ìÒLàM3405 6355l-6 -2 -5 -2 -6 -1 -5 -2 -7 -2 -5 0 -2 4 0 6 0 7 0 6 -1 6 -2 6 -1 6 -1 5 2 6 4 5 5 2 6 0 6 -1 6 1 5 2 7 4üGúHìAIûûú[ìÒLàM369 6486l6 -2 5 -2 6 -2 5 -2 6 -2 5 -2 6 -2 5 -2 6 -2 5 -2 6 -3 5 -2 6 -1 5 -1 6 0 6 2 5 4 4 4 2 5 -1 6 -2 6 -2 6 -3 5 -3 5 -4 5 -4 3 -5 2 -6 2 -6 1 -6 1 -5 1 -6 0 -6 0 -6 1 -6 1 -5 1 -6 1 -6 1 -6 2 -5 1 -6 3 -5 2 -4 4 -4 4 -4 5 -5 4 -4 3 -6 2 -5 2 -6 1 -6 0 -5 -1 -6 -2 -6 -2 -6 -1 -5 0 -6 1 -6 1 -6 1 -5 1 -6 1 -6 1 -6 0 -6 0 -6 0 -4 -3 -1 -6 2 -6 5 -3 5 -3 5 -3 5 -4 5 -3 4 -4 5 -4 4 -4 5 -3 5 -3 5 -3 5 -2 6 -2 6 -2 5 -2 6 -1 6 0 5 1 5 4 5 3 5 -1 5 -3 6 -4 5 -2 5 -2 10 -4üGúHìAIûûú[ìÒLàM2860 6683l2 -5 2 -6 1 -6 2 -5 2 -6 2 -5 2 -5 3 -6 2 -5 3 -5 3 -5 3 -5 3 -5 4 -5 3 -5 3 -5 3 -4 3 -5 4 -5 2 -5 3 -6 3 -5 3 -5 4 -5 3 -5 4 -4 4 -3 5 -3 6 -2 5 -1 6 -2 6 -1 6 -2 6 -1 5 -2 5 -3 5 -3 4 -5 4 -4 5 -3 5 -2 6 -3 5 -2 6 -2 5 -3 6 -3 6 -2 5 -1 5 0 5 3 4 5 3 5 2 6 1 6 0 6 -1 6 -2 5 -5 4 -5 3 -6 1 -5 0 -6 0 -6 0 -6 1 -6 2 -5 3 -5 3 -4 4 -3 5 -1 6 -3 5 -3 5 -3 5 -4 4 -4 4 -4 4 -5 4 -5 3 -5 2 -6 2 -6 1 -5 3 -5 3 -4 4 -5 3 -5 4 -4 4 -4 4 -5 4 -4 4 -4 4 -4 4 -4 4 -4 5 -4 4 -3 5 -4 5 -4 4 -5 3 -5 1 -12 1üGúHìAIûûú[ìÒLàM-3569 4591l5 -3 5 -3 4 -5 1 -5 2 -6 4 -4 5 -3 5 -3 5 -3 5 -3 5 -3 6 -2 5 -2 6 -1 6 0 6 -1 5 -3 4 -4 3 -5 2 -5 0 -7 1 -5 3 -5 5 -4 5 -3 5 -2 6 0 6 0 6 1 5 1 6 1 6 1 6 1 6 0 6 1 7 2 6 1 4 -1 3 -4 0 -7 -1 -6 -4 -5 -5 -3 -6 -2 -5 -1 -6 -1 -6 0 -6 0 -6 1 -5 1 -6 1 -6 1 -5 2 -6 1 -6 2 -6 2 -5 2 -6 2 -6 1 -5 1 -5 0 -6 -3 -3 -6 0 -5 1 -6 3 -6 2 -5 4 -5 3 -4 5 -4 3 -5 4 -4 3 -5 3 -5 3 -5 3 -6 2 -5 3 -5 4 -4 4 -4 6 -6üGúHìAIûûú[ìÒLàM-3415 4234l-6 3 -4 4 -3 5 -2 5 -2 6 2 6 0 5 -2 6 -1 6 -3 5 -5 4 -5 1 -6 -3 -6 -2 -6 -2 -3 2 -1 7 2 6 4 4 4 5 1 5 0 6 0 6 -1 6 0 6 -1 6 0 6 -2 5 -3 5 -3 5 -3 5 -4 5 -2 5 -2 5 -2 6 -2 5 -3 6 -2 5 -3 6 -3 5 -4 2 -6 0 -7 -1 -6 0 -6 0 -5 1 -5 3 -2 6 1 5 4 5 4 5 2 5 -1 6 -2 5 -1 6 -1 6 -1 6 -1 6 -1 5 -2 6 -2 5 -2 6 -2 5 -2 6 -2 5 -3 6 -2 6 -3 4 -4 -1 -3 -6 -3 -5 -2 -6 -2 -5 -4 -5 -3 -5 -4 -4 -4 -5 -4 -4 -3 -5 -2 -5 -2 -5 -1 -6 -1 -7 -2 -6 -3 -3 -6 1 -6 4 -2 4 0 6 1 6 1 6 2 6 1 5 0 6 -1 6 3 5 5 2 6 2 5 3 5 4 4 4 2 5 2 6 1 6 0 6 0 6 -1 5 -3 5 -1 6 1 5 2 6 3 5 5 7üGúHìAIûûú[ìÒLàM-2748 3125l-6 -1 -6 -1 -5 -2 -3 -5 1 -6 1 -6 1 -6 2 -4 5 -5 3 -4 4 -5 4 -4 2 -5 1 -6 -1 -6 -3 -5 -5 -4 -5 -2 -6 -1 -6 1 -5 1 -7 2 -6 0 -1 -3 3 -7 4 -5 5 -2 6 0 6 1 5 2 6 0 4 -3 5 -4 4 -4 5 -4 4 -4 4 -4 4 -5 3 -5 4 -4 7 -3üGúHìAIûûú[ìÒLàM-856 2935l4 -1 4 -4 4 -4 1 -6 0 -6 0 -5 3 -6 3 -5 5 -3 3 -5 2 -6 -1 -5 -4 -3 -6 -3 -3 -5 -2 -6 0 -6 1 -6 2 -5 2 -6 3 -5 4 -4 4 -5 4 -3 5 -3 7 -1 5 -2 2 -5 2 -9üGúHìAIûûú[ìÒLàM-802 2802l-6 0 -6 0 -6 1 -6 2 -5 2 -4 3 -4 5 -3 5 -2 6 -2 5 -3 5 -2 6 -2 5 -2 6 -1 5 -3 6 -2 5 0 6 2 5 4 5 3 5 -1 5 -3 6 -1 5 0 6 -1 6 -3 5 0 6 5 6üGúHìAIûûú[ìÒLàM572 2328l4 3 5 2 6 1 6 1 6 1 5 1 6 2 5 3 6 2 5 -1 6 -2 5 -3 4 -5 2 -5 2 -6 2 -5 3 -5 3 -5 5 -4 5 -1 6 -1 6 -3 5 -3 4 -3 5 -4 3 -4 4 -5 3 -5 2 -6 2 -5 2 -6 1 -6 1 -6 2 -5 2 -5 5 -4 5 -2 6 -2 6 -2 6 0 6 1 5 1 5 3 5 4 4 4 4 5 4 3 5 2 6 0 11 0üGúHìAIûûú[ìÒLxM794 2248l-2 -5 -3 -6 -3 -4 -5 -4 -5 -3 -4 -4 -5 -3 -7 -4GúHìAIûûú[ìÒLàM1514 7287l-1 -6 -1 -6 0 -6 -1 -6 -1 -5 0 -6 -1 -6 0 -6 1 -6 1 -5 3 -5 4 -5 3 -5 4 -5 3 -4 4 -4 4 -5 4 -4 5 -4 4 -4 5 -4 4 -4 5 -4 4 -4 3 -5 2 -4 1 -6 -1 -6 -1 -6 -2 -6 -2 -6 -4 -6 -3 -3 -5 0 -6 4 -4 4 -4 4 -4 5 -3 5 -4 5 -3 4 -3 6 -2 5 -3 5 -4 4 -4 4 -5 3 -6 2 -5 2 -6 3 -5 2 -6 1 -5 2 -6 2 -6 1 -5 1 -6 1 -7 0 -6 -1 -5 -1 -4 -3 -3 -5 -1 -6 0 -7 0 -6 2 -6 1 -5 -1 -5 -6 -3 -5 1 -5 2 -6 4 -4 3 -5 3 -5 4 -3 5 -4 5 -3 5 -2 6 -2 5 0 5 3 5 4 5 5 4 3 5 4 5 2 5 -1 6 -1 6 -2 6 -3 5 -4 4 -6 0 -6 0 -6 0 -6 -1 -6 1 -4 3 -5 3 -4 5 -5 4 -5 3 -5 2 -5 2 -6 2 -5 2 -6 2 -5 3 -8 5üGúHìAIûûú[ìÒLàM2600 6812l5 -4 5 -3 4 -4 5 -4 4 -5 4 -4 4 -4 2 -5 0 -7 -3 -4 -6 -1 -6 0 -6 1 -6 0 -6 1 -6 1 -5 0 -6 2 -6 1 -6 0 -6 2 -4 3 -4 4 -3 5 -4 5 -5 3 -5 2 -6 2 -6 1 -6 1 -6 0 -6 -1 -6 0 -5 2 -4 3 -5 4 -3 5 -3 5 -2 6 -1 6 -2 5 -4 5 -5 1 -5 -3 -5 -4 -6 -2 -5 -1 -6 0 -6 0 -6 1 -5 3 -2 5 1 7 3 4 5 4 5 3 5 3 6 3 5 2 5 2 6 0 6 0 6 0 6 0 6 0 5 0 6 2 6 1 6 1 5 0 6 -2 6 -2 5 -2 5 -3 4 -5 3 -5 3 -5 4 -3 6 -1 6 1 6 1 6 -1 5 -4 4 -4 4 -5 3 -4 2 -6 3 -5 2 -6üGúHìAIûûú[ìÒLgM-2710 2997l3 5 -1 6 -4 5 -3 4 -4 4 -4 5GúHìAIûûú[ìÒLàM-2041 3748l4 -3 -1 -6 -3 -5 -4 -4 -5 -3 -5 -3 -6 -2 -5 -1 -6 -1 -6 0 -6 1 -8 1üGúHìAIûûú[ìÒLwM-2100 3724l-5 1 -6 1 -6 2 -5 2 -5 3 -5 4 -4 4 -4 4 -2 9GúHìAIûûú[ìÒLOM-2092 3722l-8 2GúHìAIûûú[ìÒLàM-728 2977l-6 0 -5 -3 -4 -5 -1 -6 -2 -5 -4 -5 -5 -2 -6 0 -6 1 -5 2 -6 2 -5 2 -6 2 -5 1 -6 1 -6 1 -6 0 -6 0 -5 0 -6 2 -5 3 -5 2 -5 3 -6 2 -5 3 -4 4 -4 5üGúHìAIûûú[ìÒLàM-863 2987l-4 5 -4 4 -4 5 0 5 5 4 5 3 6 3 4 4 2 5 1 6 1 6 0 5 0 6 0 6 2 6 2 6 3 4 6 2 6 1 6 0 5 -2 2 -5 1 -6 1 -6 1 -6 -1 -6 -3 -5 -2 -5 -4 -4 -4 -5 -4 -5 -2 -5 -1 -6 0 -6 1 -5 3 -5 4 -4 3 -5 5 -3 5 -3 6 -2 6 0 5 -1 6 -1 6 0 6 0 6 1 5 0 6 1 6 1 5 3 5 3 5 3 6 2 5 2 5 2 6 1 6 1 6 -1 5 -5 -1 -4 -5 -4 -5 -3 -6 1 -7 1üGúHìAIûûú[ìÒLàM760 2215l-5 -3 -5 -3 -5 -2 -6 -1 -6 0 -6 1 -6 2 -4 3 -5 4 -4 4 -4 4 -5 4 -4 5 -3 4 -4 5 -2 5 -3 5 -1 6 -2 7üGúHìAIûûú[ìÒLàM-2840 2347l5 -3 5 -3 5 -3 4 -4 5 -4 4 -5 3 -5 4 -4 5 1 6 3 4 5 1 5 -1 6 0 6 1 6 1 7 2 5 4 2 6 0 7 0 4 3 4 4 4 5 3 6 3 6 3 5 3 5 3 3 5 0 5 -4 6 -5 5 -1 3 4 6 7üGúHìAIûûú[ìÒLàM-2712 2400l5 3 4 4 4 4 4 5 4 4 4 4 3 5 4 4 4 5 3 5 4 4 3 5 2 6 3 5 2 6 1 6 -1 5 -5 4 -5 -1 -5 -4 -5 -4 -4 -4 -3 -5 -1 -6 -2 -6 -1 -6 -2 -5 -3 -4 -5 -3 -6 -2 -6 0 -6 1 -5 3 0 8 -2 1 -4 -4 -3 -7 -1 -5 2 -6 0 -6 -3 -5 -5 -5 -4 -3 -6 0 -6 1 -5 -3 -4 -5 -4 -3 -6 -2 -5 -2 -5 -3 -5 -5 -5 -4 -4 -1 -3 3 -3 6 -3 6 -3 5 -5 5 -5 2 -4 -2 -3 -6 -1 -6 2 -5 2 -6 2 -6 1 -6 0 -5 -4 -5 -4 -4 -6 -6üGúHìAIûûú[ìÒLàM-3453 4399l5 -4 3 -5 4 -5 3 -5 1 -5 0 -6 -1 -6 -1 -6 0 -6 -1 -5 0 -6 0 -6 2 -6 1 -5 2 -6 2 -5 3 -5 4 -4 4 -5 4 -4 4 -5 3 -4 3 -6 2 -5 1 -6 1 -6 0 -5 -1 -6 -2 -6 -3 -4 -5 -7üGúHìAIûûú[ìÒLàM-1493 1087l4 3 4 5 3 5 1 5 -1 7 -2 5 -4 4 -6 -1 -6 -2 -6 -1 -5 -2 -6 0 -6 0 -9 2üGúHìAIûûùGúHìAIûûúNøú[Hfil7 str3LàM-3176 3467l-5 3 -4 3 -5 4 -5 3 -5 4 -4 3 -5 3 -5 3 -5 3 -6 2 -6 1 -5 1 -6 1 -10 1üGúHìAIûûú[ìØLàM-3544 3500l-6 0 -6 1 -6 0 -5 2 -5 2 -5 3 -5 4 -5 3 -5 3 -6 2 -5 0 -6 -2 -6 -1 -5 -2 -6 -2 -6 1 -5 2 -5 4 -4 4 -4 4 -4 4 -4 4 -4 4 -5 4 -4 4 -4 4 -5 4 -4 3 -5 4 -5 4 -4 3 -5 4 -4 3 -5 4 -4 4 -4 4 -4 4 -4 5 -3 4 -4 5 -4 5 -4 4 -4 4 -5 2 -6 1 -6 0 -6 -2 -5 -2 -6 -1 -6 -1 -6 -1 -5 1 -6 2 -5 2 -6 2 -6 1 -6 1 -5 1 -6 1 -6 0 -6 -1 -6 -1 -5 -1 -5 -3 -6 -2 -5 -2 -6 -1 -6 -1 -5 1 -6 2 -5 3 -5 4 -4 4 -5 3 -6 2 -6 1 -5 0 -5 -3 -5 -3 -5 -4 -5 -3 -5 -2 -6 -1 -6 0 -6 1 -5 -1 -6 0 -7 -1üGúHìAIûûú[ìØLàM-3997 3618l-4 4 -5 3 -5 2 -6 1 -6 0 -6 0 -5 0 -6 0 -6 0 -6 1 -6 1 -5 2 -4 4 -3 5 -2 6 -2 5 -2 6 -2 5 -4 5 -4 4 -4 4 -4 4 -4 5 -4 4 -4 4 -4 4 -4 5 -4 3 -5 4 -5 3 -5 4 -4 3 -5 3 -5 3 -5 4 -5 3 -4 4 -4 4 -3 5 -3 5 -1 6 -1 6 -3 4 -5 4 -5 3 -4 4 -3 5 -4 5 -4 4 -3 5 -2 5 -2 6 -1 6 0 6 0 5 -2 6 -2 6 -2 5 -2 5 -3 5 -4 5 -3 5 -4 4 -3 5 -4 5 -3 4 -4 5 -4 4 -4 4 -4 4 -5 4 -5 3 -4 4 -5 3 -5 4 -5 3 -5 3 -5 2 -5 1 -6 0 -6 0 -6 0 -6 0 -6 0 -6 1 -5 1 -6 2 -5 3 -5 3 -4 5 -3 4 -1 6 -2 6 -2 5 -2 6 -2 5 -3 5 -2 5 -3 6 -3 5 -3 5 -3 5 -3 6üGúHìAIûûú[ìØL_M-3252 3502l-6 1 -5 1 -6 1 -11 2GúHìAIûûú[ìØLàM-3280 3507l-6 0 -6 1 -6 1 -5 1 -6 1 -6 0 -6 -1 -6 0 -5 -1 -6 0 -6 -1 -6 0 -6 -1 -5 -1 -6 0 -6 -2 -6 -1 -5 -1 -6 0 -6 2 -5 2 -6 1 -5 2 -6 2 -5 3 -5 2 -6 2 -6 -1 -5 -1 -6 -2 -6 -1 -6 -1 -5 -1 -6 -1 -6 0 -6 -1 -5 -2 -6 -2 -5 -1 -6 -2 -6 -2 -5 0 -6 -1 -6 0 -6 1 -7 0üGúHìAIûûú[ìØLcM-2869 5541l6 -3 5 -2 5 -4 4 -4 4 -5GúHìAIûûú[ìØLàM1155 2704l-6 1 -6 1 -5 1 -6 1 -6 1 -6 1 -5 1 -6 1 -6 1 -6 0 -5 0 -6 -2 -6 -2 -5 -1 -6 -1 -6 -1 -6 -1 -6 0 -5 -1 -6 0 -6 0 -6 0 -6 0 -6 0 -5 1 -6 2 -5 3 -6 1 -5 -1 -5 -3 -5 -4 -4 -3 -5 -4 -5 -3 -5 -4 -4 -3 -5 -3 -6 -3 -5 -3 -4 -4 -3 -4 -3 -6 -1 -6 0 -5 2 -6 1 -6 2 -6 0 -5 0 -6 0 -6 0 -6 -1 -6 0 -5 -2 -6 -1 -6 -2 -5 -2 -6 -1 -6 -2 -5 -1 -6 -1 -6 -1 -6 0 -5 0 -6 1 -6 2 -5 2 -6 3 -5 4 -4 4 -4 5 -3 5 -3 6 -3 5 -2 6 -2 5 -2 6 -3 4 -3 3 -5 3 -5 2 -5 3 -6 2 -5 3 -6 2 -5 2 -6 1 -5 1 -6 1 -6 1 -6 0 -5 -1 -6 -1 -6 -2 -6 -3 -5 -4 -4 -5 -3 -4 -4 -5 -3 -4 -4 -5 -4 -4 -5 -2 -5 -2 -5 -1 -6 0 -6 -1 -6 -3 -5 -5 -3 -6 -3 -5 -2 -6 -1 -6 -1 -5 -1 -6 1 -6 2 -5 2 -6 1 -6 2 -5 2 -6 1 -6 1 -5 1 -6 0 -6 0 -6 0 -6 -1üGúHìAIûûú[ìØLàM-3921 2460l-6 2 -5 2 -4 4 -5 4 -4 3 -6 2 -6 1 -5 -1 -6 -2 -5 -3 -6 -1 -5 1 -6 1 -6 -1 -6 -2 -5 -2 -3 -5 -3 -5 -5 -2 -6 -2 -6 -1 -5 -2 -5 -3 -5 -4 -3 -5 -3 -5 -3 -5 -4 -4 -3 -5 -4 -4 -5 -5 -4 -3 -5 -3 -5 -2 -6 -2 -6 -2 -5 -2 -6 -1 -5 -2 -6 -1 -11 -2üGúHìAIûûú[ìØLàM847 2333l-6 -1 -7 -1 -4 -3 -3 -5 -2 -5 -1 -6 -1 -6 0 -6 2 -6 1 -5 1 -6 1 -6 1 -6 0 -6 -3 -4 -6 -4 -5 -2 -8 -3üGúHìAIûûú[ìØLPM794 2248l4 0 9 4GúHìAIûûú[ìØLàM3001 367l0 6 0 6 0 6 0 5 1 6 0 6 1 6 2 5 2 6 2 5 3 5 2 6 2 5 3 5 2 6 2 5 3 5 2 6 3 5 3 5 2 5 3 6 3 5 3 5 2 5 3 5 3 5 3 5 3 5 3 5 3 5 3 5 4 5 3 4 4 5 3 4 4 5 4 4 4 5 4 4 4 4 4 5 4 4 4 4 4 5 3 6üGúHìAIûûùGúHìAIûûúNøú[Hfil7 str4LàM1184 367l2 5 3 5 3 5 3 5 4 5 3 5 3 5 3 5 2 5 3 5 2 6 3 5 3 5 4 4 4 4 4 5 4 4 4 4 2 6 2 5 1 6 2 5 3 5 3 5 4 5 4 4 4 5 3 4 4 5 4 4 3 5 4 5 3 5 2 5 3 5 2 5 3 6 2 5 3 5 3 5 4 4 5 4 7 5üGúHìAIûûú[ìÜL]M-2665 3406l-5 -2 -6 -2 -10 -1GúHìAIûûú[ìÜLZM-2686 3401l-6 2 -5 2 -10 4GúHìAIûûú[ìÜLwM-2463 3452l-5 2 -6 2 -5 0 -6 -1 -6 -1 -5 -2 -6 -1 -7 -1GúHìAIûûú[ìÜLàM-3569 4591l-6 1 -5 1 -6 1 -6 -1 -6 -1 -5 -1 -6 0 -6 0 -6 2 -4 3 -4 5 -3 5 -3 5 -4 4 -4 4 -4 5 -3 5 -3 5 -2 5 -1 6 -1 6 -1 6 0 5 0 6 0 6 1 6 1 6 1 6 2 5 1 6 0 6 -1 5 -3 5 -3 5 -3 5 -3 5 -4 5 -3 5 -1 6 -1 6 1 6 1 5 3 6 2 5 2 5 0 6 1 6 0 6 0 6 0 6 0 5 1 6 2 6 1 6 1 5 2 6 0 6 0 5 -1 6 -2 6 -1 5 -1 6 0 6 1 6 2 6 -1 5 -1 6 -3 5 -2 6 -2 5 -2 6 -2 5 -2 6 -1 5 -1 6 -1 6 0 6 0 6 1 5 2 6 2 6 3 5 3 5 4 4 5 3 5 3 4 4 5 4 4 4 4 4 4 4 5 4 4 4 5 3 5 1 6 1 6 2 8 6üGúHìAIûûú[ìÜLàM-3592 5050l3 5 4 4 4 5 4 4 4 5 3 5 2 5 2 5 1 6 1 6 0 5 0 6 0 6 0 6 1 6 0 6 0 6 1 6 0 6 1 5 0 6 1 6 0 6 1 6 0 5 1 6 0 6 0 6 1 6 0 5 1 6 0 6 0 6 1 6 0 6 1 5 0 7üGúHìAIûûú[ìÜLàM-2224 3903l-4 4 -5 4 -4 3 -5 3 -6 3 -5 2 -6 2 -5 2 -5 2 -6 3 -5 3 -4 3 -5 4 -4 4 -4 4 -4 4 -5 5 -4 4üGúHìAIûûú[ìÜLàM-2420 4022l-6 2 -6 1 -5 0 -6 -2 -6 -2 -5 -2 -5 -3 -5 -3 -5 -3 -5 -3 -6 -1 -6 -1 -5 1 -6 0 -6 0 -6 0 -6 0 -6 0 -6 0 -5 -1 -6 0 -6 -1 -6 0 -6 -1 -5 -1 -10 -2üGúHìAIûûú[ìÜLàM-2571 4000l-6 0 -6 -1 -6 -1 -6 0 -6 0 -5 2 -6 1 -5 2 -6 3 -5 2 -5 3 -6 2 -5 3 -4 3 -5 4 -5 4 -4 4 -4 4 -4 5 -4 4 -4 4 -4 4 -5 3 -6 1 -6 -1 -6 0 -6 0 -5 0 -6 -2 -5 -3 -5 -3 -5 -3 -6 -2 -5 -1 -6 1 -6 0 -6 2 -6 1 -5 2 -6 2 -4 3 -4 5 -3 5 -3 5 -2 5 -2 6 -1 6 -1 5 -1 6 -1 6 -2 6 -3 4 -5 4 -5 3 -5 3 -6 2 -5 2 -6 2 -6 0 -5 -1 -6 -1 -6 -3 -5 -3 -5 -3 -4 -4 -3 -5 -1 -6 -2 -6 0 -5 0 -6 0 -6 -2 -6 -3 -5 -4 -4 -5 -3 -5 -2 -6 -2 -6 -1 -6 0 -6 1 -5 1 -6 2 -5 3 -6 2 -4 4 -5 3 -4 4 -4 5 -4 4 -5 2 -6 2 -6 2 -6 1 -5 0 -6 0 -6 1 -6 0 -6 0 -6 0 -5 0 -6 0 -6 0 -6 0 -6 0 -6 -1 -5 0 -6 -1 -6 0 -6 -1 -5 -2 -6 -1 -6 -2 -5 -2 -5 -3 -5 -3 -4 -4 -5 -4 -5 -3 -5 -3 -5 -3 -5 -3 -5 -2 -6 -1 -6 -1 -6 0 -6 1 -5 1 -6 1 -6 1 -6 1 -5 2 -6 1 -6 2 -5 1 -6 2 -5 3 -5 2 -6 2 -5 2 -6 2 -5 3 -5 2 -6 3 -5 2 -10 5üGúHìAIûûú[ìÜLàM-3286 4091l-5 3 -4 4 -4 3 -5 4 -4 4 -4 4 -5 4 -4 4 -5 3 -4 4 -5 4 -5 3 -4 3 -5 4 -5 3 -5 3 -5 4 -4 3 -5 3 -5 3 -5 4 -4 4 -4 4 -5 4 -4 4 -4 4 -4 4 -4 4 -3 5 1 6 -1 6 0 6 0 6 0 6 0 6üGúHìAIûûú[ìÜLàM-2310 4959l5 -3 5 -3 5 -3 5 -1 6 -2 6 -1 6 -1 4 -3 4 -5 3 -5 3 -5 3 -5 4 -5 4 -3 6 -2 6 -1 5 -1 6 -1 6 -2 5 -3 5 -2 6 -2 5 -2 6 -1 6 -1 6 -1 5 0 6 0 6 1 6 1 5 1 6 0 6 -1 6 -1 6 -1 5 -1 6 -2 5 -1 6 -2 6 -2 5 -2 6 -2 5 -2 6 -1 5 -2 6 -2 5 -2 6 -2 5 -1 6 -2 5 -3 6 -2 5 -3 5 -3 5 -3 5 -3 5 -2 5 -2 6 -2 6 -2 5 -3 6 -2 5 -2 5 -3 5 -2 3 -5 3 -5 4 -5 4 -4 5 -3 5 -3 5 -4 5 -2 5 -1 6 1 6 1 6 1 6 1 5 -1 6 -1 6 -1 6 -1 5 -2 6 -1 6 -2 5 -2 6 -1 5 -3 5 -2 6 -3 5 -3 4 -3 5 -4 3 -5 3 -5 3 -5 2 -6 2 -5 3 -5 5 -3 5 -3 6 -2 6 -1 5 -1 6 0 6 1 6 1 5 1 6 2 6 1 5 2 6 2 4 4 6 1 6 0 8 0üGúHìAIûûú[ìÜLàM-2481 5030l5 0 6 -1 6 -1 5 -2 5 -3 6 -3 5 -3 5 -3 5 -3 4 -3 5 -3 6 -3 5 -1 6 -1 6 -2 5 -1 6 -2 5 -3 5 -2 10 -6üGúHìAIûûú[ìÜLàM-2845 5523l2 -6 3 -5 2 -5 2 -5 2 -6 2 -6 1 -5 2 -6 2 -5 3 -6 2 -5 3 -5 3 -5 3 -5 4 -4 6 -2 6 -2 5 -3 4 -3 5 -4 4 -4 3 -5 3 -5 1 -6 1 -6 0 -6 -1 -6 0 -5 -2 -6 -1 -6 -1 -6 -2 -5 -1 -6 -1 -6 -1 -5 0 -6 1 -6 2 -6 1 -5 3 -5 3 -5 3 -5 3 -5 3 -6 2 -5 1 -6 1 -6 1 -5 2 -6 3 -5 2 -5 3 -5 3 -5 3 -5 4 -5 4 -4 4 -5 3 -4 3 -5 2 -6 1 -6 1 -5 1 -6 1 -6 1 -6 2 -5 1 -6 1 -6 1 -6 0 -5 -1 -6 -1 -6 -2 -6 -1 -5 0 -6 1 -6 1 -6 2 -5 2 -6 3 -5 4 -4 4 -4 5 -4 5 -3 5 -2 6 -2 5 -2 5 -3 5 -4 4 -3 5 -4 4 -4 4 -4 5 -4 4 -4 4 -4 5 -3 5 -2 6 -2 6 -2 5 -2 6 -1 5 -3 5 -2 6 -3 5 -2 6 -1 6 -1 5 0 6 0 6 0 6 1 5 2 6 3 5 2 6 2 5 0 6 0 6 -1 6 0 6 -1 5 0 7 -1üGúHìAIûûú[ìÜLàM-2845 5523l5 0 6 1 6 1 6 2 5 2 5 3 4 5 3 5 4 3 6 -1 4 -5 1 -6 2 -5 2 -5 4 -5 4 -4 5 -4 4 -3 5 -4 5 -3 4 -4 5 -3 5 -3 5 -3 5 -4 4 -3 5 -3 5 -4 5 -2 5 -3 6 -3 5 -2 6 -1 6 -1 6 0 5 3 5 3 5 -1 5 -4 5 -3 4 -4 4 -5 3 -5 2 -6 2 -5 0 -6 0 -6 0 -6 0 -6 2 -5 3 -5 3 -5 2 -6 0 -5 0 -6 0 -6 -1 -6 -2 -6 -2 -5 -3 -5 -4 -5 -4 -4 -5 -2 -5 -3 -6 -2 -5 -2 -6 -2 -5 -2 -5 -3 -5 -4 -5 -3 -3 -4 -3 -6 -2 -5 -2 -6 -1 -6 -1 -5 1 -6 0 -6 2 -6 1 -5 1 -6 1 -6 2 -6 1 -5 2 -6 3 -5 3 -5 3 -4 5 -4 5 -3 5 -3 5 -2 3 -5 2 -6 2 -5 2 -6 2 -5 2 -6 1 -6 1 -5 2 -6 1 -6 1 -6 0 -5 -1 -6 0 -6 0 -6 0 -6 1 -5 2 -6 3 -5 3 -5 3 -5 3 -5 4 -4 5 -4 5 -3 5 -3 5 -3 5 -3 5 -3 5 -2 6 -2 5 -2 6 -2 5 -2 6 -1 6 -1 6 0 6 0 5 0 6 0 6 0 6 1 6 0 5 -1 6 -2 5 -2 6 -3 5 -2 5 -3 7 -9üGúHìAIûûú[ìÜLàM-2370 4984l5 -2 6 -1 5 -2 6 -2 5 -3 5 -2 5 -3 6 -2 5 -3 5 -2 7 -3üGúHìAIûûú[ìÜLàM-141 1874l-3 -5 -4 -5 -5 -3 -4 -3 -5 -3 -5 -4 -5 -3 -4 -4 -5 -4 -4 -4 -4 -4 -5 -3 -5 -4 -5 -2 -5 -3 -5 -3 -5 -3 -4 -5 -2 -5 0 -6 1 -6 -1 -5 -4 -3 -6 -2 -6 -3 -4 -3 -4 -5 -3 -5 -2 -6 1 -5 2 -6 1 -6 -1 -6 -1 -5 -3 -6 -3 -5 -4 -4 -4 -4 -5 -4 -5 -3 -5 -3 -4 -4 -5 -3 -6 -2 -5 -3 -9 -5üGúHìAIûûú[ìÜLàM572 2328l-5 -3 -5 -2 -5 -3 -6 -3 -5 -2 -5 -2 -6 -2 -6 -1 -6 -1 -5 0 -6 0 -6 0 -5 2 -6 3 -5 2 -6 2 -5 1 -6 1 -6 1 -6 1 -6 1 -6 1 -6 1 -5 0 -5 -4 -3 -5 1 -4 5 -4 6 -4 3 -4 4 -5 2 -6 1 -5 -3 -6 -5 -2 -6 0 -5 3 -5 4 -5 3 -5 0 -5 -3 -6 -2 -6 -2 -5 -3 -3 -4 -3 -5 -2 -6 -2 -6 -4 -5 -3 -4 -3 -5 -4 -5 -4 -4 -4 -4 -4 -5 -4 -4 -4 -4 -4 -4 -3 -5 -4 -5 -3 -4 -3 -5 -3 -5 -3 -6 -2 -5 -1 -6 -3 -6 -3 -4 -4 -3 -6 -1 -7 -1 -5 0 -6 0 -6 1 -6 -1 -6 -1 -5 -2 -5 -2 -5 -3 -6 -3 -5 -3 -5 -3 -5 -3 -5 -3 -4 -3 -5 -3 -5 -4 -5 -3 -5 -3 -5 -3 -5 -3 -5 -3 -5 -3 -5 -3 -5 -3 -5 -3 -5 -3 -5 -3 -5 -3 -5 -3 -5 -3 -5 -3 -5 -3 -5 -3 -5 -3 -5 -2 -5 -3 -5 -3 -5 -3 -5 -3 -5 -3 -5 -4 -5 -3 -5 -3 -5 -3 -5 -4 -4 -3 -5 -3 -5 -4 -5 -3 -5 -2 -5 -3 -6 -2 -5 -2 -6 -3 -5 -2 -4 -4 -5 -3 -5 -3 -5 -4 -4 -3 -5 -4 -4 -4 -5 -3 -5 -4 -4 -3 -5 -4 -4 -4 -5 -3 -5 -4 -4 -3 -5 -3 -5 -3 -5 -3 -5 -3 -5 -4 -4 -4 -4 -4 -4 -4 -4 -5 -4 -4 -4 -5 -4 -4 -4 -4 -4 -4 -5 -3 -5 -3 -5 -3 -5 -4 -4 -4 -4 -3 -6 -6üGúHìAIûûú[ìÜLàM-473 1564l-5 -1 -6 0 -6 0 -6 0 -6 0 -6 1 -5 -2 -4 -4 -4 -5 -3 -5 -4 -4 -3 -5 -3 -5 -5 -3 -5 -1 -6 -2 -6 0 -6 1 -6 0 -5 -1 -6 -1 -5 -3 -5 -3 -5 -3 -6 -3 -5 -2 -5 -3 -5 -2 -6 -2 -5 -3 -6 -2 -5 -1 -6 -1 -6 -1 -5 -1 -6 0 -6 -1 -6 -1 -5 -2 -6 -1 -6 -1 -5 -2 -6 -1 -6 -2 -5 -1 -6 -1 -6 -2 -5 -1 -6 -3üGúHìAIûûú[ìÜLàM-3298 2439l-6 1 -5 1 -6 0 -6 -1 -6 -1 -5 -2 -6 -1 -6 -1 -5 -1 -6 -1 -6 -1 -6 0 -6 -1 -5 -1 -6 -2 -5 -2 -5 -4 -4 -4 -5 -4 -4 -4 -4 -4 -3 -5 -3 -5 -4 -4 -5 -4 -4 -4 -5 -3 -5 -2 -6 -1 -6 0 -6 1 -6 1 -6 1 -5 2 -6 2 -5 2 -5 2 -6 3 -5 3 -5 3 -5 3 -5 2 -6 2 -5 1 -6 0 -6 0 -6 -1 -6 0 -5 -1 -6 1 -6 1 -6 2 -5 2 -6 1 -5 3 -5 4 -5 0 -5 -2 -6 -4 -5 -2 -6 -2 -5 -1 -6 -1 -6 -1 -6 0 -6 0 -5 -1 -6 0 -6 0 -6 0 -6 0 -6 1 -5 1 -6 2 -5 2 -6 2 -5 3 -5 2 -5 3 -5 3 -5 3 -5 4 -4 4 -5 2 -6 3 -5 1 -6 2 -6 1 -6 1 -5 1 -6 0 -6 0 -6 0 -6 0 -5 0 -6 0 -6 0 -6 1 -6 1 -5 1 -6 1 -6 -1 -6 -1 -5 0 -6 0 -6 1 -6 1 -6 1 -5 2 -6 1 -6 1 -5 2 -6 2 -6 2üGúHìAIûûú[ìÜLàM-3146 2517l-6 -1 -6 -2 -5 0 -6 1 -5 2 -6 2 -6 2 -5 2 -6 2 -5 1 -6 -1 -6 -2 -5 -3 -4 -4 -4 -4 -4 -4 -3 -6 -3 -4 -6 -3 -4 -3 -5 -4 -5 -4 -4 -4 -2 -4 1 -6 2 -5 2 -6 0 -7 0 -6 -4 -3 -5 -3 -6 -1 -6 -1 -6 -1 -6 1 -7 1üGúHìAIûûú[ìÜLàM-2917 2335l-4 5 -4 4 -6 2 -6 0 -5 2 -4 4 -4 5 -4 4 -5 3 -5 2 -6 1 -6 0 -6 0 -6 1 -6 1 -5 1 -6 1 -5 2 -5 4 -4 4 -4 4 -5 4 -4 4 -4 4 -4 5 -4 4 -4 4 -3 5 -3 5 -3 5 -3 5 -3 5 -3 5 -3 5 -3 5 -2 5 -3 6 -2 5 -2 6 -2 5 -2 5 -2 6 -3 5 -2 5 -4 5 -4 4 -5 3 -4 4 -6 2 -6 1 -5 2 -6 0 -6 -1 -8 -1üGúHìAIûûú[ìÜLàM-310 1686l-5 -3 -5 -3 -5 -4 -5 -2 -5 -3 -5 -3 -6 -2 -5 -3 -5 -2 -5 -3 -5 -3 -6 -2 -5 -2 -6 -2 -6 -1 -6 -2 -4 -3 -3 -5 -1 -6 0 -6 -3 -6 -7 -8 -4 -4 -4 -4 -4 -5 -4 -4 -5 -4 -4 -4 -4 -3 -5 -4 -4 -4 -5 -4 -5 -2 -10 -5üGúHìAIûûùGúHìAIûûúNøú[Hfil7 str5LàM2998 367l0 6 -3 5 -5 2 -6 -1 -6 -1 -6 -1 -5 -1 -6 0 -6 1 -6 2 -5 2 -6 2 -4 3 -5 4 -4 4 -4 5 -2 5 -2 5 -2 6 -1 6 -1 5 -1 6 0 6 0 7 2 5 6 1 6 0 2 6 -2 5 -4 4 -5 4 -5 4 -4 3 -4 5 -4 4 -5 3 -4 4 -5 4 -4 4 -2 6 -1 5 1 6 1 6 1 6 1 5 2 6 2 5 3 6 2 5 4 9üGúHìAIûûú[ìàLäM1321 577l6 1 4 4 5 3 3 5 3 5 3 5 3 5 2 6 3 5 3 5 3 5 3 5 2 5 3 6 3 5 4 4 3 5 4 4 4 4 5 4 4 3 5 4 5 3 5 3 5 3 5 4 5 3 4 3 5 3 5 3 5 4 5 3 4 4 5 4 4 3 5 3 5 3 5 3 5 3 5 3 6 3 5 2 5 3 6 2 5 2 5 2 6 2 5 2 6 2 5 2 6 1 6 2 5 2 6 2 5 2 6 1 5 2 6 3 5 2 6 1 5 2 6 0 6 0 6 1 5 2 6 2 5 3 5 2 6 2 5 3 5 2 6 2 5 2 6 3 5 2 6 1 5 2 6 2 5 1 6 2 5 2 6 2 6 2 5 1 6 2 5 1 6 1 6 0 6 1 6 0 5 0 6 0 6 0 6 0 6 2 5 2 6 3 5 2 5 2 6 0 5 -2 5 -3 6 -2 6 -2 5 -1 6 1 6 1 6 1 5 1 6 -1 6 -1 6 0 5 1 6 3 5 2 6 2 5 1 6 0 6 -2 5 -2 5 -4 4 -4 4 -4 4 -4 4 -5 3 -5 4 -4 4 -4 5 -4 5 -3 5 -3 5 -3 5 -3 5 -2 5 -3 6 -2 5 -2 6 -2 6 -1 6 0 5 2 5 3 5 4 5 3 5 3 5 2 6 1 6 0 5 0 6 -1 6 -1 6 -1 6 -1 5 -1 5 -3 4 -4 4 -5 3 -5 3 -5 3 -5 3 -5 3 -5 4 -4 4 -5 5 -3 5 -3 5 -2 6 -2 6 -2 5 -1 6 -2 6 -1 5 -1 6 -1 6 0 6 1 5 2 6 2 5 2 6 -2 5 -2 6 -2 5 -1 6 -1 6 0 6 -1 6 -1 5 -1 6 -1 6 -1 6 1 5 2 6 1 5 2 6 2 6 1 5 0 6 0 6 0 6 1 5 2 6 2 6 1 6 1 6 1 5 1 6 0 6 0 5 0 5 -4 4 -4 3 -5 2 -6 2 -6 3 -5 4 -4 6 -1 5 0 6 1 6 0 6 -2 4 -3 5 -5 3 -4 3 -5 2 -6 2 -6 1 -5 3 -5 3 -6 3 -4 3 -5 4 -5 4 -4 4 -4 4 -4 4 -4 4 -5 5 -4 5 -3 5 2 5 3 6 1 6 0 6 -1 5 -1 6 -2 6 -1 5 -2 6 -2 5 -3 4 -3 5 -4 4 -4 5 -4 4 -4 4 -4 4 -4 4 -5 4 -4 4 -4 4 -4 4 -5 4 -4 4 -4 4 -4 5 -4 4 -4 5 -4 4 -3 5 -3 5 -3 6 -2 5 -3 5 -2 6 -1 6 -2 5 -2 6 -1 5 -2 6 -2 6 -1 5 -2 6 -2 5 -4 4 -4 5 -3 5 -1 6 1 6 2 5 2 6 2 6 1 5 -1 6 -3 4 -3 4 -5 4 -4 3 -5 4 -4 4 -5 4 -4 4 -4 4 -5 4 -4 5 -3 4 -4 5 -4 5 -3 5 -2 5 -2 6 1 6 0 6 1 6 1 6 1 6 -1 6 -1 5 -3 2 -4 2 -6 1 -6 1 -6 1 -6 2 -5 4 -5 3 -4 3 -5 3 -11üGúHìAIûûú[ìàLàM1321 367l3 5 3 5 2 5 3 5 4 5 3 5 4 4 4 4 5 4 4 4 5 3 5 4 5 3 5 3 5 3 5 2 5 2 6 2 6 1 6 1 5 1 6 0 6 0 6 -1 6 -1 5 -1 6 -3 5 -2 5 -3 4 -4 5 -3 5 -4 5 -3 5 -3 5 -2 6 -2 5 -2 5 -3 5 -4 3 -4 4 -5 3 -5 4 -5 4 -4 4 -3 6 -2 10 -2üGúHìAIûûú[ìàLàM770 1225l-1 -5 -1 -6 -1 -6 0 -6 -1 -6 -1 -5 0 -6 -1 -6 -1 -6 0 -6 1 -5 2 -6 1 -6 2 -5 1 -6 0 -6 1 -6 1 -5 1 -6 0 -6 1 -6 0 -6 1 -5 0 -6 0 -6 -1 -6 0 -6 -1 -6 0 -5 -1 -6 0 -6 0 -6 0 -6 0 -6 1 -6 1 -5 2 -6 4 -4 4 -5 5 -3 5 -1 6 0 6 1 6 1 6 0 6 -1 6 0 6 -1 5 0 6 -1 6 -1 6 -1 5 -1 6 -1 6 -2 5 -1 6 -2 6 -1 5 -2 5 -2 6 -3 5 -3 5 -2 6 -2 5 -1 6 0 6 0 6 0 6 0 6 0 5 1 6 0 6 0 6 -1 6 0 6 0 5 -1 6 -1 6 0 6 -1 5 -1 6 -2 6 -1 5 -2 6 -2 5 -3 5 -3 4 -4 5 -4 4 -4 4 -4 3 -5 2 -6 3 -5 3 -5 4 -4 4 -4 4 -5 4 -3 5 -4 4 -4 5 -3 5 -3 5 -3 5 -3 6 -2 5 -2 6 -2 5 -1 6 -2 6 -2 4 -3 5 -3 4 -4 4 -5 4 -4 4 -4 4 -5 4 -4 3 -5 4 -4 5 -4 4 -4 4 -4 4 -4 4 -4 4 -5 3 -5 4 -4 3 -5 3 -5 3 -5 3 -5 3 -5 1 -6 2 -5 0 -6 1 -6 1 -6 1 -6 2 -5 1 -6 2 -6 1 -5 2 -6 1 -6 2 -5 2 -5 3 -6 2 -5 3 -5 3 -5 3 -5 4 -4 4 -5 4 -4 5 -4 4 -4 4 -4 5 -4 2 -5 3 -5 2 -5 1 -6 2 -6 0 -6 1 -6 -1 -5 -1 -6 -1 -10üGúHìAIûûú[ìàLäM706 1099l1 -5 1 -6 -2 -6 -3 -5 -4 -4 -5 -4 -4 -3 -5 -3 -5 -4 -5 -3 -3 -5 -4 -5 -3 -5 -2 -5 -2 -5 0 -6 0 -6 -1 -6 -2 -5 -2 -6 -2 -5 -3 -5 -3 -6 -2 -5 -3 -5 -2 -5 -3 -6 -3 -5 -3 -5 -2 -5 -2 -6 -2 -5 -1 -6 -2 -6 -1 -5 -1 -6 -2 -6 -1 -5 -1 -6 -1 -6 -1 -6 -1 -5 0 -6 -1 -6 0 -6 0 -6 1 -5 0 -6 0 -6 1 -6 0 -6 1 -6 0 -5 0 -6 1 -6 0 -6 0 -6 0 -6 0 -5 0 -6 -1 -6 0 -6 -1 -6 -1 -5 -2 -6 -2 -5 -3 -5 -3 -5 -3 -5 -4 -5 -3 -5 -2 -5 -1 -6 -1 -6 -1 -6 0 -5 0 -6 -1 -6 -1 -6 -1 -6 -1 -5 -2 -6 -2 -5 -2 -6 -3 -5 -2 -5 -3 -6 -2 -5 -3 -5 -2 -5 -3 -6 -3 -5 -2 -5 -3 -5 -4 -5 -4 -4 -5 -2 -6 -2 -6 0 -6 -1 -6 1 -5 0 -6 1 -6 1 -6 1 -6 0 -5 0 -6 -1 -6 -2 -5 -2 -5 -3 -5 -3 -5 -3 -5 -3 -5 -4 -4 -3 -5 -4 -4 -4 -4 -5 -4 -4 -3 -5 -4 -4 -4 -4 -4 -5 -4 -4 -4 -4 -5 -4 -5 -2 -5 -2 -6 -2 -6 -1 -6 0 -6 -1 -5 1 -6 0 -6 1 -6 0 -6 -1 -5 0 -6 0 -6 0 -6 0 -6 -1 -6 0 -5 -1 -6 0 -6 -1 -6 0 -6 0 -5 1 -6 1 -6 2 -5 2 -6 1 -5 3 -5 3 -5 3 -6 2 -5 1 -6 0 -6 0 -6 0 -6 0 -6 1 -6 0 -5 -1 -6 0 -6 -2 -5 -1 -6 -2 -5 -2 -6 -2 -5 -3 -5 -3 -5 -4 -5 -3 -5 -2 -6 -2 -5 -2 -6 0 -6 2 -4 3 -4 5 -4 4 -5 3 -5 4 -3 5 -2 6 -2 5 -3 5 -4 3 -6 3 -5 2 -5 2 -6 3 -5 2 -5 3 -5 3 -5 2 -6 2 -6 2 -5 2 -5 2 -5 4 -3 5 -4 4 -4 5 -3 5 -3 5 -4 4 -4 4 -5 3 -6 2 -5 2 -6 1 -5 2 -5 4 -3 5 -4 4 -3 6 -2 5 -1 6 2 5 2 6 3 5 2 5 1 6 1 6 0 6 -1 5 -1 6 -2 6 -3 5 -4 4 -5 3 -5 3 -5 3 -5 3 -5 3 -5 3 -5 3 -6 1 -6 0 -6 -1 -6 0 -5 0 -6 0 -6 0 -6 1 -6 0 -5 1 -6 0 -6 2 -5 3 -6 1 -5 -2 -6 -2 -4 -4 -3 -5 -4 -5 -4 -4 -4 -5 -4 -5üGúHìAIûûú[ìàLàM3405 5687l-5 2 -6 3 -5 2 -5 3 -4 5 -3 5 -3 5 -3 4 -4 6 -3 4 -4 4 -5 3 -6 2 -6 2 -5 1 -6 0 -6 1 -6 0 -6 -1 -5 0 -6 0 -6 0 -6 0 -6 -1 -6 1 -5 1 -6 2 -5 2 -6 2 -6 1 -5 0 -6 0 -6 -1 -6 -1 -6 -1 -5 -1 -6 -1 -6 0 -6 -1 -5 0 -6 1 -6 1 -6 1 -6 1 -5 0 -6 0 -6 1 -6 0 -6 -1 -5 0 -6 0 -6 0 -6 -1 -6 0 -6 -1 -5 0 -6 -1 -7 -1 -6 -1 -5 0 -6 1 -4 2 -4 5 -3 6 -2 5 0 6 0 6 0 6üGúHìAIûûú[ìàLäM2442 6139l2 -6 2 -6 1 -5 1 -6 2 -6 2 -6 1 -6 1 -5 -1 -6 -2 -4 -5 -4 -5 -4 -5 -3 -6 -1 -6 -2 -5 -1 -6 -1 -6 -2 -5 -2 -6 -2 -6 -2 -6 -2 -5 -3 -4 -3 -2 -5 0 -6 0 -6 1 -6 -1 -6 -1 -6 -2 -6 -2 -5 -2 -6 -2 -5 -2 -6 -2 -5 -2 -6 -3 -4 -4 -5 -3 -4 -4 -5 -4 -4 -4 -4 -5 -4 -4 -4 -4 -4 -4 -5 -4 -4 -4 -4 -5 -4 -4 -4 -4 -4 -5 -4 -4 -3 -5 -3 -6 -3 -5 -1 -6 -1 -6 0 -6 0 -6 2 -5 2 -5 3 -5 3 -5 3 -5 2 -6 2 -6 1 -6 0 -5 0 -6 0 -6 -1 -6 0 -6 -1 -6 0 -5 -1 -6 -1 -6 -1 -6 -1 -5 -1 -6 -2 -6 -1 -5 -1 -6 -2 -6 -2 -5 -1 -6 -2 -5 -1 -6 -2 -6 -1 -5 -2 -6 -1 -6 -2 -5 -1 -6 -2 -6 -1 -5 -1 -6 -1 -6 -1 -6 0 -5 0 -6 -1 -6 0 -6 0 -6 -1 -6 0 -5 -1 -6 -1 -6 0 -6 -1 -6 0 -5 0 -6 0 -6 1 -6 1 -5 1 -6 2 -6 1 -5 2 -6 2 -5 2 -6 2 -5 2 -6 2 -5 3 -5 3 -5 2 -6 2 -5 1 -6 1 -6 1 -6 1 -5 1 -6 2 -6 1 -5 2 -6 1 -6 2 -5 0 -6 1 -6 0 -6 0 -6 1 -5 0 -6 1 -6 1 -6 1 -5 1 -6 1 -6 1 -6 1 -5 1 -6 1 -6 1 -6 1 -6 1 -5 1 -6 1 -5 2 -6 2 -5 3 -5 2 -6 2 -5 2 -6 2 -5 2 -6 2 -5 2 -6 2 -5 2 -6 2 -5 3 -5 3 -5 3 -4 4 -5 3 -5 3 -5 3 -5 3 -6 2 -5 2 -5 3 -6 2 -5 3 -5 2 -5 4 -5 3 -5 2 -6 2 -6 0 -6 -1 -5 0 -6 1 -6 2 -5 2 -6 3 -5 2 -5 3 -5 3 -2 5 -1 6 -2 6 -3 5 -5 3 -5 2 -6 2 -6 1 -5 1 -6 1 -6 1 -6 1 -5 2 -6 2 -5 3 -4 3 -4 5 -4 4 -3 5 -4 5 -4 4 -4 4 -4 4 -4 4 -5 4 -4 4 -4 4 -5 4 -5 2 -6 2 -5 1 -6 2 -6 1 -5 2 -4 4 -4 5 -5 4 -5 2 -5 1 -6 2 -6 1 -6 1 -6 1 -5 1 -6 0 -6 0 -6 0 -5 -1 -6 -1 -6 -1 -6 -1 -5 -2 -6 -1 -6 -1 -6 0 -5 1 -6 1 -6 0 -6 1 -6 0 -5 0 -6 0 -6 1 -6 1 -6 1 -5 1 -6 1 -6 0 -6 0 -6 -2 -4 -4 -3 -5 -2 -6 -4 -4 -5 -3 -5 -3 -5 -2 -6 -2 -5 -2 -6 -1 -6 -2 -6 -1 -5 0 -6 1 -6 1 -6 1 -6 2 -5 1 -6 2 -5 1 -6 2 -6 0 -6 1 -5 0 -6 0 -6 0 -6 0 -6 1 -6 0 -6 0 -5 0 -6 0 -6 0 -6 0 -6 0 -5 -1 -6 -1 -6 -1 -6 -1 -5 0 -6 -1 -6 0 -6 1üGúHìAIûûú[ìàLàM-556 6840l-5 2 -5 3 -6 3 -5 2 -5 3 -5 4 -4 3 -4 5 -4 5 -2 5 -2 5 -1 6 0 6 -1 6 0 6 -1 5 -2 6 -2 5 -2 6 -2 5 -3 6 -3 5 -3 4 -4 5 -4 4 -5 3 -5 3 -6 2 -5 2 -6 1 -6 1 -5 1 -6 1 -6 1 -6 2 -5 1 -6 3 -5 2 -5 3 -5 3 -5 2 -5 3 -6 3 -5 3 -5 3 -5 3 -4 4 -3 5 -4 4 -4 5 -4 4 -4 4 -4 4 -5 4 -4 4 -4 4 -4 4 -4 4 -4 5 -4 4 -4 4 -4 5 -4 4 -3 5 -3 5 -2 5 -2 6 -2 5 -2 6 -2 5 -3 6 -3 5 -3 5 -3 4 -4 5 -4 4 -4 4 -5 4 -5 3 -5 3 -5 2 -6 2 -5 0 -6 1 -6 2 -6 2 -5 2 -5 3 -4 4 -3 5 -2 6 -1 5 2 6 2 6 0 5 0 6 -2 6 -2 5 -2 6 -3 5 -4 5 -4 4 -4 3 -6 3 -5 2 -6 2 -5 3 -5 3 -4 4 -4 4 -3 5 -4 4 -4 5 -5 8üGúHìAIûûú[ìàLàM648 6287l0 6 0 6 0 6 1 6 2 5 1 6 2 6 2 5 3 5 1 6 0 5 -2 6 -3 5 -2 6 -4 5 -3 4 -4 5 -4 4 -3 5 -4 4 -4 5 -4 4 -5 3 -4 4 -5 3 -5 4 -4 4 -3 5 -2 5 -1 6 -4 5 -4 4 -4 4 -4 4 -5 4 -4 4 -3 4 -2 6 0 6 2 5 2 6 3 5 4 4 4 5 3 5 2 5 3 5 2 6 2 5 3 6 2 5 1 6 -1 5 -1 6 -1 6 -1 6 -1 5 -1 6 0 6 -1 6 -1 6 -1 5 -2 6 -1 6 -2 5 -2 6 -2 5 -2 6 -3 5 -3 5 -3 4 -4 5 -4 4 -5 4 -4 4 -5 3 -4 4 -5 4 -5 3 -5 3 -5 3 -4 3 -5 4 -4 4 -3 5 -4 4 -4 5 -3 5 -4 4 -3 5 -4 4 -3 5 -4 5 -3 5 -3 5 -3 5 -3 5 -3 5 -3 5 -3 4 -4 5 -4 4 -4 5 -3 4 -4 5 -3 5 -4 4 -4 5 -4 5 -3 4 -3 5 -3 5 -2 5 -2 6 -1 6 0 6 0 6 -1 5 0 6 0 6 0 6 1 6 0 6 0 5 1 6 0 6 1 6 0 6 1 5 0 6 1 6 0 6 1 6 0 6 1 5 0 6 -1 6 -1 6 -1 5 -1 6 -1 6 0 6 -1 5 0 6 -1 6 -1 6 -2 5 -1 6 -1 6 -1 5 -2 6 -1 6 -1 6 0 5 0 6 0 6 1 6 1 6 2 5 0 6 1 6 0 6 -1 6 0 6 -1 5 -2 6 -2 5 -3 5 -3 5 -4 5 -4 4 -4 5 -3 5 -2 5 -2 5 -2 6 -2 5 -2 6 -1 6 -2 5 -2 5 -3 6 -2 5 -4 5 -3 5 -3 4 -4 5 -4 4 -4 5 -3 4 -4 5 -3 5 -2 5 -5 10üGúHìAIûûú[ìàLàM-2705 7287l-4 -5 -3 -5 -3 -5 0 -6 -1 -6 0 -6 1 -6 0 -5 -2 -6 -3 -5 -5 -2 -6 -1 -6 -1 -6 -1 -6 0 -5 -1 -6 0 -6 -1 -6 -1 -5 -2 -6 -2 -5 -2 -6 -2 -5 -2 -6 -1 -5 -2 -6 -1 -6 -1 -6 -1 -6 -1 -5 -1 -6 0 -6 2 -5 2 -5 2 -5 3 -5 4 -4 4 -4 4 -4 5 -4 4 -5 4 -4 4 -4 4 -5 3 -4 4 -5 3 -5 2 -6 3 -5 3 -4 4 -5 3 -6 1 -6 0 -6 -1 -4 -4 -2 -6 -5 -2 -6 0 -6 1 -5 3 -3 5 -2 6 -1 11üGúHìAIûûú[ìàLàM-3947 3399l-5 -4 -4 -3 -2 -6 0 -6 0 -6 1 -5 2 -6 2 -6 3 -5 4 -3 6 -2 5 -1 6 -1 6 -1 5 -2 5 -3 5 -3 5 -4 5 -3 4 -3 5 -4 4 -4 4 -5 4 -4 3 -5 3 -5 3 -5 3 -5 3 -5 4 -4 4 -4 5 -4 5 -3 5 -3 5 -2 5 -3 5 -3 6 -3 5 -2 6 -1 5 -1 6 -1 6 0 6 0 6 -1 6 -1 5 -1 6 -1 6 -2 5 -1 6 -2 4 -4 5 -4 5 -2 6 0 6 1 6 0 6 1 5 -1 4 -3 4 -6 3 -4 3 -5 3 -6 1 -5 1 -6 3 -5 3 -5 5 -4 5 -3 5 -3 4 -3 5 -4 5 -4 4 -3 5 -4 5 -3 5 -3 5 -3 5 -3 5 -3 5 -3 4 -3 5 -4 5 -3 5 -2 6 -2 6 -1 5 0 6 -2 6 -1 6 -1 5 -2 6 -1 5 -2 6 -3 5 -3 4 -3 5 -4 4 -4 4 -5 3 -4 3 -5 4 -5 3 -4 4 -5 4 -4 5 -4 4 -4 5 -3 5 -4 4 -3 4 -4 4 -5 2 -5 2 -6 3 -5 3 -5 3 -5 4 -4üGúHìAIûûú[ìàLàM-4270 3123l5 2 6 2 5 1 6 2 6 2 5 0 6 -1 6 -2 5 -2 6 -2 5 -2 5 -3 4 -4 5 -4 5 -2 6 -2 5 -2 6 -1 6 -2 5 -1 6 -2 5 -2 6 -1 6 -2 5 -2 6 -2 5 -1 6 -2 5 -2 6 -2 5 -2 6 -2 5 -1 6 -2 6 -1 6 -1 5 -1 6 0 6 -1 6 1 6 1 5 2 5 4 3 5 3 5 4 4 5 4 5 3 5 2 5 -2 5 -4 5 -4 4 -4 5 -3 4 -4 5 -4 4 -4 5 -3 4 -4 4 -4 5 -4 4 -4 4 -5 3 -4 3 -5 3 -6 2 -5 2 -6 3 -5 3 -5 3 -4 5 -4 4 -4 5 -3 6 -3 5 -3 5 -2 6 -1 6 -1 5 0 6 0 6 0 6 1 6 0 6 0 6 -1 5 -1 5 -3 4 -4 5 -4 4 -4 5 -3 5 -3 6 -3 5 -2 5 -2 5 -3 6 -2 5 -2 6 -2 5 -3 6 -2 5 -2 5 -4 4 -3 4 -5 3 -4 4 -5 4 -4 4 -4 5 -4 4 -4 4 -4 5 -4 5 -3 4 -4 5 -2 6 -3 5 -1 6 -2 6 0 6 -1 6 -1 5 -2 5 -3 5 -3 5 -3 5 -2 6 -3 5 -2 5 -3 5 -2 6 -2 5 -2 6 -2 5 -1 6 -1 6 -1 6 -1 5 -2 6 -2 5 -2 5 -3 6 -3 5 -2 5 -3 5 -3 5 -3 5 -3 5 -3 5 -3 5 -3 5 -3 5 -4 4 -3 5 -3 5 -4 4 -3 5 -3 5 -3 6 -3 5 -3 5 -2 6 -1 6 0 6 0 6 0 6 1 6 1 5 1 5 3 4 4 3 5üGúHìAIûûú[ìàLàM-3997 3618l-1 -6 0 -6 -1 -6 -1 -5 -2 -6 -1 -5 1 -6 4 -5 4 -4 5 -4üGúHìAIûûú[ìàLàM-2994 3305l6 -3 4 -3 5 -5 5 -2 6 -1 5 0 6 -1 6 0 6 2 4 3 5 4 5 4 5 3 5 1 6 1 6 1 6 1 5 2 6 1 5 3 6 2 5 1 6 -1 5 -3 6 -1 6 0 6 0 5 -1 5 -4 1 -5 -3 -6 -3 -5 -3 -5 -4 -4 -2 -6 -1 -5 -1 -6 0 -6 0 -6 -1 -6 1 -6 3 -4 5 -4 4 -4 4 -4 5 -4 4 -4 4 -5 4 -4 3 -4 4 -5 4 -4 4 -5 3 -5 3 -5 3 -5 4 -4 4 -3 5 -4 5 -3 5 -3 5 -3 5 -4 4 -4 4 -4 3 -5 2 -6 2 -9üGúHìAIûûú[ìàLàM-3280 3507l4 3 4 4 4 5 3 5 3 5 3 5 2 5 2 6 1 5 2 6 2 6 2 5 2 6 2 5 2 5 3 6 2 5 3 5 4 5 3 4 4 5 4 4 4 4 4 4 5 4 4 4 4 4 5 4 5 3 4 4 5 3 5 3 5 3 5 3 5 3 5 3 6 2 5 3 5 2 6 2 6 1 5 0 6 -1 5 -3 6 -2 5 -2 6 -2 6 -2 5 0 6 1 6 2 4 4 4 4 4 4 4 5 4 4 2 6 4 5 4 3 5 3 5 2 6 2 6 1 5 2 6 1 6 0 6 1 5 1 6 0 6 1 6 0 6 0 6 1 5 0 6 0 6 1 6 1 5 2 6 1 6 2 5 1 6 2 6 1 5 2 6 1 5 2 6 2 5 2 6 1 6 2 5 2 6 1 5 2 6 2 6 1 5 2üGúHìAIûûú[ìàLYM-2668 3397l-6 0 -6 1 -6 3GúHìAIûûú[ìàLàM-1483 3350l-4 4 -6 3 -5 2 -5 3 -5 4 -4 3 -5 3 -5 4 -5 3 -4 4 -5 3 -5 2 -6 1 -6 -1 -6 0 -6 0 -6 0 -5 0 -6 0 -6 0 -6 0 -6 0 -6 0 -5 -1 -6 -2 -5 -2 -6 -2 -5 -2 -6 -1 -6 -1 -6 0 -6 1 -5 1 -6 2 -5 2 -5 3 -6 3 -4 3 -5 3 -6 3 -5 2 -5 3 -4 4 -4 5 -3 5 -3 4 -4 5 -5 4 -5 1 -6 -1 -6 -2 -4 -4 -4 -4 -4 -4 -6 -2 -5 -2 -6 -1 -6 -2 -5 -1 -6 -2 -6 -1 -5 -2 -5 -3 -4 -4 -4 -5 -4 -4 -4 -4 -4 -4 -5 -4 -4 -4 -5 -3 -5 -3 -6 -2 -5 -3 -5 -2 -6 -3 -5 -2 -5 -2 -6 -3 -5 -2 -5 -2 -5 -3 -6 -3 -5 -3 -5 -2 -5 -3 -5 -3 -5 -2 -6 -3 -5 -2 -6 -2 -5 -1 -6 -1 -6 -1 -6 0 -5 -1 -6 0 -6 -1 -6 0 -6 0 -5 1 -6 2 -6 2 -5 3 -4 3 -5 4 -4 4 -4 5 -4 4 -4 4 -4 4 -5 4 -4 4 -4 4 -4 4 -4 4 -3 5 -3 5 -3 5 -3 5 -3 5 -2 6 -3 5 -3 5 -2 5 -3 5 -3 6 -3 5 -3 5 -3 5 -4 4 -4 4 -5 3 -5 2 -6 1 -6 0 -6 0 -6 0 -6 -1 -5 -1 -6 -1 -6 -2 -5 -2 -6 -1 -5 -2 -6 -1 -6 0üGúHìAIûûú[ìàLVM-2299 3456l-4 -5 -8 -5GúHìAIûûú[ìàLàM-2208 3444l-6 0 -6 0 -6 1 -5 1 -6 2 -5 3 -5 3 -4 4 -3 5 -4 5 -4 3 -6 0 -5 1 -6 -2 -6 -2 -5 -2 -4 -4 -5 -6üGúHìAIûûú[ìàLàM-856 2935l-6 2 -6 1 -5 1 -4 5 -3 5 -4 4 -3 5 -3 5 -2 5 -2 6 -2 5 -2 6 -2 5 -2 6 -3 5 -3 5 -3 5 -3 5 -4 4 -4 4 -5 4 -4 4 -5 3 -5 3 -5 3 -5 3 -3 5 -1 6 -1 6 -3 5 -4 4 -4 5 -4 4 -4 4 -4 4 -3 5 -3 5 -3 5 -3 5 -2 6 -2 5 -2 5 -3 6 -3 5 -3 5 -3 5 -3 5 -3 4 -4 5 -4 4 -4 4 -5 4 -7 5üGúHìAIûûú[ìàLàM-1039 3175l-4 4 -5 3 -5 3 -5 4 -5 3 -4 3 -5 4 -5 3 -4 4 -5 3 -5 4 -4 4 -5 3 -4 4 -5 3 -5 4 -4 3 -5 3 -5 3 -5 3 -6 3 -5 2 -5 3 -5 3 -10 4üGúHìAIûûú[ìàLàM-1278 3261l-6 0 -5 0 -6 0 -6 -1 -6 0 -6 0 -6 -1 -5 0 -6 0 -6 0 -6 0 -7 1üGúHìAIûûú[ìàLàM-1349 3260l-6 0 -5 3 -5 3 -4 4 -5 3 -4 4 -5 4 -4 4 -5 3 -4 4 -4 5 -4 4 -1 6 -2 6 -4 2 -6 0 -6 1 -6 1 -5 2 -5 3 -6 2 -5 3 -5 2 -5 3 -5 3 -5 3 -4 4 -5 4 -4 4üGúHìAIûûú[ìàLàM-2391 4081l-6 0 -6 0 -6 0 -5 -1 -6 -2 -5 -2 -6 -2 -5 -3 -4 -4 -5 -4 -3 -4 -3 -5 -4 -5 -4 -4 -4 -4 -5 -3 -5 -3 -5 -3 -5 -3 -6 -2 -5 -2 -6 -1 -6 -1 -6 1 -6 0 -6 1 -6 0 -5 -1 -5 -2 -5 -3 -5 -3 -5 -4 -5 -3 -5 -4 -6 -5üGúHìAIûûú[ìàLàM-1958 3866l-4 -3 -5 -3 -6 -2 -5 -3 -5 -2 -6 -2 -5 -3 -5 -3 -5 -3 -5 -3 -8 -6üGúHìAIûûú[ìàLàM-904 3767l-6 1 -5 1 -6 1 -6 1 -6 1 -5 0 -6 0 -6 0 -6 -1 -6 0 -6 0 -5 0 -6 -1 -6 0 -6 0 -6 0 -6 -1 -6 0 -5 0 -6 1 -6 0 -5 3 -5 3 -5 3 -6 2 -5 3 -5 3 -5 2 -6 2 -5 2 -6 2 -6 0 -5 1 -6 0 -6 0 -6 1 -6 0 -6 0 -5 1 -6 0 -6 0 -6 0 -6 0 -6 1 -5 0 -6 0 -6 1 -6 0 -6 1 -5 1 -6 2 -5 2 -6 3 -5 3 -4 4 -3 5 -2 5 -2 6 -3 5 -3 4 -5 5 -4 3 -5 4 -5 3 -5 3 -6 2 -5 2 -6 2 -5 1 -6 1 -6 2 -5 1 -6 2 -6 1 -5 2 -6 1 -5 2 -6 3 -5 2 -5 2 -5 3 -5 3 -5 3 -5 4 -5 3 -5 3 -5 3 -5 4 -4 3 -5 4 -4 4 -4 4 -4 4 -5 3 -5 3 -5 3 -5 3 -5 3 -5 3 -6 2 -5 3 -5 3 -5 3 -5 3 -4 4 -5 3 -5 4 -5 2 -5 3 -6 2 -5 1 -6 1 -6 1 -6 0 -6 1 -6 -2 -5 -1 -6 -2 -6 0 -6 0 -6 1 -5 2 -5 2 -5 4 -4 4 -4 4 -4 5 -4 4 -3 5 -1 6 1 6 3 5 3 5 2 5 3 6 2 5 1 6 1 6 1 6 0 6 0 6 -1 5 -3 5 -5 3 -6 3 -5 3 -5 3 -6 2 -5 1 -5 0 -6 -3 -5 -3 -5 -3 -5 -3 -5 -4 -5 -3 -5 -1 -6 -1 -6 -1 -6 -1 -6 -1 -5 -2 -5 -3 -4 -4 -5 -4 -4 -4 -6 -2 -5 -2 -5 -3 -5 -4 -5 -3 -4 -4 -5 -3 -5 -3 -5 -2 -6 0 -6 1 -6 0 -6 0 -6 0 -6 1 -6 0 -5 0 -6 -1 -6 -1 -5 -2 -6 -2 -5 -3 -5 -3 -5 -3 -5 -3 -4 -4 -5 -3 -4 -4 -4 -5 -3 -5 -3 -5 -4 -4 -5 -3 -5 -3 -6 -2 -5 -2 -6 -2 -5 -3 -4 -3 -5 -4 -5 -3 -4 -4 -5 -4 -4 -4 -4 -4 -4 -4 -4 -4 -3 -5 -3 -6 -2 -5 0 -6 1 -6 1 -6 -1 -5 -2 -6 -1 -6 -3 -5 -3 -5 -5 -3 -5 -4 -5 -3 -6 -4üGúHìAIûûú[ìàLàM-847 3785l-6 0 -5 -2 -5 -3 -5 -4 -5 -4 -4 -3 -5 -3 -6 -1 -6 1 -7 1üGúHìAIûûú[ìàLàM-721 3304l-1 6 -1 6 0 6 -1 6 0 6 0 5 -1 6 -2 6 -3 5 -4 4 -5 3 -6 1 -5 2 -5 4 -3 5 -2 6 -2 5 -1 6 0 6 0 6 1 6 0 5 -2 6 -4 5 -3 4 -3 5 -3 5 -3 5 -2 6 -3 5 -2 6 -1 5 0 6 0 6 1 6 0 6 1 5 1 6 2 6 1 5 2 6 2 5 2 6 3 5 3 5 4 4 3 5 3 5 4 5 3 5 2 5 1 6 1 6 0 5 0 6 -1 6 -2 5 -2 6 -3 5 -1 6 -1 6 -1 6 0 5 0 6 1 6 1 6 1 5 2 6 0 6 1 6 0 6 0 5 1 6 0 6 1 6 0 6 1 6 0 5 0 6 0 6 0 6 -1 6 -1 5 -3 6 -3 5 -4 5 -4 3 -5 2 -6 1 -6 2 -6 1 -7 1üGúHìAIûûú[ìàLàM-45 3270l-1 -5 -2 -6 -1 -6 -1 -5 0 -6 0 -6 1 -6 0 -6 1 -5 1 -6 1 -6 1 -6 1 -5 2 -6 1 -6 2 -5 1 -6 2 -6 2 -5 3 -7üGúHìAIûûú[ìàLàM10 3325l-4 -4 -5 -4 -4 -4 -4 -4 -4 -4 -4 -4 -5 -4 -4 -4 -4 -4 -5 -4 -4 -4 -4 -4 -4 -7üGúHìAIûûú[ìàLàM512 3668l-5 -1 -6 -1 -6 -1 -5 -2 -6 -1 -6 -2 -5 -2 -4 -4 -5 -4 -4 -4 -4 -4 -4 -5 -4 -4 -5 -3 -4 -4 -5 -4 -4 -3 -5 -3 -5 -4 -5 -3 -5 -3 -5 -4 -4 -3 -5 -3 -5 -3 -5 -3 -5 -3 -5 -3 -5 -3 -6 -2 -5 -3 -5 -3 -5 -3 -5 -3 -5 -3 -4 -4 -5 -4 -4 -3 -6 -1 -6 0 -6 1 -6 0 -6 0 -5 -1 -6 0 -6 1 -6 1 -5 1 -6 1 -6 1 -6 1 -6 1 -5 1 -6 1 -6 0 -6 -1 -5 -1 -6 -2 -5 -3 -5 -4 -4 -4 -3 -5 -2 -5 -2 -6 -2 -5 -1 -6 -2 -6 -1 -6 -1 -5 -2 -6 -2 -5 -2 -6 -3 -4 -4 -5 -4 -5 -4 -4 -4 -3 -6 -1 -6 -1 -6 0 -6 0 -6 0 -5 1 -6 1 -6 1 -6 0 -6 1 -5 0 -7 0 -5 -2 -4 -3 -4 -5 -3 -5 -4 -5 -3 -4 -3 -6 -3 -5 -4 -4 -4 -5 -4 -4 -4 -4 -3 -5 -3 -5 0 -5 1 -6 1 -6 -1 -6 -1 -6 -1 -6 -2 -5 -1 -6 -2 -6 -2 -5 -3 -5 -3 -5 -4 -4 -8 -8üGúHìAIûûú[ìàLàM-477 3749l-1 -6 0 -6 -1 -5 0 -6 0 -6 0 -6 0 -6 0 -6 1 -5 0 -6 1 -6 1 -6 1 -5 2 -6 3 -5 2 -6 2 -5 1 -6 1 -6 -1 -6 -1 -5 -1 -6 -3 -5 -3 -5 -3 -5 -5 -6üGúHìAIûûú[ìàLàM39 3854l-6 -2 -6 -1 -6 -1 -5 0 -6 0 -6 -1 -6 0 -6 0 -5 1 -6 0 -6 0 -6 0 -6 0 -6 0 -5 1 -6 0 -6 1 -6 0 -6 1 -6 0 -5 1 -6 1 -6 2 -5 1 -6 2 -6 1 -5 2 -6 2 -5 3 -5 3 -5 3 -4 4 -5 3 -6 2 -5 2 -6 1 -6 2 -5 1 -6 1 -6 1 -5 2 -6 1 -6 1 -6 1 -5 1 -6 0 -6 0 -6 0 -6 0 -6 0 -5 0 -6 0 -6 0 -6 0 -6 0 -6 0 -5 0 -6 -1 -6 0 -6 -2 -5 -1 -6 -1 -6 -2 -5 -1 -6 -1 -6 -2 -5 -1 -6 -1 -6 -1 -6 0 -6 0 -6 1 -5 0 -6 0 -6 0 -6 -2 -5 -1 -6 -2 -5 -3 -5 -3 -5 -3 -4 -4 -4 -4 -4 -5 -4 -4 -3 -5 -4 -5 -3 -4 -3 -5 -3 -5 -4 -10üGúHìAIûûú[ìàLàM577 3867l-5 -3 -5 -3 -5 -3 -5 -3 -5 -3 -5 -3 -5 -3 -5 -4 -5 -3 -5 -3 -5 -2 -5 -3 -6 -1 -6 1 -6 0 -6 2 -5 1 -6 3 -5 3 -4 3 -5 4 -4 4 -4 4 -4 5 -3 4 -4 5 -3 5 -4 4 -3 5 -4 5 -4 4 -3 5 -3 5 -4 4 -2 6 -2 6 -3 5 -3 4 -5 3 -5 2 -6 2 -6 0 -6 0 -6 -1 -5 -3 -4 -4 -3 -5 -3 -5 -2 -6 -2 -5 -1 -6 -1 -6 -2 -5 -4 -5 -3 -4 -4 -5 -4 -4 -4 -5 -4 -4 -4 -4 -4 -4 -5 -4 -4 -3 -5 -4 -4 -4 -4 -4 -4 -5 -3 -4 -4 -5 -4 -4 -4 -4 -4 -4 -5 -4 -5 -3 -5 -3 -6 -2 -5 -2 -6 -2 -5 -2 -6 -1 -6 -1 -5 -2 -6 0 -6 -1 -6 0 -5 1 -6 1 -6 2 -5 1 -6 2 -5 3 -5 2 -6 3 -5 2 -6 2 -5 1 -6 1 -6 1 -6 1 -5 1 -6 1 -6 2 -5 2 -4 5 -2 5 -3 5 -3 5 -4 5 -4 4 -5 3 -5 3 -5 3 -6 1 -5 0 -6 1 -6 0 -9 0üGúHìAIûûú[ìàLàM-353 3088l-3 5 -3 5 -4 4 -3 5 -4 5 -4 4 -3 4 -5 5 -4 4 -5 3 -5 1 -6 0 -6 -1 -5 -2 -5 -3 -5 -3 -5 -4 -4 -4 -4 -4 -5 -4 -5 -3 -5 -1 -6 -1 -6 0 -6 0 -6 0 -6 0 -5 1 -6 2 -5 2 -5 3 -5 4 -4 4 -4 5 -3 5 -2 5 -2 6 -1 5 -2 6 -1 6 -1 6 0 5 -1 6 0 6 -1 6 -1 6 -2 5 -2 6 -2 5 -3 5 -3 5 -4 4 -5 3 -5 4 -3 4 -4 5 -3 5 -4 5 -3 5 -3 5 -2 5 -2 5 -2 6 -2 6 -2 5 -1 6 -1 5 -1 6 0 6 0 6 0 6 0 6 0 5 0 6 -1 6 -2 6 -2 5 -4 5 -4 4 -3 5 -2 5 -2 6 -1 6 -1 5 1 6 1 6 1 6 2 5 1 6 1 6 1 6 0 5 0 6 0 6 0 6 -1 7üGúHìAIûûú[ìàLàM-31 3155l2 -5 3 -6 3 -5 3 -5 3 -4 3 -5 3 -5 4 -5 3 -5 3 -5 4 -4 3 -5 4 -4 4 -4 4 -4 4 -5 4 -4 3 -5 3 -5 3 -5 3 -5 3 -6 2 -5 2 -5 1 -6 1 -6 -1 -6 -4 -3 -5 -3 -6 -2 -5 -2 -6 -1 -6 -1 -6 -1 -5 -1 -6 -2 -6 -1 -5 -2 -6 -1 -6 -2 -5 -1 -6 -2 -5 -2 -6 -3 -4 -3 -5 -3 -5 -4 -4 -4 -5 -3 -6 -2 -5 -2 -6 -1 -5 -2 -6 -1 -6 -2 -5 -1 -6 -1 -6 -1 -6 1 -5 2 -6 2 -5 3 -5 3 -6 1 -5 0üGúHìAIûûú[ìàLrM-797 3779l-6 1 -5 2 -6 1 -6 1 -5 1 -6 0 -6 0 -10 0GúHìAIûûú[ìàLàM-457 3819l-2 -6 -2 -5 -2 -5 -2 -6 -1 -5 -2 -6 -2 -6 -1 -5 -1 -6 -1 -6 -2 -5 -2 -9üGúHìAIûûú[ìàLàM-272 4462l-6 -1 -6 -1 -6 0 -5 0 -6 0 -6 -1 -5 -2 -6 -2 -5 -2 -6 -1 -6 -2 -5 -2 -6 -1 -6 0 -6 0 -6 0 -5 0 -6 1 -6 2 -5 1 -6 0 -5 -3 -6 -2 -5 -2 -6 -2 -5 -1 -6 -1 -6 -1 -6 -1 -6 0 -5 -1 -6 0 -6 0 -6 0 -6 0 -6 1 -5 0 -6 0 -6 1 -6 1 -6 1 -5 1 -6 1 -5 2 -6 2 -5 3 -6 2 -5 3 -5 3 -5 3 -4 4 -5 3 -4 4 -5 3 -5 4 -5 3 -4 3 -5 4 -5 3 -5 4 -5 3 -4 3 -5 3 -6 2 -6 1 -6 0 -5 2 -5 3 -4 4 -4 4 -4 5 -3 5 -4 9üGúHìAIûûú[ìàLàM380 4634l-4 3 -5 4 -5 3 -5 3 -5 2 -6 2 -6 2 -5 1 -6 2 -6 1 -5 1 -6 1 -6 1 -6 1 -5 0 -6 0 -6 0 -6 -2 -5 -1 -6 -1 -6 0 -6 0 -6 0 -5 0 -6 0 -6 0 -6 0 -6 1 -6 0 -5 1 -6 0 -6 1 -6 2 -5 1 -6 2 -5 2 -6 3 -5 2 -5 4üGúHìAIûûú[ìàLàM162 4676l-5 3 -4 5 -4 4 -4 4 -4 4 -5 4 -5 3 -4 4 -5 3 -4 4 -4 4 -5 4 -5 3 -4 4 -5 3 -5 3 -5 3 -5 3 -6 2 -5 0 -6 0 -6 -1 -6 -1 -5 -3 -3 -5 -2 -6 -1 -6 -1 -6 0 -5 0 -6 -1 -6 0 -6 -2 -6 -1 -5 -1 -6 -1 -6 -2 -5 -1 -6 -2 -6 -1 -5 -2 -6 -1 -5 -2 -6 -2 -5 -3 -6 -2 -5 -2 -6 -4 -5 -3 -4 -4 -4 -4 -4 -5 -4 -4 -4 -5 -3 -5 -4 -5 -3 -5 -3 -5 -3 -5 -2 -6 -2 -5 -2 -6 -2 -5 -2 -6 -1 -6 -1 -5 -1 -6 -1 -6 0 -6 -1 -6 0 -6 -1 -5 0 -6 0 -6 -1 -6 0 -6 0 -5 -1 -6 -1 -6 0 -6 -1 -6 -1 -5 0 -6 -1 -6 0 -6 0 -6 0 -6 0 -5 -1 -6 0 -6 -1 -6 -1 -6 -2 -5 -2 -4 -3 -2 -6 0 -6 0 -6 1 -6 2 -5 2 -6 2 -5 1 -6 1 -6 0 -6 -2 -5 -5 -4 -5 -3 -6 -1 -5 -1 -6 -1 -9 0üGúHìAIûûú[ìàLàM-1708 4748l5 -1 6 -1 6 -2 5 -2 5 -3 5 -4 4 -4 3 -5 3 -5 4 -4 5 -3 6 -2 6 0 6 0 5 2 6 2 5 2 6 2 5 1 6 2 6 1 5 1 6 2 6 1 5 2 6 2 5 2 5 3 6 2 5 2 6 1 6 0 6 0 6 1 5 0 6 0 6 -2 5 -2 4 -4 3 -6 3 -4 6 -1 6 1 5 1 6 2 5 2 6 3 5 2 5 3 4 4 3 5 3 5 3 5 5 3 5 3 5 3 5 3 6 3 5 2 5 3 5 2 6 2 5 3 6 2 5 2 6 2 5 1 6 1 6 0 6 -1 6 0 5 -2 6 -1 6 -1 5 -1 6 -1 6 -1 6 1 5 1 6 1 6 1 6 1 5 1 6 2 6 2 5 2 5 2 6 2 5 2 6 3 5 2 5 3 6 1 5 1 6 0 6 -1 6 -1 6 -1 5 -2 6 -1 6 -2 5 -1 6 -2 5 -2 6 -1 6 -2 5 -1 6 -1 6 0 6 0 6 1 5 -2 5 -3 5 -3 5 -3 5 -4 4 -4 5 -4 4 -4 3 -5 3 -5 2 -5 2 -6 2 -5 3 -5 2 -6 4 -4 4 -5 4 -3 6 -2 5 -2 6 -2 5 -2 5 -3 4 -4 5 -4 5 -3 5 -3 5 -3 4 -4 4 -4 4 -5 3 -4 4 -5 3 -5 3 -5 3 -5 3 -5 3 -5 3 -5 3 -5 3 -5 4 -4 5 -4 4 -4 5 -2 6 -2 6 -2 5 -1 6 0 6 0 6 1 6 1 5 0 6 1 6 2 6 1 5 2 8 3üGúHìAIûûú[ìàLàM1576 1466l-6 2 -5 1 -6 1 -6 1 -6 1 -5 1 -6 2 -6 1 -5 1 -6 0 -6 0 -6 0 -6 0 -5 0 -6 0 -6 0 -6 0 -6 0 -6 0 -5 0 -6 0 -6 0 -6 1 -6 0 -6 1 -5 1 -6 1 -6 1 -6 0 -5 2 -6 1 -6 2 -5 2 -6 2 -5 2 -6 2 -5 3 -4 3 -4 5 -4 4 -3 5 -3 5 -4 5 -3 5 -3 5 -2 5 -1 6 -1 6 -1 6 0 5 0 6 1 6 -1 6 -2 5 -3 6 -2 5 -2 5 -2 6 -2 6 -1 5 -2 6 -2 5 -1 6 -2 6 -1 5 0 6 0 6 0 6 0 6 1 5 0 6 1 6 1 6 1 6 1 5 0 6 -1 6 0 6 -2 5 -1 6 -3 5 -3 5 -3 5 -4 5 -4 4 -4 4 -5 3 -5 4 -4 3 -5 3 -5 3 -5 4 -5 3 -5 3 -5 3 -4 4 -5 3 -5 4 -4 4 -3 4 -5 4 -5 4 -5 3 -5 3 -5 3 -5 2 -6 1 -6 1 -5 -1 -6 -1 -6 -2 -5 -1 -6 -1 -6 0 -6 -1 -6 -1 -6 1 -6 0 -5 3 -3 3 -4 6 -3 5 -3 5 -4 4 -4 5 -4 4 -4 4 -4 5 -3 5 -2 5 -3 5 -2 6 -2 5 -2 5 -2 6 -2 6 -1 5 -1 6 -2 6 -2 5 -2 5 -3 6 -2 5 -3 5 -2 5 -3 6 -3 5 -3 4 -4 5 -3 5 -4 5 -3 4 -4 4 -4 5 -4 4 -4 5 -4 4 -4 4 -4 5 -3 4 -4 4 -4 5 -4 4 -4 4 -4 4 -5 4 -4 5 -4 4 -4 4 -4 4 -4 4 -4 4 -4 4 -5 4 -4 4 -4 4 -4 4 -4 5 -4 4 -5 4 -4 4 -3 4 -4 5 -4 4 -3 5 -3 5 -4 5 -4 4 -3 5 -4 4 -4 4 -4 5 -4 4 -4 4 -4 5 -4 4 -4 4 -4 4 -5 4 -4 3 -5 4 -8 7üGúHìAIûûú[ìàLXM812 2230l-2 5 -1 6 -2 11GúHìAIûûú[ìàLMM823 2208l-6 6GúHìAIûûú[ìàLNM817 2214l-5 16GúHìAIûûú[ìàLàM-1461 1230l-6 -2 -6 -1 -6 -1 -5 0 -6 0 -6 0 -6 2 -5 1 -5 3 -5 4 -4 4 -4 4 -5 4 -4 4 -5 4 -5 2 -6 1 -6 0 -6 -2 -5 -2 -3 -5 -3 -5 -3 -6 -2 -5 -1 -6 -1 -5 -2 -6 -1 -6 -1 -6 -1 -5 -1 -6 -1 -6 -1 -6 -1 -5 0 -6 0 -6 0 -6 0 -6 1 -6 0 -5 1 -12üGúHìAIûûú[ìàLàM-1084 1281l-6 1 -6 1 -6 -1 -5 -1 -6 -2 -5 -2 -6 -3 -5 -2 -6 -2 -5 -2 -6 -2 -5 0 -4 5 -4 3 -6 1 -6 -1 -6 -1 -6 -1 -5 0 -6 -1 -6 -1 -6 -2 -5 -3 -4 -5 -5 -4 -4 -1 -5 2 -5 4 -5 4 -4 5 -4 5 -4 1 -6 0 -6 -1 -6 -1 -6 -1 -6 0 -6 -2 -5 -1 -5 -3 -5 -3 -5 -4 -4 -4 -4 -4 -5 -4 -4 -4 -4 -4 -4 -5 -4 -4 -4 -5 -3 -4 -3 -5 -1 -6 1 -6 1 -6 -2 -6 -3 -5 -4 -3 -6 -2 -5 -2 -6 -1 -6 -1 -6 0 -6 0 -5 2 -6 3 -6 1 -6 1 -4 4 -3 5 -2 6 -1 5 1 6 1 6 -3 5 -4 4 -5 4 -6 2 -5 0 -6 0 -6 -1 -6 -2üGúHìAIûûú[ìàLàM-856 1458l-6 -2 -4 -4 -5 -3 -5 -3 -6 -1 -5 -1 -5 -3 -5 -4 -5 -3 -4 -4 -8 -6üGúHìAIûûú[ìàLàM-941 1370l-1 -6 -3 -5 -2 -5 -3 -5 -3 -5 -4 -4 -4 -4 -5 -4 -4 -4 -6 -1 -5 -2 -6 -2 -6 -1 -5 -2 -6 -2 -5 -2 -5 -3 -4 -4 -5 -4 -4 -4 -4 -4 -4 -5 -4 -4 -4 -5 -4 -3 -5 -2 -6 0 -6 0 -6 0 -6 2 -8 1üGúHìAIûûú[ìàLàM-914 1424l-3 -4 -4 -5 -3 -5 -3 -5 -3 -5 -3 -5 -3 -5 -2 -5 -1 -6 -2 -9üGúHìAIûûú[ìàLàM-734 1478l-6 -2 -5 -2 -6 -2 -5 -1 -6 1 -6 1 -5 1 -6 1 -6 2 -5 3 -5 1 -6 0 -6 0 -6 0 -6 -1 -5 -1 -4 -4 -4 -5 -4 -4 -4 -3 -6 -2 -10 -3üGúHìAIûûú[ìàLàM-2142 1626l-4 4 -5 4 -4 3 -5 3 -5 4 -5 3 -5 3 -5 3 -5 3 -5 2 -5 3 -5 3 -5 3 -5 3 -5 3 -5 3 -5 4 -5 3 -5 3 -5 3 -4 4 -5 3 -5 4 -4 3 -5 4 -4 4 -5 4 -4 3 -5 3 -5 3 -6 3 -5 3 -5 3üGúHìAIûûú[ìàLàM-2302 1733l-5 2 -5 3 -5 3 -5 4 -4 4 -4 4 -4 4 -4 4 -4 4 -4 4 -5 5 -4 4 -4 4 -4 4 -5 4üGúHìAIûûú[ìàLàM-2368 1790l-5 4 -4 4 -4 4 -5 4 -5 3 -4 3 -5 3 -6 3 -5 3 -5 3 -5 3 -5 3 -5 3 -5 3 -5 2 -5 3 -6 2 -6 1 -5 2 -5 3 -4 4 -3 5 -4 5 -3 5 -3 5 -4 5 -3 4 -3 5 -3 5 -2 6 -2 6 -2 5 -2 5 -4 5 -4 4 -4 4 -4 4 -3 5 -3 5 -4 8üGúHìAIûûú[ìàLàM-1248 2119l-5 -3 -5 -3 -5 -2 -5 -3 -6 -2 -5 -2 -6 -1 -5 -1 -6 -1 -6 -1 -6 -2 -5 -1 -6 -1 -6 -1 -5 -2 -6 -1 -6 -1 -5 -2 -6 -1 -6 -2 -5 -1 -6 -2 -5 -2 -6 -2 -5 -2 -6 -2 -6 -1 -5 0 -6 1 -6 1 -6 0 -6 0 -5 -1 -6 -2 -5 -2 -6 -2 -6 -2 -5 -2 -5 -2 -6 -3 -5 -2 -6 -1 -5 -1 -6 0 -6 0 -6 1 -6 2 -5 2 -4 4 -4 5 -2 5 -3 5 -3 6 -3 4 -4 5 -3 5 -4 4 -4 5 -3 4 -5 5üGúHìAIûûú[ìàLàM-2635 2170l-1 5 -2 6 -2 6 -2 5 -4 4 -5 2 -6 2 -6 1 -6 0 -5 3 -7 5üGúHìAIûûú[ìàLàM-2286 2213l-3 -5 -3 -6 -3 -5 -5 -2 -5 -2 -6 0 -6 -1 -6 0 -6 -1 -6 0 -6 -1 -5 0 -6 1 -6 0 -6 1 -6 0 -6 0 -6 0 -5 -1 -5 -4 -4 -4 -4 -4 -6 -1 -5 3 -5 3 -5 4 -4 3 -6 2 -6 1 -6 -1 -5 -2 -5 -3 -6 -1 -6 -1 -6 0 -5 1 -6 1 -6 1 -5 2 -6 1 -6 1 -5 2 -6 1 -6 1 -6 1 -5 1 -6 1 -6 1 -6 1 -5 -1 -3 -6 -4 -4 -5 -3 -6 -1 -5 3 -4 4 -4 4 -3 5 -2 6 0 6 -2 6 -2 5 -3 5 -5 4 -5 1 -6 -1 -6 -2 -5 -2 -6 -2 -5 -2 -5 -2 -6 -3 -5 -2 -5 -3 -6 -2 -5 -2 -6 -2 -6 -2üGúHìAIûûú[ìàLàM-1558 2118l-5 3 -6 3 -5 1 -6 -1 -6 0 -6 -1 -5 -1 -6 -2 -6 -1 -5 -2 -6 -3 -5 -3 -5 -3 -5 -2 -5 0 -6 3 -5 2 -6 0 -6 -1 -6 0 -6 -1 -5 0 -6 0 -6 0 -6 0 -6 -1 -5 -1 -6 -1 -6 -1 -6 0 -6 0 -5 0 -6 1 -6 1 -5 2 -6 2 -5 3 -6 2 -5 3 -5 3 -5 2 -6 1 -6 0 -6 0 -5 -1 -6 0 -6 0 -6 0 -6 0 -6 1 -5 0 -6 2 -6 1 -5 2 -6 2 -5 1 -6 2 -5 2 -6 2 -5 3 -6 2 -5 3 -5 2 -5 3 -6 2 -5 2 -6 2 -5 2 -6 1 -6 1 -5 1 -6 0 -6 0 -6 0 -6 0 -5 -1 -6 -1 -6 -1 -6 -1 -6 0 -5 1 -6 1 -5 3 -5 4 -4 3 -5 4 -4 4 -5 4 -4 4 -4 4 -5 3 -5 4 -4 3 -6 2 -5 1 -6 0 -6 1 -6 1 -6 1 -5 1 -6 1 -6 1 -6 1 -6 1 -5 1 -6 1 -5 2 -6 3 -5 3 -5 2 -5 3 -6 1 -6 1 -5 1 -6 0 -6 1 -6 2 -5 2 -5 3 -4 4 -4 4 -4 5 -4 5 -4 4 -4 1 -6 -2 -5 -4 -4 -4 -3 -5 -4 -4 -4 -5 -4 -4 -4 -4 -4 -4 -4 -5 -5 -7üGúHìAIûûú[ìàLàM-2114 1350l-1 6 -1 5 -1 6 -1 6 -1 5 -2 6 -2 5 -3 6 -2 5 -2 6 -2 5 -1 6 -1 6 -1 5 1 6 2 6 1 6 2 5 1 6 2 6 1 5 1 6 1 6 0 5 0 6 1 6 0 6 0 6 0 6 0 5 0 6 0 6 0 6 0 6 0 6 0 5 0 6 -1 6 0 6 -1 6 0 6 -1 6 -1 5 -1 6 -1 6 -2 5 -3 5 -5 4 -4 4üGúHìAIûûú[ìàLàM-872 1910l5 2 5 3 5 3 6 1 5 2 6 2 6 1 5 1 6 0 6 0 6 -1 6 -2 6 -1 5 1 3 5 2 6 4 4 4 4 5 3 6 2 5 2 6 2 5 2 6 2 5 2 6 2 5 3 5 2 6 3 4 4 3 5 1 5 1 6 1 6 0 6 0 6 0 6 -2 6 -2 5 -2 5 -1 6 0 6 2 6 3 5 3 4 4 5 4 4 4 5 4 4 4 4 3 5 2 5 1 6 1 6 0 6 -1 6 -1 5 -2 6 -2 5 -4 5 -4 4 -5 3 -6 2 -5 2 -6 1 -6 2 -4 4 -3 4 -2 6 -3 5 -2 6 -2 6 -2 5 -1 6 -3 5 -3 5 -4 4 -5 2 -6 2 -5 2 -6 2 -6 2 -5 1 -6 1 -6 0 -6 0 -6 -1 -5 0 -6 0 -6 1 -6 -1 -5 -3 -5 -3 -6 -1 -5 0 -6 0 -6 0 -6 0 -6 0 -6 -1 -5 -2 -6 -2 -5 -3 -5 -3 -6 -2 -5 -3 -5 -1 -6 0 -5 2 -6 3 -5 2 -6 3 -5 3 -5 2 -5 3 -6 2 -5 1 -6 0 -6 1 -6 -1 -6 0 -6 0 -6 -1 -6 -1 -3 -4 0 -7 -3 -4 -6 -3 -5 -1 -6 2 -5 3 -6 0 -5 -2 -6 -3 -5 -2 -6 -2 -5 -2 -5 -3 -4 -5 -3 -5 -4 -2 -6 2 -6 2 -4 -3 -3 -6 -3 -5 -4 -3 -6 -2 -6 -1 -5 -2 -6 -2 -5 -2 -6 -2 -6 0 -5 0 -6 1 -6 1 -6 0 -6 -1 -5 -2 -6 -2 -5 -2 -6 -2 -5 -2 -6 -2 -5 -2 -6 -2 -5 -3 -9 -5üGúHìAIûûú[ìàLàM-3441 1901l1 6 0 6 0 6 0 6 0 6 -1 5 0 6 -1 6 -1 6 -1 6 -2 5 -2 6 -2 5 -3 5 -3 5 -3 5 -4 4 -4 5 -4 4 -4 4 -5 4 -4 4 -5 3 -4 4 -5 4 -5 3 -4 3 -5 3 -5 4 -5 3 -4 4 -4 4 -4 5 -4 4 -4 4 -4 4 -5 4 -4 3 -5 4 -5 3 -6 2 -5 2 -5 2 -6 2 -6 1 -5 2 -6 2 -5 2 -6 2 -5 3 -4 3 -5 4 -5 3 -5 4 -4 3 -5 4 -4 4 -5 3 -4 4 -4 4 -5 4 -5 3 -5 3 -5 2 -6 2 -5 3 -5 2 -6 3 -5 3 -5 3 -4 4 -5 4 -3 4 -2 5 -2 6 -2 6 -1 5 -2 6 -1 6 0 6 -2 5 -1 6 -3 5 -2 6 -2 5 -3 5 -3 5 -3 5 -3 5 -3 5 -3 5 -4 5 -4 4 -4 4 -4 4 -4 4 -4 4 -4 5 -4 4 -3 5 -2 6 -3 5 -4 4 -4 4 -4 5 -4 4 -4 4 -5 4 -4 4 -4 4 -4 4 -4 4 -4 5 -4 4 -4 4 -4 4 -4 5 -4 4 -3 5 -4 4 -4 4 -4 5 -3 4 -4 5 -3 5 -3 5 -4 4 -3 5 -3 5 -3 5 -4 5 -4 7üGúHìAIûûú[ìàLàM-3720 1802l5 -4 4 -3 5 -4 5 -3 5 -3 5 -3 5 -2 6 -2 5 -2 6 -1 6 -2 5 -1 6 -1 6 -2 5 -2 5 -3 5 -3 5 -4 5 -3 5 -3 5 -1 6 -1 6 1 6 1 5 1 6 0 6 0 6 0 6 0 6 0 5 -1 6 0 6 0 6 -1 6 -1 5 -1 6 -2 5 -3 5 -4 4 -3 5 -3 5 -3 5 -4 5 -3 5 -2 6 -1 6 1 5 3 4 4 3 5 3 5 3 5 3 5 3 5 3 5 3 6 2 5 2 5 1 6 1 6 1 6 1 5 1 6 0 6 0 6 -1 6 -2 5 -2 6 -2 5 -1 6 -1 5 -1 6 -1 6 -1 6 -1 6 0 5 -1 6 0 6 1 6 0 6üGúHìAIûûú[ìàLàM-3032 1971l3 5 3 5 2 5 3 6 2 5 3 5 1 6 2 5 2 6 1 6 1 6 1 5 1 6 1 6 0 6 0 5 0 6 0 6 -1 6 0 6 -1 6 -1 5 -1 6 -1 6 -1 5 -2 6 -1 6 -2 5 -1 6 -1 6 -1 6 0 5 -1 6 0 6 -1 6 -1 6 -1 5 -2 6 -2 6 -2 5 -3 5 -4 4 -5 3 -5 4 -6 2 -5 2 -6 1 -5 2 -6 1 -6 2 -5 2 -6 2 -6 3 -5 2 -5 3 -4 4 -3 5 -2 5 0 5 0 7 -1 6 0 6 -1 6 -2 5 -2 5 -3 5 -3 5 -4 5 -3 5 -2 6 -3 5 -2 5 -3 6 -2 5 -3 5 -4 4 -5 3 -5 3 -6 2 -5 3 -5 2 -6 2 -5 2 -6 3 -5 2 -5 4 -5 3 -4 3 -6 3 -5 2 -5 1 -6 1 -6 0 -6 0 -6 2 -4 3 -5 4 -4 4 -4 5 -4 4 -3 5 -3 5 -4 5 -3 5 -2 5 -5 8üGúHìAIûûú[ìàLàM-2763 2143l-5 4 -4 4 -4 5 -3 4 -3 5 -4 5 -3 5 -3 5 -3 5 -3 5 -3 5 -3 5 -3 5 -3 5 -3 5 -3 5 -3 5 -3 5 -3 5 -1 6 -2 5 -1 6 0 6 -3 4 -5 3 -5 3 -6 0 -6 1 -6 1 -3 4 -4 5 -1 6 -2 5 -3 5 -3 5 -4 5 -4 4 -5 3 -4 3 -5 4 -5 3 -5 4 -4 3 -5 6üGúHìAIûûú[ìàLàM-2840 2347l-5 -2 -6 -2 -5 -2 -6 -2 -5 -1 -6 -1 -6 0 -6 0 -6 0 -5 0 -6 -1 -6 0 -9 -1üGúHìAIûûú[ìàLàM-3565 1344l0 6 0 6 -1 5 0 6 0 6 0 6 1 6 3 5 2 6 -1 5 0 6 -1 6 0 6 -1 6 0 6 0 5 0 6 -1 6 0 6 -1 6 -3 4 -9 5üGúHìAIûûú[ìàLàM-3264 1528l-5 -1 -5 -3 -6 -3 -4 -3 -4 -4 -4 -5 -2 -5 -3 -6 -2 -5 -2 -6 -3 -4 -4 -5 -5 -3 -5 -3 -5 -2 -6 -1 -6 0 -6 0 -6 0 -6 0 -5 0 -6 0 -6 1 -6 1 -5 1 -6 2 -5 3 -5 3 -4 4 -4 4 -5 4 -5 3 -5 3 -5 3 -5 3 -6 2 -5 1 -6 2 -6 0 -6 1 -5 -1 -6 -2 -6 -1 -6 -2 -5 0 -6 2 -5 3 -6 0 -6 -1 -5 -1 -6 -2 -5 -2 -6 -2 -5 -3 -5 -3 -5 -3 -4 -4 -5 -3 -5 -4 -5 -3 -4 -4 -7 -5üGúHìAIûûú[ìàLàM-3090 1460l1 5 1 6 0 6 -1 6 -3 5 -3 5 -3 5 -4 5 -4 4 -4 3 -6 2 -6 -1 -6 -1 -5 -1 -6 -2 -6 -2 -5 -1 -6 0 -6 1 -5 1 -6 2 -6 2 -5 2 -6 2 -5 3 -5 2 -6 2 -5 2 -6 2 -5 1 -6 2 -6 1 -6 1 -5 1 -6 0 -6 -1 -7 -2üGúHìAIûûú[ìàLàM-3577 1469l-5 3 -5 3 -6 3 -5 3 -5 2 -4 4 -3 5 -3 5 -3 5 -4 5 -4 4 -4 4 -3 5 -4 5 -3 4 -4 5 -5 4 -5 1 -6 0 -6 0 -5 2 -6 3 -5 2 -6 3 -5 -1 -5 -4 -5 -1 -6 -1 -6 0 -6 0 -6 1 -6 1 -6 0 -5 1 -5 3 -5 4 -5 2 -6 1 -6 2 -5 1 -6 1 -6 1 -6 0 -5 3 -4 4 -3 5 -3 5 -3 5 -1 6 -2 6 -1 5 -2 6 -2 8üGúHìAIûûú[ìàL}M-3818 1613l-2 5 -1 6 1 6 0 6 1 6 1 5 -1 6 -2 5 -3 5 -4 4 -6 3GúHìAIûûú[ìàLàM-2681 2209l-4 -4 -5 -4 -3 -4 -3 -5 -3 -5 -3 -6 -2 -5 -1 -6 1 -6 1 -6 -1 -5 -2 -5 -4 -5 -4 -4 -5 -3 -6 -2 -6 -1 -5 -1 -6 -1 -6 0 -6 2 -4 4 -5 6üGúHìAIûûú[ìàLàM-3834 1670l-5 3 -5 3 -5 3 -6 1 -6 1 -5 2 -5 2 -5 3 -5 4 -5 3 -5 3 -5 4 -4 3 -5 3 -5 3 -6 2 -5 2 -6 2 -6 1 -5 0 -6 0 -6 0 -6 1 -6 0 -6 0 -5 -1 -6 -1 -6 -1 -6 -1 -5 0 -6 2 -6 1 -4 4 -5 3 -4 4 -5 3 -6 2 -5 2 -6 -2 -6 -1 -5 -1 -5 3 -6 3 -5 3 -5 2 -5 3 -5 4 -4 3 -4 5 -3 5 -3 5 -3 5 -4 4 -5 4 -4 4 -4 4 -4 4 -4 4 -4 4 -5 5üGúHìAIûûú[ìàLàM-1164 3258l-6 3 -5 1 -6 0 -6 0 -6 0 -6 0 -5 0 -12 -1 -6 0 -5 0 -6 0 -6 0 -6 0 -6 0 -6 0 -5 0 -6 0 -10 0üGúHìAIûûú[ìàLàM-402 2846l-3 -5 -3 -5 -4 -5 -3 -5 -3 -4 -4 -5 -4 -4 -5 -3 -5 -3 -5 -3 -5 -3 -5 -3 -5 -2 -5 -4 -5 -3 -4 -4 -5 -3 -5 -4 -5 -3 -5 -3 -4 -4 -4 -4 -4 -5 -2 -5 -2 -5 -2 -6 -2 -6 -1 -6 -1 -5 -2 -5 -4 -4 -5 -4 -5 -3 -5 -3 -6 -2 -6 -1 -5 -1 -6 -1 -6 0 -6 1 -6 1 -6 0 -5 1 -6 1 -6 1 -6 1 -5 0 -6 0 -6 0 -6 0 -6 -1 -6 0 -5 0 -6 1 -6 2 -5 3 -5 3 -4 4 -3 5 -2 6 -2 5 -3 5 -2 6 -3 5 -4 5 -4 3 -5 2 -6 2 -6 1 -6 1 -5 1 -6 1 -6 1 -6 2 -5 1 -6 1 -6 1 -5 1 -6 0 -6 1 -6 0 -6 1 -5 2 -5 3 -3 5 -3 6 -2 9üGúHìAIûûú[ìàLàM-336 2989l-5 -3 -5 -3 -1 -1 -4 -2 -3 -5 -3 -5 -4 -5 -3 -5 -3 -4 -4 -5 -3 -5 -1 -6 -1 -6 -1 -5 -1 -6 -2 -6 -1 -5 -1 -6 -2 -6 -2 -5 -1 -6 -2 -5 -2 -6 -2 -5 -2 -6 -2 -5 -2 -6 -3 -10üGúHìAIûûùGúHìAIûûúNøú[Hfil7 str6L_M774 1248l0 -6 -1 -6 -2 -5 -1 -6GúHìAIûûú[ìèL\M692 1118l5 -4 3 -5 4 -4 2 -6GúHìAIûûú[ìèLàM3058 5776l-3 5 -3 5 -3 5 -3 5 -2 6 -3 5 -2 5 -2 6 -2 5 0 6 1 6 1 6 1 5üGúHìAIûûú[ìèLàM2501 6261l-3 -6 -2 -5 -3 -5 -2 -6 -3 -5 -3 -5 -3 -4 -4 -5 -3 -5 -4 -4 -4 -5 -3 -4 -3 -5 -4 -5 -3 -5 -4 -5 -3 -5 -3 -5 -3 -5 -1 -6 -1 -5 0 -5 1 -6 2 -6üGúHìAIûûú[ìèLàM-2298 7095l-6 -3 -5 -3 -5 -3 -5 -2 -5 -3 -6 -2 -5 -2 -6 -1 -6 0 -6 1 -5 1 -6 1 -6 1 -6 1 -6 2 -4 3 -4 5 -2 5 -2 6 -2 5 -3 6 -2 5 -3 5 -4 5 -3 4 -5 4 -4 4 -5 3 -6 3 -5 2 -6 1 -5 1 -6 1 -6 2 -5 2 -5 4 -3 5 -2 5 -1 6 0 6 0 6 0 6 0 6 0 6 0 5 -2 6 -2 6 -3 5 -4 4 -4 4 -5 4 -5 2 -6 2 -6 1 -6 0 -5 -1 -5 -3 -5 -4 -5 -3 -6 -1 -6 0 -5 1 -6 1 -6 2 -5 1 -6 0 -7 0 -5 1 -5 2 -4 4 -3 6 -3 4 -4 4 -5 4 -4 4 -4 4 -4 5 -4 4 -5 8üGúHìAIûûú[ìèLàM-3441 3011l4 -4 5 -4 4 -5 2 -5 2 -6 1 -5 -2 -6 -4 -4 -6 -2 -5 -3 -6 -1 -5 -1 -6 -1 -6 -1 -6 -1 -6 0 -5 0 -6 0 -6 0 -6 0 -6 0 -6 0 -5 2 -5 3 -4 4 -4 5üGúHìAIûûú[ìèLàM-3398 2795l3 5 3 6 2 5 1 6 1 6 -1 6 -1 6 -1 5 -1 6 -2 6 -2 5 -3 6 -2 5 -4 4 -3 5 -4 5 -4 4 -4 4 -4 4 -5 4 -4 4 -5 3 -5 3 -5 3 -5 3 -5 3üGúHìAIûûú[ìèLàM-2710 2997l5 -4 4 -4 4 -4 4 -5 3 -4 4 -5 3 -5 4 -4 4 -5 3 -5 4 -4 3 -5 4 -4 4 -4 5 -4 5 -3 5 -3 5 -2 6 -2 5 -2 5 -3 6 -2 6 -2 4 -3 4 -4 3 -5 2 -6 2 -5 0 -6 1 -6 1 -6 2 -6 1 -5 2 -6 3 -5 3 -5 5 -4 5 -3 5 -1 6 -2 6 -1üGúHìAIûûú[ìèLàM-2831 3750l6 1 6 1 6 1 5 0 6 1 6 1 6 1 5 2 5 3 5 4 3 5 3 5 2 6 0 6 0 6 0 5 -1 6 -1 6üGúHìAIûûú[ìèLàM-285 3037l-4 -4 -4 -4 -4 -4 -4 -5 -3 -4 -4 -5 -3 -5 -4 -4 -4 -4 -5 -3 -5 -3 -7 -3üGúHìAIûûú[ìèLàM-654 3268l-6 0 -6 0 -6 1 -6 0 -6 1 -6 1 -5 3 -5 3 -4 3 -4 5 -4 4 -4 5 -3 5 -2 5üGúHìAIûûú[ìèLàM-160 2973l-6 0 -6 0 -6 -1 -6 -1 -5 -2 -6 -1 -6 -1 -5 2 -6 2 -5 2 -6 1 -6 2 -5 1 -6 1 -6 1 -6 1 -5 1 -6 1üGúHìAIûûú[ìèLyM-358 3029l1 6 3 5 3 5 3 5 2 5 2 6 1 5 -2 6 -3 5 -2 5 -3 6GúHìAIûûú[ìèLàM-867 4683l-3 5 -3 5 -4 5 -3 5 -4 4 -3 5 -3 5 -4 4 -3 5 -4 5 -3 4 -4 5 -3 5 -4 4 -4 5 -4 4 -4 4 -3 5 -3 5 -3 5 -3 5 -3 5 -3 5 -2 5 -3 6 -3 5üGúHìAIûûú[ìèLàM-663 4540l-3 5 -3 5 -3 5 -3 5 -4 5 -4 4 -5 3 -5 3 -5 3 -5 3 -5 3 -4 4 -5 3 -5 3 -5 4 -5 3üGúHìAIûûú[ìèLàM1652 1411l-4 4 -5 3 -4 4 -5 3 -5 3 -5 3 -5 4 -4 4 -3 5 -4 4 -4 4 -5 4 -5 3 -5 3 -5 2 -8 2üGúHìAIûûú[ìèLàM-2080 1229l0 6 0 5 -1 6 -1 6 -2 5 -3 6 -3 5 -3 4 -4 5 -3 5 -2 5 -3 6 -2 5 -2 6 -1 5 -1 6 -1 6 -1 5 0 6 -1 6 0 6 0 6üGúHìAIûûú[ìèLàM-971 1874l3 5 3 5 4 5 4 4 5 3 5 3 5 2 6 2 5 1 6 2 6 1 6 1 6 1 5 1 6 0 6 0 6 -1 6 0 6 1üGúHìAIûûú[ìèLàM-3798 1862l5 -3 5 -3 5 -3 5 -3 4 -4 4 -4 4 -4 4 -4 5 -4 4 -4 5 -4 4 -3 5 -3 5 -4 5 -3 5 -3 4 -4üGúHìAIûûú[ìèLàM-3066 1874l2 5 4 6 2 5 3 5 2 5 2 6 1 6 0 5 0 6 0 6 1 6 1 6 1 6 2 5 2 5 3 5 4 5 4 4üGúHìAIûûú[ìèLàM-2970 1415l-5 3 -5 3 -5 3 -6 2 -5 2 -6 1 -6 0 -6 1 -5 -1 -6 0 -6 -1 -6 -1 -6 0 -5 0 -6 1 -6 2 -5 2 -5 3 -5 3 -5 3 -4 4 -3 5 -3 10üGúHìAIûûùGúHìAIûûúNøú[Hfil7 str7LSM775 1260l-1 -6 0 -6GúHìAIûûú[ììLMM688 1122l4 -4GúHìAIûûú[ììLYM3038 5846l0 6 1 6 0 6 1 8GúHìAIûûú[ììLgM2513 6287l-2 -5 -3 -6 -2 -5 -3 -5 -2 -5GúHìAIûûú[ììLmM-3528 2976l-3 5 -3 5 -2 5 -2 6 -3 5 -4 4 -5 6GúHìAIûûú[ììLmM-3458 2917l-5 3 -5 3 -5 2 -6 3 -5 2 -5 2 -9 3GúHìAIûûú[ììLYM-2769 3810l-1 6 -1 5 -4 7GúHìAIûûú[ììLmM-2554 2833l5 -1 6 -1 6 -2 4 -3 4 -5 2 -5 2 -7GúHìAIûûú[ììLUM-276 3045l-5 -4 -4 -4GúHìAIûûú[ììLXM-637 3268l-6 0 -6 0 -5 0GúHìAIûûú[ììL]M-263 2982l-6 2 -5 1 -6 1 -8 2GúHìAIûûú[ììLRM-358 3017l-1 6 1 6GúHìAIûûú[ììLmM-953 4808l-2 5 -2 6 -1 5 -2 6 -1 6 -1 5 -1 10GúHìAIûûú[ììLlM-732 4601l-4 3 -5 4 -5 3 -5 3 -4 4 -5 3 -8 6GúHìAIûûú[ììLgM1680 1389l-5 3 -4 4 -5 3 -5 4 -4 4 -5 4GúHìAIûûú[ììLtM-2084 1171l-1 6 -1 6 0 5 0 6 0 6 1 6 1 6 1 5 2 6 1 6GúHìAIûûú[ììLeM-963 1840l-2 6 -2 5 -2 6 -2 5 0 6 0 6GúHìAIûûú[ììLbM-3827 1868l6 0 6 -1 6 -1 5 -2 6 -2GúHìAIûûú[ììLkM-3061 1834l-1 6 -2 6 -1 6 -1 5 -1 6 0 6 1 5GúHìAIûûú[ììLmM-2935 1394l-5 3 -6 2 -5 3 -5 3 -5 3 -5 3 -4 4GúHìAIûûùGúHìAIûûùDKrivers_lakesGúHìAIûûúNøú[Hfil7 str8LàM-3511 537l35 -6 9 37 12 6 19 -31 45 2 -4 15 51 19 39 63 33 24 103 11 -4 48üGúHìAIûûú[íLàM-3173 725l20 -27 -4 -27 40 -8 80 20 23 -9 14 14 48 -14 70 17 89 -4 56 -19 66 20 45 -21 32 10 30 -34 38 -13 70 54 6 21 150 -4 69 21 34 36 47 -8 30 17 290 54üGúHìAIûûú[íLyM-374 834l16 -17 43 -4 42 -41 35 -69 42 -81 -2 -73 33 -182GúHìAIûûú[íLàM-1830 821l157 3 222 -74 18 18 -31 18 2 16 13 4 39 -38 81 -31 77 36 1 13 -16 1 18 23 51 -6 4 12 50 3 40 32üGúHìAIûûú[íLàM-1104 851l27 -9 39 21 -3 -30 46 -26 2 -17 75 3 21 -19 34 33 102 23 49 37üGúHìAIûûú[íLpM-712 867l50 18 63 -12 39 16 127 -40 48 -38 11 23GúHìAIûûú[íLàM2316 1366l-27 -35 2 -24 -51 -23 -16 -218 -5 -2 -9 44 -21 -2 -13 -22 20 -44 20 -9 0 -14 -18 -15 2 -8 13 1 17 -67 -16 -10 1 -6 15 2 26 -57 80 -92 61 -29 42 7 72 -90 191 -142 47 2 7 40 32 20 39 0 5 -7 -15 -12 21 -15 16 7 7 24 35 -4 60 -8 42 2 35 22 36 13 17 2 35 5 0 -2 2 -22 25 -1 23 23 18 20 41 4 35 -7 33 3 19 -19 -18 -10 12 -10 53 2 25 -5 16 -6üGúHìAIûûú[íLàM-4107 1294l-22 11 -37 -18 -4 26 -7 3 -6 -13 -16 3 -9 34 -48 35 -10 -5 1 -29 -19 -1 -3 -17 33 -73 37 -26 1 -2 -14 -23 -41 -8 -15 36 -28 -45 21 -20 -20 -30 6 -33 -3 -4 -22 -11 0 8 -24 -12 -17 25 -18 -26 20 -29 -8 -51 19 -37 49 -15 -1 -16 -19 10 -3 -26 41 -27 39 13 28 -32 20 2 7 -14 -10 -26 74 -34 68 38 58 -19 33 8 61 -46 29 19 13 -5 1 -21 17 -11 31 32 29 -6 5 -32 -25 0 -47 -33 8 -43 18 -7 -5 -10 16 -13 17 -1 35 -43 14 8 28 -27 22 5 6 -44 39 1 47 -39 21 2 1 33 -5 7 9 10 13 2 7 -22 67 -39 11 7 -18 29üGúHìAIûûú[íLàM-4136 1806l-4 2 -71 39 -2 -158 25 -15 7 4 4 -9 -5 -14 42 -46 86 -43 6 -41 -9 -5 -29 48 -70 14 1 -52 20 -5 53 -62 -8 -9 -40 29 -42 0 -18 -48 -25 -6 3 -9 26 -18 12 13 -5 9 11 10 12 -1 -4 -20 13 -6 -12 -51 34 -17 18 -45üGúHìAIûûú[íLàM2316 1366l-1 55 19 13 39 -5 19 20 -10 41 -38 22 -27 -19 -23 37 12 63 31 12 20 31 -8 34 22 39 -10 50 -55 39 -21 45 -55 52 -59 25 -24 30üGúHìAIûûú[íLbM2147 1950l-274 164 -68 128 -261 87GúHìAIûûú[íLàM1544 2329l-229 77 -24 40 -29 -12 -79 32 -139 177 24 26 32 -4 58 37 -3 2 -65 48 -50 64 -33 1 -5 -14 43 -12 -5 -28 -45 15 -41 70üGúHìAIûûú[íLàM3085 3222l-165 -75 -83 15 -8 -7 -1 -47 -24 -15 21 -31 123 -10 17 -10 -2 -11 2 0 12 24 17 -7 0 0 1 -2 1 -6 14 0 25 42 37 4 11 53 24 24 0 4 -18 -4 -2 6 18 21 -20 32üGúHìAIûûú[íL{M954 2848l-84 172 -88 101 -19 61 -56 40 -19 80 -58 69 -42 83GúHìAIûûú[íLàM2511 3605l2 -3 27 -37 0 0 9 -12 12 -67 53 -61 -6 -33 22 -8 15 -60 -10 -22 -61 -24 -53 46 -71 -33 -8 -35 34 -8 6 -28 -8 -4 -42 21 -15 -30 62 -41 0 -5 -18 0 -57 34 -67 9 -53 45 -36 9 -106 115 -113 80 -9 27 14 30 52 -1 28 44 7 1 11 -47 72 -31 46 37 -13 26 33 70 30 11 76 -12 53 59 11 3 63 -53 0 0 8 -12üGúHìAIûûú[íLàM1501 4056l-14 -26 -6 -3 -58 2 -8 -4 -7 -52 3 -8 40 -9 4 -9 -6 -35 35 -31 94 -41 43 17 -5 20 14 18 1 10 -42 36 -20 42 -43 21 -3 45 -22 7üGúHìAIûûú[íLàM588 3454l-9 46 -61 111 -6 57 0 8 24 81 50 86 -9 24 -3 7 37 82 90 103üGúHìAIûûú[íLàM1520 4191l-7 -55 24 -29 6 -1 35 47 22 9 20 -11 4 1 4 7 -2 8 -26 12 -33 -18 -14 0 -33 30üGúHìAIûûú[íLàM701 4059l131 50 -2 18 27 33 -68 49 -14 31 -61 12 -35 68 -32 -6 -115 65 -25 29 -8 51 -23 -5 -27 17 -1 94 -65 33 -3 36 -6 90 -25 16 -35 91üGúHìAIûûú[íLàM314 4831l6 29 -5 8 -12 -7 -13 9 -29 59 33 41 40 13 6 -4 -3 -17 4 -1 19 26 -19 22 -114 40 -38 -25 -49 8 -25 17 3 10 -10 2 -52 -24 -23 16 -41 -1 -72 55 -15 48 -25 -1 -60 34üGúHìAIûûú[íLàM-3554 5258l6 48 -14 10 -20 -4 -59 20 -127 87 -111 4 -112 -66 -63 12 -50 -26 -58 8 -29 -15 -1 -18 -5 -1 -5 11 -45 -17 -31 38 -95 9 -70 45 -24 -19 52 -97 -6 -29 38 -52 -7 -38 55 -103 -11 -107 20 -69 11 -7 1 -7 -22 -11 12 -129 -46 -30 36 -57 36 -123 -11 -125 -31 -50 4 -3 19 20 5 -1 1 -11 51 17 6 -6 -17 -16 20 -38 -3 -11 -11 -6 -9 1 -11 37 -65 -35 -109 56 -57 -2 -18 10 -6 -5 22 -76 -34 -83 7 -13 42 -13 13 1 12 23 -7 4 3 3 23 2 9 13 3 -3 -10 -29 22 -8 15 11 6 0 2 -15 16 -5 -1 -3 -36 2 -3 -16 70 -33 3 -12 -28 -53 -2 -47 -1 0 -11 -3 -36 51 -30 85 -21 11 -100 18 -79 -24 -6 -14 5 -18 -13 -29 55 -120 2 -90 53 -115 1 -44 -13 -24 7 -27 73 -35 96 -116 20 -102 121 -288 1 -3 -27 -41 39 -82 58 -214 10 -26 35 -3 18 -49 17 -3 0 -5 -24 -9 -1 -18 5 -11 21 -19 0 -8 -9 -10 -8 2 -21 78 -24 34 -3 -2 66 -249 -7 -86 -5 -8 -20 -32 -9 -104 -25 -62 10 -42 -23 -155 -22 -47 10 -82 72 -61üGúHìAIûûú[íLXM-2870 5540l-20 -14 -30 8GúHìAIûûú[íLàM-2920 5534l-17 51 -11 7 -2 0 -18 -9 -23 -58 -59 -69 -215 -140 10 -27 -7 -5 -30 18 6 14 -9 5 -82 -32 -113 12 -25 14 -11 -5 -20 -37 -8 -15üGúHìAIûûú[íLvM-1046 5663l-120 7 -22 23 -43 12 -90 -40 -73 16 -33 -10GúHìAIûûú[íLàM-180 5188l-76 98 -15 -8 -2 3 11 9 -65 219 -56 39 1 36 -35 21 -3 28 -34 31 -38 13 -57 -74 -45 -15 -36 22 -34 -13 -45 12 -43 79 -49 23 -35 -1 -22 -18 -28 7 -38 -39 -122 3üGúHìAIûûú[íLàM-1427 5671l-31 -11 -77 21 -68 -18 -34 25 -154 -4 -65 91 -52 19 -22 43 -56 17 -128 -4 -133 55 -43 73üGúHìAIûûú[íLXM-2290 5978l-42 60 -13 55GúHìAIûûú[íL[M-2345 6093l-6 24 -1 0 0 -24GúHìAIûûú[íLàM-2352 6093l-13 -15 -32 -2 -5 3 1 75 -90 44 -19 -3 -41 -37 -70 -14 -55 -69 -16 -7 -57 -3 -18 -12 -35 -65 -27 -14 -91 -171 16 -2 27 49 8 2 19 -27 -3 -6 -17 4 -7 -13 3 -38 -40 -31 -43 -2 -32 -72 10 -25 53 -29 14 -61 12 -13 30 1üGúHìAIûûú[íL`M-2355 6320l30 -32 -3 -11 -56 -12GúHìAIûûú[íLQM-906 6736l-20 -40GúHìAIûûú[íLàM-926 6696l-13 -33 10 -41 -16 -7 -53 111 -33 0 -36 38 -82 33 -142 -19 -71 -49 -38 11 -14 39 -30 14 -49 -12 -18 -31 -36 19 -34 -5 -62 32 -66 5 -45 28 -219 -43 -217 -148 -66 -97 -43 -22 -16 -80 -26 -14 -14 -105üGúHìAIûûú[íLàM-489 6865l-67 -25 -51 -21 -53 41 -98 -3 -56 -25 -68 -67 19 36 55 45 -19 6 -69 -33 -10 -83üGúHìAIûûú[íLàM3405 5323l-36 -9 -278 41 -37 -17 -87 30 -49 53 -90 45 -100 -1 -51 -19 -9 43 -41 15 -29 -5 -41 -40 -69 13 -56 83 -125 82 -99 5 -11 -20 -32 -7 -185 66 -91 0 -222 49 -75 -11 -50 29 -49 0 -69 24 -66 29 -44 55 -66 36 -64 10 -106 80 -68 20 -23 45 -49 22 -48 47 -3 10 -41 118 -83 71 -114 -23 -1 -5 -8 -28 -40 -23 -66 18 -23 79 -30 8 -30 39 -38 0 -16 -20 -63 -16 -26 38 -38 -2 -58 34 -71 78 -20 2 -41 128 -27 38 -43 32 -53 2 -36 23 -140 119 -24 -3 -88 40 -54 3 -64 -19 -39 9 -1 -1üGúHìAIûûú[íLàM-2384 6265l-45 4 -69 61 -61 -7 -48 35 -70 -13 -25 11 -62 211 -168 436 -144 284üGúHìAIûûú[íLfM2383 3779l-21 -19 2 -4 22 -3 4 5 -7 21GúHìAIûûùDHcoastlineGúHìAIûûúNøú[Hfil7 str9LhM-5373 7287l0 -6920 8778 0 0 6920 -8778 0GúHìAIûûú[Ifil7 str10LhM-5472 7385l0 -7117 8975 0 0 7117 -8975 0GúHìAIûûùtextøúIA10VD-4756WB344[Hfil8 fnt0GúHìAIûûúIíVD-5234WC7357[íGúHìAIûûúI@8VD-3682Wí[íGúHìAIûûúIíVD-3999Wí[íGúHìAIûûúI@6VD-2627Wí[íGúHìAIûûúIíVD-2784Wí[íGúHìAIûûúI@4VD-1581Wí[íGúHìAIûûúIíVD-1580Wí[íGúHìAIûûúI@2VC1592Wí[íGúHìAIûûúIí"VC2060Wí[íGúHìAIûûúIìvVB534Wí[íGúHìAIûûúIìvVB841Wí[íGúHìAIûûúIí"VC-522Wí[íGúHìAIûûúIí"VC-365Wí[íGúHìAIûûúIíVC2648Wí[íGúHìAIûûúIíVC3274Wí[íGúHìAIûûúIA36VC3412WC5999[íGúHìAIûûúIí+VD-5457WC6096[íGúHìAIûûúIA38Ví,WC4539[íGúHìAIûûúIí0Ví.WC4636[íGúHìAIûûúIì.VC3414WC3065[íGúHìAIûûúIì.Ví.WC3176[íGúHìAIûûúIA42VC3415WC1608[íGúHìAIûûúIí6VD-5460WC1720[íGúHìAIûûù switchøú\øúIRwestl. v. GreenwichVC-146Wí[í@systemLanguageAdeGúHìAIûûúIPwest of GreenwichVí<Wí[í^AenGúHìAIûûùGúHìAIûûú\øúIí;VB161Wí[í^í=GúHìAIûûúIí>Ví@Wí[í^í?GúHìAIûûùGúHìAIûûú\øúIöstl. v. GreenwichVB664Wí[í^í=GúHìAIûûúIPeast of GreenwichVíBWí[í^í?GúHìAIûûùGúHìAIûûú\øúIíAVB950Wí[í^í=GúHìAIûûúIíCVíDWí[í^í?GúHìAIûûùGúHìAIûûú\øúIhModifizierte Kegelprojektion nach LambertVC3500WC7501[í @styleOtext-anchor:end;^í=GúHìAIûûúIfModified conic projection after LambertVíFWíG[í_íH^í?GúHìAIûûùGúHìAIûûú\øúIäBerührungsbreitenkreise: 38° und 42° nördl. Breite, (Kanarische Inseln: 28° nördl. Breite)üVíFWC7585[í_íH^í=GúHìAIûûúIäTouching latitudes: 38° and 42° north latitude (Canary Islands: 28° north latitude)üVíFWíJ[í_íH^í?GúHìAIûûùGúHìAIûûú\øúIäZentralmeridian: 4° westl. Länge, (Kanarische Inseln: 16° westl. Länge)üVíFWC7669[í_íH^í=GúHìAIûûúIäCentral meridian: 4° west longitude, (Canary Islands: 16° west longitude)üVíFWíK[í_íH^í?GúHìAIûûùGúHìAIûûùDQgridline_letteringGúHìAIûûúSøúNøú[Ifil9 str11LeM-1010 3230l0 -663 -663 0 0 663 663 0zGúHìAIûûú[Jfil10 str11LeM-1150 3230l0 -523 -523 0 0 523 523 0zGúHìAIûûùGúHìAIûûúNøú[Jfil11 str11LdM1893 2362l0 -644 -647 0 0 644 647 0zGúHìAIûûú[íOLdM1639 2362l0 -393 -393 0 0 393 393 0zGúHìAIûûùGúHìAIûûúNøú[íOLcM-791 977l0 -334 -334 0 0 334 334 0zGúHìAIûûú[íOLcM-919 977l0 -210 -206 0 0 210 206 0zGúHìAIûûùGúHìAIûûúNøú[íOLdM-387 1045l0 -264 -264 0 0 264 264 0zGúHìAIûûú[íOLdM-491 1045l0 -164 -160 0 0 164 160 0zGúHìAIûûùGúHìAIûûúNøú[íQLcM450 4025l0 -440 -437 0 0 440 437 0zGúHìAIûûú[Jfil12 str11LcM290 4025l0 -274 -277 0 0 274 277 0zGúHìAIûûú[Ifil7 str11LJM0 3748l0 0GúHìAIûûùGúHìAIûûúNøú[íQLeM-2287 5402l0 -384 -383 0 0 384 383 0zGúHìAIûûú[íYLeM-2407 5402l0 -260 -263 0 0 260 263 0zGúHìAIûûùGúHìAIûûúNøú[íOLeM-2519 1022l0 -327 -327 0 0 327 327 0zGúHìAIûûú[íYLeM-2682 1022l0 -164 -164 0 0 164 164 0zGúHìAIûûùGúHìAIûûúNøú[íOLeM-1537 1059l0 -237 -240 0 0 237 240 0zGúHìAIûûú[íYLeM-1610 1059l0 -163 -167 0 0 163 167 0zGúHìAIûûùGúHìAIûûúNøú[íOLdM-195 1467l0 -237 -237 0 0 237 237 0zGúHìAIûûú[íYLdM-272 1467l0 -160 -160 0 0 160 160 0zGúHìAIûûùGúHìAIûûúNøú[Jfil13 str11LeM-2737 2807l0 -207 -207 0 0 207 207 0zGúHìAIûûú[íYLeM-2788 2807l0 -153 -156 0 0 153 156 0zGúHìAIûûùGúHìAIûûúNøú[íQLeM-2488 6003l0 -320 -320 0 0 320 320 0zGúHìAIûûú[íYLeM-2655 6003l0 -153 -153 0 0 153 153 0zGúHìAIûûùGúHìAIûûúNøú[íeLeM-2811 4508l0 -260 -260 0 0 260 260 0zGúHìAIûûú[íYLeM-2927 4508l0 -143 -144 0 0 143 144 0zGúHìAIûûùGúHìAIûûúNøú[íOLdM1303 1629l0 -203 -203 0 0 203 203 0zGúHìAIûûú[íYLdM1237 1629l0 -137 -137 0 0 137 137 0zGúHìAIûûùGúHìAIûûúNøú[íeLeM-3308 1106l0 -213 -214 0 0 213 214 0zGúHìAIûûú[íYLeM-3396 1106l0 -127 -126 0 0 127 126 0zGúHìAIûûùGúHìAIûûúNøú[íeLeM-2695 2041l0 -174 -173 0 0 174 173 0zGúHìAIûûú[íYLeM-2752 2041l0 -117 -116 0 0 117 116 0zGúHìAIûûùGúHìAIûûúNøú[íeLdM-353 3592l0 -170 -170 0 0 170 170 0zGúHìAIûûú[íYLdM-419 3592l0 -104 -104 0 0 104 104 0zGúHìAIûûùGúHìAIûûúNøú[íeLcM534 1659l0 -170 -170 0 0 170 170 0zGúHìAIûûú[íYLcM467 1659l0 -103 -103 0 0 103 103 0zGúHìAIûûùGúHìAIûûúNøú[íQLeM-1904 2272l0 -233 -233 0 0 233 233 0zGúHìAIûûú[Jfil14 str11LeM-1937 2272l0 -200 -200 0 0 200 200 0zGúHìAIûûùGúHìAIûûúNøú[Jfil15 str11LdM2541 3567l0 -273 -277 0 0 273 277 0zGúHìAIûûú[íwLdM2461 3567l0 -196 -197 0 0 196 197 0zGúHìAIûûùGúHìAIûûúNøú[íQLcM-14 4970l0 -320 -317 0 0 320 317 0zGúHìAIûûú[íwLdM-134 4970l0 -194 -197 0 0 194 197 0zGúHìAIûûùGúHìAIûûúNøú[íOLeM-1860 4895l0 -277 -273 0 0 277 273 0zGúHìAIûûú[íwLeM-1940 4895l0 -194 -193 0 0 194 193 0zGúHìAIûûùGúHìAIûûúNøú[íOLeM-1100 5523l0 -283 -284 0 0 283 284 0zGúHìAIûûú[íwLeM-1200 5523l0 -183 -184 0 0 183 184 0zGúHìAIûûùGúHìAIûûúNøú[íyLcM599 4608l0 -344 -343 0 0 344 343 0zGúHìAIûûú[íwLcM439 4608l0 -184 -183 0 0 184 183 0zGúHìAIûûùGúHìAIûûúNøú[íOLeM-3800 1072l0 -326 -327 0 0 326 327 0zGúHìAIûûú[íwLeM-3947 1072l0 -180 -180 0 0 180 180 0zGúHìAIûûùGúHìAIûûúNøú[íOLeM-1245 1681l0 -203 -207 0 0 203 207 0zGúHìAIûûú[íwLeM-1299 1681l0 -157 -153 0 0 157 153 0zGúHìAIûûùGúHìAIûûúNøú[íOLdM-663 1315l0 -204 -206 0 0 204 206 0zGúHìAIûûú[íwLdM-715 1315l0 -156 -154 0 0 156 154 0zGúHìAIûûùGúHìAIûûúNøú[íQLdM-458 5475l0 -224 -227 0 0 224 227 0zGúHìAIûûú[íwLdM-532 5475l0 -156 -153 0 0 156 153 0zGúHìAIûûùGúHìAIûûúNøú[íeLeM-2517 1522l0 -237 -237 0 0 237 237 0zGúHìAIûûú[íwLeM-2608 1522l0 -146 -146 0 0 146 146 0zGúHìAIûûùGúHìAIûûúNøú[íQLcM640 3226l0 -223 -223 0 0 223 223 0zGúHìAIûûú[íwLcM564 3226l0 -143 -147 0 0 143 147 0zGúHìAIûûùGúHìAIûûúNøú[íOLdM-312 4250l0 -200 -200 0 0 200 200 0zGúHìAIûûú[íwLdM-369 4250l0 -143 -143 0 0 143 143 0zGúHìAIûûùGúHìAIûûúNøú[íOLdM-723 1705l0 -183 -184 0 0 183 184 0zGúHìAIûûú[íwLdM-767 1705l0 -143 -140 0 0 143 140 0zGúHìAIûûùGúHìAIûûúNøú[íQLdM1148 2597l0 -240 -240 0 0 240 240 0zGúHìAIûûú[íwLdM1044 2597l0 -137 -136 0 0 137 136 0zGúHìAIûûùGúHìAIûûúNøú[íOLeM-1200 4922l0 -260 -257 0 0 260 257 0zGúHìAIûûú[íwLeM-1320 4922l0 -137 -137 0 0 137 137 0zGúHìAIûûùGúHìAIûûúNøú[íeLeM-1802 1675l0 -163 -164 0 0 163 164 0zGúHìAIûûú[íwLeM-1842 1675l0 -123 -124 0 0 123 124 0zGúHìAIûûùGúHìAIûûúNøú[íeLeM-2401 3769l0 -216 -216 0 0 216 216 0zGúHìAIûûú[íwLeM-2493 3769l0 -120 -124 0 0 120 124 0zGúHìAIûûùGúHìAIûûúNøú[íQLdM2259 1720l0 -237 -233 0 0 237 233 0zGúHìAIûûú[íwLdM2146 1720l0 -123 -120 0 0 123 120 0zGúHìAIûûùGúHìAIûûúNøú[íQLeM-3825 1565l0 -297 -300 0 0 297 300 0zGúHìAIûûú[íwLeM-4005 1565l0 -120 -120 0 0 120 120 0zGúHìAIûûùGúHìAIûûúNøú[íOLeM-1662 3525l0 -230 -230 0 0 230 230 0zGúHìAIûûú[íwLeM-1775 3525l0 -117 -117 0 0 117 117 0zGúHìAIûûùGúHìAIûûúNøú[íeLeM-1157 4308l0 -230 -230 0 0 230 230 0zGúHìAIûûú[íwLeM-1274 4308l0 -113 -113 0 0 113 113 0zGúHìAIûûùGúHìAIûûúNøú[íeLeM-1612 2535l0 -150 -153 0 0 150 153 0zGúHìAIûûú[íwLeM-1652 2535l0 -113 -113 0 0 113 113 0zGúHìAIûûùGúHìAIûûúNøú[Jfil16 str11LdM-803 2148l0 -130 -130 0 0 130 130 0zGúHìAIûûú[íwL`M-837 2148l0 -96 -96 0 0 96 96 0zGúHìAIûûùGúHìAIûûúNøú[íeLcM234 2837l0 -150 -150 0 0 150 150 0zGúHìAIûûú[íwL_M177 2837l0 -93 -93 0 0 93 93 0zGúHìAIûûùGúHìAIûûúNøú[íyLeM-1810 5814l0 -337 -337 0 0 337 337 0zGúHìAIûûú[Jfil17 str11LeM-1904 5814l0 -243 -243 0 0 243 243 0zGúHìAIûûùGúHìAIûûúNøú[íQLdM-933 1247l0 -186 -183 0 0 186 183 0zGúHìAIûûú[í¬LdM-946 1247l0 -166 -170 0 0 166 170 0zGúHìAIûûùGúHìAIûûúNøú[íOLeM-3130 5156l0 -223 -223 0 0 223 223 0zGúHìAIûûú[í¬LeM-3203 5156l0 -147 -150 0 0 147 150 0zGúHìAIûûùGúHìAIûûúNøú[íOLeM-3291 1785l0 -220 -220 0 0 220 220 0zGúHìAIûûú[í¬LeM-3374 1785l0 -136 -137 0 0 136 137 0zGúHìAIûûùGúHìAIûûúNøú[íeLeM-1987 2939l0 -160 -160 0 0 160 160 0zGúHìAIûûú[í¬LeM-2041 2939l0 -106 -106 0 0 106 106 0zGúHìAIûûùGúHìAIûûúNøú[íyLbM25 2378l0 -303 -300 0 0 303 300 0zGúHìAIûûú[íwLbM12 2378l0 -286 -287 0 0 286 287 0zGúHìAIûûùGúHìAIûûúNøú[Jfil18 str11LdM-723 2722l0 -150 -154 0 0 150 154 0zGúHìAIûûú[íMLdM-760 2722l0 -116 -117 0 0 116 117 0zGúHìAIûûùGúHìAIûûùDOrects_for_legendGúHìAIûûúNøúDOtextPathAtlantic_Qvisibility:hidden;LmM -4900,5300 C -4950,4300 -4950,1800 -4900,800GúHìAIûûúDMtextPathMiddle_í½LlM -1900,6500 C -1400,6400 -600,6150 -100,6000GúHìAIûûúDPtextPathMiddleSea_í½LjM 1200,5500 C 2200,5100 2400,4950 3400,4500GúHìAIûûúDOtextPathBalearic_í½LjM 1500,3600 C 2000,3200 2100,3150 2600,2900GúHìAIûûúDNtextPathMorocco_í½LmM -2700,7120 C -2200,7070 -1000,7070 -500,7120GúHìAIûûúDOtextPathPortugal_í½LnM -3900,4600 C -3850,4000 -3700,2900 -3500,2300GúHìAIûûúDQtextPathFranceText_í½LeM 50,650 C 500,850 1400,1020 1850,1050GúHìAIûûúDKtextPathEbro_í½LdM 30,1960 C 50,1970 170,2050 200,2065GúHìAIûûúDStextPathGuadalquivir_í½LnM -2860,5500 C -2850,5350 -2800,5200 -2700,5000GúHìAIûûúDOtextPathGuadiana_í½LnM -3725,4950 C -3710,4800 -3700,4720 -3670,4570GúHìAIûûù]øú\øútextPathúIQAtlantischer OzeanZP#textPathAtlantic@startOffsetA5%GúHìAIûû^í=[Ifil19 fnt1_Tletter-spacing:150px;GúHìAIûûú`úIMAtlantic OceanZíÒaB10%GúHìAIûû^í?[íÔ_Tletter-spacing:200px;GúHìAIûûùGúHìAIûûú\øú`úIFMittel-ZN#textPathMiddleaB25%GúHìAIûû^í=[íÔ_Sletter-spacing:70px;GúHìAIûûú`úIGMediter-ZíÚaíÓGúHìAIûû^í?[íÔ_Tletter-spacing:130px;GúHìAIûûùGúHìAIûûú\øú`úIländisches MeerZQ#textPathMiddleSeaaA0%GúHìAIûû^í=[íÔ_íÜGúHìAIûûú`úIIranean SeaZíàaíÓGúHìAIûû^í?[íÔ_íÞGúHìAIûûùGúHìAIûûú\øú`úIGBalearenZP#textPathBalearicaíÓGúHìAIûû^í=[Hfil8 fnt2_Sletter-spacing:85px;GúHìAIûûú`úIHBalearicsZíäaíÓGúHìAIûû^í?[íå_Sletter-spacing:80px;GúHìAIûûùGúHìAIûûú\øú`úIFMarokkoZO#textPathMoroccoaíÓGúHìAIûû^í=[Hfil8 fnt4_Tletter-spacing:220px;GúHìAIûûú`úIFMoroccoZíêaíÓGúHìAIûû^í?[íë_íìGúHìAIûûùGúHìAIûûú\øú`úIIFrankreichZR#textPathFranceTextaí×GúHìAIûû^í=[íë_íÜGúHìAIûûú`úIEFranceZíïaíÓGúHìAIûû^í?[íë_Tletter-spacing:190px;GúHìAIûûùGúHìAIûûú\øúIFSevillaVD-2247WC5318[Hfil8 fnt5^í=GúHìAIûûúIFSevilleVíóWíô[íõ^í?GúHìAIûûùGúHìAIûûú\øúIGLissabonVD-4885WC4076[íõ^í=GúHìAIûûúIELisbonVD-4806Wíù[íõ^í?GúHìAIûûùGúHìAIûûú\øúIEAlgierVC2298WC5447[íõ^í=GúHìAIûûúIFAlgiersVíýWíþ[íõ^í?GúHìAIûûùGúHìAIûûù\øúIGMallorcaVC2488WC3766[Hfil8 fnt3GúHìAIûûúIFMenorcaVC2928WC3006[îGúHìAIûûú`úIGPortugalZP#textPathPortugalaíÓGúHìAIûû[íë_íØGúHìAIûûúIHBarcelonaVC1998WC2171[íõGúHìAIûûúIGValenciaVB619WC3777[íõGúHìAIûûúIEMadridVC-966WC3255[íõGúHìAIûûúIEBilbaoVD-1400WB715[íõGúHìAIûûúILa CoruñaVD-4377WB663[íõGúHìAIûûúIHMarseilleVC3035WB484[íõGúHìAIûûúIJMontpellierVC2125WB485[íõGúHìAIûûúIHPerpignanVC1710WC1200[íõGúHìAIûûúIDPortoVD-4225WC3046[íõGúHìAIûûú`úICEbroZL#textPathEbroaíáGúHìAIûû[Ifil19 fnt6_Rletter-spacing:5px;GúHìAIûûú`úIKGuadalquivirZT#textPathGuadalquiviraíáGúHìAIûû[î&_Rletter-spacing:0px;GúHìAIûûú`úIGGuadianaZP#textPathGuadianaaíáGúHìAIûû[î&_î*GúHìAIûûúIDIbizaVC1598WC4068[Hfil8 fnt7GúHìAIûûùellipseøú[Jfil20 str12@cxD-4524@cyC4115@rxA20@ryî4GúHìAIûûú[î1cC2539dC5508eî4fî4GúHìAIûûú[î1cD-4248dC3087eî4fî4GúHìAIûûú[î1cC3344dB541eî4fî4GúHìAIûûú[î1cC2602dB516eî4fî4GúHìAIûûú[î1cC2139dC1235eî4fî4GúHìAIûûùSøú\úICTajoVìvWC3748[î&GúHìAIûûUmatrix(0.999514 -0.0311582 0.0311582 0.999514 -774.816 -1079.23)GúHìAIûûú\úICTejoVìvWî@[î&GúHìAIûûU|matrix(0.788941 -0.614468 0.614468 0.788941 -6525.95 784.685)GúHìAIûûú\úIDDueroVìvWî@[î&GúHìAIûûU{matrix(0.974789 0.22313 -0.22313 0.974789 -642.438 -1622.51)GúHìAIûûùDHletteringGúHìAIûûúSúNøú[Ifil7 str13LàM-5373 1689l93 8 103 7 103 8 103 7 103 8 53 3 50 4 104 6 103 7 103 6 103 6 103 6 104 6 103 5 103 5 104 5 103 5 3 0 100 5 103 4 104 4 103 4 103 3 104 4 103 3 104 3 103 3 103 2 56 2 48 1 103 2 103 2 104 1 103 2 104 1 103 1 103 1 104 0 103 1 104 0 5 0 98 0 103 -1 104 0 103 -1 104 -1 103 -1 103 -1 104 -2 103 -2 104 -2 58 -1 45 -1 103 -3 104 -3 103 -3 103 -3 104 -3 103 -4 104 -4 103 -4 103 -4 103 -5 9 0 95 -4 103 -5 103 -5 104 -6 103 -5 103 -6 103 -6 104 -7 103 -6 103 -7 61 -4 42 -3 103 -7 103 -7 104 -8 103 -8 103 -8 103 -8 103 -8 103 -9 103 -9 103 -9 11 -1 92 -9 103 -9 103 -10 103 -10 103 -10 103 -11 11 -1üGúHìAIûûú[îGLàM-5373 3150l87 7 106 8 106 7 107 8 54 3 52 4 106 7 107 7 106 6 106 6 106 6 107 6 106 6 107 5 106 5 106 5 3 0 104 5 106 4 107 5 106 3 107 4 106 4 106 3 107 3 106 3 107 3 57 1 49 1 107 2 106 2 107 2 106 1 107 2 106 1 107 0 106 1 107 0 106 1 6 0 101 -1 107 0 106 0 107 -1 106 -1 107 -1 106 -2 107 -2 106 -2 107 -2 60 -1 46 -1 107 -3 106 -2 106 -4 107 -3 106 -3 107 -4 106 -4 107 -4 106 -5 107 -4 8 -1 98 -4 106 -5 107 -6 106 -5 106 -6 107 -6 106 -6 106 -7 107 -6 106 -7 63 -5 43 -2 107 -8 106 -7 106 -8 106 -8 107 -9 106 -8 106 -9 106 -9 106 -9 106 -9 12 -1 94 -9 106 -10 106 -10 106 -10 75 -8üGúHìAIûûú[îGLàM-5373 4611l87 6 110 8 109 8 56 3 53 4 110 7 109 7 110 7 109 6 110 6 109 6 109 6 110 6 109 5 110 5 3 0 107 5 109 4 110 5 109 4 110 4 109 3 110 4 109 3 110 3 110 2 59 2 50 1 110 2 109 2 110 2 110 1 109 2 110 1 109 1 110 0 110 1 109 0 6 0 104 0 110 -1 109 0 110 -1 109 -1 110 -1 110 -2 109 -2 110 -2 109 -2 63 -1 47 -1 110 -3 109 -3 110 -3 109 -3 110 -4 110 -4 109 -4 110 -4 109 -5 110 -5 8 0 101 -5 110 -5 109 -5 110 -6 109 -6 110 -6 109 -7 109 -6 110 -7 109 -7 65 -5 45 -3 109 -7 109 -8 110 -8 109 -8 109 -9 110 -9 109 -9 109 -9 109 -9 109 -10 12 -1 98 -9 109 -10 109 -10 41 -4üGúHìAIûûú[îGLàM-5373 6072l94 7 112 8 58 3 55 4 112 7 113 8 112 6 113 7 113 6 112 7 113 6 112 5 113 6 113 5 3 0 109 5 113 4 112 5 113 4 113 4 112 4 113 3 113 4 112 3 113 2 61 2 52 1 113 2 112 2 113 2 113 2 112 1 113 1 113 1 113 1 112 0 113 0 6 0 107 0 113 0 112 -1 113 -1 113 -1 113 -1 112 -2 113 -1 113 -3 112 -2 64 -1 49 -1 113 -3 113 -3 112 -3 113 -4 113 -3 112 -4 113 -5 113 -4 112 -5 113 -5 9 0 103 -5 113 -5 113 -6 112 -6 113 -6 112 -6 113 -7 112 -7 113 -7 112 -7 67 -5 46 -3 112 -7 113 -8 112 -9 113 -8 112 -9 112 -9 113 -9 112 -10 112 -9 113 -10 12 -2 100 -9 112 -10 14 -1üGúHìAIûûú[îGLàM-5189 7287l1 -17 9 -139 9 -138 10 -139 9 -138 9 -139 10 -139 9 -138 9 -138 5 -72 5 -67 9 -138 9 -139 10 -138 9 -138 9 -139 10 -138 9 -138 9 -138 10 -139 9 -138 0 -4 9 -134 10 -138 9 -139 9 -138 10 -138 9 -138 9 -138 10 -139 9 -138 9 -138 5 -75 4 -63 10 -138 9 -138 9 -139 10 -138 9 -138 9 -138 10 -139 9 -138 9 -138 10 -138 0 -8 9 -131 9 -138 10 -139 9 -138 9 -138 10 -139 9 -138 9 -139 10 -138 8 -125üGúHìAIûûú[îGLàM-3976 7287l4 -88 6 -139 6 -138 6 -139 7 -139 6 -139 6 -138 6 -139 4 -71 3 -68 6 -138 6 -139 6 -138 6 -139 7 -138 6 -139 6 -138 6 -139 7 -138 6 -138 0 -4 6 -135 6 -138 6 -138 7 -139 6 -138 6 -139 6 -138 6 -138 7 -139 6 -138 3 -75 3 -63 6 -139 7 -138 6 -138 6 -139 6 -138 6 -139 7 -138 6 -139 6 -138 6 -138 1 -8 5 -131 7 -139 6 -138 6 -139 6 -138 7 -139 6 -139 6 -138 6 -139 7 -139 2 -45üGúHìAIûûú[îGLàM-2765 7287l1 -47 3 -139 3 -139 3 -139 3 -139 3 -138 3 -139 3 -139 2 -71 2 -68 3 -138 3 -139 3 -139 3 -138 3 -139 3 -138 3 -139 3 -138 4 -139 3 -139 0 -3 3 -135 3 -139 3 -138 3 -138 3 -139 3 -138 3 -139 4 -138 3 -139 3 -138 1 -75 2 -64 3 -138 3 -139 3 -138 3 -139 3 -138 4 -139 3 -138 3 -139 3 -138 3 -139 0 -7 3 -132 3 -138 3 -139 3 -138 4 -139 3 -139 3 -139 3 -138 3 -139 3 -139 2 -79 0 -2üGúHìAIûûú[îGLàM-1556 7287l0 -34 0 -139 0 -139 0 -138 0 -139 0 -139 0 -139 0 -139 0 -71 0 -67 0 -139 0 -139 0 -138 0 -139 0 -139 0 -138 0 -139 0 -138 0 -139 0 -139 0 -3 0 -135 0 -139 0 -138 0 -139 0 -138 0 -139 0 -138 0 -139 0 -138 0 -139 0 -74 0 -64 0 -139 0 -138 0 -139 0 -138 0 -139 0 -138 0 -139 0 -138 0 -139 0 -139 0 -7 0 -131 0 -139 0 -139 0 -138 0 -139 0 -139 0 -139 0 -139 0 -138 0 -139 0 -79 0 -14üGúHìAIûûú[îGLàM-346 7287l-1 -47 -3 -139 -4 -139 -3 -139 -3 -139 -3 -138 -3 -139 -3 -139 -2 -71 -1 -68 -3 -138 -3 -139 -4 -139 -3 -138 -3 -139 -3 -138 -3 -139 -3 -138 -3 -139 -3 -139 0 -3 -3 -135 -4 -139 -3 -138 -3 -138 -3 -139 -3 -138 -3 -139 -3 -138 -3 -139 -3 -138 -2 -75 -2 -64 -3 -138 -3 -139 -3 -138 -3 -139 -3 -138 -3 -139 -3 -138 -3 -139 -4 -138 -3 -139 0 -7 -3 -132 -3 -138 -3 -139 -3 -138 -3 -139 -3 -139 -3 -139 -4 -138 -3 -139 -3 -139 -2 -79 0 -2üGúHìAIûûú[îGLàM865 7287l-4 -88 -7 -139 -6 -138 -6 -139 -6 -139 -7 -139 -6 -138 -6 -139 -3 -71 -3 -68 -6 -138 -7 -139 -6 -138 -6 -139 -6 -138 -7 -139 -6 -138 -6 -139 -6 -138 -6 -138 -1 -4 -6 -135 -6 -138 -6 -138 -6 -139 -6 -138 -7 -139 -6 -138 -6 -138 -6 -139 -7 -138 -3 -75 -3 -63 -6 -139 -6 -138 -6 -138 -7 -139 -6 -138 -6 -139 -6 -138 -6 -139 -7 -138 -6 -138 0 -8 -6 -131 -6 -139 -7 -138 -6 -139 -6 -138 -6 -139 -7 -139 -6 -138 -6 -139 -6 -139 -2 -45üGúHìAIûûú[îGLàM2078 7287l-1 -17 -10 -139 -9 -138 -9 -139 -10 -138 -9 -139 -9 -139 -10 -138 -9 -138 -5 -72 -4 -67 -10 -138 -9 -139 -9 -138 -10 -138 -9 -139 -9 -138 -10 -138 -9 -138 -9 -139 -10 -138 0 -4 -9 -134 -9 -138 -10 -139 -9 -138 -9 -138 -10 -138 -9 -138 -9 -139 -10 -138 -9 -138 -5 -75 -4 -63 -9 -138 -10 -138 -9 -139 -9 -138 -10 -138 -9 -138 -9 -139 -10 -138 -9 -138 -9 -138 -1 -8 -9 -131 -9 -138 -9 -139 -10 -138 -9 -138 -9 -139 -10 -138 -9 -139 -9 -138 -9 -125üGúHìAIûûú[îGLàM3295 7287l-10 -112 -13 -138 -12 -139 -13 -138 -12 -139 -13 -138 -12 -138 -12 -138 -13 -139 -6 -71 -6 -67 -13 -138 -12 -138 -13 -138 -12 -138 -13 -138 -12 -138 -12 -138 -13 -138 -12 -138 -13 -138 0 -4 -12 -134 -12 -138 -13 -138 -12 -138 -13 -138 -12 -138 -13 -138 -12 -138 -12 -138 -13 -138 -6 -74 -6 -64 -13 -138 -12 -138 -12 -138 -13 -138 -12 -138 -13 -138 -12 -138 -13 -138 -12 -138 -12 -138 -1 -7 -12 -131 -12 -138 -13 -138 -12 -138 -13 -138 -12 -139 -12 -138 -13 -138 -12 -138 -4 -42üGúHìAIûûùGúHìAIûûDHgridlinesGúHìAIûûúNøú[Jfil20 str14LkM-12 7218l0 0 0 -1637 3344 0 0 1637 -3344 0zGúHìAIûûú[Ifil7 str15LeM85 7122l0 -1444 3149 0 0 1444 -3149 0GúHìAIûûúDMtextPathCanary_í½LiM 700,6300 C 1200,6125 2100,6000 2600,6000GúHìAIûûùTúUlmatrix(0.930151 0 0 0.929032 86.3544 3637.68)VìvWC2198XC3383YC1550Zftests/resources/images/canaryRelief.pngGúHìAIûûSøúSøúNøú[ìLàM3152 5774l-14 0 0 -3 -3 -3 3 -4 4 -6 10 -7 6 0 4 3 0 7 0 3 -7 4 0 3 -3 3züGúHìAIûûú[ìLàM3138 5898l-3 0 -3 -4 0 -3 -4 -3 4 0 3 -4 7 -6 0 -4 0 -3 0 -3 6 -20 4 0 3 0 7 3 6 3 4 4 0 6 0 4 -4 0 -3 3 -7 10 0 3 -3 7 -7 0 -6 3 -4 4züGúHìAIûûú[ìLàM2988 6178l-6 0 0 -4 -4 -3 0 -3 -6 0 -7 0 -3 -4 -4 0 -10 0 -13 0 -3 4 -4 0 -3 -7 0 -7 -3 -3 0 -3 0 -4 0 -6 3 0 7 -4 3 -6 7 -4 3 -3 0 -3 3 -4 0 -6 0 -10 4 -17 -4 -13 0 -4 4 -6 0 -4 6 -10 0 -3 7 -7 3 -3 4 -10 3 0 7 -3 6 -7 10 -10 17 0 7 -3 6 3 4 -3 3 -4 7 -3 3 -7 7 -3 3 -3 7 -10 6 0 4 0 3 0 3 0 7 -4 3 -3 7 -3 3 0 4 -4 3 4 3 0 4 3 3 3 3 4 4 0 3 0 3 0 7 -4 3 -3 4 -7 0 -3 3 -3 0 -4 0 -6 3 -4 0 -3 4 -7 0 -3 0 -3 3 -7 3 -13 14 -17 3 -3 3 3 7 3 7 4 10 10 3 6 3 4 -3 6 0 14 0 3 0 7 -3 3 -7 3 -10 7 -3 7 0 3 0 7 3 6 0 7 3 3 0 7 0 3 0 4 -3 6 -3 7 -4 33 0 4 -6 0 0 10 -4 3 -6 3 0 4 -4 0 -3 3 -3 3 -7 4 -3 0 -7 3 0 3 0 7 -3 0 -4 0 -10 0 -6 -3 -4 3 -6 3 0 4 -4 0 -6 10 0 3 -17 3 -13 7 -4 0 -10 -3 -6 0 -7 0 -10 6 -3 0 -4 4 -6 3 -4 10 -3 13 -3 0 -4 7 -3 3 -7 4 0 10züGúHìAIûûú[ìLàM2638 6761l-10 -3 -13 0 -3 0 -10 0 -7 -7 -7 -3 -3 0 -10 -4 -10 0 -20 0 -7 0 -3 4 -3 0 -4 0 -3 0 -3 -4 6 -6 4 -7 0 -7 0 -3 6 0 4 0 3 3 10 0 10 4 17 -4 3 -3 10 -3 7 -4 3 -3 17 -7 20 -10 6 -3 4 -3 6 -10 4 0 6 -7 7 -3 3 -4 4 0 6 -6 10 -14 4 -6 10 -10 3 -4 3 -10 0 -10 -3 -20 3 -6 4 -10 3 -10 0 -4 7 -6 6 -7 4 -7 3 -6 0 -4 3 -13 0 -7 4 -3 0 -3 0 -4 0 -10 0 -3 6 -7 4 -3 3 -3 3 -7 4 -7 10 -10 3 -6 3 -10 4 -10 0 -4 3 -3 3 -3 4 -7 0 -7 3 -3 3 -7 4 -3 0 -3 6 -7 7 -10 3 -3 -3 -17 3 -3 0 -7 4 -3 3 -17 3 -3 0 -10 0 -14 0 -10 4 -3 0 -3 10 -4 3 0 3 -3 4 -3 6 0 7 -7 3 0 7 -3 3 -4 7 -3 3 0 7 0 3 0 7 -3 7 3 3 0 3 3 4 7 0 3 10 4 6 10 4 3 0 3 3 14 -3 13 3 17 0 6 3 7 0 3 0 14 4 10 0 10 -4 3 0 7 0 20 -3 3 -3 13 -4 7 -3 7 -3 3 -4 7 0 6 0 4 4 10 0 3 -4 7 0 6 4 7 3 7 3 3 0 3 -6 7 0 3 -4 7 -6 3 -4 17 -3 7 0 3 -3 10 0 3 -7 7 -3 3 0 7 0 3 0 10 -7 4 0 3 -3 10 -4 7 -3 6 -10 7 -3 3 -4 0 -3 -3 -3 0 -4 0 -10 7 -3 3 -13 0 -7 3 -7 0 -10 0 -13 4 -7 3 -13 3 -10 4 -7 3 -10 7 -10 6 -10 4 -16 0 -7 6 -7 10 -3 4 -10 16 -3 4 -7 6 -3 4 -4 3 -10 10 -3 7 -3 3 -4 0 -10 10 -3 3 -3 4 -4 3züGúHìAIûûú[ìLàM1835 6994l-10 -3 -7 -7 -3 0 -10 -3 -27 0 -6 0 0 -3 -14 -14 -10 -3 -3 -3 0 -4 -13 -10 -4 -3 -3 -7 -7 -6 -10 -4 -3 -3 -3 0 0 -3 -7 -20 -7 -4 0 -6 -3 -10 -10 -17 0 -3 3 -10 0 -4 0 -6 0 -4 0 -3 0 -3 0 -14 0 -13 4 -7 3 0 3 -3 10 0 4 0 3 0 3 -7 7 -6 3 -7 7 0 3 0 4 -3 3 -4 3 -3 0 -3 0 -4 4 -3 3 0 3 -3 0 -4 4 -3 0 -7 -4 -6 4 -7 3 -3 -3 -4 3 -6 0 -7 3 -3 -3 -7 -3 -7 0 -6 13 3 10 0 3 0 10 0 4 0 3 7 10 3 7 0 3 3 3 0 17 0 10 0 7 0 3 4 3 -4 7 -3 3 0 4 3 6 4 4 -4 3 4 10 6 7 0 3 4 3 -4 7 -3 7 0 3 0 3 -3 0 -4 0 -3 0 -3 -6 -7 3 -7 10 0 3 -6 4 3 6 3 4 4 -4 3 -10 13 0 4 -3 6 0 7 3 3 7 7 0 3 0 7 0 7 -3 3 0 3 0 7 0 3 0 4 3 10 0 3 7 3 3 7 7 0 0 3 6 4 4 3 0 3 -4 7 -3 10 -3 3 0 7 3 3 3 7 0 3 0 7 7 3 0 7 -10 0 -3 3 0 4 -4 6 -3 7 3 7 0 3 4 3 6 7 4 3 -4 4 0 3 -10 7 -6 3 0 3 -4 4 -3 0 -3 6 -4 7 -3 3 -3 10 -10 7 -4 0 -16 7 -7 0 -7 3 -3 3 -3 0 -7 0 -7 4 -3 0 -3 3 -14 7 0 3 -3 3 -3 7 -4 3 -3 0züGúHìAIûûùGúHìAIûûúNøú[ìLàM415 6408l0 6 0 7 -3 3 -4 4 -3 3 -7 3 -3 4 0 6 -7 7 -3 10 -3 0 0 -3 -7 -4 -7 -6 -3 -4 0 -3 0 -7 0 -3 0 -3 -3 -4 -4 -3 0 -17 0 -6 0 -4 0 -3 0 -3 -3 -4 -13 -13 -7 -10 0 -3 0 -14 -3 -6 0 -7 -4 -3 -6 -7 0 -3 -4 -7 -6 -3 0 -7 0 -3 0 -4 -4 -6 0 -4 0 -3 -3 -7 -3 -3 -4 -3 -3 -10 -7 -4 -3 0 -7 -10 0 -3 0 -7 4 -6 0 -4 10 -10 3 -3 0 -7 0 -3 3 0 10 -3 7 -7 13 -7 7 -6 3 -4 4 -3 3 3 7 4 3 3 3 0 4 0 6 0 7 3 7 0 13 -3 7 -3 3 0 7 0 3 0 7 3 10 10 3 7 0 3 0 3 0 4 0 3 3 3 7 10 0 4 0 6 3 4 10 6 4 4 0 6 -4 7 0 3 -10 7 -6 13 -4 7 -3 10 0 10 0 3 3 7 4 13 3 10 0 7 -3 10 -4 3 0 4 -3 3 0 3 -3 7 -14 20 0 3 -3 4züGúHìAIûûú[ìLàM1128 6811l-3 0 -3 -3 -7 -4 0 -3 -3 -3 3 -14 0 -6 -3 -4 -4 -3 -3 -3 -3 0 -4 -4 -3 -3 0 -7 0 -6 -3 0 -7 -10 -10 -14 -7 -6 -3 -7 -7 -3 0 -4 -3 -3 -3 -7 -4 -16 -3 -7 -7 -3 -3 -4 -3 0 0 -3 -7 -7 0 -3 -3 -7 0 -13 -4 -17 0 -3 -3 -7 -10 -16 0 -4 -7 -10 -3 -3 -7 -3 -3 -4 -3 -6 -4 -4 -3 -6 3 -4 0 -3 10 0 7 -3 3 0 4 -4 6 -3 4 0 6 -3 10 -4 4 0 3 4 3 0 10 6 20 0 10 0 4 0 13 -6 10 0 10 3 10 -10 3 -3 4 0 3 -4 7 0 13 0 3 4 20 0 4 -4 16 0 4 -3 3 -3 3 -4 7 -6 7 -4 3 0 10 4 3 0 4 0 3 -4 3 -6 7 -4 7 -3 0 -3 3 -4 3 -6 4 -4 0 -3 6 -3 4 -4 3 0 3 -3 4 -3 3 -7 3 -13 4 -7 3 -3 7 0 6 -7 0 -3 10 3 10 -3 7 -7 7 -3 3 0 0 -4 3 -6 7 0 7 3 3 0 7 -3 3 -4 7 4 3 0 7 0 3 0 13 6 7 0 3 0 7 -3 10 0 3 0 7 -7 7 0 3 -6 3 -4 10 4 4 0 0 3 3 10 3 3 0 4 0 13 0 3 -3 7 0 3 -3 4 -7 3 -10 3 -3 0 -14 7 -13 7 -3 3 -4 0 -6 3 -7 4 -3 6 -10 10 -4 4 -3 3 -7 7 -6 10 -7 10 -7 6 -10 4 -3 3 -7 3 -6 7 -4 3 -3 4 0 13 0 3 0 14 3 6 0 4 -3 6 -3 4 -4 3 0 3 -3 4 0 6 -7 10 0 4 -10 20 -3 6 -3 10 -4 10 0 4 -6 16 0 10 0 4 0 3 -17 10 -7 3 0 4 -6 13 -7 10 -7 7 -3 3 -3 10 -4 3 -3 0 -7 10 -6 4 0 3 -4 3 -10 0 -10 0 -6 0 -20 7 -7 7 -3 3 -4 0 -10 0 -6 0 -4 3 -3 0 -7 7züGúHìAIûûú[ìLàM768 6788l-10 0 -10 -7 -13 -17 -7 0 -3 -3 -7 -7 -3 -10 -7 -6 -3 -4 0 -6 -3 -17 3 -3 0 -7 0 -10 7 -10 0 -3 0 -4 0 -3 3 -3 7 -4 3 -3 10 -7 17 -10 3 0 3 4 4 0 6 6 4 0 3 0 17 7 3 0 10 7 10 10 3 0 10 6 0 4 10 0 7 3 7 7 0 3 6 10 0 3 0 10 0 10 -3 4 0 3 -3 0 -7 10 -7 3 -3 7 -3 3 -4 0 -6 7 -7 7 -3 0 -7 3 -3 3 -4 0 -3 0 -13 -3 -4 3 -6 4 -4 0züGúHìAIûûú[ìLàM278 7051l-10 0 -3 0 -7 -7 -3 -3 -3 -3 -10 -20 -4 0 -3 -4 -3 0 -10 -3 -4 3 -6 -3 -10 0 -10 -3 -7 -4 -13 0 -4 -3 -3 0 -3 -10 -4 -10 0 -3 0 -4 0 -6 7 -7 10 -7 7 -3 3 3 7 7 3 0 7 0 6 0 7 0 7 3 3 0 7 0 6 -3 4 0 3 -3 7 -10 6 -7 4 0 10 -7 0 -3 -4 -3 -3 -4 3 -3 4 -3 3 0 10 0 3 0 4 -7 3 0 7 0 3 -3 3 -4 4 -3 3 -3 13 3 7 3 3 10 4 4 0 3 3 3 0 4 0 6 -3 4 -10 10 -4 3 -3 3 -3 7 0 3 0 4 -4 6 0 4 -3 16 -7 4 -3 3 -7 7 0 3 -3 3 -3 4 -4 3 0 7 0 6 0 4 -3 3 0 3 0 4 0 3 -7 0züGúHìAIûûùGúHìAIûûùNú[ìLäM85 7121l0 -1443 3150 0 0 1443 -3150 0m3053 -1223l4 -4 6 -3 7 0 3 -7 0 -3 7 -10 3 -3 4 0 0 -4 0 -6 -4 -4 -6 -3 -7 -3 -3 0 -4 0 -6 20 0 3 0 3 0 4 -7 6 -3 4 -4 0 4 3 0 3 3 4 3 0m-150 280l0 -10 7 -4 3 -3 4 -7 3 0 3 -13 4 -10 6 -3 4 -4 3 0 10 -6 7 0 6 0 10 3 4 0 13 -7 17 -3 0 -3 6 -10 4 0 0 -4 6 -3 4 -3 6 3 10 0 4 0 3 0 0 -7 0 -3 7 -3 3 0 7 -4 3 -3 3 -3 4 0 0 -4 6 -3 4 -3 0 -10 6 0 0 -4 4 -33 3 -7 3 -6 0 -4 0 -3 0 -7 -3 -3 0 -7 -3 -6 0 -7 0 -3 3 -7 10 -7 7 -3 3 -3 0 -7 0 -3 0 -14 3 -6 -3 -4 -3 -6 -10 -10 -7 -4 -7 -3 -3 -3 -3 3 -14 17 -3 13 -3 7 0 3 0 3 -4 7 0 3 -3 4 0 6 0 4 -3 3 0 3 -4 7 -3 3 -7 4 -3 0 -3 0 -4 0 -3 -4 -3 -3 -4 -3 -3 0 -3 -4 -4 4 -3 0 -7 3 -3 3 -7 4 -3 0 -3 0 -4 0 -6 0 -7 10 -3 3 -7 3 -3 7 -7 3 -3 4 -4 3 -6 -3 -7 3 -17 0 -10 10 -6 7 -7 3 -3 0 -4 10 -3 3 -7 7 0 3 -6 10 0 4 -4 6 0 4 4 13 -4 17 0 10 0 6 -3 4 0 3 -3 3 -7 4 -3 6 -7 4 -3 0 0 6 0 4 0 3 3 3 0 7 3 7 4 0 3 -4 13 0 10 0 4 0 3 4 7 0 6 0 0 3 4 3 0 4 6 0m-2573 230l3 -4 0 -3 14 -20 3 -7 0 -3 3 -3 0 -4 4 -3 3 -10 0 -7 -3 -10 -4 -13 -3 -7 0 -3 0 -10 3 -10 4 -7 6 -13 10 -7 0 -3 4 -7 0 -6 -4 -4 -10 -6 -3 -4 0 -6 0 -4 -7 -10 -3 -3 0 -3 0 -4 0 -3 0 -3 -3 -7 -10 -10 -7 -3 -3 0 -7 0 -3 0 -7 3 -13 3 -7 0 -7 -3 -6 0 -4 0 -3 0 -3 -3 -7 -4 -3 -3 -4 3 -3 4 -7 6 -13 7 -7 7 -10 3 -3 0 0 3 0 7 -3 3 -10 10 0 4 -4 6 0 7 0 3 7 10 3 0 7 4 3 10 4 3 3 3 3 7 0 3 0 4 4 6 0 4 0 3 0 7 6 3 4 7 0 3 6 7 4 3 0 7 3 6 0 14 0 3 7 10 13 13 3 4 0 3 0 3 0 4 0 6 0 17 4 3 3 4 0 3 0 3 0 7 0 3 3 4 7 6 7 4 0 3 3 0 3 -10 7 -7 0 -6 3 -4 7 -3 3 -3 4 -4 3 -3 0 -7 0 -6m2223 353l4 -3 3 -4 3 -3 10 -10 4 0 3 -3 3 -7 10 -10 4 -3 3 -4 7 -6 3 -4 10 -16 3 -4 7 -10 7 -6 16 0 10 -4 10 -6 10 -7 7 -3 10 -4 13 -3 7 -3 13 -4 10 0 7 0 7 -3 13 0 3 -3 10 -7 4 0 3 0 3 3 4 0 3 -3 10 -7 3 -6 4 -7 3 -10 0 -3 7 -4 0 -10 0 -3 0 -7 3 -3 7 -7 0 -3 3 -10 0 -3 3 -7 4 -17 6 -3 4 -7 0 -3 6 -7 0 -3 -3 -3 -3 -7 -4 -7 0 -6 4 -7 0 -3 -4 -10 0 -4 0 -6 4 -7 3 -3 3 -7 4 -7 3 -13 3 -3 0 -20 0 -7 4 -3 0 -10 -4 -10 0 -14 0 -3 -3 -7 0 -6 -3 -17 3 -13 -3 -14 0 -3 -4 -3 -6 -10 -10 -4 0 -3 -4 -7 -3 -3 -3 0 -7 -3 -7 3 -3 0 -7 0 -3 0 -7 3 -3 4 -7 3 -3 0 -7 7 -6 0 -4 3 -3 3 -3 0 -10 4 0 3 -4 3 0 10 0 14 0 10 -3 3 -3 17 -4 3 0 7 -3 3 3 17 -3 3 -7 10 -6 7 0 3 -4 3 -3 7 -3 3 0 7 -4 7 -3 3 -3 3 0 4 -4 10 -3 10 -3 6 -10 10 -4 7 -3 7 -3 3 -4 3 -6 7 0 3 0 10 0 4 0 3 -4 3 0 7 -3 13 0 4 -3 6 -4 7 -6 7 -7 6 0 4 -3 10 -4 10 -3 6 3 20 0 10 -3 10 -3 4 -10 10 -4 6 -10 14 -6 6 -4 0 -3 4 -7 3 -6 7 -4 0 -6 10 -4 3 -6 3 -20 10 -17 7 -3 3 -7 4 -10 3 -3 3 -17 4 -10 -4 -10 0 -3 -3 -4 0 -6 0 0 3 0 7 -4 7 -6 6 3 4 3 0 4 0 3 0 3 -4 7 0 20 0 10 0 10 4 3 0 7 3 7 7 10 0 3 0 13 0 10 3m-1870 27l4 0 6 -4 4 -3 13 3 3 0 4 0 3 -3 7 -3 3 0 7 -7 6 -7 4 0 3 -3 3 -7 7 -3 7 -10 3 0 0 -3 3 -4 0 -10 0 -10 0 -3 -6 -10 0 -3 -7 -7 -7 -3 -10 0 0 -4 -10 -6 -3 0 -10 -10 -10 -7 -3 0 -17 -7 -3 0 -4 0 -6 -6 -4 0 -3 -4 -3 0 -17 10 -10 7 -3 3 -7 4 -3 3 0 3 0 4 0 3 -7 10 0 10 0 7 -3 3 3 17 0 6 3 4 7 6 3 10 7 7 3 3 7 0 13 17 10 7 10 0m360 23l7 -7 3 0 4 -3 6 0 10 0 4 0 3 -3 7 -7 20 -7 6 0 10 0 10 0 4 -3 0 -3 6 -4 7 -10 3 0 4 -3 3 -10 3 -3 7 -7 7 -10 6 -13 0 -4 7 -3 17 -10 0 -3 0 -4 0 -10 6 -16 0 -4 4 -10 3 -10 3 -6 10 -20 0 -4 7 -10 0 -6 3 -4 0 -3 4 -3 3 -4 3 -6 0 -4 -3 -6 0 -14 0 -3 0 -13 3 -4 4 -3 6 -7 7 -3 3 -3 10 -4 7 -6 7 -10 6 -10 7 -7 3 -3 4 -4 10 -10 3 -6 7 -4 6 -3 4 0 3 -3 13 -7 14 -7 3 0 10 -3 7 -3 3 -4 0 -3 3 -7 0 -3 0 -13 0 -4 -3 -3 -3 -10 0 -3 -4 0 -10 -4 -3 4 -3 6 -7 0 -7 7 -3 0 -10 0 -7 3 -3 0 -7 0 -13 -6 -3 0 -7 0 -3 0 -7 -4 -3 4 -7 3 -3 0 -7 -3 -7 0 -3 6 0 4 -3 0 -7 3 -7 7 -10 3 -10 -3 0 3 -6 7 -7 0 -3 3 -4 7 -3 13 -3 7 -4 3 -3 3 -3 0 -4 4 -6 3 0 3 -4 4 -3 6 -3 4 0 3 -7 3 -7 4 -3 6 -3 4 -4 0 -3 0 -10 -4 -3 0 -7 4 -7 6 -3 4 -3 3 -4 3 -16 0 -4 4 -20 0 -3 -4 -13 0 -7 0 -3 4 -4 0 -3 3 -10 10 -10 -3 -10 0 -13 6 -4 0 -10 0 -20 0 -10 -6 -3 0 -3 -4 -4 0 -10 4 -6 3 -4 0 -6 3 -4 4 -3 0 -7 3 -10 0 0 3 -3 4 3 6 4 4 3 6 3 4 7 3 3 3 7 10 0 4 10 16 3 7 0 3 4 17 0 13 3 7 0 3 7 7 0 3 3 0 3 4 7 3 3 7 4 16 3 7 3 3 0 4 7 3 3 7 7 6 10 14 7 10 3 0 0 6 0 7 3 3 4 4 3 0 3 3 4 3 3 4 0 6 -3 14 3 3 0 3 7 4 3 3 3 0m707 183l3 0 4 -3 3 -7 3 -3 0 -3 14 -7 3 -3 3 0 7 -4 7 0 3 0 3 -3 7 -3 7 0 16 -7 4 0 10 -7 3 -10 3 -3 4 -7 3 -6 3 0 4 -4 0 -3 6 -3 10 -7 0 -3 4 -4 -4 -3 -6 -7 -4 -3 0 -3 -3 -7 3 -7 4 -6 0 -4 3 -3 10 0 0 -7 -7 -3 0 -7 0 -3 -3 -7 -3 -3 0 -7 3 -3 3 -10 4 -7 0 -3 -4 -3 -6 -4 0 -3 -7 0 -3 -7 -7 -3 0 -3 -3 -10 0 -4 0 -3 0 -7 0 -3 3 -3 0 -7 0 -7 0 -3 -7 -7 -3 -3 0 -7 3 -6 0 -4 10 -13 4 -3 -4 -4 -6 -3 -4 -3 -3 6 -10 0 -3 7 6 7 0 3 0 3 0 4 -3 3 -3 0 -7 0 -7 3 -3 4 -3 -4 -7 0 -10 -6 -3 -4 -4 4 -6 -4 -4 -3 -3 0 -7 3 -3 4 -3 -4 -7 0 -10 0 -17 0 -3 0 -3 -3 -7 0 -10 -3 -3 -7 -4 0 -10 0 -3 0 -10 0 -13 -3 0 6 3 7 3 7 -3 3 0 7 -3 6 3 4 -3 3 -4 7 4 6 0 7 -4 3 0 4 -3 3 -3 0 -4 3 0 4 0 3 -3 3 -3 4 -4 3 -3 0 -7 0 -3 7 -7 6 -3 7 -3 0 -4 0 -10 0 -3 3 -3 0 -4 7 0 13 0 14 0 3 0 3 0 4 0 6 0 4 -3 10 0 3 10 17 3 10 0 6 7 4 7 20 0 3 3 0 3 3 10 4 7 6 3 7 4 3 13 10 0 4 3 3 10 3 14 14 0 3 6 0 27 0 10 3 3 0 7 7 10 3m-1557 57l7 0 0 -3 0 -4 0 -3 3 -3 0 -4 0 -6 0 -7 4 -3 3 -4 3 -3 0 -3 7 -7 3 -3 7 -4 3 -16 0 -4 4 -6 0 -4 0 -3 3 -7 3 -3 4 -3 10 -10 3 -4 0 -6 0 -4 -3 -3 0 -3 -4 -4 -3 -10 -7 -3 -13 -3 -3 3 -4 3 -3 4 -3 3 -7 0 -3 0 -4 7 -3 0 -10 0 -3 0 -4 3 -3 3 3 4 4 3 0 3 -10 7 -4 0 -6 7 -7 10 -3 3 -4 0 -6 3 -7 0 -3 0 -7 -3 -7 0 -6 0 -7 0 -3 0 -7 -7 -3 -3 -7 3 -10 7 -7 7 0 6 0 4 0 3 4 10 3 10 3 0 4 3 13 0 7 4 10 3 10 0 6 3 4 -3 10 3 3 0 3 4 4 0 10 20 3 3 3 3 7 7 3 0 10 0m2874 -1277l3 -3 0 -3 7 -4 0 -3 0 -7 -4 -3 -6 0 -10 7 -4 6 -3 4 3 3 0 3 14 0züGúHìAIûûGúHìAIûûú\øúIA18VB242WC5654[Hfil8 fnt8GúHìAIûûúIA16VC1525WîV[îWGúHìAIûûúIA14VC2797WîV[îWGúHìAIûûúIîTVB222WC7192[îWGúHìAIûûúIîXVC1517Wî][îWGúHìAIûûúIîZVC2834Wî][îWGúHìAIûûúIA28VC3244WC6808[îWGúHìAIûûúIî`VA-2WC6812[îWGúHìAIûûù]ú\øúIí;VB377WîV[îW^í=GúHìAIûûúIí>VîeWîV[îW^í?GúHìAIûûùGúHìAIûûGúHìAIûûúNøú[íLàM3152 5776l2 -4 2 -3 5 -5 2 -3 0 -5 -4 -5 -6 0 -2 3 -11 3 -3 7 -1 5 1 4 2 1 13 2üGúHìAIûûú[íLàM3140 5897l-4 0 -4 -2 -1 -2 -1 -3 2 -3 3 -2 5 -5 0 -4 1 -4 1 -3 6 -19 4 -2 3 1 8 3 5 2 5 6 -1 4 -2 3 -3 2 -2 3 -6 10 0 4 -6 5 -4 0 -6 5 -3 1üGúHìAIûûú[íLàM2987 6178l-5 -1 -2 -3 -1 -3 -2 -3 -4 -1 -9 1 -3 -2 -4 -1 -9 1 -12 0 -3 2 -4 -1 -3 -5 -2 -7 -2 -3 -2 -4 0 -4 2 -4 3 -2 8 -1 3 -8 5 -5 3 -2 2 -3 1 -3 0 -8 0 -10 3 -17 -3 -11 0 -5 3 -7 1 -4 6 -9 2 -3 5 -6 4 -6 3 -7 3 -2 6 -3 9 -7 10 -10 14 0 9 -1 4 0 4 -1 6 -4 5 -4 4 -7 6 -3 3 -3 6 -8 3 -3 4 0 3 2 5 1 4 -1 6 -4 3 -2 6 -4 4 -1 4 -1 3 0 3 2 4 5 3 1 2 3 4 2 4 0 4 -2 6 -3 2 -3 4 -6 1 -5 2 -3 1 -3 0 -5 2 -4 1 -4 4 -5 1 -5 0 -5 1 -3 2 -3 3 -13 12 -18 4 0 2 3 7 3 9 2 8 11 5 5 1 4 -2 8 -2 13 1 4 -1 5 -2 3 -5 5 -10 6 -3 7 -1 4 -1 5 3 7 2 8 2 4 1 4 0 3 -1 5 -5 6 -3 6 -1 35 -2 3 -4 1 -2 9 -2 2 -6 4 -3 2 -3 2 -2 3 -3 2 -7 3 -3 3 -6 3 -3 3 0 5 -2 2 -4 -1 -9 -2 -5 0 -4 1 -6 3 -3 3 -3 2 -4 11 -3 2 -15 2 -12 8 -5 0 -11 -4 -5 -1 -8 3 -10 4 -4 1 -3 2 -5 5 -5 10 -3 12 -3 3 -4 6 -2 3 -6 4 -2 8üGúHìAIûûú[íLàM416 6407l2 -3 1 -4 13 -17 3 -7 0 -5 2 -4 1 -3 2 -3 5 -11 1 -4 -5 -11 -2 -12 -3 -7 -1 -4 0 -9 2 -12 4 -7 8 -12 8 -7 2 -3 2 -8 0 -4 -4 -4 -9 -7 -2 -2 0 -9 -2 -4 -7 -8 -2 -3 -1 -4 0 -5 2 -3 -1 -3 -4 -6 -10 -10 -7 -3 -4 -1 -5 0 -3 1 -7 4 -12 3 -8 -2 -8 -3 -5 0 -4 1 -4 -1 -4 -1 -5 -5 -3 -2 -3 2 -5 5 -7 4 -13 6 -7 9 -8 1 -3 3 -1 3 0 4 -2 4 -2 3 -8 7 -2 3 -3 7 -1 9 1 4 8 7 3 1 5 4 4 10 2 3 4 2 3 7 0 4 1 4 4 5 0 5 -1 5 2 3 3 6 6 5 1 4 4 6 4 6 2 3 1 8 2 14 0 4 7 8 12 14 2 3 0 3 1 4 1 4 0 5 1 19 2 2 2 3 1 4 -1 4 0 5 2 4 4 5 4 5 6 4 2 3 2 -1 4 -10 5 -5 3 -7 3 -3 6 -4 3 -2 4 -6 1 -3 2 -4 1 -10üGúHìAIûûú[íLàM2637 6761l3 -2 6 -4 3 -3 10 -9 3 -2 2 -3 5 -6 8 -11 3 -3 6 -4 5 -4 4 -6 10 -17 2 -2 6 -9 8 -7 18 -2 8 -1 10 -6 2 -2 9 -6 8 -2 10 -5 12 -3 7 -3 12 -3 13 -1 3 -1 9 -1 12 -2 4 -2 9 -6 3 -1 3 0 6 4 2 0 2 -3 3 -2 8 -7 4 -6 4 -7 2 -8 1 -4 5 -5 1 -9 0 -4 1 -5 1 -3 8 -8 1 -4 2 -8 2 -3 2 -9 5 -14 4 -7 4 -6 1 -3 5 -5 0 -5 -2 -4 -2 -7 -4 -6 -1 -4 2 -8 1 -4 -2 -9 0 -5 0 -4 2 -7 5 -6 4 -6 0 -5 6 -14 1 -3 1 -19 1 -8 1 -4 1 -10 -2 -8 0 -15 -1 -4 -3 -7 0 -4 -3 -18 2 -14 -3 -12 -1 -3 -2 -3 -5 -11 -11 -4 -2 -2 -1 -8 -3 -3 -4 -1 -7 -2 -7 3 -4 1 -5 0 -4 0 -7 3 -4 1 -5 5 -5 0 -4 6 -9 1 -3 2 -2 3 -3 2 -11 4 -2 3 -2 3 -1 9 2 13 -1 10 -2 3 -4 16 -4 7 -1 3 -1 4 1 18 -1 4 -7 8 -7 9 -1 3 -3 3 -4 6 -1 4 0 4 -6 9 -2 4 -2 3 -2 3 -2 8 -2 3 -2 8 -3 7 -9 11 -5 5 -4 6 -2 4 -5 4 -4 6 -1 4 -2 9 1 5 -1 4 -1 4 -1 4 -2 13 -2 3 -4 7 -2 8 -8 7 -5 5 -1 4 -3 12 -3 7 -2 9 2 18 -1 10 -3 12 -2 3 -10 11 -4 6 -11 13 -6 5 -3 2 -2 3 -7 3 -9 6 -3 2 -6 9 -3 2 -7 3 -19 11 -17 7 -3 2 -8 3 -9 6 -3 1 -17 4 -11 -4 -9 0 -5 -1 -3 -1 -5 0 -2 3 1 8 -4 6 -5 6 2 3 3 2 4 -1 4 -1 2 -2 9 -2 19 0 9 0 12 4 3 2 7 3 6 4 9 1 4 -1 13 3 9 1üGúHìAIûûú[íLàM767 6789l4 -1 6 -4 4 -1 13 2 4 0 5 -1 3 -1 6 -5 4 1 4 -6 3 -3 6 -3 3 -3 1 -3 5 -6 7 -3 6 -8 3 -3 2 -3 1 -4 1 -9 1 -9 -2 -3 -4 -11 -2 -3 -8 -8 -6 -2 -8 -2 -2 -1 -7 -8 -5 -1 -11 -9 -9 -6 -3 -2 -17 -4 -5 0 -3 -2 -6 -4 -2 -2 -4 -2 -5 0 -16 11 -10 5 -3 2 -6 4 -2 2 -2 4 -1 4 0 5 -5 10 0 10 -1 4 -2 4 1 18 3 7 2 4 7 6 4 10 5 6 3 2 7 3 15 15 9 6 9 1üGúHìAIûûú[íLàM1128 6811l6 -4 3 -3 4 -1 8 -2 8 1 4 -2 2 -2 10 -6 17 -7 9 -1 9 1 10 -1 3 -1 2 -4 5 -5 6 -9 4 -1 2 -3 5 -10 2 -3 8 -7 6 -9 6 -14 3 -3 5 -5 15 -9 2 -3 0 -4 1 -9 5 -16 0 -4 2 -8 5 -10 2 -9 10 -20 1 -4 5 -10 1 -4 5 -6 1 -3 2 -3 2 -2 4 -7 1 -4 -4 -7 -1 -13 0 -4 2 -11 1 -4 5 -5 7 -7 7 -3 3 -2 10 -5 6 -4 5 -10 8 -12 5 -5 3 -2 3 -2 3 -3 8 -12 5 -4 6 -4 7 -3 3 -2 4 -1 12 -8 14 -7 3 -1 12 -3 6 -4 3 -2 1 -5 1 -4 2 -3 0 -14 -1 -4 -2 -2 -3 -12 -1 -3 -4 0 -11 -3 -2 4 -5 5 -4 1 -9 6 -3 1 -9 1 -8 3 -4 -1 -4 -1 -14 -4 -4 -1 -5 1 -4 -1 -7 -3 -3 1 -6 4 -5 0 -7 -3 -4 0 -3 2 -1 4 -2 3 -2 3 -8 2 -7 8 -9 1 -8 -2 -3 2 -5 6 -6 3 -4 2 -4 6 -3 13 -3 6 -5 5 -4 2 -3 2 -2 3 -5 4 -2 3 -2 4 -5 5 -2 3 -1 4 -7 2 -6 5 -2 7 -3 2 -5 1 -4 -1 -8 -2 -5 1 -7 2 -6 5 -4 6 -2 3 -3 2 -18 2 -3 1 -19 -1 -4 -1 -15 0 -4 1 -3 1 -5 1 -3 2 -10 9 -9 -1 -13 0 -10 5 -5 1 -9 -1 -20 0 -11 -4 -3 -2 -3 -2 -5 0 -9 1 -6 4 -3 2 -6 4 -4 1 -4 1 -7 3 -8 1 -3 2 -2 3 -1 2 4 6 2 3 4 6 3 2 7 3 2 3 1 3 6 10 2 3 9 16 3 7 2 3 4 16 -1 14 2 8 1 3 6 6 1 3 3 2 3 2 6 4 5 5 3 17 4 6 2 3 1 3 4 5 6 5 7 8 9 14 8 8 2 3 1 4 0 9 2 4 3 2 4 1 3 2 2 3 3 5 2 4 -2 13 1 4 2 3 5 5 3 2 4 0üGúHìAIûûú[íLàM1833 6995l4 -1 3 -2 6 -8 1 -4 3 -3 10 -4 6 -4 4 -1 4 -1 7 -3 4 0 3 -2 6 -3 9 -2 16 -3 4 -2 8 -7 5 -10 1 -4 3 -6 6 -5 3 -2 2 -3 2 -3 5 -5 9 -6 2 -3 1 -4 -2 -3 -5 -5 -5 -6 -1 -3 -1 -5 2 -7 3 -7 2 -3 2 -3 8 -1 1 -4 -5 -4 -1 -7 -1 -3 -3 -7 -1 -4 0 -5 2 -3 5 -11 1 -7 0 -4 -3 -2 -5 -5 -3 -2 -4 -2 -6 -4 -4 -6 -1 -3 -2 -8 -1 -5 1 -5 -1 -4 0 -4 2 -3 2 -8 0 -5 -1 -3 -8 -8 -1 -4 0 -5 2 -8 1 -4 10 -11 1 -4 -2 -3 -5 -5 -3 -2 -4 6 -10 0 -3 2 0 4 4 6 2 4 -1 5 -1 3 -2 3 -4 1 -5 0 -7 4 -4 0 -4 0 -7 -3 -9 -7 -4 -1 -4 1 -4 -1 -6 -4 -3 0 -6 5 -5 0 -3 -1 -4 -1 -13 2 -14 -1 -5 -1 -3 -2 -5 0 -10 -5 -6 -5 -3 -1 -9 1 -5 0 -8 -2 -14 -2 0 5 2 3 3 6 1 5 -1 4 -2 8 -1 5 1 4 -2 2 -4 7 2 8 0 5 -1 5 -1 3 -2 3 -4 1 -2 3 -1 4 -2 3 -2 3 -3 2 -3 2 -3 2 -9 1 -4 7 -4 5 -5 5 -3 2 -4 1 -10 1 -4 0 -2 3 -2 4 1 14 -3 13 0 4 1 4 0 4 1 5 0 3 -4 12 1 3 10 16 1 8 2 8 5 5 6 18 2 3 4 2 3 1 7 3 8 8 4 6 5 5 11 9 2 3 2 3 10 5 12 13 2 2 5 0 29 2 7 2 4 1 9 7 7 2üGúHìAIûûú[íLàM277 7053l7 -2 2 -2 -1 -3 1 -4 2 -3 1 -4 0 -8 0 -4 2 -4 2 -2 2 -3 2 -3 2 -2 4 -6 6 -4 6 -2 1 -3 1 -15 1 -3 4 -6 1 -5 0 -4 1 -4 2 -3 3 -3 3 -2 11 -9 1 -3 1 -9 -1 -3 -1 -3 -3 -3 -1 -4 -5 -10 -5 -4 -14 -1 -4 1 -2 3 -4 6 -4 1 -5 0 -4 1 -5 5 -3 2 -9 0 -4 1 -3 2 -2 4 4 1 1 3 0 5 -9 5 -4 2 -8 7 -5 11 -2 2 -4 2 -9 2 -4 1 -5 -1 -6 -4 -5 0 -9 1 -5 -1 -3 -1 -9 -7 -4 -1 -7 3 -9 5 -5 6 -2 8 0 4 1 4 4 10 3 8 2 2 4 2 14 1 8 3 8 2 10 0 7 3 5 0 10 0 3 1 3 2 2 3 12 19 2 2 2 3 9 7 3 2 8 0üGúHìAIûûùGúHìAIûûúNøú[íyLdM2977 6617l0 -283 -283 0 0 283 283 0zGúHìAIûûú[íwLdM2901 6617l0 -206 -207 0 0 206 207 0zGúHìAIûûùGúHìAIûûúNøú[Ifil7 str16LeM85 7121l0 -1443 3150 0 0 1443 -3150 0GúHìAIûûú[îhLàM271 6790l0 -8 1 -37 0 -36 1 -37 0 -37 1 -36 1 -37 0 -36 1 -37 0 -36 1 -37 1 -36 0 -37 1 -37 0 -36 1 -37 1 -36 0 -37 1 -36 0 -37 1 -36 1 -37 0 -37 1 -36 0 -37 1 -36 1 -37 0 -36 1 -37 0 -37 1 -36 0 -7üGúHìAIûûú[îhLeM85 6786l27 1 33 0 32 1 32 1 33 0 29 1GúHìAIûûú[îhLàM2852 6790l18 -1 32 0 33 -1 32 0 33 -1 32 -1 33 0 32 -1 32 0 33 -1 32 -1 33 0 8 -1üGúHìAIûûú[îhLàM2852 6790l0 -8 -1 -37 0 -36 -1 -37 0 -37 -1 -36 -1 -37 0 -36 -1 -37 0 -36 -1 -37 -1 -36 0 -37 -1 -37 0 -36 -1 -37 -1 -36 0 -37 -1 -36 0 -37 -1 -36 -1 -37 0 -37 -1 -36 0 -37 -1 -36 -1 -37 0 -36 -1 -37 0 -37 -1 -36 0 -7üGúHìAIûûú[îhLàM1561 6800l11 0 33 0 32 0 32 0 33 0 32 0 33 0 32 0 33 0 32 0 33 0 32 -1 32 0 33 0 32 0 33 0 32 -1 33 0 32 0 33 0 32 -1 32 0 33 0 32 0 33 -1 32 0 33 0 32 -1 33 0 32 -1 32 0 33 0 32 -1 33 0 32 -1 33 0 32 -1 33 0 32 -1 32 0 15 0üGúHìAIûûú[îhLàM1561 6800l0 -8 0 -36 0 -37 0 -36 0 -37 0 -37 0 -36 0 -37 0 -36 0 -37 0 -36 0 -37 0 -36 0 -37 0 -37 0 -36 0 -37 0 -36 0 -37 0 -36 0 -37 0 -37 0 -36 0 -37 0 -36 0 -37 0 -36 0 -37 0 -37 0 -36 0 -37 0 -17üGúHìAIûûú[îhLàM271 6790l3 0 33 0 32 1 33 0 32 1 33 0 32 1 32 0 33 1 32 0 33 0 32 1 33 0 32 0 33 1 32 0 32 0 33 1 32 0 33 0 32 1 33 0 32 0 33 0 32 1 32 0 33 0 32 0 33 0 32 0 33 1 32 0 33 0 32 0 32 0 33 0 32 0 33 0 32 0 33 0 21 0üGúHìAIûûú[îhLM1561 7121l0 -36 0 -37 0 -36 0 -37 0 -37 0 -36 0 -37 0 -36 0 -29GúHìAIûûú[îhLàM2857 7121l0 -10 0 -37 -1 -37 0 -36 -1 -37 -1 -36 0 -37 -1 -36 0 -37 -1 -28üGúHìAIûûú[îhLàM265 7121l1 -10 0 -37 1 -37 0 -36 1 -37 1 -36 0 -37 1 -36 0 -37 1 -28üGúHìAIûûùGúHìAIûûúNøú[íyLdM1248 6705l0 -273 -276 0 0 273 276 0zGúHìAIûûú[í¬LdM1145 6705l0 -173 -173 0 0 173 173 0zGúHìAIûûùGúHìAIûûù]ú\øú`úIPKanarische InselnZN#textPathCanaryaíÓGúHìAIûû^í=[Hfil8 fnt9_Sletter-spacing:40px;GúHìAIûûú`úIMCanary IslandsZîoaíÓGúHìAIûû^í?[îp_Sletter-spacing:60px;GúHìAIûûùGúHìAIûû\øúIHTeneriffaVC1221WC6344[î0GúHìAIûûúIKGran CanariaVC1893WC7067[î0GúHìAIûûùDFislandsGúHìAIûûú]øúSøú\øúISpanien - BevölkerungVD-5481WB166[Ifil8 fnt10GúHìAIûûúIJ1970 - 1990VíFWB157[î~_íHGúHìAIûûúIàErstellt v. Andreas Neumann im Rahmen d. Kartenentwurfspraktikums, Sommersemester 1998,üVD-5483WC7499[îWGúHìAIûûúIägeleitet v. Prof. Ingrid Kretschmer, Institut für Geographie der Universität Wien.üVîWC7583[îWGúHìAIûûúIàVerwendete Software: Arc/Info und Module, CorelDRAW und div. Perl-Scripts.üVîWC7666[îWGúHìAIûûúIBevölkerungsdichteVC3665WB363[Ifil8 fnt11GúHìAIûûúIBevölkerungsveränderungVîWC4063[îGúHìAIûûúIBevölkerung absolutVîWC1815[îGúHìAIûûúIEinwohner/km² auf ProvinzebeneVîWB510[î0GúHìAIûûúIProzentuelle Veränderung derVîWC4210[î0GúHìAIûûúIProvinzen gegenüber Stand 1970VîWC4344[î0GúHìAIûûúIîVîWC5750[î0GúHìAIûûúI Hauptstädte gegenüber Stand 1970VîWC5884[î0GúHìAIûûúIZAuf Provinzebene und in denVîWC1962[î0GúHìAIûûúIHauptstädten (inneres Quadrat)VîWC2096[î0GúHìAIûûù^í=GúHìAIûûú\øúIQSpain - PopulationVî|Wî}[î~GúHìAIûûúIîVíFWî[î~_íHGúHìAIûûúIàCreated by Andreas Neumann for the map design course, summer semester 1998,üVîWî[îWGúHìAIûûúIàled by Prof. Ingrid Kretschmer, Geography Institute of Vienna University.üVîWî[îWGúHìAIûûúIàUsed software: Arc/Info and Modules, CorelDRAW and various Perl scripts.üVîWî[îWGúHìAIûûúIQPopulation densityVîWî[îGúHìAIûûúIPPopulation changeVîWî[îGúHìAIûûúIRPopulation absoluteVîWî[îGúHìAIûûúIInhab. per km² at province levelVîWî[î0GúHìAIûûúIWPercentual change of theVîWî[î0GúHìAIûûúIYprovince vs situation 1970VîWî[î0GúHìAIûûúIîVîWî[î0GúHìAIûûúIYcapitals vs situation 1970VîWî[î0GúHìAIûûúI]At provincial level and in theVîWî[î0GúHìAIûûúIVcapitals (inner square)VîWî[î0GúHìAIûûù^í?GúHìAIûûùGúHìAIûûú\øúIQAngaben in tausendVC4151WC3193[Ifil8 fnt41^í=GúHìAIûûúIWIndications in thousandsVî¥Wî¦[î§^í?GúHìAIûûùGúHìAIûûú\øúIVMassstab 1 : 6.000.000VD-1325WC7682[î§^í=GúHìAIûûúISScale 1 : 6.000.000VîªWî«[î§^í?GúHìAIûûùGúHìAIûûú\øúIjQuelle: Spanisches Statistisches ZentralamtVîWC7280[î§^í=GúHìAIûûúIlSource: Spanish Central Office for StatisticsVîWî®[î§^í?GúHìAIûûùGúHìAIûûú\øúI`Minimum (Provinz): Soria - 97.268VîWC3331[î§^í=GúHìAIûûúIaMinimum (Province): Soria - 97.268VîWî±[î§^í?GúHìAIûûùGúHìAIûûú\øúIdMaximum (Provinz): Madrid - 5.028.120VîWC3432[î§^í=GúHìAIûûúIeMaximum (Province): Madrid - 5.028.120VîWî´[î§^í?GúHìAIûûùGúHìAIûûú\øúIdMinimum (Hauptstadt): Teruel - 28.488VîWC3532[î§^í=GúHìAIûûúIaMinimum (capital): Teruel - 28.488VîWî·[î§^í?GúHìAIûûùGúHìAIûûú\øúIgMaximum (Hauptstadt): Madrid - 3.120.732VîWC3633[î§^í=GúHìAIûûúIdMaximum (capital): Madrid - 3.120.732VîWîº[î§^í?GúHìAIûûùGúHìAIûûú\øúIIStand 1990VC4779WC1362[î§^í=GúHìAIûûúIMSituation 1990Vî½Wî¾[î§^í?GúHìAIûûùGúHìAIûûú\øúIî¼VC5063WC3022[î§^í=GúHìAIûûúIHSit. 1990VîÀWîÁ[î§^í?GúHìAIûûùGúHìAIûûùSøúNøú[Ifil0 str11LaM3665 634l196 0 0 98 -196 0 0 -98zGúHìAIûûú[í[LîÄGúHìAIûûùGúHìAIûûúNøú[Ifil1 str11LaM3665 791l196 0 0 99 -196 0 0 -99zGúHìAIûûú[í[LîÆGúHìAIûûùGúHìAIûûúNøú[Ifil2 str11LaM3665 949l196 0 0 98 -196 0 0 -98zGúHìAIûûú[í[LîÈGúHìAIûûùGúHìAIûûúNøú[Ifil3 str11LbM3665 1106l196 0 0 99 -196 0 0 -99zGúHìAIûûú[í[LîÊGúHìAIûûùGúHìAIûûúNøú[Ifil4 str11LbM3665 1264l196 0 0 98 -196 0 0 -98zGúHìAIûûú[í[LîÌGúHìAIûûùGúHìAIûûúrectú[í[VD-2090WC7529XC2295YA39GúHìAIûûNøú[í[LPM-2090 7568l0 -48GúHìAIûûú[í[LPM-2024 7568l0 -40GúHìAIûûú[í[LPM-1959 7568l0 -40GúHìAIûûú[í[LPM-1893 7568l0 -40GúHìAIûûú[í[LPM-1827 7568l0 -40GúHìAIûûú[í[LPM-1762 7568l0 -48GúHìAIûûú[í[LPM-1434 7568l0 -40GúHìAIûûú[í[LPM-1106 7568l0 -48GúHìAIûûú[í[LOM-778 7568l0 -40GúHìAIûûú[í[LOM-450 7568l0 -48GúHìAIûûú[í[LOM-121 7568l0 -40GúHìAIûûú[í[LNM206 7567l0 -47GúHìAIûûú[í[LPM-1434 7547l328 0GúHìAIûûú[í[LOM-1828 7547l66 0GúHìAIûûú[í[LOM-1959 7547l65 0GúHìAIûûú[í[LOM-2090 7547l65 0GúHìAIûûú[í[LOM-778 7547l328 0GúHìAIûûú[í[LOM-122 7547l328 0GúHìAIûûù\øúIìvVD-1783WC7500[Ifil8 fnt42GúHìAIûûúIìbVD-1167Wîä[îåGúHìAIûûúIB200VC-511Wîä[îåGúHìAIûûúIE300 kmVB146Wîä[îåGúHìAIûûúIì:VD-2131Wîä[îåGúHìAIûûùGúHìAIûûùgøú[í¦VîWC4473XB197Yì\GúHìAIûûú[íOVîWC6014XîíYì\GúHìAIûûú[íeVîWC4631XîíYì\GúHìAIûûú[íYVîWC6172XîíYì\GúHìAIûûú[íOVîWC4788XîíYì\GúHìAIûûú[íwVîWC6329XîíYì\GúHìAIûûú[íQVîWC4946XîíYì\GúHìAIûûú[í¬VîWC6487XîíYì\GúHìAIûûú[íyVîWC5103XîíYì\GúHìAIûûú[íyVîWC6644XîíYì\GúHìAIûûù\øúI@<VC4250WB723[Ifil8 fnt12GúHìAIûûúID 25VC4304Wîù[Ifil8 fnt13GúHìAIûûúIî÷VC4338WC4563[Ifil8 fnt14GúHìAIûûúIF 85 %VC4392Wîÿ[Ifil8 fnt15GúHìAIûûúIî÷VîþWC6104[Ifil8 fnt16GúHìAIûûúIE 115 %VïWï[Ifil8 fnt17GúHìAIûûúIB25 VC4111WB881[ïGúHìAIûûúID 45VîüWï +[ïGúHìAIûûúIî÷VîøWï +[Ifil8 fnt18GúHìAIûûúID85 % VC4086WC4720[Ifil8 fnt19GúHìAIûûúIE 100 %VïWï[ïGúHìAIûûúIî÷VîþWï[Ifil8 fnt20GúHìAIûûúIE115 % VC4030WC6261[Ifil8 fnt21GúHìAIûûúIE 130 %VïWï[ïGúHìAIûûúIî÷VîþWï[Ifil8 fnt22GúHìAIûûúIB45 Vï WC1038[Ifil8 fnt23GúHìAIûûúID 75VîüWï[ïGúHìAIûûúIî÷VîøWï[Ifil8 fnt24GúHìAIûûúIE100 % VïWC4878[Ifil8 fnt25GúHìAIûûúIïVïWï[ï GúHìAIûûúIî÷VîþWï[Ifil8 fnt26GúHìAIûûúIE130 % VïWC6417[Ifil8 fnt27GúHìAIûûúIE 145 %VC4391Wï#[ï$GúHìAIûûúIî÷VC4337Wï#[Ifil8 fnt28GúHìAIûûúIB75 Vï WC1196[Ifil8 fnt29GúHìAIûûúIC 150VîüWï*[ï+GúHìAIûûúIî÷VC4251Wï*[Ifil8 fnt30GúHìAIûûúIïVïWC5035[Ifil8 fnt31GúHìAIûûúIïVïWï/[ï0GúHìAIûûúIî÷VîþWï/[Ifil8 fnt32GúHìAIûûúIE145 % VïWC6576[Ifil8 fnt33GúHìAIûûúIE 160 %VïWï3[ï4GúHìAIûûúIî÷VîþWï3[Ifil8 fnt34GúHìAIûûúIC150 VC4054WC1353[Ifil8 fnt35GúHìAIûûúIî÷VC4249Wï9[Ifil8 fnt36GúHìAIûûúIï"VC4035WC5193[Ifil8 fnt37GúHìAIûûúIî÷VC4343Wï>[Ifil8 fnt38GúHìAIûûúIE160 % Vï=WC6734[Ifil8 fnt39GúHìAIûûúIî÷Vï@WïC[Ifil8 fnt40GúHìAIûûúID5.000VC4712WC2359[î§GúHìAIûûúID1.000VC4709WC2484[î§GúHìAIûûúIB500VC4769WC2608[î§GúHìAIûûúIîçVC4770WC2733[î§GúHìAIûûúIìbVïOWC2857[î§GúHìAIûûúIì:VC4809WC2982[î§GúHìAIûûúIhMin.: Soria - 9,46, Max.: Madrid - 628,91VîWC1543[î§GúHìAIûûúIXMinimum: Soria - 84,61 %,VîWC5400[î§GúHìAIûûúI]Maximum: Las Palmas - 141,24 %VîWC5500[î§GúHìAIûûúIZMinimum: Vizcaya - 93,50 %,VîWC6939[î§GúHìAIûûúI^Maximum: Guadalajara - 199,18 %VîWC7040[î§GúHìAIûûùNøú[Ifil7 str17LdM4451 3032l0 -783 -786 0 0 783 786 0zGúHìAIûûú[ï^LdM4022 3032l0 -357 -357 0 0 357 357 0zGúHìAIûûú[ï^LdM3928 3032l0 -263 -263 0 0 263 263 0zGúHìAIûûú[ï^LdM3851 3032l0 -184 -186 0 0 184 186 0zGúHìAIûûú[ï^LdM3812 3032l0 -143 -147 0 0 143 147 0zGúHìAIûûú[ï^LdM3778 3032l0 -114 -113 0 0 114 113 0zGúHìAIûûú[Ifil7 str18LPM4680 2334l-232 0GúHìAIûûú[ïeLYM4680 2460l-331 0 -327 277GúHìAIûûú[ïeLYM4738 2576l-389 0 -424 263GúHìAIûûú[ïeLYM4738 2706l-389 0 -498 209GúHìAIûûú[ïeLYM4738 2832l-389 0 -536 137GúHìAIûûú[ïeLXM4779 2952l-430 0 -570 51GúHìAIûûùDJtext_legendGúHìAIûûù@xml:spaceGpreserveVA25WïnXB550YE382.36_àshape-rendering:geometricPrecision; text-rendering:auto; image-rendering:optimizeSpeedü@viewBoxQ-5483 0 11053 7684GúHìAIûûiJ0 0 600 420XB600YB420GúHìAIûûû \ No newline at end of file
diff --git a/1.9.10/samples-smile/ns-invoice100.xml.smile b/1.9.10/samples-smile/ns-invoice100.xml.smile new file mode 100644 index 0000000..75a75a4 --- /dev/null +++ b/1.9.10/samples-smile/ns-invoice100.xml.smile
@@ -0,0 +1,4 @@ +:) +úns1:invoiceú HeaderúIssueDateTimeú$X2003-03-13T13:13:32-08:00 @xmlnsúns1qhttp://www.sun.com/schema/spidermarkexpress/sm-invûûIdentifierúCG15570720@schemeAgencyNameBISO@schemeNameFInvoiceDúEûûPOIdentifierúCB691HFGenericGDúEûûBuyerPartyúPartyIDúC@1HPSpiderMarkExpressGCSUNWDúEûûNameúCQIDES Retail INC USDúEûûAddressú StreetúCGHill St.DúEûûHouseIDúCC5555HFHouseIDGDhouseDúEûû RoomIDúCFSuite 3HERoomIDGCroomDúEûûCityNameúCEBostonDúEûûPostalZoneIDúCD01234HFZipcodeGCUSPSDúEûûStateNameúCAMADúEûûCountryIdentificationCodeúCAUS@listAgencyId@listIdC3166DúEûûDúEûûContactúLúCHJoe BuyerDúEûûCommunicationøúValueúCK313-555-1212DúEûûChannelIDúCDphoneH G +DúEûûDúEûûúYúCK313-555-1213DúEûûZúCBfaxH G +DúEûûDúEûûùDúEûûDúEûûSellerPartyúKúCA10HGDúEûûLúCV1YvMdIkxZRXszgQfmoKqkitDúEûûMúNúCBZNkDúEûûOúCC1234HGDúEûûPúCFSte 301HGDúEûûQúCMtzFMMtlE1lxdagDúEûûRúCH992292786HGDúEûûSúCAFLDúEûûTúCASYUVDúEûûDúEûûWúLúCMjjzxxgwwqgwqjfDúEûûXøúYúCijjzxxgwwqgwqjf@1YvMdIkxZRXszgQfmoKqkit.comDúEûûZúCDemailHGDúEûûDúEûûúYúCO9433593740064593DúEûûZúCHGDúEûûDúEûûúYúCM38667976759785DúEûûZúCHGDúEûûDúEûûùDúEûûDúEûûShipmentúShipDateúCDúEûûTransportModeIDúCBseaGHLTransportModeDúEûûCarrierIDúCBUPSGHFCarrierDúEûûDúEûûPaymentMeansúPaymentDateúCI2003-04-13DúEûûPayeeFinancialAccountúFúCH312098283GHFAccountDúEûûFinancialInstitutionúFúCG33747420GAUNHTFinancial InstitutionDúEûûLúCDCaacoDúEûûMúNúCNH9LHLljO StreetDúEûûOúCA15HGDúEûûQúCGYigmnviiDúEûûRúCD48839HGDúEûûSúCACTDúEûûTúCUVDúEûûDúEûûDúEûû TypeIDúCEvozbixGHKAccount TypeDúEûûAccountNameúCGAdrvgrriDúEûûDúEûûDúEûûDúEûûLineItemøú LineIDúC@0HGDúEûûItemúStandardItemIdentifierúCA20HFGenericGDúEûûDescriptionúClvZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7tDúEûûQuantityúCA10@unitCodeEnumberDúEûûDúEûûOrderStatusúCHFULFILLEDVJOrderStatusUBSunDúEûûPricingúGrossUnitPriceAmountúCE437.00@currencyIdBUSDDúEûûNetUnitPriceAmountúCE367.08pìIDúEûûDúEûûPricingVariationúServiceIDúCGdiscountHìAGDúEûûConditionIDúCHallowanceHìAGDúEûûRateúCD16.00DúEûûDúEûûTotalAmountúCF3670.80pìIDúEûûDúEûûúgúC@1HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúC@2HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúC@3HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúC@4HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúC@5HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúC@6HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúC@7HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúC@8HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúC@9HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCìCHìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA11HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA12HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA13HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA14HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCì8HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA16HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA17HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA18HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA19HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCì@HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA21HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA22HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA23HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA24HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA25HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA26HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA27HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA28HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA29HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA30HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA31HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA32HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA33HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA34HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA35HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA36HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA37HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA38HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA39HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA40HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA41HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA42HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA43HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA44HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA45HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA46HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA47HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA48HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA49HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA50HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA51HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA52HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA53HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA54HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA55HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA56HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA57HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA58HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA59HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA60HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA61HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA62HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA63HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA64HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA65HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA66HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA67HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA68HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA69HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA70HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA71HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA72HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA73HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA74HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA75HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA76HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA77HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA78HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA79HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA80HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA81HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA82HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA83HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA84HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA85HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA86HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA87HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA88HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA89HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA90HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA91HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA92HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA93HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA94HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA95HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA96HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA97HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA98HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûúgúCA99HìAGDúEûûhúiúCì@HìAGDúEûûjúCìBDúEûûkúCìClìDDúEûûDúEûûmúCìEVìFUìGDúEûûnúoúCìHpìIDúEûûqúCìJpìIDúEûûDúEûûrúsúCìKHìAGDúEûûtúCìLHìAGDúEûûuúCìMDúEûûDúEûûvúCìNpìIDúEûûDúEûûùSummaryúLineItemCountValueúCìPDúEûûSubtotalAmountúCG18215.80pìIDúEûûrúsúCTshipping and handlingHIVariationsGDúEûûtúCEchargeHIConditionsGDúEûûLumpSumAmountúCC7.00pìIDúEûûDúEûûPriceAmountúCG18222.80pìIDúEûûPackingSlipIdentifierúCE156263GHKPacking SlipDúEûûDúEûûDúEûûû \ No newline at end of file
diff --git a/1.9.10/samples-smile/ns-soap.xml.smile b/1.9.10/samples-smile/ns-soap.xml.smile new file mode 100644 index 0000000..9e348ac --- /dev/null +++ b/1.9.10/samples-smile/ns-soap.xml.smile Binary files differ
diff --git a/1.9.10/samples-smile/numbers-fp-4k.smile b/1.9.10/samples-smile/numbers-fp-4k.smile new file mode 100644 index 0000000..a2afc2d --- /dev/null +++ b/1.9.10/samples-smile/numbers-fp-4k.smile Binary files differ
diff --git a/1.9.10/samples-smile/numbers-fp-64k.smile b/1.9.10/samples-smile/numbers-fp-64k.smile new file mode 100644 index 0000000..f99929e --- /dev/null +++ b/1.9.10/samples-smile/numbers-fp-64k.smile Binary files differ
diff --git a/1.9.10/samples-smile/numbers-int-4k.smile b/1.9.10/samples-smile/numbers-int-4k.smile new file mode 100644 index 0000000..540d68c --- /dev/null +++ b/1.9.10/samples-smile/numbers-int-4k.smile Binary files differ
diff --git a/1.9.10/samples-smile/numbers-int-64k.smile b/1.9.10/samples-smile/numbers-int-64k.smile new file mode 100644 index 0000000..cab77a8 --- /dev/null +++ b/1.9.10/samples-smile/numbers-int-64k.smile Binary files differ
diff --git a/1.9.10/samples-smile/test1.smile b/1.9.10/samples-smile/test1.smile new file mode 100644 index 0000000..c70f47c --- /dev/null +++ b/1.9.10/samples-smile/test1.smile
@@ -0,0 +1,4 @@ +:) +útest key#nullField!fooÂfoo2úaÆûÂaãb$ + 2øÂÄÆù"foo"Ffoo +barû \ No newline at end of file
diff --git a/1.9.10/samples-smile/test2.smile b/1.9.10/samples-smile/test2.smile new file mode 100644 index 0000000..f44dcb4 --- /dev/null +++ b/1.9.10/samples-smile/test2.smile
@@ -0,0 +1,2 @@ +:) +ú"abKey"Æfoo"û \ No newline at end of file
diff --git a/1.9.10/samples/db100.xml.jsn b/1.9.10/samples/db100.xml.jsn new file mode 100644 index 0000000..36231e7 --- /dev/null +++ b/1.9.10/samples/db100.xml.jsn
@@ -0,0 +1 @@ +{"table":{"row":[{"id":{"$":"0000"},"firstname":{"$":"Al"},"lastname":{"$":"Aranow"},"street":{"$":"1 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0001"},"firstname":{"$":"Bob"},"lastname":{"$":"Aranow"},"street":{"$":"2 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0002"},"firstname":{"$":"Charles"},"lastname":{"$":"Aranow"},"street":{"$":"3 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0003"},"firstname":{"$":"David"},"lastname":{"$":"Aranow"},"street":{"$":"4 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0004"},"firstname":{"$":"Egon"},"lastname":{"$":"Aranow"},"street":{"$":"5 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0005"},"firstname":{"$":"Farbood"},"lastname":{"$":"Aranow"},"street":{"$":"6 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0006"},"firstname":{"$":"George"},"lastname":{"$":"Aranow"},"street":{"$":"7 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0007"},"firstname":{"$":"Hank"},"lastname":{"$":"Aranow"},"street":{"$":"8 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0008"},"firstname":{"$":"Inki"},"lastname":{"$":"Aranow"},"street":{"$":"9 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0009"},"firstname":{"$":"James"},"lastname":{"$":"Aranow"},"street":{"$":"10 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0010"},"firstname":{"$":"Al"},"lastname":{"$":"Barker"},"street":{"$":"11 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0011"},"firstname":{"$":"Bob"},"lastname":{"$":"Barker"},"street":{"$":"12 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0012"},"firstname":{"$":"Charles"},"lastname":{"$":"Barker"},"street":{"$":"13 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0013"},"firstname":{"$":"David"},"lastname":{"$":"Barker"},"street":{"$":"14 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0014"},"firstname":{"$":"Egon"},"lastname":{"$":"Barker"},"street":{"$":"15 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0015"},"firstname":{"$":"Farbood"},"lastname":{"$":"Barker"},"street":{"$":"16 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0016"},"firstname":{"$":"George"},"lastname":{"$":"Barker"},"street":{"$":"17 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0017"},"firstname":{"$":"Hank"},"lastname":{"$":"Barker"},"street":{"$":"18 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0018"},"firstname":{"$":"Inki"},"lastname":{"$":"Barker"},"street":{"$":"19 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0019"},"firstname":{"$":"James"},"lastname":{"$":"Barker"},"street":{"$":"20 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0020"},"firstname":{"$":"Al"},"lastname":{"$":"Corsetti"},"street":{"$":"21 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0021"},"firstname":{"$":"Bob"},"lastname":{"$":"Corsetti"},"street":{"$":"22 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0022"},"firstname":{"$":"Charles"},"lastname":{"$":"Corsetti"},"street":{"$":"23 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0023"},"firstname":{"$":"David"},"lastname":{"$":"Corsetti"},"street":{"$":"24 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0024"},"firstname":{"$":"Egon"},"lastname":{"$":"Corsetti"},"street":{"$":"25 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0025"},"firstname":{"$":"Farbood"},"lastname":{"$":"Corsetti"},"street":{"$":"26 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0026"},"firstname":{"$":"George"},"lastname":{"$":"Corsetti"},"street":{"$":"27 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0027"},"firstname":{"$":"Hank"},"lastname":{"$":"Corsetti"},"street":{"$":"28 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0028"},"firstname":{"$":"Inki"},"lastname":{"$":"Corsetti"},"street":{"$":"29 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0029"},"firstname":{"$":"James"},"lastname":{"$":"Corsetti"},"street":{"$":"30 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0030"},"firstname":{"$":"Al"},"lastname":{"$":"Dershowitz"},"street":{"$":"31 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0031"},"firstname":{"$":"Bob"},"lastname":{"$":"Dershowitz"},"street":{"$":"32 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0032"},"firstname":{"$":"Charles"},"lastname":{"$":"Dershowitz"},"street":{"$":"33 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0033"},"firstname":{"$":"David"},"lastname":{"$":"Dershowitz"},"street":{"$":"34 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0034"},"firstname":{"$":"Egon"},"lastname":{"$":"Dershowitz"},"street":{"$":"35 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0035"},"firstname":{"$":"Farbood"},"lastname":{"$":"Dershowitz"},"street":{"$":"36 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0036"},"firstname":{"$":"George"},"lastname":{"$":"Dershowitz"},"street":{"$":"37 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0037"},"firstname":{"$":"Hank"},"lastname":{"$":"Dershowitz"},"street":{"$":"38 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0038"},"firstname":{"$":"Inki"},"lastname":{"$":"Dershowitz"},"street":{"$":"39 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0039"},"firstname":{"$":"James"},"lastname":{"$":"Dershowitz"},"street":{"$":"40 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0040"},"firstname":{"$":"Al"},"lastname":{"$":"Engleman"},"street":{"$":"41 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0041"},"firstname":{"$":"Bob"},"lastname":{"$":"Engleman"},"street":{"$":"42 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0042"},"firstname":{"$":"Charles"},"lastname":{"$":"Engleman"},"street":{"$":"43 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0043"},"firstname":{"$":"David"},"lastname":{"$":"Engleman"},"street":{"$":"44 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0044"},"firstname":{"$":"Egon"},"lastname":{"$":"Engleman"},"street":{"$":"45 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0045"},"firstname":{"$":"Farbood"},"lastname":{"$":"Engleman"},"street":{"$":"46 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0046"},"firstname":{"$":"George"},"lastname":{"$":"Engleman"},"street":{"$":"47 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0047"},"firstname":{"$":"Hank"},"lastname":{"$":"Engleman"},"street":{"$":"48 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0048"},"firstname":{"$":"Inki"},"lastname":{"$":"Engleman"},"street":{"$":"49 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0049"},"firstname":{"$":"James"},"lastname":{"$":"Engleman"},"street":{"$":"50 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0050"},"firstname":{"$":"Al"},"lastname":{"$":"Franklin"},"street":{"$":"51 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0051"},"firstname":{"$":"Bob"},"lastname":{"$":"Franklin"},"street":{"$":"52 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0052"},"firstname":{"$":"Charles"},"lastname":{"$":"Franklin"},"street":{"$":"53 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0053"},"firstname":{"$":"David"},"lastname":{"$":"Franklin"},"street":{"$":"54 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0054"},"firstname":{"$":"Egon"},"lastname":{"$":"Franklin"},"street":{"$":"55 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0055"},"firstname":{"$":"Farbood"},"lastname":{"$":"Franklin"},"street":{"$":"56 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0056"},"firstname":{"$":"George"},"lastname":{"$":"Franklin"},"street":{"$":"57 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0057"},"firstname":{"$":"Hank"},"lastname":{"$":"Franklin"},"street":{"$":"58 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0058"},"firstname":{"$":"Inki"},"lastname":{"$":"Franklin"},"street":{"$":"59 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0059"},"firstname":{"$":"James"},"lastname":{"$":"Franklin"},"street":{"$":"60 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0060"},"firstname":{"$":"Al"},"lastname":{"$":"Grice"},"street":{"$":"61 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0061"},"firstname":{"$":"Bob"},"lastname":{"$":"Grice"},"street":{"$":"62 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0062"},"firstname":{"$":"Charles"},"lastname":{"$":"Grice"},"street":{"$":"63 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0063"},"firstname":{"$":"David"},"lastname":{"$":"Grice"},"street":{"$":"64 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0064"},"firstname":{"$":"Egon"},"lastname":{"$":"Grice"},"street":{"$":"65 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0065"},"firstname":{"$":"Farbood"},"lastname":{"$":"Grice"},"street":{"$":"66 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0066"},"firstname":{"$":"George"},"lastname":{"$":"Grice"},"street":{"$":"67 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0067"},"firstname":{"$":"Hank"},"lastname":{"$":"Grice"},"street":{"$":"68 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0068"},"firstname":{"$":"Inki"},"lastname":{"$":"Grice"},"street":{"$":"69 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0069"},"firstname":{"$":"James"},"lastname":{"$":"Grice"},"street":{"$":"70 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0070"},"firstname":{"$":"Al"},"lastname":{"$":"Haverford"},"street":{"$":"71 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0071"},"firstname":{"$":"Bob"},"lastname":{"$":"Haverford"},"street":{"$":"72 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0072"},"firstname":{"$":"Charles"},"lastname":{"$":"Haverford"},"street":{"$":"73 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0073"},"firstname":{"$":"David"},"lastname":{"$":"Haverford"},"street":{"$":"74 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0074"},"firstname":{"$":"Egon"},"lastname":{"$":"Haverford"},"street":{"$":"75 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0075"},"firstname":{"$":"Farbood"},"lastname":{"$":"Haverford"},"street":{"$":"76 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0076"},"firstname":{"$":"George"},"lastname":{"$":"Haverford"},"street":{"$":"77 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0077"},"firstname":{"$":"Hank"},"lastname":{"$":"Haverford"},"street":{"$":"78 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0078"},"firstname":{"$":"Inki"},"lastname":{"$":"Haverford"},"street":{"$":"79 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0079"},"firstname":{"$":"James"},"lastname":{"$":"Haverford"},"street":{"$":"80 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0080"},"firstname":{"$":"Al"},"lastname":{"$":"Ilvedson"},"street":{"$":"81 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0081"},"firstname":{"$":"Bob"},"lastname":{"$":"Ilvedson"},"street":{"$":"82 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0082"},"firstname":{"$":"Charles"},"lastname":{"$":"Ilvedson"},"street":{"$":"83 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0083"},"firstname":{"$":"David"},"lastname":{"$":"Ilvedson"},"street":{"$":"84 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0084"},"firstname":{"$":"Egon"},"lastname":{"$":"Ilvedson"},"street":{"$":"85 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0085"},"firstname":{"$":"Farbood"},"lastname":{"$":"Ilvedson"},"street":{"$":"86 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0086"},"firstname":{"$":"George"},"lastname":{"$":"Ilvedson"},"street":{"$":"87 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0087"},"firstname":{"$":"Hank"},"lastname":{"$":"Ilvedson"},"street":{"$":"88 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0088"},"firstname":{"$":"Inki"},"lastname":{"$":"Ilvedson"},"street":{"$":"89 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0089"},"firstname":{"$":"James"},"lastname":{"$":"Ilvedson"},"street":{"$":"90 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0090"},"firstname":{"$":"Al"},"lastname":{"$":"Jones"},"street":{"$":"91 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0091"},"firstname":{"$":"Bob"},"lastname":{"$":"Jones"},"street":{"$":"92 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0092"},"firstname":{"$":"Charles"},"lastname":{"$":"Jones"},"street":{"$":"93 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0093"},"firstname":{"$":"David"},"lastname":{"$":"Jones"},"street":{"$":"94 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0094"},"firstname":{"$":"Egon"},"lastname":{"$":"Jones"},"street":{"$":"95 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0095"},"firstname":{"$":"Farbood"},"lastname":{"$":"Jones"},"street":{"$":"96 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0096"},"firstname":{"$":"George"},"lastname":{"$":"Jones"},"street":{"$":"97 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0097"},"firstname":{"$":"Hank"},"lastname":{"$":"Jones"},"street":{"$":"98 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0098"},"firstname":{"$":"Inki"},"lastname":{"$":"Jones"},"street":{"$":"99 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}},{"id":{"$":"0099"},"firstname":{"$":"James"},"lastname":{"$":"Jones"},"street":{"$":"100 Any St."},"city":{"$":"Anytown"},"state":{"$":"AL"},"zip":{"$":"22000"}}]}}
diff --git a/1.9.10/samples/json-org-sample1-nows.jsn b/1.9.10/samples/json-org-sample1-nows.jsn new file mode 100644 index 0000000..0a109b9 --- /dev/null +++ b/1.9.10/samples/json-org-sample1-nows.jsn
@@ -0,0 +1,7 @@ +{"glossary": {"title": "example glossary", +"GlossDiv": {"title": "S", +"GlossList": {"GlossEntry": {"ID": "SGML","SortAs": "SGML", +"GlossTerm":"Standard Generalized Markup Language","Acronym":"SGML","Abbrev":"ISO 8879:1986", +"GlossDef":{"para": "A meta-markup language, used to create markup languages such as DocBook.","GlossSeeAlso": ["GML", "XML"]},"GlossSee": "markup" +}}}}} +
diff --git a/1.9.10/samples/json-org-sample1.jsn b/1.9.10/samples/json-org-sample1.jsn new file mode 100644 index 0000000..dd01f7d --- /dev/null +++ b/1.9.10/samples/json-org-sample1.jsn
@@ -0,0 +1,23 @@ +{ + "glossary": { + "title": "example glossary", + "GlossDiv": { + "title": "S", + "GlossList": { + "GlossEntry": { + "ID": "SGML", + "SortAs": "SGML", + "GlossTerm": "Standard Generalized Markup Language", + "Acronym": "SGML", + "Abbrev": "ISO 8879:1986", + "GlossDef": { + "para": "A meta-markup language, used to create markup languages such as DocBook.", + "GlossSeeAlso": ["GML", "XML"] + }, + "GlossSee": "markup" + } + } + } + } +} +
diff --git a/1.9.10/samples/json-org-sample2.jsn b/1.9.10/samples/json-org-sample2.jsn new file mode 100644 index 0000000..5600991 --- /dev/null +++ b/1.9.10/samples/json-org-sample2.jsn
@@ -0,0 +1,11 @@ +{"menu": { + "id": "file", + "value": "File", + "popup": { + "menuitem": [ + {"value": "New", "onclick": "CreateNewDoc()"}, + {"value": "Open", "onclick": "OpenDoc()"}, + {"value": "Close", "onclick": "CloseDoc()"} + ] + } +}}
diff --git a/1.9.10/samples/json-org-sample3.jsn b/1.9.10/samples/json-org-sample3.jsn new file mode 100644 index 0000000..64832a6 --- /dev/null +++ b/1.9.10/samples/json-org-sample3.jsn
@@ -0,0 +1,26 @@ +{"widget": { + "debug": "on", + "window": { + "title": "Sample Konfabulator Widget", + "name": "main_window", + "width": 500, + "height": 500 + }, + "image": { + "src": "Images/Sun.png", + "name": "sun1", + "hOffset": 250, + "vOffset": 250, + "alignment": "center" + }, + "text": { + "data": "Click Here", + "size": 36, + "style": "bold", + "name": "text1", + "hOffset": 250, + "vOffset": 100, + "alignment": "center", + "onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;" + } +}}
diff --git a/1.9.10/samples/json-org-sample4-nows.jsn b/1.9.10/samples/json-org-sample4-nows.jsn new file mode 100644 index 0000000..3392be9 --- /dev/null +++ b/1.9.10/samples/json-org-sample4-nows.jsn
@@ -0,0 +1,88 @@ +{"web-app":{ +"servlet":[ +{ +"servlet-name": "cofaxCDS", +"servlet-class": "org.cofax.cds.CDSServlet", +"init-param": { +"configGlossary:installationAt": "Philadelphia, PA", +"configGlossary:adminEmail": "ksm@pobox.com", +"configGlossary:poweredBy": "Cofax", +"configGlossary:poweredByIcon": "/images/cofax.gif", +"configGlossary:staticPath": "/content/static", +"templateProcessorClass": "org.cofax.WysiwygTemplate", +"templateLoaderClass": "org.cofax.FilesTemplateLoader", +"templatePath": "templates", +"templateOverridePath": "", +"defaultListTemplate": "listTemplate.htm", +"defaultFileTemplate": "articleTemplate.htm", +"useJSP": false, +"jspListTemplate": "listTemplate.jsp", +"jspFileTemplate": "articleTemplate.jsp", +"cachePackageTagsTrack": 200, +"cachePackageTagsStore": 200, +"cachePackageTagsRefresh": 60, +"cacheTemplatesTrack": 100, +"cacheTemplatesStore": 50, +"cacheTemplatesRefresh": 15, +"cachePagesTrack": 200, +"cachePagesStore": 100, +"cachePagesRefresh": 10, +"cachePagesDirtyRead": 10, +"searchEngineListTemplate": "forSearchEnginesList.htm", +"searchEngineFileTemplate": "forSearchEngines.htm", +"searchEngineRobotsDb": "WEB-INF/robots.db", +"useDataStore": true, +"dataStoreClass": "org.cofax.SqlDataStore", +"redirectionClass": "org.cofax.SqlRedirection", +"dataStoreName": "cofax", +"dataStoreDriver": "com.microsoft.jdbc.sqlserver.SQLServerDriver", +"dataStoreUrl": "jdbc:microsoft:sqlserver://LOCALHOST:1433;DatabaseName=goon", +"dataStoreUser": "sa", +"dataStorePassword": "dataStoreTestQuery", +"dataStoreTestQuery": "SET NOCOUNT ON;select test='test';", +"dataStoreLogFile": "/usr/local/tomcat/logs/datastore.log", +"dataStoreInitConns": 10, +"dataStoreMaxConns": 100, +"dataStoreConnUsageLimit": 100, +"dataStoreLogLevel": "debug", +"maxUrlLength": 500}}, +{ +"servlet-name": "cofaxEmail", +"servlet-class": "org.cofax.cds.EmailServlet", +"init-param": { +"mailHost": "mail1", +"mailHostOverride": "mail2"}}, +{ +"servlet-name": "cofaxAdmin", +"servlet-class": "org.cofax.cds.AdminServlet"}, + +{ +"servlet-name": "fileServlet", +"servlet-class": "org.cofax.cds.FileServlet"}, +{ +"servlet-name": "cofaxTools", +"servlet-class": "org.cofax.cms.CofaxToolsServlet", +"init-param": { +"templatePath": "toolstemplates/", +"log": 1, +"logLocation": "/usr/local/tomcat/logs/CofaxTools.log", +"logMaxSize": "", +"dataLog": 1, +"dataLogLocation": "/usr/local/tomcat/logs/dataLog.log", +"dataLogMaxSize": "", +"removePageCache": "/content/admin/remove?cache=pages&id=", +"removeTemplateCache": "/content/admin/remove?cache=templates&id=", +"fileTransferFolder": "/usr/local/tomcat/webapps/content/fileTransferFolder", +"lookInContext": 1, +"adminGroupID": 4, +"betaServer": true}}], +"servlet-mapping": { +"cofaxCDS": "/", +"cofaxEmail": "/cofaxutil/aemail/*", +"cofaxAdmin": "/admin/*", +"fileServlet": "/static/*", +"cofaxTools": "/tools/*"}, +"taglib": { +"taglib-uri": "cofax.tld", +"taglib-location": "/WEB-INF/tlds/cofax.tld"} +}}
diff --git a/1.9.10/samples/json-org-sample4.jsn b/1.9.10/samples/json-org-sample4.jsn new file mode 100644 index 0000000..d5a8b35 --- /dev/null +++ b/1.9.10/samples/json-org-sample4.jsn
@@ -0,0 +1,89 @@ +{"web-app": { + "servlet": [ + { + "servlet-name": "cofaxCDS", + "servlet-class": "org.cofax.cds.CDSServlet", + "init-param": { + "configGlossary:installationAt": "Philadelphia, PA", + "configGlossary:adminEmail": "ksm@pobox.com", + "configGlossary:poweredBy": "Cofax", + "configGlossary:poweredByIcon": "/images/cofax.gif", + "configGlossary:staticPath": "/content/static", + "templateProcessorClass": "org.cofax.WysiwygTemplate", + "templateLoaderClass": "org.cofax.FilesTemplateLoader", + "templatePath": "templates", + "templateOverridePath": "", + "defaultListTemplate": "listTemplate.htm", + "defaultFileTemplate": "articleTemplate.htm", + "useJSP": false, + "jspListTemplate": "listTemplate.jsp", + "jspFileTemplate": "articleTemplate.jsp", + "cachePackageTagsTrack": 200, + "cachePackageTagsStore": 200, + "cachePackageTagsRefresh": 60, + "cacheTemplatesTrack": 100, + "cacheTemplatesStore": 50, + "cacheTemplatesRefresh": 15, + "cachePagesTrack": 200, + "cachePagesStore": 100, + "cachePagesRefresh": 10, + "cachePagesDirtyRead": 10, + "searchEngineListTemplate": "forSearchEnginesList.htm", + "searchEngineFileTemplate": "forSearchEngines.htm", + "searchEngineRobotsDb": "WEB-INF/robots.db", + "useDataStore": true, + "dataStoreClass": "org.cofax.SqlDataStore", + "redirectionClass": "org.cofax.SqlRedirection", + "dataStoreName": "cofax", + "dataStoreDriver": "com.microsoft.jdbc.sqlserver.SQLServerDriver", + "dataStoreUrl": "jdbc:microsoft:sqlserver://LOCALHOST:1433;DatabaseName=goon", + "dataStoreUser": "sa", + "dataStorePassword": "dataStoreTestQuery", + "dataStoreTestQuery": "SET NOCOUNT ON;select test='test';", + "dataStoreLogFile": "/usr/local/tomcat/logs/datastore.log", + "dataStoreInitConns": 10, + "dataStoreMaxConns": 100, + "dataStoreConnUsageLimit": 100, + "dataStoreLogLevel": "debug", + "maxUrlLength": 500}}, + { + "servlet-name": "cofaxEmail", + "servlet-class": "org.cofax.cds.EmailServlet", + "init-param": { + "mailHost": "mail1", + "mailHostOverride": "mail2"}}, + { + "servlet-name": "cofaxAdmin", + "servlet-class": "org.cofax.cds.AdminServlet"}, + + { + "servlet-name": "fileServlet", + "servlet-class": "org.cofax.cds.FileServlet"}, + { + "servlet-name": "cofaxTools", + "servlet-class": "org.cofax.cms.CofaxToolsServlet", + "init-param": { + "templatePath": "toolstemplates/", + "log": 1, + "logLocation": "/usr/local/tomcat/logs/CofaxTools.log", + "logMaxSize": "", + "dataLog": 1, + "dataLogLocation": "/usr/local/tomcat/logs/dataLog.log", + "dataLogMaxSize": "", + "removePageCache": "/content/admin/remove?cache=pages&id=", + "removeTemplateCache": "/content/admin/remove?cache=templates&id=", + "fileTransferFolder": "/usr/local/tomcat/webapps/content/fileTransferFolder", + "lookInContext": 1, + "adminGroupID": 4, + "betaServer": true}}], + "servlet-mapping": { + "cofaxCDS": "/", + "cofaxEmail": "/cofaxutil/aemail/*", + "cofaxAdmin": "/admin/*", + "fileServlet": "/static/*", + "cofaxTools": "/tools/*"}, + + "taglib": { + "taglib-uri": "cofax.tld", + "taglib-location": "/WEB-INF/tlds/cofax.tld"} +}}
diff --git a/1.9.10/samples/json-org-sample5-nows.jsn b/1.9.10/samples/json-org-sample5-nows.jsn new file mode 100644 index 0000000..a235a86 --- /dev/null +++ b/1.9.10/samples/json-org-sample5-nows.jsn
@@ -0,0 +1,27 @@ +{"menu": { +"header": "SVG Viewer", +"items": [ +{"id": "Open"}, +{"id": "OpenNew", "label": "Open New"}, +null, +{"id": "ZoomIn", "label": "Zoom In"}, +{"id": "ZoomOut", "label": "Zoom Out"}, +{"id": "OriginalView", "label": "Original View"}, +null, +{"id": "Quality"}, +{"id": "Pause"}, +{"id": "Mute"}, +null, +{"id": "Find", "label": "Find..."}, +{"id": "FindAgain", "label": "Find Again"}, +{"id": "Copy"}, +{"id": "CopyAgain", "label": "Copy Again"}, +{"id": "CopySVG", "label": "Copy SVG"}, +{"id": "ViewSVG", "label": "View SVG"}, +{"id": "ViewSource", "label": "View Source"}, +{"id": "SaveAs", "label": "Save As"}, +null, +{"id": "Help"}, +{"id": "About", "label": "About Adobe CVG Viewer..."} +] +}}
diff --git a/1.9.10/samples/json-org-sample5.jsn b/1.9.10/samples/json-org-sample5.jsn new file mode 100644 index 0000000..49980ca --- /dev/null +++ b/1.9.10/samples/json-org-sample5.jsn
@@ -0,0 +1,27 @@ +{"menu": { + "header": "SVG Viewer", + "items": [ + {"id": "Open"}, + {"id": "OpenNew", "label": "Open New"}, + null, + {"id": "ZoomIn", "label": "Zoom In"}, + {"id": "ZoomOut", "label": "Zoom Out"}, + {"id": "OriginalView", "label": "Original View"}, + null, + {"id": "Quality"}, + {"id": "Pause"}, + {"id": "Mute"}, + null, + {"id": "Find", "label": "Find..."}, + {"id": "FindAgain", "label": "Find Again"}, + {"id": "Copy"}, + {"id": "CopyAgain", "label": "Copy Again"}, + {"id": "CopySVG", "label": "Copy SVG"}, + {"id": "ViewSVG", "label": "View SVG"}, + {"id": "ViewSource", "label": "View Source"}, + {"id": "SaveAs", "label": "Save As"}, + null, + {"id": "Help"}, + {"id": "About", "label": "About Adobe CVG Viewer..."} + ] +}}
diff --git a/1.9.10/samples/jvm-ser1.json b/1.9.10/samples/jvm-ser1.json new file mode 100644 index 0000000..d97d4c0 --- /dev/null +++ b/1.9.10/samples/jvm-ser1.json
@@ -0,0 +1 @@ +{"content":{"size":256000000,"format":"mpeg","player":"FLASH","uri":"http://www.cowtowncoder.com","title":"CowTown Blog Rulez Ok","width":640,"height":480,"duration":360000,"bitrate":320,"persons":["Cowtowncoder","Billy-bob"],"copyright":"GPL"},"images":[{"size":"SMALL","uri":"http://images.r.us/foobar.jpeg","title":"Fabulous FUBAR incident","width":320,"height":256},{"size":"LARGE","uri":"http://images.r.us/total-cluster.jpeg","title":"More of the same -- add keywords for SEO","width":640,"height":480},{"size":"SMALL","uri":"http://images.r.us/barf.png","title":"One more angle, gotta see this","width":320,"height":256}]} \ No newline at end of file
diff --git a/1.9.10/samples/map-spain.xml.jsn b/1.9.10/samples/map-spain.xml.jsn new file mode 100644 index 0000000..faa1281 --- /dev/null +++ b/1.9.10/samples/map-spain.xml.jsn
@@ -0,0 +1 @@ +{"svg":{"svg":{"defs":{"font":[{"font-face":{"@id":"Symbol","@font-variant":"normal","@font-weight":"400","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"missing-glyph":{"@horiz-adv-x":"500","@d":"M63 0V800H438V0H63ZM125 63H375V738H125V63Z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"glyph":{"path":{"@d":"M51 3688l0 5 -40 20 40 19 0 5 -48 -23 0 -3 48 -23zm-48 55l48 0 0 5 -48 0 0 -5z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"163","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@id":"FontID5","@horiz-adv-x":"1000","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"font-face":{"@id":"Humnst777_Lt_BT","@font-variant":"normal","@font-style":"italic","@font-weight":"400","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"missing-glyph":{"@horiz-adv-x":"500","@d":"M63 0V800H438V0H63ZM125 63H375V738H125V63Z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"glyph":[{"path":{"@d":"M5 3698l41 0 -2 9 -41 0 2 -9z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"45","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M15 3632l54 0 0 10 -43 -1 0 42 41 0 0 10 -41 0 0 55 -11 0 0 -116z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"70","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M15 3632l17 0 39 95c0,2 1,3 1,5 1,2 1,4 1,6 1,-2 1,-4 1,-5 1,-2 1,-3 2,-5l41 -96 16 0 0 116 -10 0 0 -98c0,0 -1,0 -1,-1 0,-1 0,-1 0,-2 0,-1 0,-2 1,-3 0,-1 0,-2 0,-4 -1,3 -2,6 -3,8 0,1 0,1 0,1l-42 99 -10 0 -41 -99c0,-1 -1,-3 -2,-6 0,-1 0,-2 0,-3 0,2 0,4 0,7 0,2 0,3 0,3l0 98 -10 0 0 -116z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"77","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M101 3677c0,-12 -3,-21 -9,-28 -6,-6 -14,-10 -24,-10 -6,0 -12,2 -18,5 -6,2 -11,7 -15,12 -5,6 -9,13 -11,21 -3,8 -5,17 -5,25 0,12 3,21 9,28 6,7 14,10 24,10 7,0 13,-1 19,-4 6,-3 11,-8 16,-15 4,-5 8,-12 10,-20 3,-8 4,-16 4,-24zm-32 -47c13,0 24,4 32,13 8,8 11,19 11,33 0,8 -1,16 -3,24 -2,8 -5,15 -9,21 -6,9 -13,17 -21,22 -8,5 -17,7 -27,7 -14,0 -24,-4 -32,-13 -8,-9 -12,-20 -12,-35 0,-10 2,-20 5,-30 4,-10 10,-18 16,-25 5,-5 11,-9 18,-12 7,-3 14,-5 22,-5z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"79","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M68 3642l-39 65 50 0 -11 -65zm-4 -10l12 0 23 116 -11 0 -7 -31 -58 0 -19 31 -12 0 72 -116z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"65","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M26 3642l0 47 12 0c9,0 16,-2 21,-7 6,-4 8,-10 8,-17 0,-7 -2,-13 -7,-17 -5,-4 -11,-6 -19,-6l-15 0zm-11 -10l25 0c12,0 22,3 29,9 6,5 10,13 10,24 0,10 -4,19 -11,25 -7,5 -17,8 -30,8l-12 0 0 50 -11 0 0 -116z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"80","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M44 3672c-8,0 -13,3 -18,9 -4,6 -6,14 -6,24 0,11 2,19 6,25 5,6 11,9 18,9 8,0 14,-3 18,-9 5,-6 7,-14 7,-24 0,-11 -2,-19 -7,-25 -4,-6 -10,-9 -18,-9zm26 9l0 -16 10 0 0 74c0,15 -3,27 -10,34 -6,8 -15,12 -28,12 -4,0 -9,-1 -14,-2 -4,0 -8,-2 -12,-3l1 -11c4,2 8,4 12,5 4,1 9,1 13,1 9,0 16,-3 21,-9 5,-6 7,-14 7,-25l0 -11c-3,6 -7,11 -12,14 -4,3 -10,4 -16,4 -10,0 -18,-4 -24,-11 -6,-8 -9,-18 -9,-31 0,-13 3,-24 9,-31 6,-8 14,-12 25,-12 6,0 11,2 16,5 5,3 9,7 11,13z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"103","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M15 3624l10 0 0 73 37 -32 13 0 -40 35 45 48 -14 0 -41 -44 0 44 -10 0 0 -124z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"107","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M46 3672c-8,0 -14,3 -19,9 -5,7 -8,15 -8,25 0,11 3,19 8,25 5,7 11,10 19,10 9,0 15,-3 20,-10 5,-6 8,-14 8,-25 0,-10 -3,-18 -8,-25 -4,-6 -11,-9 -20,-9zm0 -9c12,0 22,4 29,12 6,8 10,18 10,31 0,14 -4,24 -10,32 -7,8 -17,12 -29,12 -11,0 -21,-4 -28,-12 -7,-8 -10,-18 -10,-31 0,-14 3,-24 10,-32 7,-8 17,-12 28,-12z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"111","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M67 3698c0,-8 -2,-14 -6,-18 -4,-5 -9,-8 -16,-8 -3,1 -6,1 -9,2 -3,2 -6,4 -8,6 -4,4 -7,10 -10,16 -2,7 -4,14 -4,21 0,7 2,13 6,18 4,4 9,6 15,6 5,0 9,-1 13,-4 4,-3 8,-7 11,-12 3,-3 4,-8 6,-12 1,-5 2,-10 2,-15zm17 -74l10 0 -26 124 -9 0 2 -14c-4,5 -8,9 -13,12 -5,3 -10,4 -15,4 -9,0 -17,-3 -22,-9 -5,-6 -8,-14 -8,-25 0,-5 1,-11 3,-17 1,-6 4,-11 7,-16 4,-7 8,-11 14,-15 5,-3 11,-5 17,-5 7,0 13,2 18,5 4,3 8,8 10,14l12 -58z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"100","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M77 3702l0 6 -59 0c0,11 3,19 8,25 6,5 13,8 22,8 4,0 8,-1 11,-2 4,-1 8,-2 11,-4l0 10c-3,2 -7,3 -11,4 -4,1 -8,1 -12,1 -12,0 -22,-4 -29,-12 -7,-7 -10,-18 -10,-32 0,-13 3,-23 10,-31 7,-8 16,-12 27,-12 9,0 17,4 23,11 6,7 9,16 9,28zm-10 -1c-1,-10 -3,-17 -7,-22 -4,-5 -10,-7 -17,-7 -6,0 -12,2 -17,8 -4,5 -7,12 -8,21l49 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"101","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M15 3624l10 0 0 55c3,-5 7,-9 11,-12 5,-2 10,-4 17,-4 9,0 15,3 20,9 5,6 7,14 7,25l0 51 -10 0 0 -48c0,-10 -2,-16 -5,-21 -3,-4 -8,-6 -15,-6 -8,0 -14,2 -18,8 -5,6 -7,14 -7,24l0 43 -10 0 0 -124z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"104","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M69 3668l-1 10c-2,-1 -5,-3 -8,-3 -3,-1 -7,-1 -10,-1 -9,0 -17,3 -22,9 -6,6 -9,14 -9,23 0,11 3,19 8,24 6,6 13,9 22,9 3,0 6,0 9,-1 4,-1 7,-2 11,-3l1 10c-4,1 -7,2 -11,3 -3,1 -7,1 -11,1 -12,0 -22,-4 -29,-12 -7,-7 -11,-18 -11,-31 0,-12 4,-22 12,-30 7,-8 18,-12 30,-12 4,0 7,1 10,1 3,1 6,1 9,3z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"99","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M14 3665l10 0 0 83 -10 0 0 -83zm-1 -39l12 0 0 14 -12 0 0 -14z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"105","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M80 3697l0 51 -10 0 0 -48c0,-10 -2,-16 -5,-21 -3,-4 -8,-6 -15,-6 -8,0 -14,2 -18,8 -5,6 -7,14 -7,24l0 43 -10 0 0 -83 9 0 0 16c3,-6 7,-11 12,-13 5,-3 10,-5 17,-5 9,0 15,3 20,9 5,6 7,14 7,25z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"110","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M48 3706c-10,0 -17,1 -22,5 -6,3 -8,8 -8,14 0,4 1,8 4,11 3,3 8,5 13,5 7,0 13,-3 18,-8 5,-5 7,-11 7,-20l0 -7 -12 0zm22 -11l0 53 -9 0 0 -14c-3,5 -7,9 -12,11 -4,3 -10,4 -16,4 -8,0 -14,-2 -19,-6 -5,-5 -7,-10 -7,-18 0,-9 4,-15 11,-20 7,-5 18,-8 31,-8l11 0c0,0 0,0 0,-1 0,-1 0,-1 0,-1 0,-7 -2,-13 -5,-17 -4,-4 -8,-6 -14,-6 -5,0 -9,1 -13,2 -4,1 -7,3 -11,5l0 -10c4,-2 8,-3 12,-4 4,-1 9,-2 13,-2 9,0 16,3 21,8 5,5 7,13 7,24z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"97","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M14 3624l10 0 0 124 -10 0 0 -124z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"108","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M13 3665l10 0 0 48c0,9 2,16 5,20 3,5 8,7 15,7 8,0 14,-3 18,-9 5,-6 7,-15 7,-27l0 -39 10 0 0 83 -9 0 0 -16c-4,5 -7,10 -12,13 -5,3 -10,4 -17,4 -9,0 -16,-3 -20,-9 -5,-5 -7,-14 -7,-25l0 -50z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"117","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M14 3665l61 0 -2 9 -64 66 51 0 -2 8 -64 0 2 -10 65 -65 -48 0 1 -8z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"122","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M53 3664l0 11c-1,0 -2,0 -3,-1 -1,0 -2,0 -3,0 -7,0 -12,3 -16,8 -4,5 -6,13 -6,22l0 44 -10 0 0 -83 9 0 0 18c2,-6 5,-11 10,-14 4,-3 9,-5 14,-5 1,0 2,0 2,0 1,0 2,0 3,0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"114","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M61 3667l-3 10c-3,-2 -6,-3 -9,-4 -3,-1 -6,-1 -10,-1 -5,0 -10,1 -13,3 -4,2 -6,5 -6,9 0,4 5,9 14,15 3,2 5,4 6,5 5,3 8,6 10,10 2,3 3,7 3,11 0,8 -3,14 -9,18 -6,5 -14,7 -25,7 -4,0 -8,0 -12,-1 -4,-1 -8,-2 -12,-4l4 -10c3,2 7,3 10,4 4,1 8,2 12,2 6,0 11,-2 15,-4 4,-3 5,-7 5,-12 0,-3 0,-5 -2,-8 -2,-2 -5,-5 -11,-9 -1,-1 -1,-1 -1,-1 -12,-8 -17,-15 -17,-21 0,-7 3,-13 8,-17 5,-4 13,-6 22,-6 4,0 7,0 10,1 4,1 7,2 11,3z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"115","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M32 3640l-1 25 20 0 0 9 -20 0 0 48c0,7 1,11 3,14 2,3 5,4 9,4 2,0 3,0 5,0 1,-1 2,-1 4,-2l0 10c-2,0 -4,1 -5,1 -2,0 -4,0 -6,0 -7,0 -12,-2 -15,-6 -3,-3 -5,-10 -5,-19l0 -50 -17 0 0 -9 17 0 0 -21 11 -4z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"116","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M58 3705c-1,0 -2,0 -3,0 -1,0 -3,0 -6,0 -13,0 -23,2 -29,5 -6,3 -9,9 -9,16 0,4 2,8 5,10 3,3 6,5 11,5 9,0 16,-4 21,-10 5,-6 9,-15 10,-26zm11 -5l-5 26c-1,7 -2,12 -3,14 0,3 -1,6 -1,8l-9 0 2 -13c-4,5 -8,8 -13,11 -4,2 -9,3 -15,3 -7,0 -13,-2 -18,-6 -5,-4 -7,-10 -7,-17 0,-9 4,-17 12,-22 8,-5 19,-8 33,-8 2,0 4,0 6,1 2,0 5,0 8,0 1,-2 1,-4 1,-5 0,-1 0,-2 0,-3 0,-5 -1,-10 -4,-13 -3,-3 -8,-4 -14,-4 -3,0 -6,0 -10,1 -5,1 -9,3 -15,5l1 -11c6,-1 10,-3 14,-3 4,-1 8,-1 11,-1 9,0 15,2 20,6 5,5 7,11 7,19 0,1 0,3 0,5 0,2 -1,4 -1,7zm-13 -66l12 0 -3 14 -12 0 3 -14zm-26 0l11 0 -2 14 -12 0 3 -14z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"228","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@id":"FontID1","@horiz-adv-x":"1000","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"font-face":{"@id":"Humnst777_BT","@font-variant":"normal","@font-style":"italic","@font-weight":"400,700","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"missing-glyph":{"@horiz-adv-x":"500","@d":"M63 0V800H438V0H63ZM125 63H375V738H125V63Z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"glyph":[{"path":{"@d":"M56 3723c-2,0 -4,1 -5,3 -1,1 -2,4 -2,7 0,4 1,6 2,8 1,2 3,3 5,3 2,0 4,-1 5,-3 2,-2 2,-4 2,-8 0,-3 0,-6 -2,-7 -1,-2 -3,-3 -5,-3zm0 -5c4,0 8,1 10,4 2,3 4,7 4,11 0,5 -2,9 -4,12 -2,3 -6,4 -10,4 -4,0 -7,-1 -10,-4 -2,-3 -3,-7 -3,-12 0,-4 1,-8 3,-11 3,-3 6,-4 10,-4zm-39 -24c-2,0 -4,1 -5,3 -2,2 -2,4 -2,8 0,3 0,6 2,7 1,2 3,3 5,3 2,0 3,-1 5,-3 1,-1 1,-4 1,-7 0,-4 0,-6 -1,-8 -2,-2 -3,-3 -5,-3zm32 -5l6 0 -31 60 -6 0 31 -60zm-32 0c4,0 7,1 9,4 3,3 4,7 4,12 0,4 -1,8 -4,11 -2,3 -5,4 -9,4 -4,0 -8,-1 -10,-4 -3,-3 -4,-6 -4,-11 0,-5 1,-9 4,-12 2,-3 6,-4 10,-4z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"37","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M16 3699l5 0 -20 55 -5 0 20 -55z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"47","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M4 3722l21 0 0 6 -21 0 0 -6z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"45","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M2 3685l6 0c5,7 8,13 10,19 2,6 3,12 3,18 0,6 -1,12 -3,18 -2,6 -5,13 -10,19l-6 0c4,-7 7,-13 9,-19 2,-6 3,-12 3,-18 0,-6 -1,-12 -3,-18 -2,-6 -5,-12 -9,-19z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"41","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M19 3685l6 0c-4,7 -7,13 -9,19 -2,6 -3,12 -3,18 0,6 1,12 3,18 2,6 5,12 9,19l-6 0c-5,-6 -8,-13 -10,-19 -2,-6 -3,-12 -3,-18 0,-6 1,-12 3,-18 2,-6 5,-13 10,-19z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"40","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M9 3739l9 0 -7 19 -7 0 5 -19z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"44","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M8 3739l8 0 0 9 -8 0 0 -9z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"46","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M8 3690l32 0 0 6 -24 0 -1 16c2,0 3,0 4,0 2,0 3,-1 4,-1 6,0 11,2 14,5 4,3 5,8 5,13 0,6 -2,11 -6,14 -4,4 -9,6 -16,6 -3,0 -5,-1 -7,-1 -2,0 -4,-1 -6,-2l0 -7c2,1 4,2 6,2 2,1 4,1 7,1 4,0 8,-1 10,-3 3,-3 4,-6 4,-10 0,-3 -1,-6 -4,-8 -2,-2 -5,-3 -10,-3 -1,0 -3,0 -5,0 -2,0 -5,1 -7,2l0 -30z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"53","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M5 3690l36 0 0 7 -22 51 -9 0 23 -51 -28 0 0 -7z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"55","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M35 3708c0,-4 -1,-7 -3,-9 -2,-3 -5,-4 -8,-4 -3,0 -6,2 -8,4 -2,2 -3,6 -3,9 0,4 1,7 3,9 2,2 4,3 8,3 3,0 6,-1 8,-3 2,-2 3,-6 3,-9zm-28 39l1 -7c1,1 3,1 4,2 2,0 4,0 6,0 6,0 10,-2 13,-6 3,-3 5,-9 5,-17 -1,3 -3,5 -6,6 -2,1 -5,2 -8,2 -5,0 -9,-2 -12,-5 -4,-4 -5,-8 -5,-13 0,-6 2,-11 5,-14 4,-4 8,-6 14,-6 6,0 11,2 14,7 4,5 6,12 6,20 0,11 -3,19 -7,24 -4,6 -10,9 -18,9 -2,0 -4,0 -6,-1 -2,0 -4,-1 -6,-1z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"57","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M8 3739l8 0 0 9 -8 0 0 -9zm0 -33l8 0 0 9 -8 0 0 -9z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"58","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M28 3718c4,0 7,2 10,4 2,3 3,6 3,9 0,5 -2,10 -6,13 -4,3 -10,4 -17,4 -2,0 -5,0 -7,0 -3,0 -5,-1 -7,-2l1 -7c2,1 4,2 6,2 2,1 4,1 6,1 5,0 8,-1 11,-3 3,-2 4,-5 4,-8 0,-3 -1,-6 -3,-7 -2,-2 -6,-3 -10,-3l-6 0 0 -6 6 0c4,0 7,-1 10,-3 2,-2 3,-4 3,-7 0,-2 -1,-5 -3,-6 -3,-2 -6,-3 -9,-3 -2,0 -4,0 -6,1 -3,0 -5,1 -7,2l0 -7c2,-1 5,-1 7,-2 3,0 5,0 7,0 6,0 11,1 14,4 4,3 5,6 5,11 0,3 -1,6 -3,8 -2,2 -5,4 -9,5z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"51","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M12 3743l22 0 0 5 -30 0 0 -6c9,-8 15,-15 18,-19 3,-4 4,-8 4,-11 0,-2 -1,-4 -2,-5 -2,-1 -4,-2 -7,-2 -2,0 -3,0 -5,1 -2,0 -4,1 -6,2l0 -6c2,-1 4,-2 6,-2 3,-1 5,-1 7,-1 4,0 7,1 10,4 3,2 4,5 4,9 0,4 -2,8 -5,12 -3,5 -8,11 -16,19z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"50","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M30 3697l-21 32 21 0 0 -32zm-2 -7l9 0 0 39 9 0 0 6 -9 0 0 13 -7 0 0 -13 -28 0 0 -7 26 -38z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"52","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M25 3718c-3,0 -6,1 -8,3 -2,3 -3,6 -3,9 0,4 1,7 3,9 2,3 5,4 8,4 3,0 6,-1 8,-4 2,-2 3,-5 3,-9 0,-4 -1,-7 -3,-9 -2,-2 -5,-3 -8,-3zm17 -27l-1 7c-1,-1 -3,-1 -4,-2 -2,0 -4,0 -6,0 -6,0 -10,2 -13,6 -3,4 -5,9 -5,17 1,-3 3,-4 6,-6 2,-1 5,-2 8,-2 5,0 9,2 12,5 4,4 5,8 5,13 0,6 -2,11 -5,14 -4,4 -8,6 -14,6 -6,0 -11,-2 -15,-7 -3,-5 -5,-11 -5,-20 0,-11 2,-18 7,-24 4,-6 10,-9 18,-9 2,0 4,1 6,1 2,0 4,1 6,1z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"54","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M24 3715c4,-1 6,-3 8,-5 1,-2 2,-4 2,-7 0,-2 -1,-4 -2,-6 -2,-1 -5,-2 -7,-2 -4,0 -6,1 -8,2 -2,2 -3,4 -3,7 0,2 1,4 2,6 2,2 5,4 8,5zm-1 6c-4,1 -6,3 -8,5 -2,2 -3,4 -3,6 0,3 1,6 3,8 3,2 5,3 9,3 3,0 6,-1 8,-3 2,-2 4,-4 4,-7 0,-3 -1,-5 -3,-7 -2,-2 -6,-4 -10,-5zm8 -3c4,1 7,3 10,6 2,2 3,5 3,9 0,5 -2,9 -6,12 -3,3 -8,4 -14,4 -6,0 -11,-2 -15,-5 -3,-3 -5,-6 -5,-11 0,-4 1,-7 3,-9 3,-3 6,-5 10,-6 -3,-2 -6,-4 -8,-6 -2,-3 -3,-6 -3,-9 0,-4 2,-7 5,-10 4,-3 8,-4 14,-4 5,0 9,1 12,4 3,2 5,6 5,10 0,3 -1,6 -3,8 -2,3 -5,5 -8,7z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"56","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M24 3695c-4,0 -7,2 -9,6 -2,4 -3,10 -3,18 0,8 1,14 3,18 2,4 5,6 9,6 4,0 7,-2 8,-6 2,-4 3,-10 3,-18 0,-8 -1,-14 -2,-18 -2,-4 -5,-6 -9,-6zm0 -6c6,0 11,3 15,8 3,5 5,12 5,22 0,10 -2,17 -5,22 -4,6 -9,8 -15,8 -6,0 -11,-2 -15,-8 -3,-5 -5,-12 -5,-22 0,-10 2,-17 5,-22 4,-5 9,-8 15,-8z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"48","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M23 3690l7 0 0 58 -8 0 0 -49 -9 8 -4 -5 14 -12z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"49","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M7 3690l8 0 0 25 27 0 0 -25 8 0 0 58 -8 0 0 -27 -27 0 0 27 -8 0 0 -58z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"72","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M6 3700l8 0 21 37c1,1 1,2 1,3 1,1 1,2 2,4 -1,-2 -1,-4 -1,-5 0,-1 0,-3 0,-4l0 -35 6 0 0 48 -8 0 -22 -38c0,0 0,-1 -1,-2 0,-1 0,-3 -1,-4 1,2 1,4 1,6 0,1 0,2 0,3l0 35 -6 0 0 -48z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"78","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M13 3705l0 37 5 0c6,0 11,-1 14,-5 4,-3 5,-7 5,-13 0,-6 -1,-11 -5,-14 -3,-3 -7,-5 -14,-5l-5 0zm-7 -5l11 0c9,0 16,2 21,6 4,4 6,10 6,18 0,8 -2,14 -7,18 -4,4 -11,6 -20,6l-11 0 0 -48z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"68","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M10 3671l41 0 0 8 -31 0 0 25 30 0 0 8 -30 0 0 27 32 0 0 9 -42 0 0 -77z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"69","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M28 3697l-11 30 22 0 -11 -30zm-5 -7l10 0 23 58 -9 0 -5 -15 -28 0 -5 15 -9 0 23 -58z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"65","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M41 3702l-1 5c-2,0 -3,-1 -5,-1 -2,-1 -4,-1 -6,-1 -5,0 -10,2 -13,5 -4,4 -5,8 -5,14 0,6 1,10 5,14 3,3 8,5 14,5 1,0 3,-1 5,-1 2,0 3,-1 5,-2l0 6c-1,1 -3,1 -5,2 -2,0 -4,0 -6,0 -8,0 -14,-2 -19,-6 -4,-5 -7,-10 -7,-18 0,-7 3,-13 7,-18 5,-4 11,-6 19,-6 2,0 4,0 6,0 2,0 4,1 6,2z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"67","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M6 3700l7 0 0 48 -7 0 0 -48z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"73","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M29 3705l0 29 11 0c6,0 11,-1 15,-4 3,-2 5,-6 5,-11 0,-4 -2,-8 -5,-10 -3,-3 -8,-4 -14,-4l-12 0zm0 -40l0 27 9 0c7,0 11,-1 15,-4 3,-2 5,-5 5,-9 0,-5 -2,-8 -5,-10 -3,-3 -8,-4 -13,-4l-11 0zm-18 -13l32 0c11,0 19,2 25,6 6,4 9,10 9,19 0,5 -2,9 -5,13 -3,4 -8,6 -13,8 6,1 11,4 15,8 3,4 5,9 5,15 0,9 -3,16 -9,20 -7,5 -16,7 -28,7l-31 0 0 -96z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"66","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M7 3690l8 0 0 51 23 0 0 7 -31 0 0 -58z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"76","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M6 3700l7 0 0 21 20 -21 8 0 -22 22 24 26 -9 0 -21 -24 0 24 -7 0 0 -48z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"75","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M7 3690l12 0 18 45c0,1 0,2 0,3 1,2 1,3 1,4 0,-1 0,-3 1,-4 0,-2 0,-2 0,-3l18 -45 12 0 0 58 -8 0 0 -45c0,-2 0,-3 0,-5 1,-1 1,-3 1,-4 0,1 -1,3 -1,4 -1,1 -1,2 -1,4l-19 46 -7 0 -18 -47c-1,-1 -1,-2 -1,-3 0,-1 -1,-3 -1,-4 0,2 0,4 0,6 0,1 0,2 0,3l0 45 -7 0 0 -58z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"77","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M51 3693l-1 7c-2,-2 -4,-2 -7,-3 -2,0 -5,-1 -7,-1 -7,0 -13,2 -17,7 -4,4 -6,9 -6,16 0,7 2,13 6,17 4,4 10,6 17,6 2,0 3,0 5,-1 1,0 3,0 4,-1l0 -17 -12 0 0 -7 20 0 0 29c-3,1 -5,2 -8,2 -3,1 -6,1 -10,1 -9,0 -17,-2 -22,-8 -6,-5 -9,-12 -9,-21 0,-9 3,-16 9,-21 5,-5 13,-8 22,-8 3,0 6,0 9,1 2,0 5,1 7,2z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"71","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M42 3747l12 12 -9 0 -11 -10c-1,0 -1,0 -2,0 0,0 -1,0 -1,0 -8,0 -15,-3 -20,-8 -4,-5 -7,-13 -7,-22 0,-9 3,-17 7,-22 5,-5 11,-8 20,-8 8,0 14,3 19,8 4,5 7,13 7,22 0,7 -2,13 -4,17 -3,5 -6,8 -11,11zm-11 -51c-6,0 -10,2 -13,6 -4,4 -5,10 -5,17 0,7 1,13 5,17 3,4 7,6 13,6 5,0 9,-2 12,-6 4,-4 5,-10 5,-17 0,-7 -1,-13 -5,-17 -3,-4 -7,-6 -12,-6z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"81","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M1 3700l7 0 9 38c0,1 1,1 1,2 0,1 0,3 0,4 0,-1 0,-2 0,-3 1,-1 1,-2 1,-2l10 -39 9 0 9 39c1,0 1,1 1,2 0,1 0,2 0,3 0,-1 0,-2 1,-3 0,-1 0,-2 0,-2l10 -39 6 0 -13 48 -8 0 -10 -39c-1,-1 -1,-2 -1,-3 0,-1 0,-2 0,-3 0,2 0,4 -1,4 0,1 0,2 0,2l-10 39 -8 0 -13 -48z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"87","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M6 3700l6 0 0 28c0,5 1,9 3,12 2,2 5,3 9,3 4,0 6,-1 8,-4 2,-2 3,-6 3,-11l0 -28 7 0 0 28c0,7 -2,12 -5,16 -3,3 -7,5 -14,5 -5,0 -10,-2 -13,-5 -3,-4 -4,-9 -4,-16l0 -28z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"85","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M13 3705l0 16 5 0c3,0 6,0 8,-2 2,-1 3,-3 3,-6 0,-3 -1,-5 -3,-6 -2,-1 -5,-2 -8,-2l-5 0zm-7 -5l13 0c5,0 10,1 12,3 3,2 5,5 5,9 0,3 -1,6 -3,8 -2,2 -5,3 -8,4 1,0 3,1 4,2 0,1 1,2 2,5l8 17 -8 0 -6 -16c-1,-2 -2,-3 -3,-4 -1,-1 -3,-1 -5,-1l-4 0 0 21 -7 0 0 -48z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"82","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M1 3690l40 0 0 7 -16 0 0 51 -8 0 0 -51 -16 0 0 -7z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"84","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M15 3696l0 22 6 0c4,0 7,-1 9,-3 3,-2 4,-4 4,-8 0,-3 -1,-6 -3,-8 -2,-2 -5,-3 -9,-3l-7 0zm-8 -6l15 0c6,0 12,2 15,4 4,3 5,8 5,13 0,6 -2,10 -5,13 -4,3 -9,4 -16,4l-6 0 0 24 -8 0 0 -58z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"80","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M37 3692l-1 7c-2,-1 -3,-2 -5,-2 -2,-1 -4,-1 -6,-1 -4,0 -6,1 -8,2 -2,1 -3,3 -3,5 0,2 0,4 2,5 1,2 4,4 8,6 6,3 10,6 12,9 2,2 3,5 3,9 0,5 -2,9 -5,12 -4,3 -8,4 -14,4 -3,0 -5,0 -8,0 -2,-1 -5,-1 -7,-2l1 -8c2,1 5,2 7,3 2,0 4,1 6,1 4,0 7,-1 9,-3 2,-1 3,-3 3,-6 0,-3 -4,-8 -12,-12 -2,-1 -3,-2 -4,-2 -3,-2 -5,-4 -7,-7 -2,-2 -2,-5 -2,-8 0,-4 1,-8 5,-10 3,-3 8,-4 14,-4 2,0 4,0 6,0 2,1 4,1 6,2z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"83","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M1 3690l9 0 17 50 17 -50 8 0 -21 58 -9 0 -21 -58z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"86","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M4 3690l37 0 0 7 -30 44 31 0 0 7 -39 0 0 -8 30 -43 -29 0 0 -7z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"90","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M27 3711c-4,0 -7,2 -9,4 -2,3 -3,7 -3,12 0,5 1,8 3,11 2,3 5,4 8,4 4,0 6,-1 8,-4 3,-2 4,-6 4,-11 0,-5 -1,-9 -3,-12 -2,-2 -5,-4 -8,-4zm-20 -25l8 0 0 27c1,-3 3,-5 5,-6 3,-1 5,-2 8,-2 6,0 10,2 13,6 3,4 5,9 5,15 0,7 -2,12 -5,16 -3,5 -7,7 -13,7 -3,0 -6,-1 -8,-3 -2,-1 -4,-3 -6,-7l0 9 -7 0 0 -62z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"98","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M40 3714c2,-3 4,-5 6,-6 3,-2 5,-3 8,-3 5,0 8,2 10,5 3,3 4,7 4,13l0 25 -8 0 0 -24c0,-4 -1,-7 -2,-9 -1,-2 -3,-3 -6,-3 -3,0 -6,1 -8,4 -2,3 -3,6 -3,11l0 21 -8 0 0 -24c0,-4 0,-7 -2,-9 -1,-2 -3,-3 -6,-3 -3,0 -6,1 -7,4 -2,3 -3,6 -3,11l0 21 -8 0 0 -42 7 0 0 8c2,-3 3,-5 6,-7 2,-1 5,-2 8,-2 3,0 5,1 7,3 3,1 4,3 5,6z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"109","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M26 3727c-5,0 -9,1 -11,3 -3,1 -4,3 -4,6 0,2 1,4 2,5 2,1 3,2 6,2 3,0 6,-1 8,-3 2,-3 3,-6 3,-10l0 -3 -4 0zm12 -4l0 25 -7 0 0 -7c-2,3 -4,4 -6,6 -2,1 -5,2 -8,2 -4,0 -8,-2 -10,-4 -2,-2 -4,-5 -4,-9 0,-4 2,-8 6,-10 4,-3 9,-4 16,-4l5 0 0 -1c0,-3 0,-5 -2,-7 -2,-2 -5,-3 -8,-3 -2,0 -4,0 -6,1 -2,0 -4,1 -6,3l0 -7c2,-1 5,-2 7,-2 2,-1 5,-1 7,-1 6,0 9,2 12,5 3,2 4,7 4,13z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"97","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M6 3696l6 0 0 31 14 -14 8 0 -16 15 17 20 -8 0 -15 -18 0 18 -6 0 0 -52z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"107","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M7 3706l7 0 0 44c0,6 -1,10 -3,12 -1,3 -4,4 -9,4 0,0 -1,0 -2,0 -1,0 -2,-1 -3,-1l1 -5c0,0 1,0 1,0 1,0 1,0 2,0 2,0 3,-1 4,-2 1,-2 2,-4 2,-8l0 -44zm0 -19l7 0 0 8 -7 0 0 -8z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"106","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M23 3711c-3,0 -6,2 -8,4 -2,3 -3,7 -3,12 0,4 1,8 3,11 2,2 5,4 8,4 4,0 7,-2 9,-4 2,-3 3,-7 3,-11 0,-5 -1,-9 -3,-12 -2,-2 -5,-4 -9,-4zm13 3l0 -8 7 0 0 37c0,8 -2,14 -5,18 -4,3 -9,5 -16,5 -2,0 -5,0 -7,0 -3,-1 -5,-1 -7,-2l1 -7c2,1 4,2 6,2 2,1 4,1 6,1 5,0 8,-1 11,-4 2,-3 3,-6 3,-11l0 -5c-1,2 -3,4 -6,6 -2,1 -5,2 -8,2 -5,0 -9,-2 -12,-6 -3,-4 -5,-9 -5,-15 0,-7 2,-12 5,-16 3,-4 7,-6 13,-6 3,0 6,1 8,2 2,2 4,4 6,7z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"103","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M39 3665l0 8c-2,0 -3,0 -4,-1 0,0 -1,0 -2,0 -3,0 -5,1 -6,3 -2,2 -2,5 -2,9l0 8 13 0 0 8 -13 0 0 48 -11 0 0 -48 -11 0 0 -8 11 0 0 -9c0,-6 2,-11 5,-14 3,-3 7,-5 13,-5 1,0 2,0 3,0 1,0 3,1 4,1z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"102","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M23 3711c-3,0 -6,2 -8,4 -2,3 -3,7 -3,12 0,5 1,8 3,11 2,3 5,4 8,4 4,0 7,-1 9,-4 2,-3 3,-6 3,-11 0,-5 -1,-9 -3,-12 -2,-2 -5,-4 -9,-4zm12 -25l8 0 0 62 -7 0 0 -9c-2,4 -4,6 -6,7 -3,2 -6,3 -9,3 -5,0 -9,-2 -12,-7 -3,-4 -5,-9 -5,-16 0,-6 1,-11 5,-15 3,-4 7,-6 12,-6 3,0 6,1 8,2 3,1 4,3 6,6l0 -27z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"100","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M25 3711c-4,0 -7,2 -10,4 -2,3 -3,7 -3,12 0,5 1,9 3,11 3,3 6,5 10,5 3,0 6,-2 9,-4 2,-3 3,-7 3,-12 0,-5 -1,-9 -3,-12 -3,-2 -6,-4 -9,-4zm-1 -6c7,0 12,2 16,6 3,4 5,9 5,16 0,7 -2,12 -5,16 -4,4 -9,6 -16,6 -6,0 -11,-2 -15,-6 -3,-4 -5,-9 -5,-16 0,-7 2,-12 5,-16 4,-4 9,-6 15,-6z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"111","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M7 3686l8 0 0 27c1,-3 3,-5 5,-6 3,-1 5,-2 9,-2 4,0 8,2 10,5 3,3 4,7 4,13l0 25 -8 0 0 -24c0,-4 -1,-7 -2,-9 -2,-2 -4,-3 -7,-3 -4,0 -6,1 -8,4 -2,2 -3,6 -3,11l0 21 -8 0 0 -62z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"104","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M36 3708l-1 6c-1,0 -2,-1 -4,-1 -1,-1 -3,-1 -5,-1 -4,0 -7,1 -10,4 -3,3 -4,7 -4,11 0,5 1,8 4,11 2,3 6,4 10,4 2,0 3,0 5,-1 2,0 3,0 5,-1l0 7c-2,0 -3,1 -5,1 -2,0 -4,0 -6,0 -6,0 -12,-1 -15,-5 -4,-4 -6,-9 -6,-16 0,-6 2,-11 6,-15 4,-4 9,-6 16,-6 2,0 3,0 5,0 2,1 3,1 5,2z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"99","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M7 3706l7 0 0 42 -7 0 0 -42zm0 -19l7 0 0 8 -7 0 0 -8z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"105","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M43 3723l0 25 -8 0 0 -24c0,-4 -1,-7 -2,-9 -2,-2 -4,-3 -7,-3 -4,0 -6,1 -8,4 -2,2 -3,6 -3,11l0 21 -8 0 0 -42 7 0 0 8c2,-3 4,-5 6,-7 2,-1 5,-2 9,-2 4,0 8,2 10,5 3,3 4,7 4,13z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"110","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M7 3686l7 0 0 62 -7 0 0 -62z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"108","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M41 3726l0 3 -30 0c1,4 2,8 5,10 2,3 6,4 10,4 2,0 4,0 6,-1 2,0 4,-1 6,-2l0 7c-2,0 -4,1 -7,1 -2,1 -4,1 -7,1 -6,0 -11,-2 -15,-6 -3,-4 -5,-9 -5,-16 0,-7 2,-12 5,-16 4,-4 8,-6 14,-6 6,0 10,2 13,6 3,3 5,8 5,15zm-7 -2c-1,-4 -2,-8 -4,-10 -1,-2 -4,-3 -7,-3 -3,0 -6,1 -8,3 -2,3 -3,6 -4,10l23 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"101","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M1 3706l8 0 12 35 11 -35 8 0 -17 46c-2,5 -4,9 -6,11 -2,2 -5,3 -9,3 0,0 -1,0 -2,0 -1,0 -2,0 -3,0l1 -7c1,0 1,0 2,1 0,0 1,0 2,0 1,0 3,-1 5,-3 1,-1 2,-4 4,-7l-16 -44z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"121","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M2 3706l9 0 9 15 9 -15 9 0 -13 20 14 22 -9 0 -10 -17 -11 17 -8 0 14 -22 -13 -20z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"120","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M34 3723c0,-3 -1,-6 -2,-8 -2,-2 -5,-3 -8,-3 -3,0 -7,1 -10,5 -2,4 -4,9 -4,15 0,3 1,6 3,8 1,2 4,3 7,3 4,0 7,-2 10,-6 3,-4 4,-8 4,-14zm4 -17l8 0 -13 59 -7 0 5 -23c-2,3 -4,4 -6,5 -3,1 -5,2 -8,2 -5,0 -8,-2 -11,-5 -3,-3 -4,-7 -4,-13 0,-4 1,-7 2,-11 1,-3 3,-6 5,-9 2,-2 4,-3 7,-4 2,-1 4,-2 7,-2 4,0 6,1 9,3 2,1 4,4 4,7l2 -9z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"113","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M6 3706l8 0 0 23c0,5 0,8 2,10 1,2 4,3 7,3 4,0 6,-2 8,-4 2,-3 3,-7 3,-13l0 -19 8 0 0 42 -7 0 0 -8c-2,3 -4,5 -6,6 -2,2 -5,3 -9,3 -4,0 -8,-2 -10,-5 -3,-3 -4,-7 -4,-13l0 -25z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"117","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M15 3741l0 24 -8 0 0 -59 7 0 0 8c2,-3 4,-5 6,-7 3,-1 6,-2 9,-2 5,0 9,2 12,6 3,4 5,9 5,15 0,7 -2,13 -5,17 -3,4 -7,6 -13,6 -3,0 -5,-1 -8,-2 -2,-1 -4,-3 -5,-6zm23 -14c0,-5 -1,-9 -3,-12 -2,-2 -5,-4 -8,-4 -4,0 -7,2 -9,5 -2,2 -3,6 -3,11 0,5 1,9 3,11 2,3 5,5 8,5 4,0 7,-2 9,-5 2,-3 3,-6 3,-11z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"112","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M4 3706l31 0 0 7 -23 29 23 0 0 6 -32 0 0 -7 24 -29 -23 0 0 -6z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"122","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M29 3706l0 7c-1,0 -1,0 -2,0 0,0 -1,0 -1,0 -4,0 -7,1 -8,3 -2,3 -3,6 -3,11l0 21 -8 0 0 -42 7 0 0 9c1,-3 3,-6 5,-7 2,-2 4,-3 7,-3 0,0 1,0 2,0 0,1 1,1 1,1z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"114","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M1 3706l8 0 11 35 12 -35 7 0 -14 42 -9 0 -15 -42z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"118","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M18 3693l0 13 10 0 0 6 -10 0 0 22c0,3 0,5 1,7 1,1 3,2 5,2 1,0 1,0 2,0 1,-1 1,-1 2,-1l0 6c-1,0 -2,0 -3,1 -1,0 -2,0 -3,0 -4,0 -7,-1 -9,-4 -2,-2 -3,-5 -3,-11l0 -22 -8 0 0 -6 9 0 0 -10 7 -3z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"116","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M30 3707l0 7c-2,-1 -4,-2 -5,-2 -2,-1 -4,-1 -6,-1 -2,0 -4,1 -5,1 -1,1 -2,2 -2,4 0,1 1,2 2,3 1,1 3,3 6,4 5,2 8,4 9,6 2,2 3,4 3,7 0,4 -2,7 -5,9 -3,2 -7,3 -12,3 -2,0 -4,0 -6,0 -2,0 -3,-1 -5,-2l0 -6c2,1 4,2 6,2 2,1 4,1 5,1 3,0 5,-1 6,-2 2,-1 3,-2 3,-4 0,-2 -1,-3 -2,-4 -1,-1 -3,-2 -6,-4 -4,-2 -7,-4 -9,-6 -2,-2 -2,-4 -2,-6 0,-4 1,-6 4,-8 2,-2 6,-3 11,-3 1,0 3,0 5,0 2,0 3,1 5,1z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"115","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M2 3692l11 0 12 43c0,0 0,1 0,2 0,2 1,3 1,5 0,-3 0,-4 1,-5 0,-1 0,-2 0,-2l12 -43 13 0 13 43c0,0 0,1 0,2 0,1 1,3 1,5 0,-2 0,-3 0,-5 1,-1 1,-2 1,-2l12 -43 11 0 -19 56 -11 0 -14 -44c0,-1 0,-2 0,-3 0,-1 0,-2 -1,-4 0,2 0,3 0,4 0,1 0,2 -1,3l-13 44 -12 0 -17 -56z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"119","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M18 3708c0,-1 -1,-3 -2,-4 -1,-2 -3,-2 -5,-2 -1,0 -3,0 -4,2 -2,1 -2,3 -2,4 0,2 0,4 2,5 1,1 3,2 4,2 2,0 4,-1 5,-2 1,-1 2,-3 2,-5zm-7 -9c3,0 5,1 7,2 2,2 3,5 3,7 0,3 -1,5 -3,7 -2,2 -4,3 -7,3 -2,0 -5,-1 -7,-3 -1,-2 -2,-4 -2,-7 0,-2 1,-5 3,-7 1,-1 4,-2 6,-2z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"176","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M34 3720c-6,0 -11,1 -14,3 -4,2 -5,5 -5,9 0,3 1,5 3,7 1,1 4,2 7,2 5,0 8,-1 11,-4 3,-3 5,-7 5,-12l0 -5 -7 0zm17 -6l0 34 -10 0 0 -9c-2,3 -5,6 -8,7 -3,2 -7,3 -11,3 -5,0 -9,-2 -13,-5 -3,-3 -5,-7 -5,-12 0,-6 3,-10 8,-14 5,-3 12,-4 21,-4l8 0 0 -2c0,-4 -2,-7 -4,-10 -3,-2 -6,-3 -10,-3 -3,0 -5,0 -8,1 -2,1 -5,2 -8,3l0 -8c3,-1 6,-2 9,-3 3,-1 6,-1 10,-1 7,0 12,2 15,6 4,4 6,9 6,17zm-17 -43l9 0 0 10 -9 0 0 -10zm-18 0l9 0 0 10 -9 0 0 -10z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"228","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M8 3692l10 0 0 31c0,6 1,10 3,13 2,3 5,4 10,4 4,0 8,-2 11,-6 2,-3 4,-9 4,-16l0 -26 10 0 0 56 -10 0 0 -11c-2,4 -4,7 -7,9 -4,2 -7,3 -12,3 -6,0 -11,-2 -14,-6 -3,-4 -5,-10 -5,-18l0 -33zm29 -21l9 0 0 10 -9 0 0 -10zm-18 0l9 0 0 10 -9 0 0 -10z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"252","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":{"@d":"M43 3689c-5,0 -10,2 -13,6 -4,5 -5,10 -5,18 0,7 1,12 5,17 3,4 8,6 13,6 6,0 10,-2 14,-6 3,-5 5,-10 5,-17 0,-8 -2,-13 -5,-18 -4,-4 -8,-6 -14,-6zm0 -13c12,0 21,3 28,10 6,6 10,15 10,27 0,11 -4,20 -10,27 -7,7 -16,10 -28,10 -11,0 -21,-3 -27,-10 -7,-7 -10,-16 -10,-27 0,-12 3,-21 10,-27 6,-7 16,-10 27,-10zm5 -27l14 0 0 15 -14 0 0 -15zm-24 0l14 0 0 15 -14 0 0 -15z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@unicode":"246","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@id":"FontID0","@horiz-adv-x":"1000","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"style":{"$":"\n .str18 {stroke:#1F1A17;stroke-width:3}\n .str7 {stroke:#0093DD;stroke-width:4;stroke-linejoin:round}\n .str2 {stroke:#0093DD;stroke-width:4;stroke-linejoin:round}\n .str11 {stroke:#1F1A17;stroke-width:4}\n .str15 {stroke:#1F1A17;stroke-width:4;stroke-linejoin:round}\n .str16 {stroke:#131516;stroke-width:4;stroke-linejoin:round}\n .str13 {stroke:#1F1A17;stroke-width:4;stroke-linejoin:round}\n .str6 {stroke:#0093DD;stroke-width:6;stroke-linejoin:round}\n .str17 {stroke:#1F1A17;stroke-width:6}\n .str9 {stroke:#131516;stroke-width:6;stroke-linejoin:round}\n .str0 {stroke:#4E4B4A;stroke-width:6;stroke-linejoin:round}\n .str5 {stroke:#0093DD;stroke-width:8;stroke-linejoin:round}\n .str12 {stroke:#1F1A17;stroke-width:8}\n .str14 {stroke:#131516;stroke-width:8;stroke-linejoin:round}\n .str8 {stroke:#449285;stroke-width:8;stroke-linejoin:round}\n .str4 {stroke:#0093DD;stroke-width:10;stroke-linejoin:round}\n .str3 {stroke:#0093DD;stroke-width:12;stroke-linejoin:round}\n .str10 {stroke:#131516;stroke-width:12;stroke-linejoin:round}\n .str1 {stroke:#4E4B4A;stroke-width:12;stroke-linejoin:round}\n .fil7 {fill:none}\n .fil19 {fill:#0093DD}\n .fil8 {fill:#1F1A17}\n .fil20 {fill:#FFFFFF}\n .fil9 {fill:#DA251D}\n .fil18 {fill:#F1A400}\n .fil16 {fill:#0096D4}\n .fil13 {fill:#96C7EB}\n .fil5 {fill:#C4E1F6}\n .fil15 {fill:#E1553F}\n .fil17 {fill:#E57A51}\n .fil10 {fill:#EDF5D4}\n .fil11 {fill:#EEA45C}\n .fil14 {fill:#EFB289}\n .fil12 {fill:#F5E0A0}\n .fil6 {fill:#C3C3C2;fill-opacity:0.501961}\n .fil4 {fill:#DA251D;fill-opacity:0.501961}\n .fil3 {fill:#EC914F;fill-opacity:0.501961}\n .fil1 {fill:#EECB97;fill-opacity:0.501961}\n .fil2 {fill:#F4B770;fill-opacity:0.501961}\n .fil0 {fill:#FFFEE3;fill-opacity:0.501961}\n .fnt0 {font-weight:normal;font-size:69;font-family:FontID0, 'Humnst777 BT'}\n .fnt42 {font-weight:normal;font-size:69;font-family:FontID34, 'Humnst777 BT'}\n .fnt8 {font-weight:normal;font-size:69;font-family:FontID4, 'Humnst777 BT'}\n .fnt41 {font-weight:normal;font-size:83;font-family:FontID34, 'Humnst777 BT'}\n .fnt5 {font-weight:normal;font-size:83;font-family:FontID4, 'Humnst777 BT'}\n .fnt17 {font-weight:normal;font-size:97;font-family:FontID10, 'Humnst777 BT'}\n .fnt19 {font-weight:normal;font-size:97;font-family:FontID12, 'Humnst777 BT'}\n .fnt21 {font-weight:normal;font-size:97;font-family:FontID14, 'Humnst777 BT'}\n .fnt23 {font-weight:normal;font-size:97;font-family:FontID16, 'Humnst777 BT'}\n .fnt25 {font-weight:normal;font-size:97;font-family:FontID18, 'Humnst777 BT'}\n .fnt27 {font-weight:normal;font-size:97;font-family:FontID20, 'Humnst777 BT'}\n .fnt29 {font-weight:normal;font-size:97;font-family:FontID22, 'Humnst777 BT'}\n .fnt31 {font-weight:normal;font-size:97;font-family:FontID24, 'Humnst777 BT'}\n .fnt33 {font-weight:normal;font-size:97;font-family:FontID26, 'Humnst777 BT'}\n .fnt35 {font-weight:normal;font-size:97;font-family:FontID28, 'Humnst777 BT'}\n .fnt37 {font-weight:normal;font-size:97;font-family:FontID30, 'Humnst777 BT'}\n .fnt39 {font-weight:normal;font-size:97;font-family:FontID32, 'Humnst777 BT'}\n .fnt13 {font-weight:normal;font-size:97;font-family:FontID6, 'Humnst777 BT'}\n .fnt15 {font-weight:normal;font-size:97;font-family:FontID8, 'Humnst777 BT'}\n .fnt18 {font-weight:normal;font-size:97;font-family:FontID11, Symbol}\n .fnt20 {font-weight:normal;font-size:97;font-family:FontID13, Symbol}\n .fnt22 {font-weight:normal;font-size:97;font-family:FontID15, Symbol}\n .fnt24 {font-weight:normal;font-size:97;font-family:FontID17, Symbol}\n .fnt26 {font-weight:normal;font-size:97;font-family:FontID19, Symbol}\n .fnt28 {font-weight:normal;font-size:97;font-family:FontID21, Symbol}\n .fnt30 {font-weight:normal;font-size:97;font-family:FontID23, Symbol}\n .fnt32 {font-weight:normal;font-size:97;font-family:FontID25, Symbol}\n .fnt34 {font-weight:normal;font-size:97;font-family:FontID27, Symbol}\n .fnt36 {font-weight:normal;font-size:97;font-family:FontID29, Symbol}\n .fnt38 {font-weight:normal;font-size:97;font-family:FontID31, Symbol}\n .fnt40 {font-weight:normal;font-size:97;font-family:FontID33, Symbol}\n .fnt12 {font-weight:normal;font-size:97;font-family:FontID5, Symbol}\n .fnt14 {font-weight:normal;font-size:97;font-family:FontID7, Symbol}\n .fnt16 {font-weight:normal;font-size:97;font-family:FontID9, Symbol}\n .fnt3 {font-weight:normal;font-size:111;font-family:FontID2, 'Humnst777 BT'}\n .fnt7 {font-weight:normal;font-size:111;font-family:FontID4, 'Humnst777 BT'}\n .fnt2 {font-weight:normal;font-size:130;font-family:FontID2, 'Humnst777 BT'}\n .fnt9 {font-weight:normal;font-size:130;font-family:FontID4, 'Humnst777 BT'}\n .fnt11 {font-weight:bold;font-size:130;font-family:FontID4, 'Humnst777 BT'}\n .fnt4 {font-weight:normal;font-size:167;font-family:FontID3, 'Humnst777 Lt BT'}\n .fnt10 {font-weight:bold;font-size:222;font-family:FontID4, 'Humnst777 BT'}\n .fnt6 {font-style:italic;font-weight:normal;font-size:83;font-family:FontID4, 'Humnst777 BT'}\n .fnt1 {font-style:italic;font-weight:normal;font-size:167;font-family:FontID1, 'Humnst777 Lt BT'}\n ","@type":"text\/css","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"g":[{"image":{"@transform":"matrix(0.555102 0 0 0.555268 -5368.74 5205.7)","@x":"0","@y":"-8696","@width":"15792","@height":"12444","@xlink:href":"tests\/resources\/images\/spainRelief.png","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@id":"relief","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil0","@d":"M-1948 1100l87 -3 57 -27 23 7 33 53 60 13 10 77 14 7 30 -17 3 20 -30 17 57 36 -10 20 -20 -13 -80 50 13 43 -17 47 24 50 -4 23 -33 7 -13 20 10 33 26 0 44 184 46 3 24 20 -17 17 7 26 46 0 7 10 -13 27 13 17 53 -17 -3 20 -43 23 -10 27 -50 17 -4 26 27 47 -30 -3 -17 -24 -60 -3 -36 27 -47 -14 -20 20 -23 0 -17 -13 10 -27 -13 -13 -37 13 -33 -46 -27 -4 -33 34 -30 -7 -40 -63 -60 10 -10 -20 53 -107 -13 -43 -50 -10 16 -90 20 -4 10 -23 0 -13 -16 3 3 -23 37 -14 -10 -33 16 -67 -13 -13 23 -117 -33 -26 23 -30 0 -57 20 -7 37 -83 33 -20z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil0","@d":"M199 1140l0 20 53 23 37 54 20 -7 10 -27 60 17 47 -37 60 40 23 -3 27 47 53 26 100 -40 43 10 24 30 33 -36 40 23 113 -10 17 -23 -20 -24 10 -63 23 -13 70 20 -73 103 7 47 36 16 -16 74 -20 10 30 60 6 63 -20 143 -30 97 -40 43 24 44 -144 153 20 53 44 4 10 33 -24 40 -30 10 0 50 -6 3 -50 -10 -7 14 -7 -4 -3 -3 -7 -3 -6 0 -4 0 -6 3 -7 0 -3 3 -7 4 -3 3 -4 7 -3 3 -7 3 -3 4 -3 6 -4 4 0 6 -3 7 0 7 -37 0 -6 -14 -7 0 0 14 -27 -10 -66 -164 -24 -3 -20 17 -63 -40 -10 -37 -73 -27 -7 -80 -77 -80 -60 0 -60 -30 30 -66 17 26 13 -10 -6 -130 16 -40 -6 -50 -7 -3 -10 10 0 17 -17 46 -33 -6 -13 26 -17 -6 53 -104 -46 -23 3 -60 -23 -3 16 -27 -16 -17 13 -20 -7 -36 17 -24 -17 -16 4 -27 30 -27 -4 -46 17 -47 50 -10z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil0","@d":"M-3064 1633l40 34 36 -7 84 30 93 -13 53 43 97 -3 43 23 37 -17 20 27 43 -20 24 17 33 -17 43 67 34 -37 13 30 13 30 -10 23 20 7 10 -30 37 -17 47 47 -27 27 17 20 -14 63 7 3 -3 20 -30 24 0 23 23 37 0 50 30 10 -10 26 17 14 -4 23 -40 23 -3 4 17 43 -17 37 23 83 -26 47 26 6 -3 34 -20 13 -33 -17 -10 -36 -30 6 -7 24 -43 -54 -24 7 -26 -27 -67 17 -70 -17 -30 57 -10 3 -3 -10 -17 7 -10 -7 0 -30 -43 -3 -7 -7 -3 -3 -4 0 -6 7 -4 3 -6 0 -4 -3 -3 -4 -3 -6 -4 -7 0 -3 -6 -7 -4 -3 -3 -4 -7 0 -6 0 -4 -3 -3 -3 0 -7 0 -7 0 -6 0 -7 0 -3 -7 -7 -3 -3 -7 0 -3 3 -3 7 -4 3 -3 7 -7 3 -3 3 -7 4 -3 0 -7 0 -3 -4 -7 -3 -6 0 -4 0 -6 0 -7 -3 -7 0 -3 0 -7 0 -6 0 -7 0 -10 0 7 -7 3 -3 7 -4 3 -3 7 -3 3 -4 7 -3 3 -3 3 -7 4 -3 3 -7 0 -3 3 -7 4 -3 3 -7 3 0 7 0 7 0 6 -3 4 -4 3 -3 0 -7 0 -6 3 -7 0 -3 4 -7 3 -3 3 -7 4 -3 3 -7 3 -3 0 -7 4 -3 3 -7 3 -3 4 -7 3 -3 3 -7 4 -3 3 -7 3 -3 4 -4 3 -6 7 -4 10 -16 -84 -67 -50 -7 -36 17 -24 -20 -6 -47 30 -86 -30 -14 10 -40 -17 -20 -20 20 -53 0 -30 -26 -10 -14 -27 30 -50 0 -30 -20 13 -46 -20 -17 0 -23 30 -27 10 -33 40 -34 34 10 10 -30m530 317l-4 7 -3 3 -3 7 -4 3 -6 0 -4 0 -3 7 -3 3 0 7 0 6 3 7 3 3 4 7 0 3 0 7 0 7 -4 6 -3 4 -3 3 -4 3 -6 4 -4 6 -3 4 -3 6 0 4 -7 3 -3 7 -7 0 -3 0 -4 3 -3 7 0 6 0 7 0 7 -3 3 -7 3 -3 0 -7 4 -7 3 -3 3 -7 0 -6 0 -4 0 0 7 0 7 7 3 3 3 0 7 0 7 4 3 0 7 3 6 3 -3 7 -3 3 -4 0 -6 -3 -4 0 -6 3 -7 0 -3 4 -7 6 -3 7 0 3 0 7 -4 3 -3 0 -7 0 -6 4 -4 0 -6 3 -7 3 -3 7 0 3 -4 7 4 7 0 6 -4 0 -3 -3 -7 -3 -6 -4 -4 4 -6 0 -7 6 0 7 0 3 0 7 0 7 -3 6 -4 0 -3 0 -7 -3 -6 0 -7 -3 -3 -4 -7 -3 -3 -3 -7 0 -7 0 -3 0 -7 3 -3 3 -7 4 -3 3 -7 0 -6 -3 -7z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil0","@d":"M-964 1820l23 10 33 -23 7 -47 27 -13 16 23 -20 53 90 14 37 -50 0 -20 10 -14 7 4 33 -24 67 -3 20 40 40 -17 33 7 -13 37 26 23 4 47 76 23 57 -30 27 77 -24 43 40 57 -16 40 -24 0 -36 43 -20 -7 -17 10 13 30 -6 44 26 60 -50 23 -6 -37 -37 -6 -10 50 -23 36 16 100 50 24 -3 50 -7 0 -26 -20 -17 0 -13 20 -34 -4 -46 24 -20 -17 -30 20 -27 -17 -37 -56 -23 6 -7 -6 4 -14 -24 -10 14 -16 -4 -4 -13 4 -10 -20 -37 -4 -3 -13 -10 -3 -27 16 -30 -10 -26 -33 -20 0 -17 13 -57 14 -80 -20 -80 -64 7 -50 -47 -13 -16 -40 -20 10 -20 -13 -10 -30 3 -24 43 17 7 -20 20 -43 23 -14 4 -30 36 -23 0 -53 20 -10 50 40 30 -44 -3 -16 47 -7 10 -30 20 -3 3 -37 27 -30z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil0","@d":"M-1304 2147l10 30 20 13 20 -10 16 40 47 13 -7 50 80 64 -26 33 -77 -3 -17 13 4 27 -74 33 -43 13 -90 110 -63 24 -27 43 -17 87 -53 0 -47 70 -63 6 7 10 -10 10 -20 0 -24 4 -30 -10 -6 -54 -27 -30 -7 -43 -30 -3 0 -4 10 -16 -16 -14 -4 -50 -50 -66 -36 -14 0 -66 20 -24 20 7 6 -3 -6 -30 43 -37 -10 -27 7 -6 33 10 17 -24 -17 -50 90 -30 133 -23 64 -30 10 -43 43 20 43 53 17 -27 10 4 0 26 7 7 10 0 6 -40 27 -27 77 -16z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil0","@d":"M766 2463l6 24 27 10 13 36 -23 57 17 53 -24 37 -33 20 3 10 -73 33 -13 -30 -47 10 -63 -43 -20 27 -10 46 -37 20 -13 -13 -27 13 3 37 47 3 -3 70 23 24 -43 30 36 46 -60 57 -10 37 -50 16 -26 -10 0 40 -37 87 -30 23 -40 0 -10 30 -30 17 -3 43 26 30 -53 20 -23 -76 -44 -14 -80 10 -13 -30 47 -20 0 -20 -40 -36 -54 0 -16 -30 -14 -27 -13 0 -3 40 -67 -3 0 -37 -60 7 -73 -77 -4 3 -13 -13 3 -3 -3 -4 -7 -6 -3 -4 -3 -3 -7 -3 -3 -7 -4 -3 -3 -4 -3 -6 -4 -4 -3 -3 -7 -3 -3 -4 -7 -3 30 -47 30 -13 10 -80 47 17 27 -20 3 -64 -17 -36 14 -54 -47 -56 -3 -47 83 -7 13 -26 -10 -20 54 -54 16 24 24 3 23 -17 -7 -33 27 -17 33 7 27 -27 43 20 24 -6 -10 36 30 14 33 -50 17 26 30 0 23 -46 43 33 34 -60 -30 -23 20 -14 0 -43 23 -3 0 3 3 -3 4 -30 46 3 44 53 36 17 14 -13 50 46 120 47 33 53 17 -23 80 3z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil0","@d":"M-1118 2347l80 20 57 -14 17 -13 20 0 26 33 30 10 27 -16 10 3 3 13 37 4 10 20 13 -4 4 4 -14 16 24 10 -4 14 7 6 23 -6 37 56 27 17 30 -20 20 17 46 -24 34 4 13 -20 17 0 26 20 7 0 3 -50 54 -20 16 23 70 37 104 103 3 47 47 56 -14 54 17 36 -3 64 -27 20 -47 -17 -10 80 -30 13 -30 47 -6 -3 -4 -4 -3 0 -3 -3 0 -3 -4 -7 -3 -3 -3 -7 -4 -3 -6 -4 0 -6 -4 -7 0 -3 0 -7 -3 -7 0 -3 -3 -7 0 -6 0 -7 -4 -3 -3 -7 0 -7 -3 -3 0 -7 -4 -6 0 -4 -3 -6 -3 -10 -20 -10 -7 16 -27 -3 -40 -37 -33 -10 -23 30 -54 -6 4 36 -17 10 -50 -30 -10 20 23 27 -10 17 -63 10 -10 16 17 30 -7 14 -7 0 -3 -4 -3 -3 -4 -7 0 -3 -3 -7 -7 0 -6 0 -4 0 -6 4 -7 0 -3 3 -7 0 -7 3 -3 0 -7 0 -6 0 -7 0 -3 0 -7 4 -3 3 -7 0 -7 3 -3 4 -7 3 -3 3 -3 4 -7 -7 -17 7 -13 46 13 67 -13 43 -47 34 -53 -34 -10 37 -30 0 0 -3 -17 -84 -40 27 -10 -7 34 -106 -14 -24 -26 -13 0 -50 -30 -20 -20 7 0 -24 -24 -23 10 -37 -26 4 -14 -34 -10 14 -33 -14 13 -50 -33 -26 57 -147 -24 -37 4 -23 -34 -10 -30 -50 74 -33 -4 -27 17 -13 77 3 26 -33m314 456l-7 0 -3 0 -7 0 -7 4 -6 0 -4 3 -3 7 -3 3 0 7 -4 6 -3 4 -3 6 0 4 -4 6 0 7 -3 3 -3 7 0 7 3 3 3 7 4 3 0 7 -4 3 0 7 -3 6 0 7 0 3 -3 7 6 7 4 0 3 -7 3 -3 4 -7 0 -3 0 -7 3 -7 3 -3 4 -3 3 -7 3 -3 -3 -7 -3 -3 -7 -4 -3 -3 0 -7 0 -6 0 -7 3 -3 0 -7 3 -3 4 -7 6 -3 4 -4 3 -3 7 0 6 -3 4 -4 0 -10z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil0","@d":"M-1954 2457l0 66 36 14 50 66 4 50 16 14 -10 16 0 4 30 3 7 43 27 30 6 54 30 10 24 -4 20 0 10 -10 -7 -10 63 -6 -6 50 -40 13 -17 -13 -7 6 4 24 -24 26 0 97 -56 7 -24 60 -30 -14 -10 7 4 27 -24 56 -50 10 -23 -63 -57 10 -3 33 -90 80 -20 0 -10 -36 -77 53 -93 -23 -20 -47 10 -40 -20 -13 -23 3 -24 30 -36 10 -107 -77 30 -30 -3 -56 33 -34 37 -10 -7 24 30 16 3 -30 27 0 17 -53 -10 -17 -37 10 3 -33 30 7 27 -14 27 -33 -7 -23 73 -40 50 -57 37 -127 -7 -26 -23 -17 13 -63 74 -17 80 47 26 -30 44 -10z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil0","@d":"M-731 2977l7 -14 -17 -30 10 -16 63 -10 10 -17 -23 -27 10 -20 50 30 17 -10 -4 -36 54 6 23 -30 33 10 40 37 27 3 7 -16 20 10 3 10 3 6 0 4 4 6 0 7 3 3 0 7 3 7 4 3 0 7 0 6 3 7 0 3 3 7 0 7 0 3 4 7 0 6 6 4 4 3 3 7 3 3 4 7 0 3 3 3 3 0 4 4 6 3 7 3 3 4 7 3 3 3 4 4 3 6 3 4 4 3 3 7 7 3 3 3 3 4 7 6 3 4 -3 3 13 13 4 -3 73 77 60 -7 0 37 40 96 43 7 37 7 40 -14 13 30 -36 17 3 17 3 46 -36 87 3 43 -27 14 -36 -10 -64 86 -13 87 13 20 -133 77 -27 30 -60 -17 -53 7 -20 -44 -37 -3 0 10 4 3 0 7 0 7 3 3 0 7 3 6 0 4 4 6 3 7 0 3 3 7 -70 -10 -56 40 -30 -40 -30 33 -74 -73 -80 10 -6 0 -7 3 -3 0 -7 0 -7 4 -6 0 -4 0 -10 0 -13 -37 -20 -7 -20 24 -3 3 -30 -7 13 -23 -33 -57 6 -130 -46 -50 -44 -100 -30 -16 17 -80 -33 -7 -7 -53 57 -17 -20 -40 13 -10 30 0 10 -37 53 34 47 -34 13 -43 -13 -67 13 -46 17 -7 7 7 -4 6 -6 4 -4 6 0 4 7 3 3 3 7 4 3 3 4 7 0 6 0 4 0 6 0 7 3 7 0 3 3 7 4 3 3 3 7 0 6 0 4 0 3 -6 0 -7 3 -7 0 -3 0 -7 -3 -6 -3 -4 -4 -3 -3 -7 -3 -3 -4 -7 0 -3 0 -7 0 -6 4 -4 3 -6 3 -4 4 -3 6 -3 7 0 3 -4 7 0 7 0 6 0 4 0 6 0 7 0 7 4 3 0 7 3 3 3 7 0 3 4 7 3 6 0 4 3 6 0 7 0 3 -6 0 -4 -3 -3 -7 -3 -6 0 -7 0m247 626l-4 -6 -3 -4 -3 -6 -4 -4 0 -6 0 -4 -3 -6 -7 -4 -6 0 -7 0 -3 0 -7 -3 -3 -3 -4 -7 -6 -3 -4 -4 -3 -6 0 -4 -3 -6 0 -7 3 -3 3 -7 0 -3 -6 -7 -4 0 -6 0 -7 0 -7 -3 -3 -4 -3 -6 0 -4 -4 -6 -3 -4 -7 -3 -3 -3 -3 -4 -4 7 0 7 0 6 4 4 0 6 3 7 0 3 7 4 3 3 3 3 4 7 3 7 3 3 4 3 3 7 7 3 3 4 3 3 4 7 3 3 0 7 0 6 3 4 7 3 3 3 7 0 7 0 6 0 4 4 3 3 3 7 4 3 6 3 4 4 6 0 4 -4z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil0","@d":"M-2521 3073l107 77 36 -10 24 -30 23 -3 20 13 -10 40 20 47 -23 16 3 60 -27 97 44 -7 23 14 -20 70 7 6 3 4 3 3 7 0 7 3 3 0 7 0 3 -3 3 -7 4 -3 6 -7 4 0 6 -3 4 -3 6 0 7 0 3 0 7 0 -3 30 16 26 -36 90 133 134 -7 0 -6 0 -4 3 -6 0 -4 3 -6 4 -4 6 -3 4 -3 10 -7 0 -27 -17 -13 40 -57 23 -43 -20 -23 14 -7 53 -23 47 -37 3 -30 -33 -33 0 -20 16 16 24 -10 30 -43 20 -77 -44 -13 24 -53 16 -14 -20 -33 34 -7 -34 -20 -3 -53 53 -50 -40 -40 -10 -10 -46 -20 -4 -13 7 -87 -17 -7 20 -40 -30 -43 10 -43 -10 -17 -40 33 -53 -26 -17 -4 -33 -46 -3 -90 -37 -10 17 26 20 -26 46 -17 7 -7 -33 17 -17 -30 -7 -27 24 -6 16 10 4 -24 36 -20 -3 -43 -50 13 -90 -46 -23 -4 -24 -66 -60 -10 -43 6 0 4 0 6 0 7 0 7 0 3 3 7 0 6 4 4 0 6 3 7 0 3 0 7 3 7 0 6 0 4 4 6 0 7 3 7 0 3 -3 7 0 3 -4 7 -3 6 -3 4 0 6 -4 7 0 3 0 7 0 7 4 6 0 4 0 6 0 7 3 3 0 7 0 7 0 6 0 4 0 6 3 7 0 7 -3 3 0 7 0 6 0 7 -3 10 0 7 0 3 -4 7 0 20 -96 43 -40 30 -107 -33 -67 -44 -20 -10 -46 17 -27 77 -27 20 20 36 7 24 -17 16 14 67 -20 10 -40 190 -107 83 60 -3 7 -10 3 -3 7 -4 3 -3 3 -3 7 -4 3 -3 4 -7 3 -3 3 -7 7 -3 0 -7 -3 -6 0 -4 -4 -6 4 -4 6 -3 7 0 3 7 0 6 -3 7 0 7 -3 3 3 7 0 3 3 3 7 0 7 0 3 0 7 -6 3 -4 7 -3 3 -3 3 -4 7 0 7 -3 3 0 7 3 3 7 3 3 4 7 0 7 -4 6 0 7 0 3 -3 7 -3 3 -4 4 -3 3 -3 0 -7 0 -7 0 -6 -7 -4 -3 0 -7 -3 -3 -3 -7 -4 0 -6 -3 -7 0 -3 0 -7 0 -7 3 -6 4 -4 3 -3 7 -3 40 13 20 27 43 16 13 -30 50 -20 0 44 37 -4m-150 324l7 3 6 0 4 -3 3 -4 7 -3 3 -3 7 -4 6 -3 0 -3 0 -7 4 -7 0 -3 3 -7 0 -6 -3 -4 -7 0 -3 4 -4 6 0 7 0 3 -3 7 -3 7 -4 3 -3 3 -7 0 -6 4 -4 3 -3 7m207 56l6 0 4 0 6 -3 4 -3 6 -4 4 -3 6 0 7 -3 3 0 7 0 7 0 6 0 4 0 6 0 7 3 3 7 7 0 3 -4 7 -3 3 0 7 -3 7 0 6 -4 4 4 6 3 4 3 3 4 10 0 -7 -4 -3 -3 -3 -7 0 -6 0 -7 3 -3 0 -7 3 -7 0 -3 0 -7 -3 -6 -7 0 -6 0 0 3 -4 7 0 6 -3 7 -3 3 -7 4 -3 3 -7 0 -7 0 -3 3 -7 -3 -6 3 -7 0 -3 0 -7 0 -7 0 -6 0 -4 0 -6 0 -7 4 -3 0 -7 0 -7 3 -3 3 -7 4 -3 3 -3 3 0 10m-204 -46l7 3 3 3 7 4 3 3 7 0 3 3 4 7 3 7 3 0 7 3 7 0 6 0 4 0 6 0 7 3 3 4 4 6 3 4 3 3 4 3 6 0 7 0 7 0 3 0 7 -3 6 0 4 -3 6 0 7 0 3 -4 7 -3 -3 -3 3 -7 3 -3 4 -4 6 -3 0 -7 -3 -3 -7 0 -3 3 -3 4 -4 6 -3 4 -3 3 -7 3 -7 4 -3 3 -3 3 -7 0 -7 0 -6 0 -4 -3 -6 0 -4 -3 -3 -7 -7 -3 -3 -4 -7 -3 -3 0 -7 0 -6 -3 -4 0 -3 -7 -3 -7 -4 -3 -3 -3 -7 3 -6 0 -7 -3 -3 0 -14 0m-510 60l4 3 6 0 7 0 3 -3 7 -4 3 -3 4 -3 6 -4 4 -3 6 0 7 0 7 -3 3 0 7 3 6 0 4 0 6 0 7 0 7 0 3 0 7 0 6 0 7 0 3 0 7 -3 3 0 7 0 7 3 3 0 7 7 3 3 7 3 3 4 7 3 3 3 7 0 3 4 7 3 3 3 7 4 0 6 0 4 -4 6 4 7 6 0 4 0 6 0 4 3 3 7 3 3 4 7 3 3 3 7 0 7 4 3 3 7 3 3 4 7 3 3 3 3 7 4 3 3 7 3 3 4 7 0 7 0 6 0 4 0 6 0 7 0 7 0 3 0 7 3 6 0 4 3 6 4 7 0 3 3 7 3 3 4 4 3 6 3 4 4 6 3 4 3 6 0 7 0 3 0 7 -3 0 -7 -3 -3 -7 -3 -3 0 -7 -4 -7 0 -3 -3 -7 -3 -3 -4 -7 -3 -3 -3 -7 -4 -3 -3 -7 -3 -3 -4 -3 -3 -7 -3 -7 0 -3 0 -7 0 -6 3 -7 0 -3 0 -7 0 -7 0 -6 -3 -4 -4 -6 0 -4 -6 -3 -4 -3 -3 -4 -7 -3 -3 -3 -3 -4 -7 -6 -3 -4 -7 -3 -3 -3 -4 0 -6 -4 -7 -3 -3 3 -7 4 -3 6 -4 7 0 3 -3 7 0 7 -3 3 0 7 0 6 -4 7 0 3 0 7 -3 7 0 3 -3 7 0 6 0 7 0 3 0 7 0 7 0 3 -4 7 0 6 -3 4 -3 6 0 7 -4 3 -3 7 -3 3 0 7 -4 7 -3 3 0 7 -3 6 0 4 0 6 0 4 -4 3 -6 7 -4 3 -3 3 -3 10 -7 -3 -7 0 -6 0 -7 -3 0 -7 7 0 3 0 7 -7 6 -3 4 -3 3 -7 3 -3 0 -7 0 -7 4 -3 3 -7 0 -6 3 -4 4 -6 0 -7 3 -3 0 -7 3 -3 4 -7 0 -7 3 -3 0 -7 3 -6 0 -7 0 -3 0 -7 4 -7 0 -6 0 -4 0 -6 0 -7 3 -3 0 -7 0 -7 3 -3 4 -7 3 -3 3 -7 0 -3 0 -7 -3 0 -7 0 -3 -6 -3 -7 0 -3 -4 -7 0 -7 4 -3 6 0 4 -7 3 -6 -3 -7 0 -3 -4 -4 -3 -6 -3 -4 -4 -6 -3 -4 -3 -3 -4 -3 -6 -4 -7 -3 -3 -3 -4 -7 4 -7 0 -6 0 -4 3 -3 3 -7 4 -6 0 -7 0 -3 -4 0 -6 6 -4 4 -3 -4 -7 -3 0 -7 4 -3 3 -3 3 -7 4 -3 0 -7 3 -7 0 -6 0 -4 3 -6 4 -7 0 -3 3 -7 3 -3 0 -7 4 -3 3 -7 3 -3 -3 -4 -3 7 -7 3 -3 4 -4 3 -6 3 -4 4 -6 3 -4 3 -6 4 -4 0 -6 3 -4 3 -6 0 -7 4 -3 3 -7 0 -3 3 -7 7 0 7 -3 6 0 4 -4 6 0 7 0 3 -3 4 -7 6 -3 4 -3 3 -4 7 -3 3 -3 7 -4 3 0 7 -3 6 0 4 0 6 -3 7 -4 3 -3 7 0 7 0 0 -3 -4 -7 -6 0 -7 0 -7 3 -3 0 -7 4 -3 3 -7 3 -3 0 -7 4 -6 3 -4 3 -3 4 -7 3 -3 3 -7 0 -3 -3 0 -7 3 -6 -3 -4 -7 -3 -3 7 0 6 0 4 0 6 0 7 -7 3 -3 0 -7 4 -3 3 -7 3 -3 4 -7 3 -3 3 -3 7 -4 3 0 7 -3 3 -3 7 -4 3 0 7 -3 3 -3 7 -4 7 0 3 -3 7 -3 3 -4 7 -3 3 -3 7 -4 3 -3 7 0 3 3 7z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil0","@d":"M-901 3767l20 -24 20 7 13 37 14 40 -64 93 17 70 -43 73 63 34 23 73 57 40 -17 60 -33 27 -17 -7 0 70 -73 53 -17 -10 -63 17 -20 -23 -40 26 -113 -23 -20 7 -14 33 -40 20 -40 -7 -16 -30 -24 37 -110 -20 -53 43 -213 -23 -10 37 -104 -30 -46 -57 -44 -17 -56 -60 -84 -30 -6 -50 -54 0 -40 -33 30 -7 27 -90 23 -20 30 4 7 -30 -50 -27 -23 -63 46 13 27 -10 -23 -37 16 -50 20 -26 50 3 7 -13 -27 -70 27 -14 23 -60 -10 -26 37 -4 7 -26 60 -47 20 50 23 -30 107 33 26 -16 20 -50 60 -4 10 40 -16 7 -4 40 -23 0 -17 67 24 16 16 -16 54 10 6 43 60 27 44 -24 33 17 43 -20 64 -7 66 -70 60 4 10 -57 54 0 23 -17 83 37 44 -17 33 57 -13 23 30 7 3 -3z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil0","@d":"M-2094 3723l13 -13 23 -73 24 -17 53 40 -3 60 -57 30 -3 0 6 -3 -3 -7 0 -7 -7 -3 -3 -3 -7 0 -6 -4 -4 -3 -6 0 -7 0 -3 3 -10 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil0","@d":"M-798 3780l80 -10 74 73 30 -33 30 40 56 -40 70 10 -3 -7 0 -3 -3 -7 -4 -6 0 -4 -3 -6 0 -7 -3 -3 0 -7 0 -7 -4 -3 0 -10 37 3 20 44 53 -7 60 17 27 -30 133 -77 34 40 26 -10 34 27 100 20 -10 76 0 4 -40 106 73 84 103 -10 24 43 0 67 -20 16 33 64 -67 23 -50 -37 -6 -26 -30 -10 -47 16 -47 40 -16 -13 -20 7 -27 26 -3 57 -27 30 17 113 -44 44 -53 10 -23 -40 -37 -7 -3 3 -87 64 -47 13 -33 -20 -30 47 -63 36 -67 124 -120 -40 60 -87 7 -53 -10 -7 -24 -13 0 -70 -50 -14 -13 -70 -53 10 -44 -23 0 -70 17 7 33 -27 17 -60 -57 -40 -23 -73 -63 -34 43 -73 -17 -70 64 -93 -14 -40 10 0 4 0 6 0 7 -4 7 0 3 0 7 -3 6 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil1","@d":"M-3514 537l36 -4 10 37 10 7 20 -34 44 4 -4 13 54 20 36 63 34 24 103 10 -3 50 -30 40 -37 0 -3 30 20 6 3 34 33 30 4 46 46 27 0 47 44 -24 26 20 -23 37 -40 10 -30 40 13 23 24 -13 40 20 10 50 -20 27 0 53 -30 37 -27 0 -43 36 16 44 -23 16 7 27 -20 57 -50 83 -7 -3 -7 0 -3 -4 -7 -3 -3 -3 -3 -7 -4 -7 0 -3 -3 -7 0 -6 -3 -4 -7 -3 -3 -3 -7 -4 -3 -3 -7 0 -7 0 -6 0 -4 0 -6 0 -7 0 -7 0 -3 0 -7 3 -6 0 -4 4 -6 0 -4 3 -6 7 -4 3 -3 3 -7 4 -3 3 -7 3 -3 0 -7 4 -6 0 -4 3 -6 0 -7 0 -7 0 -3 -3 -7 0 -6 0 -4 0 -6 0 -7 3 -3 0 -7 0 -7 -3 -6 0 -4 -4 -6 0 -4 -3 -6 -3 -4 -4 -6 -3 -4 -3 -6 -4 -4 -3 -3 -3 -10 -7 3 0 -20 -13 10 -10 -3 -7 -73 -10 10 -33 -17 -20 37 -100 -57 -47 7 -53 -14 -4 50 -80 -16 -66 16 -34 -23 -70 23 -46 -6 -20 30 -37 0 -47 33 0 30 -50 27 -110 20 -16 -10 -27 10 -33m-54 810l7 -7 3 -3 0 -7 0 -7 0 -6 0 -4 0 -6 4 -7 0 -3 6 -4 4 -3 6 -3 0 -7 0 -7 4 -3 3 -7 3 -3 0 -7 4 -3 3 -7 3 -3 4 -7 3 -3 0 -7 3 -3 7 -3 7 -4 3 -3 3 -3 4 -7 3 -3 3 -7 4 -3 -7 -4 -7 4 -6 0 -4 3 -3 7 -7 3 -3 3 -3 7 -4 3 0 7 -3 3 -3 7 -4 3 -3 4 -7 6 -3 4 -3 3 0 7 -4 6 0 4 -3 6 -3 4 -4 3 -6 3 -4 7 -3 3 0 7 -3 7 0 3 0 7 0 6 0 7 3 3 3 7 0 7z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil1","@d":"M-2001 973l-3 57 36 20 20 50 -33 20 -37 83 -20 7 0 57 -23 30 33 26 -23 117 13 13 -16 67 10 33 -37 14 -3 23 16 -3 0 13 -10 23 -20 4 -23 -7 -3 13 -14 0 -6 -6 -14 -17 -36 33 -27 -6 -13 23 6 7 -6 6 -20 -3 -10 20 -20 -10 -20 20 0 33 3 70 -37 17 -10 30 -20 -7 10 -23 -13 -30 -13 -30 -34 37 -43 -67 -33 17 -24 -17 -43 20 -20 -27 -37 17 -43 -23 -97 3 -53 -43 -93 13 -84 -30 -36 7 -40 -34 30 -63 -57 -50 17 -50 -17 -10 -50 -23 -23 20 -50 -10 20 -57 -7 -27 23 -16 -16 -44 43 -36 27 0 30 -37 0 -53 20 -27 33 20 33 -27 77 10 63 -16 4 -17 -10 -7 6 -13 14 0 30 -47 73 37 10 -27 50 17 17 -30 33 10 20 -10 17 40 36 23 60 10 27 -36 43 -14 54 17 30 -3 10 -24 40 4 16 -30 80 6 37 -23 17 13 26 -56 37 0 47 -40 26 6 17 30z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil1","@d":"M-1251 1010l83 -47 67 27 -17 27 24 16 -4 47 -16 13 60 7 43 57 -67 23 -60 -33 -33 56 33 34 10 -27 24 0 10 -10 6 7 -10 66 10 10 10 -3 7 0 3 0 7 0 7 0 6 0 4 3 3 7 3 3 4 4 6 6 4 4 3 3 7 3 3 4 7 3 3 0 7 3 6 0 4 4 6 0 7 3 3 3 4 4 6 3 4 3 3 7 3 3 0 7 4 7 0 3 -27 13 -27 -13 -50 3 -6 14 3 20 -23 26 0 10 16 4 -6 36 23 27 -3 43 -7 4 -10 -24 -10 10 20 30 -30 14 17 60 -20 46 53 84 57 0 10 43 -27 30 -3 37 -20 3 -10 30 -47 7 3 16 -30 44 -50 -40 -20 10 0 53 -36 23 -4 30 -23 14 -20 43 -7 20 -43 -17 -3 24 -77 16 -27 27 -6 40 -10 0 -7 -7 0 -26 -10 -4 -17 27 -43 -53 -43 -20 -17 -27 0 -3 -17 6 7 -56 -30 -27 20 -30 -27 -47 4 -26 50 -17 10 -27 43 -23 3 -20 -53 17 -13 -17 13 -27 -7 -10 -46 0 -7 -26 17 -17 -24 -20 -46 -3 -44 -184 -26 0 -10 -33 13 -20 33 -7 4 -23 -24 -50 17 -47 -13 -43 80 -50 20 13 10 -20 76 4 27 -30 40 0 -3 -27 -4 -27 -33 20 -10 -23 43 -27 -10 -20 -53 30 -20 -16 17 -50 10 0 6 0 4 0 6 0 7 3 3 0 7 3 3 -6 4 -4 0 -6 0 -7 -4 -3 -3 -7 -3 -3 23 -14 7 -26 43 -7 50 -60 77 30 43 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil1","@d":"M1042 1167l50 23 14 -10 70 10 46 53 30 -13 67 3 53 80 -10 44 30 16 -26 20 20 37 53 0 23 -27 30 0 7 -26 30 -7 3 10 0 40 44 13 -4 34 0 3 30 -3 -3 43 -87 23 14 34 -7 26 27 7 6 17 -20 23 14 37 -24 26 14 20 -24 17 20 7 -3 6 -17 7 0 33 -36 37 30 10 -17 67 -27 16 -23 -20 -13 14 -4 -24 -26 7 3 50 -17 17 37 43 -43 20 20 27 -4 16 -93 -3 -27 27 7 36 -30 14 -27 -10 -10 6 10 20 -63 74 -43 10 -20 -14 -14 24 -30 0 -76 36 -20 -16 -74 10 -10 23 -23 0 -20 -37 13 -20 -33 -23 7 -17 6 -3 0 -50 30 -10 24 -40 -10 -33 -44 -4 -20 -53 144 -153 -24 -44 40 -43 30 -97 20 -143 -6 -63 -30 -60 20 -10 16 -74 -36 -16 -7 -47 73 -103z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil1","@d":"M-921 1257l123 20 7 16 -17 30 20 17 7 3 10 -6 10 0 3 16 -10 7 -53 0 -23 -20 -44 10 -53 -50 20 -43z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil1","@d":"M-2841 2347l3 3 7 7 3 3 4 3 3 7 -3 7 0 6 -4 4 -3 6 3 7 0 3 7 4 3 -4 7 -3 3 -7 4 -3 0 -7 3 -3 7 0 3 7 3 3 7 3 7 0 3 4 7 3 3 7 3 0 7 0 7 0 3 3 3 7 4 3 0 7 0 6 0 4 3 6 3 4 4 0 0 -7 3 -3 7 0 6 0 7 0 3 3 4 3 3 7 0 7 3 3 0 7 4 6 3 4 7 3 3 3 3 4 7 -7 0 -3 0 -7 -3 -7 0 -3 -4 -7 -3 -3 -3 -7 -4 -3 -3 -7 -3 -3 -7 -3 -3 -7 -4 -3 -3 -4 -3 -6 -4 -4 -6 -3 43 3 0 30 10 7 17 -7 3 10 10 -3 30 -57 70 17 67 -17 26 27 24 -7 43 54 7 -24 30 -6 10 36 33 17 20 -13 3 -34 7 -13 20 3 13 24 20 -4 30 24 -13 63 23 17 7 26 -37 127 -50 57 -73 40 7 23 -27 33 -27 14 -30 -7 -3 33 37 -10 10 17 -17 53 -27 0 -3 30 -30 -16 7 -24 -37 10 -33 34 3 56 -30 30 -37 4 0 -44 -50 20 -13 30 -43 -16 -20 -27 -40 -13 3 -4 3 -6 4 -4 3 -3 3 -7 -3 -6 3 -7 -83 -60 -190 107 -10 40 -67 20 -16 -14 -24 17 -36 -7 -20 -20 46 -60 -33 -66 33 -54 -26 -36 23 -64 -13 -73 6 -60 14 -10 -50 -93 6 -37 7 0 7 0 6 0 4 0 6 -3 7 -4 3 -3 7 -3 3 -4 4 -3 3 -7 3 -3 0 -7 4 -6 0 -4 3 -6 3 -4 0 -6 4 -7 3 -3 3 -7 4 -3 3 -7 3 -3 4 -7 0 -3 3 -7 3 -3 7 -4 3 -3 4 -7 3 -3 7 -3 3 -4 3 -6 7 -4 3 0 7 -3 7 0 3 0 7 0 6 -3 7 0 3 0 7 0 3 -4 7 -6 3 -4 4 -3 6 -3 7 0 3 -4 4 -3 3 -3 10 0 7 0 6 0 7 0 3 0 7 0 7 3 6 0 4 0 6 0 7 3 3 4 7 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil1","@d":"M-2301 3207l93 23 77 -53 10 36 20 0 90 -80 3 -33 57 -10 23 63 50 -10 27 14 47 -30 30 -44 16 4 7 26 30 27 30 -40 30 -13 30 36 43 -16 34 36 110 30 23 27 20 -7 57 20 6 24 -13 23 -7 0 -3 3 -7 4 -3 3 -3 3 -7 4 -3 6 -4 4 -6 3 -4 3 -3 4 -3 6 -4 4 0 6 -6 4 -4 0 -6 0 -7 0 -7 3 -3 3 -7 4 -3 0 -7 3 -3 3 -7 4 -3 3 -7 3 -3 4 -3 3 23 27 7 3 50 -47 50 -10 0 -20 60 -20 13 -20 27 0 6 0 7 0 7 0 3 0 7 0 6 0 10 0 7 0 7 0 6 0 4 0 6 0 7 0 3 -3 4 0 26 0 40 -30 7 17 7 53 33 7 -17 80 30 16 44 100 46 50 -6 130 -44 17 -83 -37 -23 17 -54 0 -10 57 -60 -4 -66 70 -64 7 -43 20 -33 -17 -44 24 -60 -27 -6 -43 -54 -10 -16 16 -24 -16 17 -67 23 0 4 -40 16 -7 -10 -40 -60 4 -20 50 -26 16 -107 -33 -23 30 -20 -50 -60 47 -7 26 -37 4 -36 23 3 -60 -53 -40 -24 17 -23 73 -13 13 -7 4 -133 -134 36 -90 -16 -26 3 -30 -7 0 -3 0 -7 0 -6 0 -4 3 -6 3 -4 0 -6 7 -4 3 -3 7 -3 3 -7 0 -3 0 -7 -3 -7 0 -3 -3 -3 -4 -7 -6 20 -70 -23 -14 -44 7 27 -97 -3 -60 23 -16z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil1","@d":"M-1984 3720l36 -23 10 26 -23 60 -27 14 27 70 -7 13 -50 -3 -20 26 -16 50 23 37 -27 10 -46 -13 23 63 50 27 -7 30 -30 -4 -23 20 -27 90 -30 7 -63 0 -13 10 6 23 -13 10 -43 24 -30 36 -40 0 -20 50 -90 57 -4 70 27 50 3 43 -10 34 -30 20 -26 -4 -50 40 -14 -30 30 -20 -10 -20 -26 -10 -47 10 -50 47 3 33 -20 40 -96 20 -44 30 -96 -46 -4 -24 -30 -20 -23 4 -13 33 -60 -13 -10 -44 -120 -23 10 -50 -80 -27 -90 24 -30 -74 -70 -110 -20 -13 3 -3 3 -7 4 -3 3 -7 3 -3 0 -7 -3 -7 0 -6 0 -4 0 -6 0 -7 0 -3 0 -7 3 -7 0 -6 4 -4 3 -6 3 -4 4 -3 3 -7 3 -3 4 -3 3 -7 3 -7 0 -3 4 -7 0 -6 -4 -4 0 -6 -3 -7 -7 -3 0 -7 0 -7 0 -6 0 -7 0 -3 0 -7 4 -7 3 -3 3 -3 7 -4 3 -6 4 -4 6 -3 4 -3 3 -4 7 -3 3 -3 7 -4 3 -3 7 -3 3 -4 3 -3 7 -3 3 -4 7 -3 3 -3 4 -4 6 -6 4 -4 3 -3 7 -3 3 -4 3 -3 7 -7 3 -3 -3 -30 53 -80 -6 -40 -27 -30 -73 0 6 -43 -56 -30 6 -47 20 3 24 -36 -10 -4 6 -16 27 -24 30 7 -17 17 7 33 17 -7 26 -46 -26 -20 10 -17 90 37 46 3 4 33 26 17 -33 53 17 40 43 10 43 -10 40 30 7 -20 87 17 13 -7 20 4 10 46 40 10 50 40 53 -53 20 3 7 34 33 -34 14 20 53 -16 13 -24 77 44 43 -20 10 -30 -16 -24 20 -16 33 0 30 33 37 -3 23 -47 7 -53 23 -14 43 20 57 -23 13 -40 27 17 7 0 0 3 -4 7 0 6 0 4 0 6 -3 7 0 7 0 3 -3 7 -4 6 -3 4 -3 6 -4 4 -3 3 -7 3 -3 4 -7 3 -3 3 -7 0 -3 -3 -3 -7 -4 -3 0 -7 -6 0 -4 4 0 3 0 7 0 6 0 7 0 3 -3 7 0 7 -3 3 0 7 -4 6 0 7 0 3 4 10 3 4 7 -4 -4 -6 0 -4 0 -6 0 -7 0 -7 4 -3 6 -3 4 -4 6 -3 4 -3 6 0 4 -4 6 -3 4 -3 6 -4 4 -3 6 -3 4 -4 3 -6 3 -4 4 -6 3 -4 3 -6 0 -4 4 -6 3 -7 0 -3 3 -7 0 -7 4 -3 3 -7 0 -3 7 -3 3 -4 7 -3 6 0 7 3 3 4 4 6 3 4 3 6 4 4 3 3 3 7 7 3 3 0 7 3 3 7 0 3 4 7 3 7 0 3 3 7 4 3 6 3 10 0 -3 -3 0 -7 -3 -6 -4 -4 -3 -6 -3 -4 3 -6 3 -7 -3 -3 -3 -4 -4 -3 -6 -3 -4 -4 -6 -3 -4 -3 -6 -4 -4 -3 0 -7 7 -3 3 3 7 0 7 -3 3 0 57 -30m-437 303l0 4 7 0 6 0 4 -4 6 -3 4 -3 6 -4 4 -3 6 0 7 -3 3 0 7 -4 7 -3 3 -3 7 -4 3 -3 3 -3 7 -4 3 -3 4 -3 3 -7 10 -7 -7 0 -6 0 -7 0 -3 4 -7 3 -3 3 -7 4 -3 3 0 7 -7 3 -3 3 -7 0 -7 4 -3 3 -7 0 -6 3 -4 0 -6 4 -7 0 -3 3 -4 7 -3 6m30 60l3 -3 7 0 7 0 6 3 4 0 6 0 7 4 3 0 7 3 7 0 6 0 4 0 6 -3 7 0 3 -7 7 0 3 0 7 -3 7 0 6 0 4 0 6 0 7 0 7 0 3 3 7 3 3 4 0 6 3 7 4 3 3 4 7 3 3 3 7 4 3 3 3 3 7 4 3 3 7 3 7 0 3 -6 0 -7 -3 -3 -4 -7 -3 -3 -7 0 -6 -4 -4 -3 -6 0 -4 -3 -6 -7 -4 -3 -3 -4 -3 -6 3 -7 0 -3 3 -7 0 -7 -3 -3 -7 0 -6 0 -4 3 -6 4 -4 3 -6 3 -7 0 -3 0 -7 0 -7 0 -6 0 -4 0 -6 0 -7 0 -3 4 -7 3 -3 3 -7 0 -7 4 -6 0 -4 0 -6 -4 -7 0 -3 -3 -7 -3 -3 -4 -7 0 -7 4 -3 3 0 7 0 6z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil1","@d":"M-2818 4783l4 17 26 7 -20 33 20 27 -36 20 -7 40 -17 3 -20 -20 -116 23 -44 60 7 17 80 10 0 33 47 90 -30 17 6 37 -23 13 27 37 -14 40 4 86 -27 30 17 64 -14 40 27 30 -17 50 -13 6 -20 -10 -23 -56 -57 -70 -217 -140 10 -27 -6 -3 -30 16 6 14 -10 6 -80 -33 -113 13 -27 14 -10 -7 -20 -37 -6 -13 -4 -7 0 -6 0 -7 0 -7 0 -3 0 -7 0 -6 0 -4 -3 -6 0 -7 0 -7 0 -3 0 -7 0 -6 0 -7 0 -3 -3 -7 0 -7 0 -6 0 -4 0 -6 0 -7 0 -7 0 -3 0 -7 0 -6 -4 -7 0 -7 0 -3 -3 -7 0 -3 -3 -7 -4 -3 -6 -7 -4 -3 -3 -3 -3 -7 -7 -7 47 -73 16 -73 77 -64 30 -106 70 -7 13 -30 57 13 47 -130 80 27 -10 50 120 23 10 44 60 13 13 -33 23 -4 30 20 4 24 96 46z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil2","@d":"M-348 880l47 -10 20 40 30 -30 83 17 7 50 -20 53 -27 27 27 33 43 7 4 -50 16 -10 10 6 -6 20 20 20 30 -6 146 70 60 3 44 -13 13 33 -50 10 -17 47 4 46 -30 27 -67 37 -7 40 -56 0 -27 70 -27 -7 -16 23 10 37 -37 37 -7 33 14 23 -30 37 -17 63 17 70 50 54 -50 86 -4 14 -46 -10 -30 13 -60 -40 -24 10 -40 -30 -43 -3 -27 -20 0 -34 44 -56 53 3 13 -20 -3 -13 -7 -4 -3 -3 -7 -3 -3 -4 -7 0 -3 -3 -7 -3 -6 -4 -4 -3 -6 0 -4 -3 -6 -4 -7 0 -3 -3 -7 0 -7 -3 -3 -4 -3 -3 0 -7 0 -6 -4 -7 -6 -7 -4 -3 -6 -7 -4 -3 -3 -3 -3 -4 -7 -3 -3 -7 -4 -3 -6 -3 -4 -4 -3 -3 -13 -3 -7 -4 -7 0 -3 0 -7 0 -6 0 -7 0 -3 0 -4 -3 -6 -7 -4 -3 -3 -7 -3 -3 -4 -3 -3 -4 -7 -3 -3 0 -7 0 -6 0 -7 0 -3 0 -7 -3 -7 0 -3 -4 -7 -3 -3 -3 -7 -4 -3 -3 -7 0 -3 -3 -7 -4 -6 0 -4 -3 -6 0 -7 0 -7 0 -3 -3 -7 0 -6 0 -7 -4 -3 0 -7 -3 -7 0 -3 0 -7 -3 -6 0 -4 -4 -6 0 -7 0 -7 -3 37 -7 13 -50 -13 -26 -23 20 -24 -30 47 -37 27 20 36 -17 -20 -56 27 -14 -3 -36 23 -34 -10 -36 23 -44 40 10 20 -26 27 -7 13 -60 60 -47 -6 -60 43 -10 23 -46 30 -7z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil2","@d":"M-391 1827l43 3 40 30 24 -10 60 40 30 -13 46 10 4 -14 50 -86 -50 -54 -17 -70 17 -63 30 -37 -14 -23 7 -33 37 -37 -10 -37 16 -23 27 7 27 -70 56 0 7 -40 67 -37 -4 27 17 16 -17 24 7 36 -13 20 16 17 -16 27 23 3 -3 60 46 23 -53 104 17 6 13 -26 33 6 17 -46 0 -17 10 -10 7 3 6 50 -16 40 6 130 -13 10 -17 -26 -30 66 60 30 60 0 77 80 7 80 73 27 10 37 63 40 20 -17 24 3 66 164 27 10 0 -14 7 0 6 14 37 0 -3 6 -4 4 -3 3 -7 3 -6 0 -4 0 -6 0 -7 0 -3 4 -7 3 0 7 0 6 -3 4 0 6 0 7 -7 0 -7 0 -3 0 -7 -3 -6 -4 -4 0 -6 0 -7 0 -3 4 -7 3 0 10 3 3 7 0 7 0 6 4 4 0 6 0 7 3 3 3 7 0 7 0 3 0 7 -3 3 -7 3 -3 0 -7 4 -6 3 -4 3 -6 4 -4 6 0 4 -3 6 0 7 -3 3 -4 4 -3 3 -7 3 -3 4 -7 3 -3 3 -7 0 -6 4 -4 0 -6 0 -7 3 -3 3 -4 7 -3 7 -3 6 0 4 0 6 0 7 0 3 3 7 3 3 7 4 3 3 4 7 3 6 0 10 0 -3 -7 -3 -3 -4 -7 -3 -3 -3 -3 -7 -4 -3 -3 -7 -3 7 -14 50 10 -7 17 33 23 -13 20 20 37 -3 23 0 4 -34 23 -6 37 -47 26 7 40 -80 -3 -17 23 -33 -53 -120 -47 -50 -46 -14 13 -36 -17 -44 -53 -46 -3 -4 30 -3 3 0 -3 -23 3 0 43 -20 14 30 23 -34 60 -43 -33 -23 46 -30 0 -17 -26 -33 50 -30 -14 10 -36 -24 6 -43 -20 -27 27 -33 -7 -27 17 7 33 -23 17 -24 -3 -16 -24 -54 54 10 20 -13 26 -83 7 -104 -103 -70 -37 -16 -23 -54 20 -50 -24 -16 -100 23 -36 10 -50 37 6 6 37 50 -23 -26 -60 6 -44 -13 -30 17 -10 20 7 36 -43 24 0 16 -40 -40 -57 24 -43 -27 -77 0 -33z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil2","@d":"M-914 1427l33 -47 33 27 -10 53 10 3 7 0 3 4 4 3 3 7 3 3 7 0 7 3 6 0 4 0 6 0 7 -3 3 -3 7 0 7 0 3 -4 7 0 6 0 7 0 3 4 7 0 3 3 7 3 7 0 6 0 4 4 6 0 7 3 3 0 7 0 7 3 3 0 7 4 6 0 7 0 3 3 7 0 7 0 6 0 4 3 6 0 7 4 3 3 7 0 3 3 7 4 3 3 7 3 3 4 7 0 7 3 3 0 7 0 6 0 7 0 3 0 7 3 3 4 4 3 3 3 3 7 4 3 6 7 4 3 3 0 7 0 6 0 7 0 3 0 7 0 7 4 13 3 3 3 4 4 6 3 4 3 3 7 7 3 3 4 3 3 4 3 6 7 4 3 6 7 4 7 0 6 0 7 3 3 3 4 7 3 7 0 3 3 7 0 6 4 4 3 6 0 4 3 6 4 7 3 3 3 7 0 3 4 7 3 3 3 7 4 3 13 -13 20 -53 -3 -44 56 0 34 27 20 0 33 -57 30 -76 -23 -4 -47 -26 -23 13 -37 -33 -7 -40 17 -20 -40 -67 3 -33 24 -7 -4 -10 14 0 20 -37 50 -90 -14 20 -53 -16 -23 -27 13 -7 47 -33 23 -23 -10 -10 -43 -57 0 -53 -84 20 -46 -17 -60 30 -14 -20 -30 10 -10 10 24 7 -4 3 -43 -23 -27 6 -36 -16 -4 0 -10 23 -26 -3 -20 6 -14 50 -3 27 13 27 -13 3 10 0 7 3 3 4 7 3 3 3 7 4 3 3 7 3 3 4 7z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil2","@d":"M-3671 1377l17 20 -10 33 73 10 3 7 -10 10 20 13 -3 0 10 7 3 3 4 3 6 4 4 3 6 3 4 4 6 3 4 3 6 0 4 4 6 0 7 3 7 0 3 0 7 -3 6 0 4 0 6 0 7 0 3 3 7 0 7 0 6 0 4 -3 6 0 7 -4 3 0 7 -3 3 -3 7 -4 3 -3 4 -3 6 -7 4 -3 6 0 4 -4 6 0 7 -3 3 0 7 0 7 0 6 0 4 0 6 0 7 0 7 0 3 3 7 4 3 3 7 3 3 4 0 6 3 7 0 3 4 7 3 7 3 3 7 3 3 4 7 0 7 3 50 -83 50 10 23 -20 50 23 17 10 -17 50 57 50 -30 63 -10 30 -34 -10 -40 34 -10 33 -30 27 0 23 20 17 -13 46 -30 17 -43 -33 -34 6 -10 70 -70 27 -26 -3 -27 23 -17 -37 -6 0 -17 -6 -13 23 -47 3 7 -33 -57 -23 -73 13 -20 17 -7 0 -3 -34 -14 0 -6 20 -27 0 -43 40 -44 7 -20 -10 4 -33 -24 -10 -6 -27 36 -50 40 -23 4 -27 -24 -20 -30 10 -6 -70 3 0 3 -7 4 -3 3 -7 0 -3 0 -7 0 -6 0 -7 -3 -3 3 -7 0 -7 -27 7 -16 -13 3 -40 -37 -37 -6 -100 93 -50 87 17 53 -20z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil2","@d":"M-2098 1627l-16 90 50 10 13 43 -53 107 10 20 60 -10 40 63 30 7 33 -34 27 4 33 46 37 -13 13 13 -10 27 17 13 23 0 20 -20 47 14 36 -27 60 3 17 24 30 3 -20 30 30 27 -7 56 17 -6 0 3 17 27 -10 43 -64 30 -133 23 -90 30 17 50 -17 24 -33 -10 -7 6 10 27 -43 37 6 30 -6 3 -20 -7 -20 24 -44 10 -26 30 -80 -47 -74 17 -30 -24 -20 4 -13 -24 -20 -3 -7 13 -26 -6 26 -47 -23 -83 17 -37 -17 -43 3 -4 40 -23 4 -23 -17 -14 10 -26 -30 -10 0 -50 -23 -37 0 -23 30 -24 3 -20 -7 -3 14 -63 -17 -20 27 -27 -47 -47 -3 -70 0 -33 20 -20 20 10 10 -20 20 3 6 -6 -6 -7 13 -23 27 6 36 -33 14 17 6 6 14 0 3 -13 23 7z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil2","@d":"M752 2710l24 0 13 20 33 10 -6 37 70 20 23 36 43 17 -83 170 -90 103 -17 60 -56 40 -20 80 -57 70 -43 80 -47 -16 -17 -30 -36 -7 -24 40 -43 33 -23 -33 -67 3 -10 -63 -20 -7 -20 27 -37 -47 -26 -30 3 -43 30 -17 10 -30 40 0 30 -23 37 -87 0 -40 26 10 50 -16 10 -37 60 -57 -36 -46 43 -30 -23 -24 3 -70 -47 -3 -3 -37 27 -13 13 13 37 -20 10 -46 20 -27 63 43 47 -10 13 30 73 -33z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil2","@d":"M-2148 4220l40 33 54 0 6 50 84 30 56 60 44 17 46 57 104 30 20 6 16 34 -3 36 30 64 -60 113 -3 3 -7 147 43 13 -20 40 40 27 -26 47 30 10 60 76 -7 14 43 63 -53 -7 -37 44 -43 6 -13 80 -40 34 -34 -27 -10 -43 -36 6 -17 37 -27 10 -33 0 -10 -30 -23 -3 -27 -70 -50 16 -17 -16 -10 -60 -30 -7 -30 -50 4 -67 -4 -6 -16 3 -4 -3 10 -27 -30 -47 -43 7 0 17 -7 0 -10 -14 -3 17 -10 3 -33 -6 -97 66 -30 -33 0 -33 3 -4 7 0 7 -3 3 -3 7 0 3 -4 7 -3 3 -3 7 0 6 -4 7 -3 -7 -47 -16 -13 -4 -40 -36 -23 0 -54 -37 -30 0 -33 -57 -73 30 -20 10 -34 -3 -43 -27 -50 4 -70 90 -57 20 -50 40 0 30 -36 43 -24 13 -10 -6 -23 13 -10 63 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil2","@d":"M-1714 4497l10 -37 213 23 53 -43 110 20 24 -37 16 30 40 7 40 -20 14 -33 20 -7 113 23 40 -26 20 23 63 -17 17 10 73 -53 44 23 53 -10 13 70 50 14 0 70 24 13 10 7 -7 53 -60 87 -27 13 -10 57 -26 16 -27 -6 -47 40 -63 123 7 53 -47 30 -10 27 -33 -10 -30 13 -50 -33 -27 0 -40 40 -47 20 -80 -40 -60 63 -80 37 -23 -3 -27 70 -56 10 -34 -17 -43 -63 7 -14 -60 -76 -30 -10 26 -47 -40 -27 20 -40 -43 -13 7 -147 3 -3 60 -113 -30 -64 3 -36 -16 -34 -20 -6m846 186l7 -3 7 -3 3 -4 3 -6 4 -4 0 -6 -4 -4 -3 -6 -3 -7 0 -3 0 -7 3 -3 3 -7 7 -3 3 -4 4 -6 3 -4 3 -3 0 -7 0 -3 -6 0 -4 7 -3 3 -3 7 -4 3 -3 3 -3 7 -7 3 3 4 0 6 0 7 -3 7 0 3 0 7 -3 6 -4 4 0 6 -3 7 3 3z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil2","@d":"M-721 4687l120 40 77 76 -47 37 -3 50 13 20 -27 67 7 40 -33 -4 -4 14 10 50 -10 16 -40 10 -3 14 -50 23 -53 47 -14 120 -13 10 -47 -14 -13 -20 -37 -10 -56 130 -30 -3 -10 10 26 90 -53 47 27 50 -67 40 3 26 -120 7 -23 23 -40 14 -93 -40 -74 16 -30 -10 7 -43 -33 -40 -127 -37 -33 -33 -64 -27 -6 -23 -30 -3 -10 -77 -20 -43 40 -34 13 -80 43 -6 37 -44 53 7 34 17 56 -10 27 -70 23 3 80 -37 60 -63 80 40 47 -20 40 -40 27 0 50 33 30 -13 33 10 10 -27 47 -30 -7 -53 63 -123 47 -40 27 6 26 -16 10 -57 27 -13z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil2","@d":"M-524 4803l23 20 23 -10 24 17 43 0 17 23 -10 40 3 104 103 146 54 0 63 47 -77 97 -16 -7 0 3 10 7 -64 220 -56 40 0 33 -34 24 -3 26 -37 30 -36 14 -57 -74 -43 -13 -37 20 -33 -10 -47 10 -43 80 -50 23 -34 -3 -23 -17 -27 7 -40 -40 -120 3 -3 -26 67 -40 -27 -50 53 -47 -26 -90 10 -10 30 3 56 -130 37 10 13 20 47 14 13 -10 14 -120 53 -47 50 -23 3 -14 40 -10 10 -16 -10 -50 4 -14 33 4 -7 -40 27 -67 -13 -20 3 -50 47 -37z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil3","@d":"M-3514 537l-10 33 10 27 -20 16 -27 110 -30 50 -33 0 0 47 -30 37 6 20 -23 46 23 70 -16 34 16 66 -50 80 -33 7 -17 -13 -53 -7 -17 7 4 16 -27 -6 -10 13 -20 -17 -10 10 -7 24 -30 0 -10 26 -73 -10 -97 40 -10 34 -23 10 -37 -20 -3 26 -7 4 -6 -14 -17 4 -10 33 -47 37 -10 -7 0 -27 -16 -3 -4 -17 30 -73 40 -27 -13 -23 -43 -7 -14 34 -30 -44 24 -20 -20 -30 6 -33 -3 -3 -23 -10 0 6 -24 -13 -16 27 -20 -27 20 -30 -7 -50 20 -37 47 -16 0 -14 -20 10 0 -26 40 -27 36 13 30 -33 20 3 7 -13 -10 -27 73 -36 70 40 57 -20 33 6 60 -43 30 17 14 -4 0 -23 16 -10 30 33 30 -6 7 -30 -27 0 -46 -34 10 -43 16 -7 -6 -10 16 -13 17 0 37 -47 13 10 30 -26 20 3 7 -43 40 0 46 -37 20 0 0 33 -3 7 7 10 13 3 7 -23 66 -37 14 7 -20 27z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil3","@d":"M-3174 727l20 -27 -4 -27 40 -10 80 20 20 -10 17 17 47 -13 70 16 90 -6 56 -17 64 20 46 -23 30 10 34 -34 36 -13 70 57 7 20 150 -4 67 20 36 37 47 -10 30 17 290 56 -17 30 14 30 -7 24 -40 -17 -13 20 -47 7 -7 53 -53 3 -17 -30 -26 -6 -47 40 -37 0 -26 56 -17 -13 -37 23 -80 -6 -16 30 -40 -4 -10 24 -30 3 -54 -17 -43 14 -27 36 -60 -10 -36 -23 -17 -40 -20 10 -33 -10 -17 30 -50 -17 -10 27 -73 -37 -30 47 -14 0 -6 13 10 7 -4 17 -63 16 -77 -10 -33 27 -33 -20 -10 -50 -40 -20 -24 13 -13 -23 30 -40 40 -10 23 -37 -26 -20 -44 24 0 -47 -46 -27 -4 -46 -33 -30 -3 -34 -20 -6 3 -30 37 0 30 -40z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil3","@d":"M-1831 823l157 0 220 -73 20 20 -34 17 4 16 13 4 40 -37 80 -30 77 33 0 14 -14 3 17 20 50 -3 7 10 46 3 44 33 0 27 -17 13 -77 -3 -63 47 10 73 -43 0 -77 -30 -50 60 -43 7 -7 26 -23 14 -7 0 -7 -4 -6 0 -4 0 -6 -3 -7 0 -3 3 -7 4 -3 3 -4 7 -3 3 -3 3 -7 4 -3 3 -7 0 -7 -3 -3 0 -7 -4 -6 0 -7 0 -3 4 -7 0 -3 3 -4 7 4 6 3 4 3 3 7 3 7 -3 6 0 7 0 7 -3 6 0 7 0 3 0 7 -4 7 -3 3 0 7 -3 -17 50 20 16 53 -30 10 20 -43 27 10 23 33 -20 4 27 3 27 -40 0 -27 30 -76 -4 -57 -36 30 -17 -3 -20 -30 17 -14 -7 -10 -77 -60 -13 -33 -53 -23 -7 -57 27 -87 3 -20 -50 -36 -20 3 -57 53 -3 7 -53 47 -7 13 -20 40 17 7 -24 -14 -30 17 -30z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil3","@d":"M-778 1040l10 30 -40 27 4 23 26 13 77 0 80 44 10 36 -23 34 3 36 -27 14 20 56 -36 17 -27 -20 -47 37 24 30 23 -20 13 26 -13 50 -37 7 -3 -3 -7 0 -3 -4 -7 0 -6 0 -7 0 -3 4 -7 0 -7 0 -3 3 -7 3 -6 0 -4 0 -6 0 -7 -3 -7 0 -3 -3 -3 -7 -4 -3 -3 -4 -7 0 -10 -3 10 -53 -33 -27 -33 47 -4 -7 -3 -3 -3 -7 -4 -3 -3 -7 -3 -3 -4 -7 -3 -3 0 -7 -3 -10 0 -3 -4 -7 0 -7 -3 -3 -3 -7 -4 -3 -6 -3 -4 -4 -3 -3 -7 -3 -6 0 -4 -4 -6 0 -7 -3 -3 0 -7 -3 -3 -4 -7 -3 -3 -3 -4 -4 -6 -6 -4 -4 -3 -3 -3 -7 -4 -3 -6 0 -7 0 -7 0 -3 0 -7 0 -10 3 -10 -10 10 -66 -6 -7 -10 10 -24 0 -10 27 -33 -34 33 -56 60 33 67 -23 -43 -57 -60 -7 16 -13 4 -47 -24 -16 17 -27 57 3 3 -36 30 3 20 40 -13 40 93 43 83 7 -10 -40 60 -10m-143 217l-20 43 53 50 44 -10 23 20 53 0 10 -7 -3 -16 -10 0 -10 6 -7 -3 -20 -17 17 -30 -7 -16 -123 -20z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil3","@d":"M1532 1380l114 27 3 6 20 47 23 13 40 -10 27 -43 67 -17 93 27 20 30 30 10 23 -23 40 6 20 -43 57 -10 80 -53 50 0 30 30 43 -10 0 56 20 14 37 -7 20 20 -10 40 -37 23 -26 -20 -24 37 10 63 34 14 20 30 -10 33 23 40 -10 50 -53 40 -24 43 -53 54 -60 23 -23 30 -14 -60 -56 -3 -60 26 -44 -46 -73 -14 -7 -43 4 -7 20 4 50 -30 -4 -17 -26 -20 26 -10 10 -37 -10 -30 -36 4 -34 -37 -33 10 -20 -27 -73 30 -64 -23 -16 -20 3 -13 23 0 0 -14 -10 -13 17 -47 -77 -13 -43 10 3 -43 -30 3 0 -3 4 -34 -44 -13 0 -40z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil3","@d":"M1396 2057l26 6 4 20 -27 20 47 30 3 54 57 26 -10 14 16 33 24 -3 -7 30 -20 3 3 7 30 10 0 23 -230 77 -23 40 -30 -10 -77 30 -140 176 24 27 33 -3 57 36 -4 4 -63 46 -50 64 -33 0 -7 -14 43 -10 -3 -30 -47 17 -40 70 -43 -17 -23 -36 -70 -20 6 -37 -33 -10 -13 -20 -24 0 -3 -10 33 -20 24 -37 -17 -53 23 -57 -13 -36 -27 -10 -6 -24 -7 -40 47 -26 6 -37 34 -23 0 -4 3 -23 23 0 10 -23 74 -10 20 16 76 -36 30 0 14 -24 20 14 43 -10 63 -74 -10 -20 10 -6 27 10 30 -14 -7 -36 27 -27 93 3 4 -16z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil3","@d":"M-601 4727l67 -124 63 -36 30 -47 33 20 47 -13 87 -64 3 -3 37 7 23 40 53 -10 44 -44 -17 -113 27 -30 3 -57 27 -26 20 -7 16 13 47 -40 47 -16 30 10 6 26 50 37 10 113 -43 60 7 50 50 14 16 33 -6 57 -30 56 6 34 7 10 67 103 43 40 43 13 7 27 -7 10 -10 -7 -13 7 -30 60 33 40 40 13 7 -3 -3 -17 3 0 20 24 -20 23 -113 40 -37 -23 -50 6 -27 17 4 10 -10 3 -54 -26 -20 16 -43 0 -70 54 -17 50 -23 0 -60 33 -63 -47 -54 0 -103 -146 -3 -104 10 -40 -17 -23 -43 0 -24 -17 -23 10 -23 -20 -77 -76z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil3","@d":"M-2468 4647l57 73 0 33 37 30 0 54 36 23 4 40 16 13 7 47 -7 3 -6 4 -7 0 -3 3 -7 3 -3 4 -7 0 -3 3 -7 3 -7 0 -3 4 0 33 30 33 97 -66 33 6 10 -3 3 -17 10 14 7 0 0 -17 43 -7 30 47 -10 27 4 3 16 -3 4 6 -4 67 30 50 30 7 10 60 17 16 50 -16 27 70 -44 3 7 37 -40 30 -23 -34 -30 30 -24 -6 -6 6 16 17 -6 20 -60 43 -70 17 -7 17 -43 36 -20 -3 -24 -37 -26 -3 -57 50 -10 -3 -10 -24 23 -20 0 -26 -33 -7 -17 10 17 30 -3 17 -30 33 -17 0 -13 -17 -24 -10 -33 4 -13 20 -84 13 -26 43 -100 -3 -64 -33 -43 -4 0 -3 -20 -13 -30 10 -27 -30 14 -40 -17 -64 27 -30 -4 -86 14 -40 -27 -37 23 -13 -6 -37 30 -17 -47 -90 0 -33 -80 -10 -7 -17 44 -60 116 -23 20 20 17 -3 7 -40 36 -20 -20 -27 20 -33 -26 -7 -4 -17 44 -30 96 -20 20 -40 -3 -33 50 -47 47 -10 26 10 10 20 -30 20 14 30 50 -40 26 4z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil3","@d":"M-2871 5540l0 3 43 4 64 33 100 3 26 -43 84 -13 13 -20 33 -4 24 10 13 17 17 0 30 -33 3 -17 -17 -30 17 -10 33 7 0 26 -23 20 10 24 10 3 57 -50 26 3 24 37 20 3 43 -36 23 30 7 40 -27 50 -33 10 -37 -30 -26 -4 -30 30 30 44 -24 66 -36 34 -37 10 -40 63 -47 -10 -6 3 3 20 43 10 20 -23 17 -3 30 3 43 80 10 60 10 7 17 -7 20 20 -43 60 -14 53 -6 0 -14 -13 -30 -3 -6 3 0 77 -90 43 -17 -3 -40 -37 -73 -17 -54 -66 -16 -7 -57 -3 -17 -14 -36 -63 -27 -17 -90 -170 17 0 26 47 7 3 20 -26 -3 -7 -17 3 -7 -13 0 -37 -36 -30 -44 -3 -33 -73 10 -24 53 -30 14 -60 13 -13 30 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil4","@d":"M-1104 853l26 -10 37 20 -3 -30 46 -23 4 -20 73 3 23 -20 34 34 100 23 50 40 -10 23 10 17 -37 47 -3 63 -24 20 -60 10 10 40 -83 -7 -93 -43 13 -40 -20 -40 -30 -3 -3 36 -57 -3 -67 -27 -83 47 -10 -73 63 -47 77 3 17 -13 0 -27z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil4","@d":"M-378 833l30 47 -30 7 -23 46 -43 10 6 60 -60 47 -13 60 -27 7 -20 26 -40 -10 -23 44 -80 -44 -77 0 -26 -13 -4 -23 40 -27 -10 -30 24 -20 3 -63 37 -47 -10 -17 10 -23 50 17 63 -14 40 17 127 -40 46 -37 10 20z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil4","@d":"M-4108 1297l10 -34 97 -40 73 10 10 -26 30 0 7 -24 10 -10 20 17 10 -13 27 6 -4 -16 17 -7 53 7 17 13 33 -7 14 4 -7 53 57 47 -37 100 -53 20 -87 -17 -93 50 6 100 37 37 -3 40 16 13 27 -7 0 7 -3 7 3 3 0 7 0 6 0 7 0 3 -3 7 -4 3 -3 7 -3 0 -7 3 -3 4 -7 3 -7 0 -3 3 -7 0 -6 4 -4 3 -6 3 -4 4 -3 3 -7 3 -3 4 -7 3 -3 3 -7 0 -6 4 -4 0 -6 3 -7 0 -7 0 -3 0 -7 0 -6 0 -7 0 -3 0 -7 -3 -7 0 -3 0 -7 0 -6 0 -7 3 -3 3 -4 4 -6 3 -4 3 -6 4 -4 0 -6 0 -7 -4 -7 0 -3 4 -7 3 -3 0 -7 3 -3 4 -7 3 -3 3 -3 7 -4 3 -3 7 -3 3 -4 4 -3 6 -7 4 -3 3 -3 3 -4 4 -6 6 -4 4 -3 3 -73 40 0 -160 23 -13 7 3 6 -10 -6 -13 43 -47 83 -43 7 -40 -7 -7 -30 50 -70 13 0 -53 20 -3 54 -64 -7 -10 -40 30 -43 0 -17 -46 -27 -7 4 -10 26 -17 10 14 -3 10 10 10 13 -4 -3 -20 13 -3 -13 -53 33 -17 20 -43z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil4","@d":"M1599 1510l43 -10 77 13 -17 47 10 13 0 14 -23 0 -3 13 16 20 64 23 73 -30 20 27 33 -10 34 37 36 -4 10 30 -10 37 -26 10 26 20 4 17 -50 30 -20 -4 -4 7 7 43 73 14 44 46 60 -26 56 3 14 60 -274 167 -70 126 -260 87 0 -23 -30 -10 -3 -7 20 -3 7 -30 -24 3 -16 -33 10 -14 -57 -26 -3 -54 -47 -30 27 -20 -4 -20 -26 -6 -20 -27 43 -20 -37 -43 17 -17 -3 -50 26 -7 4 24 13 -14 23 20 27 -16 17 -67 -30 -10 36 -37 0 -33 17 -7 3 -6 -20 -7 24 -17 -14 -20 24 -26 -14 -37 20 -23 -6 -17 -27 -7 7 -26 -14 -34 87 -23z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil4","@d":"M-1308 2450l30 50 34 10 -4 23 24 37 -57 147 33 26 -13 50 33 14 10 -14 14 34 26 -4 -10 37 24 23 0 24 20 -7 30 20 0 50 26 13 14 24 -34 106 10 7 40 -27 17 84 0 3 -13 10 20 40 -57 17 -7 -17 -40 30 -26 0 -4 0 -3 3 -7 0 -6 0 -4 0 -6 0 -7 0 -7 0 -10 0 -6 0 -7 0 -3 0 -7 0 -7 0 -6 0 -27 0 -13 20 -60 20 0 20 -50 10 -50 47 -7 -3 -23 -27 3 -3 3 -4 7 -3 3 -3 7 -4 3 -3 7 -3 3 0 7 -4 3 -3 7 -3 7 0 6 0 4 0 6 -4 0 -6 4 -4 3 -6 3 -4 4 -3 6 -3 4 -4 3 -6 7 -4 3 -3 3 -3 7 -4 3 -3 7 0 13 -23 -6 -24 -57 -20 -20 7 -23 -27 -110 -30 -34 -36 -43 16 -30 -36 -30 13 -30 40 -30 -27 -7 -26 -16 -4 -30 44 -47 30 -27 -14 24 -56 -4 -27 10 -7 30 14 24 -60 56 -7 0 -97 24 -26 -4 -24 7 -6 17 13 40 -13 6 -50 47 -70 53 0 17 -87 27 -43 63 -24 90 -110 43 -13z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil4","@d":"M3082 3223l-163 -76 -83 16 -10 -6 0 -47 -24 -17 20 -30 124 -10 16 -10 0 -10 14 24 16 -7 0 -3 4 -7 13 0 23 43 37 4 13 53 24 23 0 7 -20 -7 0 7 16 20 -20 33z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil4","@d":"M-131 3167l67 3 3 -40 13 0 14 27 16 30 54 0 40 36 0 20 -47 20 -40 14 -37 -7 -43 -7 -40 -96z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil4","@d":"M2509 3607l-7 10 -3 0 -60 53 -13 0 -54 -60 -73 10 -30 -10 -33 -70 13 -27 -47 -36 -73 30 -10 46 -7 0 -30 -43 -50 0 -13 -30 7 -27 113 -80 107 -113 36 -10 54 -47 66 -6 57 -37 17 3 3 4 -63 40 13 30 43 -20 7 3 -7 30 -33 7 10 36 70 34 53 -47 60 23 10 20 -13 64 -23 6 6 34 -53 60 -13 66 -7 14 -27 36 -3 4z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil4","@d":"M242 3353l37 47 20 -27 20 7 10 63 67 -3 23 33 43 -33 24 -40 36 7 17 30 47 16 -7 47 -63 113 -7 57 0 7 27 83 46 83 -6 24 -4 6 37 84 90 103 0 23 -23 -23 -40 23 -14 -16 -30 23 -53 -20 -83 60 -67 3 0 24 40 3 7 13 -67 47 -17 -37 -50 -16 -46 23 -20 -27 -27 0 -13 -16 0 -67 -24 -43 -103 10 -73 -84 40 -106 0 -4 10 -76 -100 -20 -34 -27 -26 10 -34 -40 -13 -20 13 -87 64 -86 36 10 27 -14 -3 -43 36 -87 -3 -46 -3 -17 36 -17 80 -10 44 14 23 76 53 -20z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil4","@d":"M2382 3780l-23 -20 3 -3 24 -4 3 7 -7 20z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil4","@d":"M1499 4057l-13 -27 -7 0 -57 0 -10 -3 -6 -54 3 -6 40 -10 3 -10 -6 -34 36 -30 94 -43 43 17 -7 20 17 20 0 10 -40 33 -23 43 -40 20 -4 47 -23 7z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil4","@d":"M699 4060l130 50 0 17 27 33 -70 50 -14 30 -60 13 -33 67 -33 -3 -117 63 -23 30 -10 50 -20 -7 -30 20 0 94 -64 33 -3 33 -7 94 -26 13 -34 93 -43 -13 -43 -40 -67 -103 -7 -10 -6 -34 30 -56 6 -57 -16 -33 -50 -14 -7 -50 43 -60 -10 -113 67 -23 -33 -64 20 -16 13 16 27 0 20 27 46 -23 50 16 17 37 67 -47 -7 -13 -40 -3 0 -24 67 -3 83 -60 53 20 30 -23 14 16 40 -23 23 23 0 -23z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil4","@d":"M1519 4193l-10 -56 27 -30 6 0 34 46 23 10 20 -10 3 0 4 7 -4 7 -23 13 -33 -17 -14 0 -33 30z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil4","@d":"M-1934 5297l23 3 10 30 33 0 27 -10 17 -37 36 -6 10 43 34 27 20 43 10 77 30 3 6 23 64 27 33 33 127 37 33 40 -7 43 -33 -13 -77 23 -66 -20 -34 27 -156 -7 -64 94 -53 20 -20 43 -57 17 -126 -7 -134 57 -43 73 -20 -20 -17 7 -10 -7 -10 -60 -43 -80 -30 -3 -17 3 -20 23 -43 -10 -3 -20 6 -3 47 10 40 -63 37 -10 36 -34 24 -66 -30 -44 30 -30 26 4 37 30 33 -10 27 -50 -7 -40 -23 -30 7 -17 70 -17 60 -43 6 -20 -16 -17 6 -6 24 6 30 -30 23 34 40 -30 -7 -37 44 -3z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil5","@d":"M-3514 537l20 -27 -14 -7 -66 37 -7 23 -13 -3 -7 -10 3 -7 0 -33 -20 0 -46 37 -40 0 -7 43 -20 -3 -30 26 -13 -10 -37 47 -17 0 -16 13 6 10 -16 7 -10 43 46 34 27 0 -7 30 -30 6 -30 -33 -16 10 0 23 -14 4 -30 -17 -60 43 -33 -6 -57 20 -70 -40 -73 36 10 27 -7 13 -20 -3 -30 33 -36 -13 -40 27 0 26 20 -10 0 14 -47 16 -20 37 7 50 -20 30 20 27 16 -27 24 13 0 -6 23 10 3 3 -6 33 20 30 -24 20 30 44 14 -34 43 7 13 23 -40 27 -30 73 4 17 16 3 0 27 10 7 47 -37 10 -33 17 -4 6 14 7 -4 3 -26 37 20 23 -10 -20 43 -33 17 13 53 -13 3 3 20 -13 4 -10 -10 3 -10 -10 -14 -26 17 -4 10 27 7 17 46 43 0 40 -30 7 10 -54 64 -20 3 0 53 70 -13 30 -50 7 7 -7 40 -83 43 -43 47 6 13 -6 10 -7 -3 -23 13 0 160 73 -40 3 -3 -73 60 -10 83 23 47 24 156 -10 40 23 64 10 103 20 33 7 7 6 87 -66 250 3 0 23 -34 20 -80 10 0 7 10 0 7 -20 20 -3 10 0 20 23 10 0 3 -17 4 -20 50 -33 0 -10 26 -60 214 -37 83 27 40 0 3 -123 287 -20 103 -94 117 -73 33 -7 30 10 24 0 43 -53 113 0 94 -57 120 14 26 -7 20 7 14 80 23 100 -17 20 -13 30 -83 36 -50 14 0 3 50 27 50 -4 13 -70 33 4 17 36 -3 0 3 -16 7 -4 13 -3 0 -17 -10 -20 7 7 30 0 3 -10 -13 -23 -4 -4 -3 7 -3 -10 -24 -13 0 -44 14 -6 13 33 83 -20 74 7 6 16 -10 57 0 110 -53 63 33 10 -36 10 0 10 6 4 10 -20 37 16 17 -3 6 -53 -16 0 10 -7 0 -17 -17 -3 0 30 50 10 127 -33 123 -37 57 43 30 -10 126 20 14 0 6 -10 7 -20 70 10 107 -53 103 7 37 -37 53 3 30 -50 97 24 16 70 -43 93 -10 33 -37 44 17 3 -13 7 3 3 17 27 16 56 -10 54 27 60 -13 113 66 110 -3 127 -87 60 -20 20 4 13 -10 -3 -47 6 13 20 37 10 7 27 -14 113 -13 80 33 10 -6 -6 -14 30 -16 6 3 -10 27 217 140 57 70 23 56 20 10 13 -6 17 -50 30 -10 20 13 -30 0 -13 13 -14 60 -53 30 -10 24 33 73 44 3 36 30 0 37 7 13 17 -3 3 7 -20 26 -7 -3 -26 -47 -17 0 90 170 27 17 36 63 17 14 57 3 16 7 54 66 73 17 40 37 17 3 90 -43 0 -77 6 -3 30 3 14 13 0 24 6 -24 14 -53 43 -60 43 -73 134 -57 126 7 57 -17 20 -43 53 -20 64 -94 156 7 34 -27 66 20 77 -23 33 13 30 10 74 -16 93 40 40 -14 23 -23 120 -7 120 -3 40 40 27 -7 23 17 34 3 50 -23 43 -80 47 -10 33 10 37 -20 43 13 57 74 36 -14 37 -30 3 -26 34 -24 0 -33 56 -40 64 -220 -10 -7 0 -3 16 7 77 -97 60 -33 23 0 17 -50 70 -54 43 0 20 -16 54 26 10 -3 -4 -10 27 -17 50 -6 37 23 113 -40 20 -23 -20 -24 -3 0 3 17 -7 3 -40 -13 -33 -40 30 -60 13 -7 10 7 7 -10 -7 -27 34 -93 26 -13 7 -94 3 -33 64 -33 0 -94 30 -20 20 7 10 -50 23 -30 117 -63 33 3 33 -67 60 -13 14 -30 70 -50 -27 -33 0 -17 -130 -50 -90 -103 -37 -84 4 -6 6 -24 -46 -83 -27 -83 0 -7 7 -57 63 -113 7 -47 43 -80 57 -70 20 -80 56 -40 17 -60 90 -103 83 -170 40 -70 47 -17 3 30 -43 10 7 14 33 0 50 -64 63 -46 4 -4 -57 -36 -33 3 -24 -27 140 -176 77 -30 30 10 23 -40 230 -77 260 -87 70 -126 274 -167 23 -30 60 -23 53 -54 24 -43 53 -40 10 -50 -23 -40 10 -33 -20 -30 -34 -14 -10 -63 24 -37 26 20 37 -23 10 -40 -20 -20 -37 7 -20 -14 0 -56 -26 -34 3 -23 -50 -23 -17 -220 -3 0 -10 43 -23 -3 -10 -24 20 -43 20 -7 0 -16 -20 -14 3 -6 13 0 17 -67 -17 -10 0 -7 17 4 23 -60 80 -90 64 -30 43 6 70 -90 190 -140 47 0 10 40 30 20 40 0 3 -6 -13 -10 20 -17 16 7 7 23 37 -3 60 -7 40 0 36 23 34 14 16 0 37 6 0 -3 3 -20 24 -3 23 23 17 20 43 3 33 -3 34 0 20 -17 -20 -10 13 -10 53 0 24 -3 16 -7 0 4750 -36 -6 -277 40 -37 -17 -86 30 -50 53 -90 44 -100 0 -50 -20 -10 43 -40 17 -30 -7 -40 -40 -70 13 -57 84 -123 80 -100 6 -10 -20 -34 -6 -183 66 -93 0 -220 47 -77 -10 -50 30 -50 0 -67 23 -66 30 -44 54 -66 36 -64 10 -106 80 -67 20 -23 44 -50 23 -47 47 -3 10 -40 120 -87 70 -110 -24 -3 -3 -7 -30 -40 -23 -67 20 -23 76 -30 10 -30 37 -37 0 -16 -20 -64 -17 -26 40 -37 -3 -60 33 -70 80 -20 0 -40 130 -27 37 -43 33 -53 4 -37 20 -140 120 -23 -4 -87 40 -57 4 -63 -20 -40 10 -67 -27 -50 -20 -53 40 -100 -3 -57 -24 -66 -66 20 36 53 44 -20 6 -67 -33 -10 -83 -20 -40 -13 -34 10 -40 -17 -6 -53 110 -33 0 -34 36 -83 34 -140 -17 -73 -50 -37 10 -13 40 -30 13 -50 -10 -20 -33 -34 20 -36 -7 -60 34 -67 6 -43 27 -220 -43 -217 -147 -67 -97 -43 -23 -17 -80 -26 -13 -14 -107 30 -30 -3 -13 -53 -10 -47 3 -70 60 -60 -7 -47 37 -70 -13 -26 10 -60 213 -170 433 -144 284 -2296 0 0 -6920 5206 0 -33 183 3 73 -43 80 -33 70 -44 40 -43 4 -17 16 -10 -20 -46 37 -127 40 -40 -17 -63 14 -50 -17 -50 -40 -100 -23 -34 -34 -23 20 -73 -3 -4 20 -46 23 3 30 -37 -20 -26 10 -44 -33 -46 -3 -7 -10 -50 3 -17 -20 14 -3 0 -14 -77 -33 -80 30 -40 37 -13 -4 -4 -16 34 -17 -20 -20 -220 73 -157 0 -290 -56 -30 -17 -47 10 -36 -37 -67 -20 -150 4 -7 -20 -70 -57 -36 13 -34 34 -30 -10 -46 23 -64 -20 -56 17 -90 6 -70 -16 -47 13 -17 -17 -20 10 -80 -20 -40 10 4 27 -20 27 3 -50 -103 -10 -34 -24 -36 -63 -54 -20 4 -13 -44 -4 -20 34 -10 -7 -10 -37 -36 4m6596 2686l20 -33 -16 -20 0 -7 20 7 0 -7 -24 -23 -13 -53 -37 -4 -23 -43 -13 0 -4 7 0 3 -16 7 -14 -24 0 10 -16 10 -124 10 -20 30 24 17 0 47 10 6 83 -16 163 76m-573 384l3 -4 27 -36 7 -14 13 -66 53 -60 -6 -34 23 -6 13 -64 -10 -20 -60 -23 -53 47 -70 -34 -10 -36 33 -7 7 -30 -7 -3 -43 20 -13 -30 63 -40 -3 -4 -17 -3 -57 37 -66 6 -54 47 -36 10 -107 113 -113 80 -7 27 13 30 50 0 30 43 7 0 10 -46 73 -30 47 36 -13 27 33 70 30 10 73 -10 54 60 13 0 60 -53 3 0 7 -10m-127 173l7 -20 -3 -7 -24 4 -3 3 23 20m-883 277l23 -7 4 -47 40 -20 23 -43 40 -33 0 -10 -17 -20 7 -20 -43 -17 -94 43 -36 30 6 34 -3 10 -40 10 -3 6 6 54 10 3 57 0 7 0 13 27m20 136l33 -30 14 0 33 17 23 -13 4 -7 -4 -7 -3 0 -20 10 -23 -10 -34 -46 -6 0 -27 30 10 56z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil5","@d":"M-1494 1087l3 3 3 7 4 3 0 7 0 6 -4 4 -3 6 -7 -3 -3 0 -7 -3 -6 0 -4 0 -6 0 -10 0 -7 3 -3 0 -7 3 -7 4 -3 0 -7 0 -6 0 -7 3 -7 0 -6 0 -7 3 -7 -3 -3 -3 -3 -4 -4 -6 4 -7 3 -3 7 0 3 -4 7 0 6 0 7 4 3 0 7 3 7 0 3 -3 7 -4 3 -3 3 -3 4 -7 3 -3 7 -4 3 -3 7 0 6 3 4 0 6 0 7 4 7 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil5","@d":"M-3568 1347l0 -7 -3 -7 -3 -3 0 -7 0 -6 0 -7 0 -3 3 -7 0 -7 3 -3 4 -7 6 -3 4 -3 3 -4 3 -6 0 -4 4 -6 0 -7 3 -3 3 -4 7 -6 3 -4 4 -3 3 -7 3 -3 0 -7 4 -3 3 -7 3 -3 7 -3 3 -7 4 -3 6 0 7 -4 7 4 -4 3 -3 7 -3 3 -4 7 -3 3 -3 3 -7 4 -7 3 -3 3 0 7 -3 3 -4 7 -3 3 -3 7 -4 3 0 7 -3 3 -3 7 -4 3 0 7 0 7 -6 3 -4 3 -6 4 0 3 -4 7 0 6 0 4 0 6 0 7 0 7 -3 3 -7 7z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil5","@d":"M-2534 1950l3 7 0 6 -3 7 -4 3 -3 7 -3 3 0 7 0 3 0 7 3 7 3 3 4 7 3 3 0 7 3 6 0 7 0 3 -6 4 -7 3 -7 0 -3 0 -7 0 -6 0 0 7 -4 6 4 4 3 6 3 7 0 3 -6 4 -7 0 -7 -4 -3 4 -7 0 -3 3 -3 7 0 6 -4 4 0 6 0 7 -3 3 -7 4 -3 0 -7 0 -6 3 -4 7 0 3 -3 7 0 6 3 4 0 6 -3 4 -7 3 -3 3 -3 -6 0 -7 -4 -3 0 -7 0 -7 -3 -3 -7 -3 0 -7 0 -7 4 0 6 0 7 0 3 -3 7 -3 7 -4 3 0 7 -3 3 -3 0 -7 0 -7 0 -6 3 -7 4 -3 3 0 7 0 3 -7 7 -3 0 -4 3 -6 3 -4 4 -6 6 -4 4 -3 3 -3 3 -4 4 -6 0 -7 0 -7 0 -3 -4 -7 -3 -3 -3 -7 0 -6 0 -7 3 -3 3 -7 4 0 6 0 4 -3 3 -7 3 -3 4 -7z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil5","@d":"M759 2217l7 3 3 3 7 4 3 3 3 3 4 7 3 3 3 7 -10 0 -6 0 -7 -3 -3 -4 -4 -3 -3 -7 -7 -3 -3 -3 -7 0 -6 0 -4 0 -6 0 -7 3 -7 3 -3 4 -3 3 0 7 0 6 -4 4 0 6 -3 7 -3 3 -4 7 -3 3 -3 7 -4 3 -3 4 -7 3 -6 0 -4 3 -6 0 -4 4 -3 6 -3 4 -4 6 0 7 -3 3 -3 7 -7 3 -3 0 -7 0 -7 0 -3 -3 -7 -3 -6 0 -4 0 -6 -4 -7 0 -7 0 -3 -3 0 -10 7 -3 3 -4 7 0 6 0 4 0 6 4 7 3 3 0 7 0 7 0 0 -7 0 -6 3 -4 0 -6 0 -7 7 -3 3 -4 7 0 6 0 4 0 6 0 7 -3 3 -3 4 -4 3 -6 0 -7 3 -7 0 -6 4 -4 3 -6 3 -4 7 -3 3 -3 4 -7 3 -3 7 -4 3 -3 7 0 6 -3 4 0 6 0 7 3 3 3 7 4z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil5","@d":"M-2838 2350l-3 -3 3 0 7 -4 3 -3 7 -3 3 -7 4 -3 3 -7 3 -3 7 0 3 3 7 7 0 3 0 7 0 6 0 7 0 7 3 3 4 3 6 0 7 0 3 4 4 3 6 7 0 3 4 7 3 6 3 4 4 3 6 0 4 -3 6 -7 4 0 3 3 7 7 6 3 4 4 3 6 3 4 4 3 3 7 7 3 3 3 3 7 4 3 3 7 3 3 4 7 0 3 3 7 0 7 0 3 -7 7 -3 -4 -3 -3 -7 -3 -3 -4 -4 -6 0 -7 -3 -3 0 -7 -3 -7 -4 -3 -3 -3 -7 0 -6 0 -7 0 -3 3 0 7 -4 0 -3 -4 -3 -6 0 -4 0 -6 0 -7 -4 -3 -3 -7 -3 -3 -7 0 -7 0 -3 0 -3 -7 -7 -3 -3 -4 -7 0 -7 -3 -3 -3 -3 -7 -7 0 -3 3 0 7 -4 3 -3 7 -7 3 -3 4 -7 -4 0 -3 -3 -7 3 -6 4 -4 0 -6 3 -7 -3 -7 -4 -3 -3 -3 -7 -7z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil5","@d":"M-804 2803l0 10 -4 4 -6 3 -7 0 -3 3 -4 4 -6 3 -4 7 -3 3 0 7 -3 3 0 7 0 6 0 7 3 3 7 4 3 3 3 7 -3 3 -3 7 -4 3 -3 3 -3 7 0 7 0 3 -4 7 -3 3 -3 7 -4 0 -6 -7 3 -7 0 -3 0 -7 3 -6 0 -7 4 -3 0 -7 -4 -3 -3 -7 -3 -3 0 -7 3 -7 3 -3 0 -7 4 -6 0 -4 3 -6 3 -4 4 -6 0 -7 3 -3 3 -7 4 -3 6 0 7 -4 7 0 3 0 7 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil5","@d":"M-731 2977l7 0 6 0 7 3 3 3 0 4 -3 6 -7 0 -6 0 -4 -3 -6 0 -7 -3 -3 -4 -7 0 -3 -3 -7 -3 -3 0 -7 -4 -7 0 -6 0 -4 0 -6 0 -7 0 -7 0 -3 4 -7 0 -6 3 -4 3 -3 4 -3 6 -4 4 0 6 0 7 0 3 4 7 3 3 3 7 4 3 3 4 3 6 0 7 0 3 -3 7 0 7 -3 6 -4 0 -6 0 -7 0 -3 -3 -4 -3 -3 -7 0 -3 -3 -7 0 -7 0 -6 0 -4 0 -6 -4 -7 -3 -3 -7 -4 -3 -3 -7 -3 0 -4 4 -6 6 -4 4 -6 3 -4 3 -3 7 -3 3 -4 7 -3 7 0 3 -3 7 -4 3 0 7 0 6 0 7 0 3 0 7 -3 7 0 3 -3 7 0 6 -4 4 0 6 0 7 0 3 7 0 3 4 7 3 3 3 4 7 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil5","@d":"M-2711 2997l3 6 -3 7 -3 3 -4 4 -3 6 -3 4 -7 3 -3 3 -4 4 -3 6 0 7 0 7 0 3 3 7 0 6 7 4 3 3 7 3 3 0 7 4 0 6 0 7 0 7 -3 3 -4 3 -3 4 -7 3 -3 3 -7 0 -6 0 -7 4 -7 0 -3 -4 -7 -3 -3 -3 0 -7 3 -3 0 -7 4 -7 3 -3 3 -3 4 -7 6 -3 0 -7 0 -3 0 -7 -3 -7 -3 -3 -7 0 -3 -3 -7 3 -7 0 -6 3 -7 0 0 -3 3 -7 4 -6 6 -4 4 4 6 0 7 3 3 0 7 -7 3 -3 7 -3 3 -4 4 -3 3 -7 3 -3 4 -3 3 -7 10 -3z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil5","@d":"M-3178 3467l-3 -7 0 -3 3 -7 4 -3 3 -7 3 -3 4 -7 3 -3 3 -7 0 -3 4 -7 3 -7 3 -3 0 -7 4 -3 3 -7 3 -3 0 -7 4 -3 3 -7 3 -3 7 -3 3 -4 7 -3 3 -3 7 -4 3 0 7 -3 0 -7 0 -6 0 -4 0 -6 3 -7 7 3 3 4 -3 6 0 7 3 3 7 0 3 -3 7 -3 3 -4 4 -3 6 -3 7 -4 3 0 7 -3 3 -3 7 -4 3 0 7 -3 7 0 6 0 4 7 0 3 -7 0 -7 0 -3 3 -7 4 -6 3 -4 0 -6 0 -7 3 -3 0 -7 4 -3 3 -7 3 -3 4 -4 3 -6 3 -4 7 -3 3 -7 0 -6 0 -4 4 -6 0 -7 3 -7 0 -3 7 0 3 -3 7 -4 3 0 7 -3 6 -3 4 0 6 -4 4 -3 6 -3 4 -4 6 -3 4 -3 6 -4 4 -3 3 -7 7 4 3 3 3 7 -3 3 -3 7 -4 3 0 7 -3 3 -3 7 0 6 -4 4 -3 6 0 7 0 7 -3 3 0 7 -4 3 -3 3 -3 7 -4 3 0 4 7 -4 3 -6 4 0 6 3 4 7 0 6 0 7 -4 3 -3 4 -3 6 0 7 0 7 -4 3 4 3 3 4 7 3 6 3 4 4 3 6 3 4 4 6 3 4 3 3 4 7 0 6 3 7 -3 0 -4 3 -6 7 -4 7 0 3 4 7 0 6 3 0 3 0 7 7 3 3 0 7 0 3 -3 7 -3 3 -4 7 -3 7 0 3 0 7 -3 6 0 4 0 6 0 7 0 7 -4 3 0 7 0 6 0 7 -3 3 0 7 -3 7 0 3 -4 7 -3 3 0 7 -3 6 0 4 -4 6 -3 7 0 3 -3 7 -4 7 0 3 0 7 -3 3 -3 3 -4 7 -6 0 -7 0 -3 7 -7 3 0 0 7 0 6 3 7 -10 7 -3 3 -3 3 -7 4 -3 6 -4 4 -6 0 -4 0 -6 0 -7 3 -3 0 -7 3 -7 4 -3 0 -7 3 -3 3 -7 4 -6 0 -4 3 -6 3 -7 0 -3 4 -7 0 -7 0 -3 0 -7 0 -6 0 -7 0 -3 3 -7 0 -7 3 -3 0 -7 0 -6 4 -7 0 -3 0 -7 3 -7 0 -3 3 -7 0 -6 4 -4 3 -3 7 3 3 4 7 0 6 3 4 3 3 4 7 6 3 4 7 3 3 3 3 4 7 3 3 3 4 4 6 6 0 4 4 6 3 7 0 7 0 3 0 7 0 6 -3 7 0 3 0 7 0 7 3 3 3 3 4 7 3 3 3 7 4 3 3 7 3 3 4 7 3 3 3 7 0 7 4 3 0 7 3 3 3 0 7 -7 3 -3 0 -7 0 -6 0 -4 -3 -6 -3 -4 -4 -6 -3 -4 -3 -3 -4 -7 -3 -3 -3 -7 0 -6 -4 -4 -3 -6 0 -7 -3 -3 0 -7 0 -7 0 -6 0 -4 0 -6 0 -7 0 -7 0 -3 -4 -7 -3 -3 -3 -7 -4 -3 -3 -3 -3 -4 -7 -3 -3 -3 -7 -4 -3 0 -7 -3 -7 -3 -3 -4 -7 -3 -3 -3 -7 -4 -3 -6 0 -4 0 -6 0 -4 -7 4 -6 0 -4 0 -6 -7 -4 -3 -3 -7 -3 -3 -4 -7 0 -3 -3 -7 -3 -3 -4 -7 -3 -3 -3 -7 -7 -3 0 -7 -3 -7 0 -3 0 -7 3 -3 0 -7 0 -6 0 -7 0 -3 0 -7 0 -7 0 -6 0 -4 0 -6 0 -7 -3 -3 0 -7 3 -7 0 -6 0 -4 3 -6 4 -4 3 -3 3 -7 4 -3 3 -7 0 -6 0 -4 -3z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil5","@d":"M-2671 3397l3 -7 4 -3 6 -4 7 0 3 -3 4 -3 3 -7 3 -7 0 -3 0 -7 4 -6 3 -4 7 0 3 4 0 6 -3 7 0 3 -4 7 0 7 0 3 -6 3 -7 4 -3 3 -7 3 -3 4 -4 3 -6 0 -7 -3z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil5","@d":"M-2464 3453l0 -10 3 -3 3 -3 7 -4 3 -3 7 -3 7 0 3 0 7 -4 6 0 4 0 6 0 7 0 7 0 3 0 7 0 6 -3 7 3 3 -3 7 0 7 0 3 -3 7 -4 3 -3 3 -7 0 -6 4 -7 0 -3 6 0 7 0 3 6 0 7 0 3 -3 7 0 7 -3 3 0 7 0 6 3 7 3 3 7 4 -10 0 -3 -4 -4 -3 -6 -3 -4 -4 -6 4 -7 0 -7 3 -3 0 -7 3 -3 4 -7 0 -3 -7 -7 -3 -6 0 -4 0 -6 0 -7 0 -7 0 -3 0 -7 3 -6 0 -4 3 -6 4 -4 3 -6 3 -4 0 -6 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil5","@d":"M-3991 3567l0 -7 0 -7 3 -6 4 -4 6 0 7 4 3 -4 7 -3 3 -3 0 -7 -3 -3 -7 -4 0 -6 0 -7 4 -3 3 -7 3 -3 4 -7 3 -3 3 -4 4 -6 3 -4 0 -6 0 -7 0 -7 0 -3 0 -7 0 -6 0 -7 3 -3 0 -7 -3 -3 -3 -7 -4 -3 0 -7 4 0 6 0 7 3 7 0 3 4 3 6 -3 7 0 7 -3 3 0 7 -4 6 0 4 0 6 0 7 0 7 0 3 -3 7 0 6 0 7 0 3 7 4 6 0 4 3 3 3 -3 4 -7 0 -7 0 -3 0 -7 0 -3 6 0 4 3 6 0 7 0 7 -3 0 -3 3 -7 3 -3 7 -4 3 -3 7 -3 3 -4 4 -6 3 -7 0 -3 -3 -7 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil5","@d":"M-2668 3407l14 0 3 0 7 3 6 0 7 -3 3 3 4 3 3 7 3 7 4 0 6 3 7 0 3 0 7 3 3 4 7 3 3 7 4 3 6 0 4 3 6 0 7 0 7 0 3 -3 3 -3 7 -4 7 -3 3 -3 3 -4 4 -6 3 -4 3 -3 7 0 3 3 0 7 -6 3 -4 4 -3 3 -3 7 3 3 -7 3 -3 4 -7 0 -6 0 -4 3 -6 0 -7 3 -3 0 -7 0 -7 0 -6 0 -4 -3 -3 -3 -3 -4 -4 -6 -3 -4 -7 -3 -6 0 -4 0 -6 0 -7 0 -7 -3 -3 0 -3 -7 -4 -7 -3 -3 -7 0 -3 -3 -7 -4 -3 -3 -7 -3z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil5","@d":"M-484 3603l-4 4 -6 0 -4 -4 -6 -3 -4 -3 -3 -7 -3 -3 -4 -4 -6 0 -7 0 -7 0 -3 -3 -7 -3 -3 -4 0 -6 0 -7 -3 -3 -4 -7 -3 -3 -3 -4 -7 -3 -3 -7 -4 -3 -3 -3 -3 -7 -4 -7 -3 -3 -3 -3 -7 -4 0 -3 -3 -7 0 -6 -4 -4 0 -6 0 -7 4 -7 3 4 3 3 7 3 3 4 4 6 0 4 3 6 3 4 7 3 7 0 6 0 4 0 6 7 0 3 -3 7 -3 3 0 7 3 6 0 4 3 6 4 4 6 3 4 7 3 3 7 3 3 0 7 0 6 0 7 4 3 6 0 4 0 6 4 4 3 6 3 4 4 6z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil5","@d":"M-2094 3723l10 0 3 -3 7 0 6 0 4 3 6 4 7 0 3 3 7 3 0 7 3 7 -6 3 -7 3 -7 0 -3 -3 -7 3 0 7 4 3 6 4 4 3 6 3 4 4 6 3 4 3 3 4 3 3 -3 7 -3 6 3 4 3 6 4 4 3 6 0 7 3 3 -10 0 -6 -3 -4 -3 -3 -7 0 -3 -3 -7 -4 -7 0 -3 -3 -7 -7 -3 -3 0 -7 -3 -3 -7 -3 -3 -4 -4 -3 -6 -3 -4 -4 -6 -3 -4 -7 -3 -6 0 -7 3 -3 4 -7 3 0 3 -3 7 -4 3 0 7 -3 7 0 3 -3 7 -4 6 0 4 -3 6 -3 4 -4 6 -3 4 -3 6 -4 4 -6 3 -4 3 -6 4 -4 3 -6 3 -4 4 -6 0 -4 3 -6 3 -4 4 -6 3 -4 3 0 7 0 7 0 6 0 4 4 6 -7 4 -3 -4 -4 -10 0 -3 0 -7 4 -6 0 -7 3 -3 0 -7 3 -7 0 -3 0 -7 0 -6 0 -7 0 -3 4 -4 6 0 0 7 4 3 3 7 3 3 7 0 3 -3 7 -3 3 -4 7 -3 3 -3 4 -4 3 -6 3 -4 4 -6 3 -7 0 -3 0 -7 3 -7 0 -6 0 -4 0 -6 4 -7 0 -3 3 -10 3 -4 4 -6 6 -4 4 -3 6 0 4 -3 6 0 7 0 7 -4z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil5","@d":"M-2421 4023l3 -6 4 -7 3 -3 7 0 6 -4 4 0 6 -3 7 0 3 -3 7 -4 7 0 3 -3 7 -3 0 -7 3 -3 7 -4 3 -3 7 -3 3 -4 7 0 6 0 7 0 -10 7 -3 7 -4 3 -3 3 -7 4 -3 3 -3 3 -7 4 -3 3 -7 3 -7 4 -3 0 -7 3 -6 0 -4 3 -6 4 -4 3 -6 3 -4 4 -6 0 -7 0 0 -4z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil5","@d":"M-2391 4083l0 -6 0 -7 3 -3 7 -4 7 0 3 4 7 3 3 3 7 0 6 4 4 0 6 0 7 -4 7 0 3 -3 7 -3 3 -4 7 0 6 0 4 0 6 0 7 0 7 0 3 0 7 0 6 -3 4 -3 6 -4 4 -3 6 0 7 0 3 3 0 7 -3 7 0 3 -3 7 3 6 3 4 4 3 6 7 4 3 6 0 4 3 6 4 7 0 3 3 4 7 3 3 0 7 -3 6 -7 0 -7 -3 -3 -3 -7 -4 -3 -3 -3 -3 -7 -4 -3 -3 -7 -3 -3 -4 -4 -3 -3 -7 0 -6 -3 -4 -7 -3 -3 -3 -7 0 -7 0 -6 0 -4 0 -6 0 -7 0 -7 3 -3 0 -7 0 -3 7 -7 0 -6 3 -4 0 -6 0 -7 0 -7 -3 -3 0 -7 -4 -6 0 -4 0 -6 -3 -7 0 -7 0 -3 3z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil5","@d":"M-3454 4400l-7 7 -3 3 -4 3 -3 7 -3 3 -4 7 -3 3 -3 7 -4 3 -3 7 -3 3 -4 4 -3 6 -3 4 -4 6 -3 4 0 6 0 7 3 3 7 4 3 0 7 0 7 0 3 -4 7 0 6 -3 4 0 6 -3 7 0 3 -4 7 0 7 0 6 -3 4 0 6 0 7 3 7 0 3 4 7 0 3 6 0 7 0 7 -3 3 -4 0 -6 0 -7 0 -3 -3 -7 0 -7 0 -6 -4 -7 0 -3 0 -7 0 -7 0 -3 0 -7 0 -6 4 -4 3 -3 7 0 3 0 7 -3 6 -4 4 -3 6 -7 0 -3 4 -7 0 -6 0 -7 3 -3 0 -7 3 -3 4 -7 3 -3 3 -7 4 -3 3 0 7 -4 3 -3 7 -3 3 -7 3 -7 -6 0 -7 -3 -7 0 -3 0 -7 3 -6 0 -4 0 -6 0 -7 0 -7 -3 -3 0 -7 -3 -3 -7 -3 -3 -4 -7 -3 -7 0 -3 -7 3 -6 0 -4 -3 -6 0 -7 -3 -3 0 -7 0 -7 3 -3 7 -3 3 -4 3 4 4 6 0 7 0 7 3 3 3 7 4 3 3 7 3 3 4 3 3 7 3 3 4 7 3 3 0 7 3 7 4 0 3 -4 3 -6 4 -7 0 -3 3 -7 3 -7 0 -3 4 -7 0 -6 3 -4 0 -6 0 -7 0 -3 3 -7 4 -7 0 -6 -4 -4 -3 -6 -3 -4 0 -6 0 -4 3 -3 7 -3 6 0 7 0 7 3 6 0 4 -3 3 -4 3 -6 0 -7 4 -3 3 -7 0 -7 3 -3 4 -7 3 -3 3 -7 4 -3 0 -7 3 -3 0 -7 0 -6 0 -7 3 -3 0 -7 0 -7 -3 -6 -3 -4 -4 -3 -3 -7 0 -6 3 -4 7 4 7 3 6 0 4 0 6 -3 4 -7 0 -3 3 -7 0 -7 -3 -6 3 -4 0 -6 3 -4 7 -6 3 0 7 3 3 7 0 6 4 4 0 6 -4 7 0 3 -3 7 -3 7 -4 3 -3 3 -3 7 -4 3 -3 4 -3 6 -4 4 0 6 -3 7 0 7 0 3 0 7 0 6 0 4 0 6 3 7 0 7 -3 3 -3 7 -4 3 -3 7 -3 3z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil5","@d":"M-868 4683l-3 -3 3 -7 0 -6 4 -4 3 -6 0 -7 0 -3 3 -7 0 -7 0 -6 -3 -4 7 -3 3 -7 3 -3 4 -3 3 -7 3 -3 4 -7 6 0 0 3 0 7 -3 3 -3 4 -4 6 -3 4 -7 3 -3 7 -3 3 0 7 0 3 3 7 3 6 4 4 0 6 -4 4 -3 6 -3 4 -7 3 -7 3z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil5","@d":"M3402 6413l-6 -6 -4 0 -6 0 -7 0 -7 0 -3 -4 -7 -3 0 -7 0 -6 4 -4 0 -6 0 -7 0 -7 0 -6 0 -7 3 -3 3 0 7 3 7 0 6 3 7 0 3 4 0 56z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil5","@d":"M366 6487l6 -4 7 0 3 -3 7 0 7 -3 3 -4 7 0 6 -3 4 0 6 -3 7 -4 3 0 7 -3 7 0 3 0 7 3 6 4 4 3 0 7 0 3 0 7 -4 6 -3 4 -3 6 -4 4 -3 3 -7 3 -6 4 -4 0 -6 0 -7 0 -7 3 -3 0 -7 0 -6 0 -7 0 -3 3 -7 0 -7 0 -3 4 -7 3 -3 0 -7 7 -3 3 -3 3 -7 4 -3 3 -7 3 -3 4 -7 0 -7 0 -3 -4 -7 0 -6 -3 -7 0 -3 0 -7 0 -7 3 -3 0 -7 0 -6 4 -7 0 -3 0 -7 0 -7 0 -3 -4 -3 -6 3 -7 3 -3 7 -4 7 -3 3 0 3 -7 7 -3 3 -3 4 -4 6 -3 4 -3 6 -4 4 0 6 -3 7 -3 7 0 3 0 7 -4 6 4 4 3 6 3 4 0 6 -3 4 -3 6 -4 7 -3 7 -3z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil5","@d":"M2859 6683l0 -3 3 -7 0 -6 4 -4 0 -6 3 -7 3 -3 0 -7 4 -3 3 -7 3 -3 4 -7 3 -3 3 -7 4 -3 3 -7 3 -3 4 -7 3 -3 0 -7 3 -3 4 -7 3 -7 3 -3 4 -3 3 -7 7 -3 3 0 7 -4 3 -3 7 0 6 0 7 -3 3 0 7 -4 7 -3 3 -3 3 -4 4 -3 6 -3 4 -4 6 -3 7 0 3 -3 7 -4 7 -3 3 0 7 -3 6 0 4 3 3 7 3 3 4 7 0 6 0 7 0 3 -4 7 -3 3 -7 4 -3 0 -7 3 -6 -3 -7 3 -3 0 -7 0 -7 3 -3 4 -7 3 0 7 -3 3 -3 7 -4 6 0 4 -6 3 -4 7 -3 3 -7 3 -3 4 -7 3 -3 0 -7 0 -6 3 -4 4 -3 3 -7 3 -3 4 -3 6 -7 4 -3 3 -4 3 -6 4 -4 6 -3 4 -3 3 -4 7 -3 3 -3 3 -7 7 -3 3 -7 0 -10 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil5","@d":"M2599 6813l-3 7 -4 3 -3 7 0 3 -7 7 -3 3 -3 4 -7 0 -7 0 -6 0 -4 0 -6 3 -4 3 0 7 -6 3 -4 4 -6 3 -4 3 -6 0 -7 0 -7 0 -3 -3 -7 0 -6 0 -4 0 -6 0 -7 0 -7 0 -3 0 -7 0 -6 -3 -4 -4 -6 -3 -4 -3 -6 -4 -4 -3 0 -7 0 -6 7 -4 7 0 6 0 4 0 6 0 7 4 3 3 7 3 3 0 4 -6 3 -4 0 -6 3 -7 4 -3 3 -7 3 -3 7 -4 3 -3 7 0 7 3 3 0 7 -3 6 0 7 -3 3 0 7 -4 3 -3 4 -7 3 -3 3 -3 7 -4 7 0 6 0 4 -3 6 0 7 0 7 0 3 0 7 -3 6 0 7 3 3 3 0 7 -3 3 -3 7 -4 3 -6 4 -4 6 -3 4 -7 3 -3 3z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil5","@d":"M1512 7287l-220 0 7 -4 7 -3 3 -3 7 0 3 -4 7 0 6 -3 4 -3 6 -4 4 -3 3 -7 7 0 3 -3 7 3 6 0 7 0 7 0 3 -6 3 -4 0 -6 4 -7 0 -3 -4 -7 -3 -3 -3 -7 -4 -3 -6 -7 0 -3 0 -7 0 -3 3 -7 3 -7 4 -3 3 -3 3 -7 7 -3 3 -4 7 -3 3 0 7 -3 3 3 4 7 -4 3 0 7 0 6 0 7 0 7 4 3 3 3 7 4 6 0 7 0 3 -4 7 0 7 0 6 -3 4 0 6 -3 7 0 3 -4 7 -3 3 0 7 -3 3 -4 7 -3 0 -7 3 -6 4 -4 3 -6 3 -4 4 -6 3 -4 3 -3 7 -7 3 -3 7 0 3 3 4 7 0 7 3 6 0 4 3 6 -3 7 0 3 -3 7 -4 3 -6 4 -4 3 -6 3 -4 7 -3 3 -3 4 -7 3 -3 7 -4 3 -3 7 -3 3 -4 3 -3 7 0 7 0 3 0 7 0 6 0 7 0 3 0 7 0 7 3 6 0 4z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil6","@d":"M2996 367l3 0 403 0 0 206 -16 7 -24 3 -53 0 -13 10 20 10 -20 17 -34 0 -33 3 -43 -3 -17 -20 -23 -23 -24 3 -3 20 0 3 -37 -6 -16 0 -34 -14 -36 -23 -40 0 -60 7 -37 3 -7 -23 -16 -7 -20 17 13 10 -3 6 -40 0 -30 -20 -10 -40 -47 0 -190 140 -70 90 -43 -6 -64 30 -80 90 -23 60 -17 -4 0 7 17 10 -17 67 -13 0 -3 6 20 14 0 16 -20 7 -20 43 10 24 23 3 10 -43 3 0 17 220 50 23 -3 23 26 34 -43 10 -30 -30 -50 0 -80 53 -57 10 -20 43 -40 -6 -23 23 -30 -10 -20 -30 -93 -27 -67 17 -27 43 -40 10 -23 -13 -20 -47 -3 -6 -114 -27 -3 -10 3 -37 24 -13 -27 -10 -3 -20 -130 -17 -7 37 -17 3 -53 -80 -67 -3 -30 13 -46 -53 -70 -10 -14 10 -50 -23 -70 -20 -23 13 -10 63 20 24 -17 23 -113 10 -40 -23 -33 36 -24 -30 -43 -10 -100 40 -53 -26 -27 -47 -23 3 -60 -40 -47 37 -60 -17 -10 27 -20 7 -37 -54 -53 -23 0 -20 -13 -33 -44 13 -60 -3 -146 -70 -30 6 -20 -20 6 -20 -10 -6 -16 10 -4 50 -43 -7 -27 -33 27 -27 20 -53 -7 -50 -83 -17 -30 30 -20 -40 -47 10 -30 -47 17 -16 43 -4 44 -40 33 -70 43 -80 -3 -73 33 -183 3164 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil6","@d":"M1372 1313l17 -3 7 -37 130 17 3 20 27 10 -24 13 -3 37 -30 7 -7 26 -30 0 -23 27 -53 0 -20 -37 26 -20 -30 -16 10 -44z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil6","@d":"M-3834 1670l6 70 30 -10 24 20 -4 27 -40 23 -36 50 6 27 24 10 -4 33 20 10 44 -7 43 -40 27 0 6 -20 14 0 3 34 7 0 20 -17 73 -13 57 23 -7 33 47 -3 13 -23 17 6 6 0 17 37 27 -23 26 3 70 -27 10 -70 34 -6 43 33 30 -17 30 20 50 0 27 -30 10 14 30 26 53 0 20 -20 17 20 -10 40 30 14 -30 86 6 47 24 20 36 -17 50 7 84 67 -10 16 -7 4 -3 6 -4 4 -3 3 -3 7 -4 3 -3 7 -3 3 -4 7 -3 3 -3 7 -4 3 0 7 -3 3 -3 7 -4 3 -3 7 -3 3 -4 7 0 3 -3 7 0 6 0 7 -3 3 -4 4 -6 3 -7 0 -7 0 -3 0 -3 7 -4 3 -3 7 0 3 -3 7 -4 3 -3 7 -3 3 -7 3 -3 4 -7 3 -3 3 -7 4 -3 3 -7 7 -3 3 -4 3 -3 4 -7 0 -6 3 -4 3 -3 4 -7 6 -3 4 -7 0 -3 0 -7 0 -6 3 -7 0 -3 0 -7 0 -7 3 -3 0 -7 4 -3 6 -3 4 -7 3 -3 3 -4 7 -3 3 -7 4 -3 3 -3 7 0 3 -4 7 -3 3 -3 7 -4 3 -3 7 -3 3 -4 7 0 6 -3 4 -3 6 0 4 -4 6 0 7 -3 3 -3 7 -4 3 -3 4 -7 3 -3 3 -7 4 -6 3 -4 0 -6 0 -7 0 -7 0 -6 37 50 93 -14 10 -6 60 13 73 -23 64 26 36 -33 54 33 66 -46 60 -77 27 -17 27 10 46 44 20 33 67 -30 107 -43 40 -20 96 -7 0 -3 4 -7 0 -10 0 -7 3 -6 0 -7 0 -3 0 -7 3 -7 0 -6 -3 -4 0 -6 0 -7 0 -7 0 -3 0 -7 -3 -6 0 -4 0 -6 0 -7 -4 -7 0 -3 0 -7 0 -6 4 -4 0 -6 3 -7 3 -3 4 -7 0 -3 3 -7 0 -7 -3 -6 0 -4 -4 -6 0 -7 0 -7 -3 -3 0 -7 0 -6 -3 -4 0 -6 -4 -7 0 -3 -3 -7 0 -7 0 -6 0 -4 0 -6 0 10 43 66 60 4 24 46 23 -13 90 43 50 -6 47 56 30 -6 43 73 0 27 30 6 40 -53 80 3 30 -3 3 -7 7 -3 3 -3 4 -7 3 -3 3 -4 4 -6 6 -4 4 -3 3 -7 3 -3 4 -7 3 -3 3 -3 4 -7 3 -3 3 -7 4 -3 3 -7 3 -3 4 -4 3 -6 3 -4 4 -3 6 -7 4 -3 3 -3 3 -4 7 0 7 0 3 0 7 0 6 0 7 0 7 -3 0 -7 6 -3 4 0 6 -3 4 3 6 0 7 -3 7 0 3 -4 7 -6 3 -4 0 -6 0 -7 -3 -7 -4 -3 4 0 6 3 7 4 3 3 4 3 6 0 7 0 7 -3 3 0 7 0 6 0 7 -3 3 0 7 -4 3 -3 7 -3 3 -4 7 -3 3 0 7 -3 7 -4 3 0 7 -3 6 -3 4 -4 3 -6 0 -7 -3 -7 0 -6 0 -7 3 -3 3 0 4 0 6 3 4 3 6 4 4 0 6 -4 7 -3 7 0 3 0 7 0 6 -3 4 0 6 -4 7 0 3 -3 7 -3 7 0 3 -4 7 -3 6 -3 4 -4 0 -3 -7 0 -7 -3 -3 -4 -7 -3 -3 -3 -7 -4 -3 -3 -3 -3 -7 -4 -3 -3 -7 -3 -3 0 -7 0 -7 -4 -6 -3 -4 -3 4 -7 3 -3 3 0 7 0 7 3 3 0 7 3 6 0 4 -3 6 3 7 7 0 7 3 3 4 7 3 3 3 0 7 3 3 0 7 0 7 0 6 0 4 -3 6 0 7 0 3 3 7 0 7 7 6 7 -3 3 -3 3 -7 4 -3 0 -7 3 -3 7 -4 3 -3 7 -3 3 -4 7 -3 3 0 7 -3 6 0 7 0 3 -4 7 0 3 -6 4 -4 3 -6 0 -7 0 -3 3 -7 4 -3 6 -4 7 0 3 0 7 0 7 0 3 0 7 0 6 4 7 0 7 0 3 3 7 0 6 0 4 0 3 -3 0 -7 0 -7 -3 -6 -7 0 -3 -4 -7 0 -7 -3 -6 0 -4 0 -6 3 -7 0 -7 0 -3 4 -7 0 -6 3 -4 0 -6 3 -7 0 -3 4 -7 0 -7 0 -3 0 -7 -4 -3 -3 0 -7 0 -6 3 -4 4 -6 3 -4 3 -6 4 -4 3 -3 3 -7 4 -3 3 -7 3 -3 4 -7 3 -3 3 -7 4 -3 3 -3 7 -7 20 13 70 110 30 74 90 -24 -47 130 -57 -13 -13 30 -70 7 -30 106 -77 64 -16 73 -47 73 7 7 3 7 3 3 4 3 6 7 4 3 3 7 0 3 3 7 0 3 0 7 4 7 0 6 0 7 0 3 0 7 0 7 0 6 0 4 0 6 0 7 3 7 0 3 0 7 0 6 0 7 0 3 0 7 0 7 3 6 0 4 0 6 0 7 0 3 0 7 0 7 0 6 4 7 3 47 -13 10 -20 -4 -60 20 -127 87 -110 3 -113 -66 -60 13 -54 -27 -56 10 -27 -16 -3 -17 -7 -3 -3 13 -44 -17 -33 37 -93 10 -70 43 -24 -16 50 -97 -3 -30 37 -53 -7 -37 53 -103 -10 -107 20 -70 10 -7 0 -6 -20 -14 10 -126 -43 -30 37 -57 33 -123 -10 -127 -30 -50 3 0 17 17 7 0 0 -10 53 16 3 -6 -16 -17 20 -37 -4 -10 -10 -6 -10 0 -10 36 -63 -33 -110 53 -57 0 -16 10 -7 -6 20 -74 -33 -83 6 -13 44 -14 13 0 10 24 -7 3 4 3 23 4 10 13 0 -3 -7 -30 20 -7 17 10 3 0 4 -13 16 -7 0 -3 -36 3 -4 -17 70 -33 4 -13 -27 -50 -3 -50 -14 0 -36 50 -30 83 -20 13 -100 17 -80 -23 -7 -14 7 -20 -14 -26 57 -120 0 -94 53 -113 0 -43 -10 -24 7 -30 73 -33 94 -117 20 -103 123 -287 0 -3 -27 -40 37 -83 60 -214 10 -26 33 0 20 -50 17 -4 0 -3 -23 -10 0 -20 3 -10 20 -20 0 -7 -7 -10 -10 0 -20 80 -23 34 -3 0 66 -250 -6 -87 -7 -7 -20 -33 -10 -103 -23 -64 10 -40 -24 -156 -23 -47 10 -83 73 -60 4 -4 6 -6 4 -4 3 -3 3 -3 7 -4 3 -6 4 -4 3 -3 3 -7 4 -3 3 -7 3 -3 7 -3 3 -4 7 -3 3 0 7 -3 3 -4 7 0 7 4 6 0 4 0 6 -4 4 -3 6 -3 4 -4 3 -3 7 -3 6 0 7 0 3 0 7 0 7 3 3 0 7 0 6 0 7 0 3 0 7 0 7 0 6 -3 4 0 6 -4 7 0 3 -3 7 -3 3 -4 7 -3 3 -3 4 -4 6 -3 4 -3 6 -4 7 0 3 -3 7 0 7 -3 3 -4 7 -3m-157 1897l7 0 3 3 7 0 6 -3 4 -4 3 -3 3 -7 4 -3 3 -7 7 -3 3 -3 3 0 0 -7 0 -7 -3 -6 0 -4 3 -6 7 0 3 0 7 0 7 0 3 -4 -3 -3 -4 -3 -6 0 -7 -4 0 -3 0 -7 0 -6 3 -7 0 -3 0 -7 0 -7 0 -6 0 -4 4 -6 0 -7 3 -3 0 -7 3 -7 -3 -6 -3 -4 -7 0 -7 -3 -6 0 -4 0 0 7 4 3 3 7 3 3 0 7 -3 3 0 7 0 6 0 7 0 3 0 7 0 7 0 6 -3 4 -4 6 -3 4 -3 3 -4 7 -3 3 -3 7 -4 3 0 7 0 6 7 4 3 3 0 7 -3 3 -7 3 -3 4 -7 -4 -6 0 -4 4 -3 6 0 7 0 7z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil6","@d":"M3402 6357l-3 -4 -7 0 -6 -3 -7 0 -7 -3 -3 0 -3 3 0 7 0 6 0 7 0 7 0 6 -4 4 0 6 0 7 7 3 3 4 7 0 7 0 6 0 4 0 6 6 0 874 -1890 0 0 -4 -3 -6 0 -7 0 -7 0 -3 0 -7 0 -6 0 -7 0 -3 0 -7 3 -7 4 -3 3 -3 3 -7 4 -3 3 -7 7 -3 3 -4 3 -3 4 -7 6 -3 4 -3 6 -4 4 -3 3 -7 0 -3 3 -7 -3 -6 0 -4 -3 -6 0 -7 -4 -7 -3 -3 -7 0 -3 3 -7 7 -3 3 -3 4 -4 6 -3 4 -3 6 -4 4 -3 6 0 7 -7 3 -3 4 -7 3 -3 0 -7 3 -3 4 -7 0 -6 3 -4 0 -6 3 -7 0 -7 0 -3 4 -7 0 -6 0 -7 -4 -3 -3 -4 -3 0 -7 0 -7 0 -6 0 -7 4 -3 -4 -7 -3 -3 -7 3 -3 0 -7 3 -3 4 -7 3 -3 7 -3 3 -4 3 -3 7 -3 7 0 3 0 7 0 3 6 7 4 3 3 7 3 3 4 7 0 3 -4 7 0 6 -3 4 -3 6 -7 0 -7 0 -6 0 -7 -3 -3 3 -7 0 -3 7 -4 3 -6 4 -4 3 -6 3 -7 0 -3 4 -7 0 -3 3 -7 3 -7 4 -1633 0 -57 -94 0 -46 34 -57 -34 -63 -40 -84 -30 -23 -23 -53 40 -10 63 20 57 -4 87 -40 23 4 140 -120 37 -20 53 -4 43 -33 27 -37 40 -130 20 0 70 -80 60 -33 37 3 26 -40 64 17 16 20 37 0 30 -37 30 -10 23 -76 67 -20 40 23 7 30 3 3 110 24 87 -70 40 -120 3 -10 47 -47 50 -23 23 -44 67 -20 106 -80 64 -10 66 -36 44 -54 66 -30 67 -23 50 0 50 -30 77 10 220 -47 93 0 183 -66 34 6 10 20 100 -6 123 -80 57 -84 70 -13 40 40 30 7 40 -17 10 -43 50 20 100 0 90 -44 50 -53 86 -30 37 17 277 -40 36 6 0 1034m-3036 130l-7 3 -7 3 -6 4 -4 3 -6 3 -4 0 -6 -3 -4 -3 -6 -4 -7 4 -3 0 -7 0 -7 3 -6 3 -4 0 -6 4 -4 3 -6 3 -4 4 -3 3 -7 3 -3 7 -3 0 -7 3 -7 4 -3 3 -3 7 3 6 3 4 7 0 7 0 3 0 7 0 6 -4 7 0 3 0 7 -3 7 0 3 0 7 0 6 3 7 0 3 4 7 0 7 0 3 -4 7 -3 3 -3 7 -4 3 -3 3 -3 7 -7 3 0 7 -3 3 -4 7 0 7 0 3 -3 7 0 6 0 7 0 3 0 7 -3 7 0 6 0 4 0 6 -4 7 -3 3 -3 4 -4 3 -6 3 -4 4 -6 0 -7 0 -3 0 -7 -4 -3 -6 -4 -7 -3 -3 0 -7 0 -7 3 -3 0 -7 4 -6 3 -4 0 -6 3 -7 0 -3 4 -7 3 -7 0 -3 3 -7 0 -6 4m2493 196l10 0 7 0 3 -3 7 -7 3 -3 3 -3 4 -7 3 -3 3 -4 4 -6 6 -4 4 -3 3 -3 7 -4 3 -6 3 -4 7 -3 3 -3 4 -4 6 -3 7 0 3 0 7 -3 3 -4 7 -3 3 -3 4 -7 6 -3 0 -4 4 -6 3 -7 3 -3 0 -7 7 -3 3 -4 7 -3 7 0 3 0 7 -3 6 3 7 -3 3 0 7 -4 3 -3 4 -7 0 -3 0 -7 0 -6 -4 -7 -3 -3 -3 -7 -4 -3 -6 0 -7 3 -3 0 -7 3 -7 4 -3 3 -7 0 -6 3 -4 4 -6 3 -4 3 -3 4 -3 3 -7 3 -7 4 -3 0 -7 3 -6 0 -7 0 -3 3 -7 4 -3 0 -7 3 -3 7 -4 3 -3 3 -3 7 -4 7 -3 3 0 7 -3 3 -4 7 -3 3 -3 7 -4 3 -3 7 -3 3 -4 7 -3 3 -3 7 -4 3 0 7 -3 3 -3 7 0 6 -4 4 0 6 -3 7 0 3m-260 130l3 -3 7 -3 3 -4 4 -6 6 -4 4 -3 3 -7 3 -3 0 -7 -3 -3 -7 -3 -6 0 -7 3 -3 0 -7 0 -7 0 -6 0 -4 3 -6 0 -7 0 -7 4 -3 3 -3 3 -4 7 -3 3 -7 4 -3 0 -7 3 -6 0 -7 3 -3 0 -7 -3 -7 0 -3 3 -7 4 -3 3 -3 7 -4 3 -3 7 0 6 -3 4 -4 6 -3 0 -7 -3 -3 -3 -7 -4 -6 0 -4 0 -6 0 -7 0 -7 4 0 6 0 7 4 3 6 4 4 3 6 3 4 4 6 3 7 0 3 0 7 0 7 0 6 0 4 0 6 0 7 0 3 3 7 0 7 0 6 0 4 -3 6 -3 4 -4 6 -3 0 -7 4 -3 6 -3 4 0 6 0 7 0 7 0 3 -4 3 -3 7 -7 0 -3 3 -7 4 -3 3 -7z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil6","@d":"M-2354 6093l6 0 -6 24 0 -24z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil6","@d":"M-2358 6320l14 107 26 13 17 80 43 23 67 97 217 147 220 43 43 -27 67 -6 60 -34 36 7 34 -20 20 33 50 10 30 -13 13 -40 37 -10 73 50 140 17 83 -34 34 -36 33 0 53 -110 17 6 -10 40 13 34 -10 36 30 4 10 83 67 33 20 -6 -53 -44 -20 -36 66 66 57 24 100 3 53 -40 50 20 67 27 23 53 30 23 40 84 34 63 -34 57 0 46 57 94 -2737 0 144 -284 170 -433 60 -213 26 -10 70 13 47 -37 60 7 70 -60 47 -3 26 53z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil6","@d":"M-2358 6320l-26 -53 53 10 3 13 -30 30z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil6","@d":"M-928 6697l0 0 -10 36 30 4 -20 -40z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@id":"areas_density","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"g":[{"path":[{"@class":"fil7 str0","@d":"M3001 367l-3 0","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-1830 821l-15 32 14 28 -8 26 -41 -18 -13 22 -47 6 -6 51 -54 3","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-1248 1007l83 -46 67 27","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-1104 851l2 29 -16 12 -78 -4 -63 48 11 71","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-712 867l-11 25 10 16 -37 47 -2 65 -25 18","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-1493 1087l24 -16 6 -26 43 -7 52 -59 76 29 44 -1","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-777 1038l-60 13 11 38 -83 -7 -94 -45 14 -37 -20 -40 -29 -5 -5 36 -55 -3","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-2000 971l-1 57 34 20 22 50","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-3173 725l-30 42 -37 0 -4 28 21 8 3 33 33 28 5 49 45 27 2 46 43 -23 27 19 -25 35 -41 10 -27 41 12 23 23 -12 39 20 12 50","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-2000 971l-15 -29 -28 -7 -47 41 -35 -2 -27 59 -18 -13 -37 21 -77 -6 -17 30 -43 -1 -8 20 -30 6 -53 -18 -45 12 -25 38 -61 -8 -37 -26 -15 -38 -20 10 -34 -12 -17 32 -50 -16 -8 24 -74 -36 -31 45 -12 1 -7 14 9 8 -3 16 -64 18 -76 -11 -36 26 -31 -20","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-3511 537l-13 33 10 24 -19 18 -25 110 -31 51 -32 -2 -3 48 -30 36 10 20 -24 48 21 71 -17 31 18 66 -50 80","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-346 877l-29 9 -25 46 -43 12 7 59 -60 46 -12 59 -28 8 -21 26 -40 -11 -22 44","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-777 1038l11 32 -39 25 3 23 28 13 77 0 78 44","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M200 1138l-48 12 -19 45 3 46 -28 29","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-1098 988l-19 28 23 16 -2 46 -16 13 58 9 46 57 -67 20 -62 -33 -34 59 36 32 11 -25 23 -2 7 -9 8 7 -10 65 12 10","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-1945 1098l88 -3 54 -25 24 7 35 52 58 13 10 77 14 7 31 -16 2 19 -28 17 55 38","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-1602 1284l75 1 27 -28 42 -3 -3 -24 -5 -29 -32 21 -12 -25 44 -24 -10 -22 -53 31 -20 -15 17 -50","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-4107 1294l13 -32 95 -41 72 10 12 -25 28 0 8 -25 12 -8 18 17 11 -15 25 7 -4 -15 18 -7 54 5 15 15 34 -9","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-920 1257l123 19 9 17 -17 28 18 19 7 1 10 -7 10 2 3 17 -10 7 -52 -3 -22 -17 -46 9 -53 -51 20 -41","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-3696 1171l14 4 -8 53 58 46 -36 101","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-3212 1444l19 -54 -6 -27 24 -16 -16 -45 42 -37 25 1 30 -36 1 -54 21 -27","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-914 1424l34 -44 34 27 -10 51","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-3668 1375l16 22 -10 31 71 12 6 6 -9 11 17 12","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-619 1175l10 37 -22 33 3 38 -28 12 21 56 -37 19 -26 -21 -46 37 22 30 23 -22 12 28 -13 50 -34 6","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M1535 1379l-1 39 45 14 -3 34 0 2 30 -3 -4 44","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-3264 1528l52 -84","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-3668 1375l-54 21 -87 -19 -93 53 6 99 35 35 -2 40 18 15 27 -6","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-1945 1098l-33 21 -38 85 -20 6 0 55 -23 30 32 29 -23 114 15 14 -16 66 7 35 -35 13 -4 23 18 -2 1 13 -13 24 -20 1","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-3212 1444l49 11 25 -19 48 24 18 8 -17 51 57 49 -31 64","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-2097 1625l-21 -7 -4 13 -15 2 -5 -7 -13 -17 -38 34 -25 -8 -13 22 4 8 -6 7 -20 -4 -10 21 -19 -9 -21 18 1 35 2 69","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-941 1370l-28 13 -27 -15 -48 3 -9 14 5 20 -24 26 1 11 16 2 -8 38 23 27 -3 44 -5 2 -12 -23 -10 9 20 30 -28 14 17 62 -21 45 55 83 53 1 10 43","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-310 1686l4 13 -14 20 -54 -3 -41 55 0 35 26 19","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-3063 1632l-10 31 -32 -12 -41 35 -11 32 -30 28 0 24 21 14 -12 48","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-3063 1632l41 34 35 -5 83 29 95 -14 53 42 97 -1 42 23 38 -17 21 26 44 -19 21 17 35 -18 43 65 33 -34 14 30 12 28 -11 23 20 9 11 -31 36 -17","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-389 1825l-2 34","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M108 1270l-68 34 -6 40 -55 0 -29 71 -25 -5 -16 24 8 35 -36 37 -6 35 13 22 -31 35 -15 65 15 69 50 52 -48 90 -6 11 -45 -8 -31 11 -58 -39 -26 10 -40 -30 -42 -4","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-964 1819l24 9 35 -21 6 -47 26 -14 17 24 -21 53 93 14 34 -52 2 -19 11 -12 6 2 32 -25 68 -3 20 40 38 -17 35 7 -13 36 25 26 3 44 78 25 54 -30","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M1602 1509l42 -11 78 15 -18 46 11 15 -1 13 -22 -1 -5 13 17 20 64 22 74 -28 18 27 36 -11 33 38 35 -6 12 30 -10 38 -28 10 28 20 1 18 -48 29 -20 -5 -6 8 10 44 70 14 43 47 60 -27 58 3 13 60","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-1602 1284l-11 19 -21 -13 -78 49 13 42 -18 48 24 50 -4 24 -31 6 -13 19 9 33 27 1 43 183 45 5 24 19 -17 16 9 28 45 0 8 9 -14 28 13 15 52 -16 0 21 -45 21 -9 30 -52 14 -3 27 26 47","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-2097 1625l-15 92 50 8 14 43 -55 107 11 22 61 -11 39 64 28 5 35 -32 25 3 35 45 36 -11 13 11 -8 28 14 13 25 0 18 -19 48 14 36 -29 62 6 17 22 28 3","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M1602 1509l-88 24 15 33 -7 25 26 7 5 17 -18 23 14 39 -24 24 14 20 -25 19 19 4 -1 9 -16 5 -2 35 -37 34 31 13 -17 66 -28 18 -23 -22 -12 13 -2 -22 -29 5 4 50 -16 17 37 45 -43 18 17 28","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-1580 2009l-18 28 30 30 -6 56 15 -6 1 1 15 27","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-964 1819l-26 30 -3 37 -21 4 -10 29 -46 7 4 16 -31 45 -48 -43 -20 11 0 55 -39 22 -1 31 -23 12 -20 44 -8 19 -43 -16 -4 24","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M1043 1166l-73 104 9 47 35 14 -16 75 -20 9 30 61 5 64 -18 142 -30 97 -40 43 24 45 -144 151 18 55 44 2 9 35 -22 38 -29 10 -2 50","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M760 2215l8 -11 49 10","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-1303 2146l-76 17 -26 27 -6 37 -12 2 -7 -6 0 -28 -8 -3 -18 27 -44 -54 -43 -20","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M108 1270l-4 27 19 15 -20 25 8 34 -15 23 20 15 -17 28 20 2 0 61 44 24 -51 101 15 7 13 -28 33 9 20 -46 -4 -18 12 -11 8 4 4 49 -14 42 5 131 -14 7 -17 -26 -29 66 61 33 59 -1 78 79 6 80 73 28 11 35 61 41 21 -17 25 4 64 164 29 9 -2 -13 8 -1 7 12 35 1","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M1396 2056l-3 17 -91 -3 -29 26 7 35 -30 14 -26 -10 -10 9 10 17 -63 75 -43 11 -22 -14 -12 24 -30 -1 -77 36 -19 -15 -75 10 -7 22 -27 0","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M812 2230l31 21 -12 21 18 37","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M1396 2056l30 6 1 19 -27 20 49 30 3 55 55 25 -9 14 15 35 24 -5 -7 31 -18 3 3 5 30 10 -1 25","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-1303 2146l11 31 20 12 19 -9 18 39 45 14 -5 51 79 63","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-2300 1802l49 48 -26 27 15 18 -15 63 8 4 -3 20 -31 23 -1 25 25 35 1 50 28 10 -8 26 16 15 -2 21 -42 26 -3 2 17 45 -17 36 22 82 -26 47 28 6","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-391 1859l27 75 -20 46 38 56 -15 39 -25 1 -35 43 -21 -8 -16 12 12 28 -6 46 25 59 -49 21 -7 -34 -37 -9 -7 52 -26 35 16 101 53 25","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-1116 2347l-28 32 -74 -5 -17 16 4 26 -75 34","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-1543 2145l-9 43 -65 32 -133 21 -88 30 14 50 -14 25 -35 -9 -7 6 11 25 -44 39 7 27 -6 6 -20 -7 -21 24","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M849 2309l-2 24 -1 3 -31 22 -6 38 -48 26 6 40","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-2265 2431l4 -13 22 3 12 23 21 -1 29 24","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-2265 2431l-4 34 -19 13 -33 -16 -12 -35 -30 4 -6 23 -44 -53 -22 8 -29 -27 -66 16 -69 -15 -29 57 -10 3 -6 -11 -15 6 -9 -7 -1 -28 -43 -3","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-1953 2457l-43 10 -26 29 -82 -47 -73 18","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-484 2447l-4 48 -8 2 -25 -21 -16 0 -17 19 -32 -3 -46 24 -20 -18 -29 19 -29 -15 -36 -58 -23 9 -6 -6 4 -15 -23 -10 13 -17 -3 -4 -14 4 -12 -19 -35 -4 -6 -14 -9 -2 -24 15 -33 -8 -24 -33 -22 -2 -16 15 -56 13 -81 -19","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M767 2462l-78 -4 -19 24 -32 -52 -121 -48 -49 -45 -12 13 -38 -18 -44 -52 -45 -6 -3 32 -6 2 -1 -2 -22 1 2 46 -21 12 31 24 -36 59 -43 -33 -22 47 -29 0 -18 -27 -34 50 -29 -14 9 -37 -24 9 -41 -21 -26 28 -34 -9 -28 19 6 32 -22 18 -25 -3 -14 -24 -55 52 12 21 -14 26 -85 8","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-484 2447l52 -20 17 24 70 34 102 105","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M767 2462l8 23 28 9 12 39 -25 56 19 52 -24 38 -36 20 6 11","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-1306 2450l-42 14 -91 109 -63 23 -28 43 -16 85 -52 2 -47 70","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-1645 2796l-64 6 6 11 -9 9 -21 2 -22 3 -32 -10 -4 -55 -27 -31 -6 -43 -30 -3 -3 -4 10 -15 -15 -15 -4 -49 -50 -65 -35 -14 -2 -66","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M755 2710l23 -1 12 21 33 10 -7 36 71 19 23 36 44 17","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-728 2977l5 -16 -15 -29 8 -18 63 -7 12 -19 -23 -25 9 -21 51 29 14 -10 -2 -34 53 7 24 -33 35 12 37 36 28 4 5 -16 22 9","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-243 2590l3 46 48 56 -13 53 17 37 -6 64 -26 20 -46 -17 -9 81 -29 11 -32 48","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-2177 2467l-13 62 26 17 4 28 -36 124 -51 57 -72 41 7 22 -28 35 -26 14 -29 -7 -4 32 36 -9 12 15 -17 53 -29 1 -2 30 -30 -15 6 -26 -36 11 -32 34 3 55 -31 32","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-2519 3073l-37 2 0 -42 -49 20 -14 30 -43 -17 -19 -27 -42 -13","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-2710 2997l5 -9 -86 -59 -187 105 -12 43 -65 17 -19 -12 -22 16 -37 -5 -19 -20","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-1645 2796l-7 50 -40 13 -18 -12 -7 5 3 24 -22 26 2 96 -59 7 -22 61 -32 -14 -8 6 4 27 -24 56","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-276 3045l-1 3 12 14 3 -2 74 75 58 -5 -1 37","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-1306 2450l31 49 32 10 -4 23 24 37 -56 147 32 25 -12 52 33 13 11 -15 13 34 28 -3 -11 37 24 23 -2 25 21 -9 29 20 0 51 29 12 11 24 -32 106 11 8 38 -27 17 83 1 4","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-1038 3179l28 2 12 -39 54 35 46 -33 13 -44 -13 -69 14 -44 14 -9 7 9","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-2519 3073l107 75 35 -8 26 -32 24 -3 17 15 -9 39 21 48","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-2298 3207l91 22 76 -53 11 35 22 0 87 -80 5 -30 55 -11 24 61 52 -10","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-1088 3246l55 -19 -18 -38 13 -10","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-1164 3258l0 1 28 1 41 -30 7 16","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-1875 3141l25 14 48 -28 30 -44 15 3 8 25 29 27 31 -39 31 -14 28 36 45 -16 33 37 108 32 26 26 18 -7 58 21 5 22 -12 24","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-131 3167l70 3 1 -40 15 -2 14 27 16 31 51 0 43 36 -2 19 -45 22","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-131 3167l42 97 44 6 35 6 42 -13","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M32 3263l11 28","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M755 2710l-75 32 -12 -28 -46 7 -63 -41 -23 24 -9 50 -35 20 -15 -14 -26 13 4 36 48 4 -4 70 20 21 -41 32 37 47 -61 55 -9 39 -51 14 -25 -8 0 39 -37 87 -33 22 -40 2 -6 30 -34 16 0 44 25 30","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M244 3353l-53 21 -22 -79 -43 -13 -83 9","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-1483 3350l23 27 8 1 50 -46 49 -10 -1 -20 61 -20 15 -21","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-2298 3207l-23 15 3 60 -26 96 42 -7 22 15 -19 70","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M588 3454l-46 -18 -18 -32 -36 -7 -23 43 -45 31 -22 -31 -67 4 -11 -65 -18 -7 -23 27 -35 -46","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-1088 3246l7 54 30 6 -16 81 32 15 44 99 46 52 -8 129","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M43 3291l-36 17 3 17 6 46 -39 90 5 41 -26 13 -40 -8 -63 85 -11 87 13 19","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-1981 3718l34 -22","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-2092 3722l15 -13 22 -73 23 -16 53 40 -2 58","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-2208 3444l-6 32 18 25 -36 91 132 132","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-1981 3718l-58 31 -2 -1","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-953 3682l35 56 -14 24 28 5","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-901 3767l24 -24 17 6 13 36","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-477 3749l37 5 20 43 53 -9 63 19 25 -31 134 -78","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-1947 3696l40 -4 4 -25 61 -47 20 49 22 -29 108 31 25 -15 21 -51 59 -2 11 38 -15 7 -5 42 -24 0 -17 66 24 17 18 -17 54 9 6 43 59 29 42 -24 34 17 45 -22 61 -5 67 -70 61 1 12 -54 50 -2 24 -16 85 38 42 -18","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-797 3779l82 -10 74 74 29 -35 31 42 55 -40 69 9","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-2142 3754l-7 3 -26 -19 -16 40 -56 23 -44 -18 -21 11 -7 55 -24 47 -36 4 -31 -33 -34 -2 -20 18 19 21 -10 32 -43 21 -79 -46 -13 24 -53 17 -12 -19 -33 33 -7 -34 -20 -2 -54 53 -49 -39 -41 -12 -9 -46 -21 -5 -12 7 -89 -15 -5 18 -42 -29 -41 10 -44 -11 -18 -37 34 -54 -25 -18 -6 -35 -47 0 -87 -39 -12 17 26 22 -26 47 -17 3 -7 -33 17 -15 -30 -7 -25 23 -7 17 11 5 -25 34 -20 -1","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-145 3698l34 41 24 -11 33 26 103 22 -10 78 -1 2 -42 105 74 85 104 -9 24 42 0 67","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M701 4059l0 23 -22 -22 -42 22 -12 -16 -32 22 -51 -19 -85 60 -66 2 1 24 38 5 7 13 -67 45 -15 -35 -51 -19 -47 23 -19 -25 -28 0 -12 -16","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-2147 4219l30 -7 28 -91 25 -18 27 3 9 -31 -51 -25 -22 -64 47 14 27 -11 -24 -37 14 -51 21 -24 49 2 10 -12 -1 -1 -29 -72 29 -13 22 -57 -11 -28","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M198 4146l-20 17 34 63 -68 22","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-844 4360l-1 -70 16 4 35 -24 15 -61 -57 -41 -22 -71 -63 -35 43 -75 -19 -67 64 -96 -14 -39 0 0","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-1714 4497l10 -39 214 23 55 -41 111 20 23 -39 17 30 39 7 40 -19 12 -35 19 -6 114 26 42 -28 19 23 64 -17 16 10 75 -52","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-2147 4219l41 32 54 0 7 51 81 30 60 61 43 17 45 55 102 32","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-2147 4219l-61 1 -15 8 6 23 -10 12 -46 22 -28 38 -40 -1 -22 49 -89 56 -4 73 28 48 3 43 -12 34 -28 21","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-844 4360l41 23 55 -10 12 70 50 11 2 71 21 15 9 7 -6 53 -60 87","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-599 4725l66 -122 65 -39 29 -44 35 17 45 -10 87 -65 3 -3 35 6 25 42 55 -10 42 -46 -16 -112 26 -30 3 -56 26 -28 21 -7 18 15 47 -42 45 -15 31 11 7 26 48 35","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-720 4687l121 38","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-2465 4646l-28 -4 -49 40 -15 -28 31 -23 -11 -20 -27 -10 -45 11 -51 48 5 33 -21 41 -95 17 -44 31","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-2815 4782l-97 -45 -5 -23 -29 -22 -22 4 -15 31 -58 -10 -11 -46 -119 -23 8 -49 -78 -26","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-599 4725l76 79","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M144 4248l9 116 -41 59 6 50 50 13 17 34 -7 56 -30 57 6 31 8 12 66 102 44 42 42 11","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-2465 4646l55 73 0 34 37 29 0 54 38 23 3 38 18 17 4 45","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-523 4804l25 18 21 -11 25 18 43 1 17 23 -10 40 4 102 103 147 53 1 62 45","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-1554 5190l-45 -64 5 -15 -60 -75 -29 -9 29 -48 -41 -27 20 -40 -45 -14 9 -145 3 -5 60 -111 -30 -65 2 -36 -17 -34 -21 -5","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-720 4687l-26 11 -11 58 -26 15 -24 -6 -49 40 -64 125 8 53 -46 29 -12 27 -31 -9 -33 12 -48 -32 -28 0 -38 40 -49 20 -80 -40 -57 62 -81 38 -23 -4 -26 71 -57 8 -33 -15","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-2370 4984l0 33 32 34 96 -67 34 9 10 -4 1 -17 2 -1 9 15 7 -2 0 -14 42 -6 32 46 -10 26 3 4 15 -4 5 7 -3 68 30 47 28 8 10 59 19 17 48 -16 28 69","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-1554 5190l-55 -6 -37 43 -42 5 -15 79 -40 34","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-1932 5295l23 3 10 32 34 0 25 -10 19 -39 37 -4 9 41 32 27","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-2219 5475l7 -15 68 -19 62 -42 5 -19 -15 -19 5 -6 24 8 29 -31 24 34 42 -31 -7 -37 43 -3","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-2920 5534l-26 -28 15 -41 -16 -62 24 -31 -4 -87 15 -40 -26 -36 21 -12 -5 -36 30 -19 -48 -89 0 -36 -80 -9 -4 -15 40 -60 118 -26 21 23 17 -5 6 -40 37 -19 -21 -26 22 -33 -28 -8 -3 -17","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-2870 5540l1 1 45 4 62 35 100 4 25 -46 86 -11 13 -23 33 -1 21 9 14 16 16 -1 32 -32 3 -16 -16 -30 17 -10 32 8 -1 25 -23 19 12 26 11 1 55 -50 26 4 23 36 20 3 44 -36","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-523 4804l-47 34 -3 51 14 21 -26 64 6 42 -35 -3 -3 13 12 49 -11 19 -38 7 -4 16 -52 21 -53 47 -11 119 -16 10 -47 -10 -13 -22 -37 -9 -56 130 -29 -5 -11 12 26 90 -52 46 26 50 -66 38 3 29","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-1743 5345l22 43 10 79 28 1 7 23 62 27 35 35 128 37 32 38 -8 43","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str0","@d":"M-2219 5475l25 31 4 41 -26 50 -33 10 -36 -32 -28 -3 -28 32 28 41 -24 69 -35 33 -39 7 -39 65 -45 -10 -7 4 2 18 43 10 22 -22 15 -4 29 6 44 77 12 62 10 4 17 -4 18 18","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil7 str1","@d":"M-374 834l28 43","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str1","@d":"M-346 877l49 -8 18 40 31 -29 81 17 9 48 -20 54 -27 28 27 34 42 3 2 -49 17 -8 10 6 -7 18 22 21 28 -5 149 70 61 3 40 -16 14 34","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str1","@d":"M200 1138l0 21 54 25 38 51 18 -5 11 -26 61 16 46 -39 60 42 24 -6 25 48 55 28 97 -41 45 9 24 31 32 -37 39 25 116 -10 15 -23 -18 -24 9 -64 25 -12 67 19","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str1","@d":"M1043 1166l50 24 14 -10 72 10 45 52 30 -14 66 3 56 81","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str1","@d":"M1376 1312l15 -5 7 -34 128 14 4 22 29 10 -24 13 -6 37","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str1","@d":"M1529 1369l6 10","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str1","@d":"M1376 1312l-11 44 28 18 -24 19 19 35 52 -1 25 -24 29 -1 8 -27 27 -6","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str1","@d":"M1535 1379l114 25 3 7 20 47 22 14 39 -9 29 -45 67 -16 91 27 21 29 31 11 22 -22 42 6 17 -45 57 -9 81 -55 50 0 29 30 46 -8","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str1","@d":"M-3834 1670l7 69 31 -9 25 18 -5 27 -41 23 -34 51 6 27 22 11 -1 31 17 10 46 -7 42 -38 27 -2 8 -18 10 0 5 31 8 2 20 -17 72 -12 58 22 -9 34 46 -6 15 -22 18 6 4 2 17 37 27 -26 26 5 70 -27 11 -68 33 -9 44 33 31 -16","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str1","@d":"M-3178 1832l30 20 49 2 25 -32 13 12 29 30 54 -2 19 -18 18 20 -13 38 32 14 -31 87 6 47 25 20 35 -19 50 9 84 66 -10 17","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str1","@d":"M-3146 2517l-8 38 50 93 -13 10 -5 61 14 74 -24 62 26 37 -34 55 36 64 -48 62","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str1","@d":"M-3152 3073l-77 25 -16 28 8 47 44 21 34 64 -30 108 -43 41 -20 95","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str1","@d":"M-3544 3500l13 43 64 58 3 24 50 24 -14 90 42 51","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str1","@d":"M-3386 3790l-6 46 56 30 -6 42 73 3 27 29 8 40 -56 79 4 32","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str1","@d":"M-3453 4399l21 15 70 108 30 72 91 -21","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str1","@d":"M-3241 4573l-47 129 -57 -14 -14 31 -71 8 -30 107 -76 62 -17 72 -46 73 7 9","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str1","@d":"M-2352 6093l7 0","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str1","@d":"M-2355 6320l-29 -55","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str1","@d":"M-906 6736l-31 -4 11 -36","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str1","@d":"M-489 6865l22 54 30 23 40 83 33 65 -33 57 2 44 56 96","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@id":"borders","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"g":[{"path":[{"@class":"fil7 str2","@d":"M-1532 1117l-6 2 -5 1 -6 2 -6 2 -5 1 -6 1 -6 1 -6 1 -9 2","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str2","@d":"M-1587 1130l-6 1 -6 0 -5 -1 -6 -3 -3 -5 -1 -6 1 -6 4 -3 5 -3 6 -1 6 0 6 1 6 1 5 1 6 1 6 1 5 -2 6 -3 4 -3 4 -5 2 -5 4 -5 4 -4 6 -1 5 0 6 1 6 1 6 1 6 2 6 2","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str2","@d":"M-3565 1344l-2 -5 -2 -6 -2 -5 -1 -6 0 -6 0 -6 1 -6 1 -5 2 -6 2 -5 4 -5 5 -3 4 -3 4 -5 3 -5 2 -5 1 -6 2 -6 3 -4 4 -5 4 -4 4 -4 3 -5 3 -5 3 -5 3 -5 3 -5 3 -5 4 -5 4 -4 4 -4 5 -3 5 -2 7 -1 5 1 -1 4 -4 6 -3 5 -4 5 -3 4 -5 4 -5 2 -6 3 -3 4 -2 6 -1 5 -3 5 -4 5 -4 4 -2 6 -3 5 -3 5 -4 4 0 6 -1 6 -2 6 -4 4 -5 2 -5 3 -3 5 -1 6 -1 6 0 6 0 6 0 6 0 6 -3 4 -6 5","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str2","@d":"M-2635 2170l6 -3 2 -4 0 -6 -1 -6 -1 -6 2 -6 3 -5 3 -5 4 -4 6 0 7 0 5 -1 3 -5 1 -6 1 -6 0 -6 1 -6 3 -5 4 -3 6 -3 6 -1 6 1 6 1 5 -2 1 -5 -2 -7 -4 -4 -3 -5 1 -6 3 -5 5 -3 6 1 6 0 6 -1 6 -3 5 -3 1 -4 0 -6 -2 -6 -2 -6 -2 -6 -3 -5 -4 -4 -2 -5 -1 -6 0 -6 0 -6 3 -5 4 -4 3 -5 2 -6 2 -5 -4 -8","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str2","@d":"M-2532 1949l-3 6 -3 5 -3 5 -4 3 -6 1 -5 1 -4 5 -1 6 -1 5 1 6 1 6 3 5 3 5 2 6 0 6 0 5 -2 6 -4 5 -4 3 -5 4 -4 4 -4 4 -4 4 -2 6 -3 5 -4 4 -4 4 -6 1 -5 1 -3 4 -2 6 -2 6 1 6 0 6 -4 4 -5 3 -6 2 -5 3 -5 3 -5 2 -6 1 -7 0 -5 2 0 6 3 4 5 4 3 5 1 5 1 6 1 6 2 6 1 5 5 -1","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str2","@d":"M680 2265l-2 6 -3 5 -5 3 -5 2 -6 2 -6 0 -5 -2 -6 2 -5 3 -4 4 -3 5 -1 6 0 6 0 7 -2 4 -5 2 -7 0 -6 -1 -5 -3 -5 -3 -6 -2 -5 0 -6 2 -6 3 -3 3 -1 9","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str2","@d":"M-2723 3026l-5 3 -5 4 -4 4 -2 6 -1 5 0 6 2 6 2 6 2 5 3 4 5 3 6 3 5 2 5 3 1 6 -1 6 1 6 -2 5 -4 4 -5 4 -5 3 -5 2 -6 1 -6 1 -6 1","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str2","@d":"M-2668 3397l6 1 5 0 5 -3 5 -4 4 -3 6 -3 5 -2 5 -3 2 -5 1 -6 0 -6 3 -5 2 -5 0 -6 -5 -4 -5 -1 -3 4 -3 6 -1 6 -1 6 -1 5 -3 5 -5 4 -4 3 -6 3 -6 1 -3 4 -3 8","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str2","@d":"M-2311 3446l-4 -4 -3 -5 -3 -5 -1 -6 0 -5 2 -6 2 -6 1 -5 1 -6 -1 -6 -3 -5 -5 -2 -6 1 -3 5 0 6 -2 6 -3 5 -4 4 -4 3 -6 3 -6 1 -5 2 -6 0 -6 -1 -6 1 -5 1 -6 1 -6 0 -6 0 -6 0 -6 0 -5 1 -6 0 -6 1 -6 2 -5 1 -5 3 -5 3 -4 5 -3 5 -1 8","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str2","@d":"M-2463 3452l6 1 5 -1 6 -3 5 -2 5 -3 5 -3 5 -3 6 -2 5 0 6 0 6 1 6 0 6 0 6 0 5 3 4 4 5 1 6 -2 5 -3 6 -2 5 -2 6 -1 6 -1 6 0 4 5 4 4 5 2 7 1","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str2","@d":"M-2509 3450l-3 -5 2 -5 4 -4 5 -4 4 -4 2 -6 -4 -3 -6 0 -4 3 -4 5 -3 5 -3 5 -5 3 -5 3 -5 2 -5 4 -4 3 -6 1 -6 0 -6 -1 -6 -1 -5 -3 -4 -4 -4 -4 -4 -4 -5 -4 -5 -2 -6 -1 -6 -1 -6 -1 -5 -3 -3 -5 -2 -5 -3 -5 -5 -3 -6 2 -6 -1 -6 -1 -5 -1 -12 1","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str2","@d":"M-2665 3406l5 4 5 3 4 3 6 3 6 1 3 4 3 5 3 5 5 3 6 1 6 1 6 -1 6 1 5 0 5 3 5 4 4 5 2 5 3 4 6 1 6 1 6 1 5 0 6 0 6 -3 5 -2 5 -3 6 -1 6 0 5 -2 6 -2","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str2","@d":"M-2994 3305l-3 -5 -5 0 -6 0 -6 1 -6 2 -4 4 -5 2 -6 2 -5 2 -6 3 -5 3 -5 2 -4 4 -5 4 -5 3 -6 0 -3 -4 0 -6 2 -6 -3 -4 -6 -2 -3 5 -1 6 1 6 1 6 -1 5 -5 3 -6 2 -5 3 -6 2 -5 3 -5 3 -4 4 -4 4 -3 5 -2 6 -2 5 -2 6 -4 4 -3 5 -2 6 -3 5 -2 5 -2 6 -3 5 -3 5 -3 5 -3 5 -3 5 -3 5 -2 5 -4 5 -2 5 4 7","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str2","@d":"M-2707 3409l-1 -6 -1 -6 -1 -6 -3 -1 -5 5 -2 6 -1 5 -3 5 -5 4 -4 4 -5 3 -5 1 -6 1 -6 2 -5 2 -6 2 -5 2 -5 2 -6 2 -5 2 -6 2 -5 2 -6 2 -5 2 -6 2 -5 2 -6 1 -6 1 -6 1 -5 0 -6 1 -6 1 -6 -1 -6 0 -5 1 -6 2 -6 2 -5 1 -6 2 -5 2 -5 4 -4 4 -6 1 -6 0 -3 -5 -1 -6 -1 -4 -5 -2 -6 -2 -6 0 -7 0 -4 2 -4 6 -3 5 -5 1 -6 -1 -5 -3 -5 -2 -5 -4 -5 -3 -5 -3 -5 -3 -4 -4 -5 -4 -2 -5 -1 -6 -4 -4 -6 -3 -5 2 -6 1 -6 1 -5 2 -4 4 -6 3 -6 0 -6 -1 -3 -3 0 -7 5 -3 3 -5 -1 -6 -5 0 -6 3 -4 4 -4 4 -6 3 -5 2 -6 2 -5 0 -6 1 -6 2 -5 2 -5 2 -6 3 -5 2 -6 2 -5 3 -5 4 -5 2 -5 -2 0 -5 4 -5 3 -5 5 -4 3 -4 4 -5 3 -5 3 -5 3 -5 3 -5 2 -5 2 -6 2 -5 2 -6 2 -5 2 -6 3 -5 4 -4 5 -2 6 -2 6 -1 5 -1 6 -1 6 -2 5 -3 4 -4 4 -4 4 -4 5 -4 4 -3 5 -4 5 -2 6 -2 6 -1 6 0 5 -2 5 -3 6 -2 5 -3 6 -1 6 0 -1 -4","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str2","@d":"M-3947 3399l2 5 2 6 3 5 4 4 1 6 -3 5 -1 6 0 6 -1 6 0 5 1 6 0 6 0 6 -2 5 -3 5 -4 5 -4 4 -3 5 -4 5 -3 5 -2 5 -2 6 1 6 5 4 4 4 -1 5 -3 5 -5 4 -5 0 -6 -2 -6 1 -5 3 -2 6 0 6 0 7","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str2","@d":"M-3989 3565l5 2 6 2 6 -1 5 -2 5 -3 4 -5 2 -5 4 -5 4 -4 4 -4 6 -3 4 -3 -1 -5 -2 -6 -1 -6 0 -6 3 -5 5 -1 6 2 6 0 7 -1 3 -2 -3 -6 -6 -3 -6 -1 -5 -1 -2 -5 2 -6 0 -6 1 -6 0 -6 0 -6 0 -6 0 -5 2 -6 2 -6 1 -5 2 -6 2 -5 1 -6 -2 -6 -5 -4 -5 -1 -6 -2 -6 0 -6 -1","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str2","@d":"M-604 3461l5 3 5 4 4 4 4 4 3 5 2 6 3 5 4 4 5 3 6 2 6 -2 5 1 5 4 0 5 -4 5 -1 6 0 6 1 5 3 6 3 5 4 4 4 5 4 3 5 4 5 3 6 1 6 0 5 2 5 3 5 4 1 5 -1 6 3 5 3 4 4 5 5 6","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str2","@d":"M-481 3602l-5 3 -6 0 -4 -2 -5 -5 -4 -4 -4 -5 -3 -5 -4 -2 -6 0 -7 0 -5 0 -6 -2 -5 -3 -2 -5 -2 -6 -2 -6 -1 -6 -3 -5 -4 -4 -4 -4 -5 -3 -4 -5 -4 -4 -3 -5 -2 -5 -3 -5 -5 -4 -5 -3 -4 -4 -2 -5 -2 -6 -1 -6 -1 -5 -1 -6 0 -6 1 -8","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str2","@d":"M-3176 3467l4 3 6 0 6 -1 5 -2 5 -3 4 -4 4 -5 5 -2 6 -3 5 -1 6 -2 6 0 6 0 5 2 6 1 6 0 6 0 5 0 6 0 6 0 6 0 6 0 6 0 5 -2 5 -3 6 0 6 1 6 2 5 2 4 4 5 4 5 3 4 3 5 4 5 3 5 3 5 3 5 3 5 3 5 3 3 5 -1 6 -2 6 1 4 6 3 6 0 6 -1 4 4 3 5 3 5 3 6 2 5 3 5 2 5 3 5 3 5 3 6 3 4 4 5 4 4 5 3 5 3 5 3 6 2 5 1 6 0 6 0 6 1 6 0 6 0 6 0 5 0 6 2 6 2 5 2 5 2 6 3 5 2 5 4 4 3 5 4 4 4 5 3 5 3 5 2 6 2 6 0 6 -1 4 -5 1 -6 -4 -4 -5 -3 -6 -1 -6 0 -5 -3 -5 -2 -5 -4 -5 -3 -5 -3 -5 -3 -5 -3 -5 -3 -4 -4 -5 -3 -5 -4 -5 -3 -6 0 -5 0 -6 1 -6 1 -6 1 -6 1 -5 -1 -6 -1 -6 -2 -5 -2 -5 -3 -5 -4 -4 -4 -4 -4 -3 -5 -3 -5 -4 -5 -3 -4 -4 -5 -3 -5 -4 -4 -3 -5 -3 -5 -2 -6 -1 -6 1 -5 5 -4 5 -2 6 -2 6 -1 5 -1 6 -2 5 -2 6 -1 6 -1 5 -1 6 -1 6 -2 5 -1 6 -1 6 0 6 0 6 0 5 -1 6 -1 6 -1 6 -1 5 -2 6 -2 5 -2 5 -2 6 -3 5 -2 5 -3 5 -3 6 -2 5 -3 5 -2 6 -1 6 0 6 1 5 -2 5 -3 3 -5 4 -4 5 -4 4 -4 8 -6","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str2","@d":"M-2017 3833l-1 -6 -2 -5 -3 -5 -3 -5 -3 -5 -2 -5 1 -6 3 -6 -1 -5 -4 -4 -5 -4 -5 -3 -5 -3 -5 -3 -5 -3 -5 -3 -4 -4 1 -6 5 -2 6 1 6 1 7 -4","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str2","@d":"M-2142 3754l-1 6 -1 6 -1 5 -1 6 -1 6 -1 6 -1 5 -2 6 -2 5 -2 6 -3 5 -3 5 -4 4 -5 4 -5 3 -5 3 -5 4 -5 3 -5 0 -5 -3 -4 -5 -2 -6 -1 -6 -4 -1 -6 4 0 5 2 6 -1 6 0 6 -1 6 -1 5 -2 6 -2 5 -1 6 -2 6 -1 5 -1 6 3 10","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str2","@d":"M-2224 3903l5 2 5 -3 0 -5 -1 -6 -2 -6 0 -6 2 -5 3 -5 5 -4 4 -4 6 -2 5 -2 6 -3 5 -3 5 -3 5 -3 4 -3 5 -3 5 -4 4 -4 4 -5 3 -4 3 -5 3 -5 3 -6 2 -5 3 -5 2 -6 2 -5 2 -6 2 -5 2 -6 2 -5 2 -5 5 -4 5 -2 6 -2 6 1 6 1 4 4 3 5 3 5 3 5 4 5 3 5 5 3 5 3 5 3 4 4 4 4 3 5 2 6 2 5 2 6 3 5 4 5 5 2 9 1","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str2","@d":"M-2310 3962l-6 1 -6 0 -6 1 -5 1 -6 2 -5 4 -4 4 -3 5 -3 5 -4 4 -5 3 -6 2 -5 2 -6 2 -5 1 -6 2 -6 1 -5 2 -5 3 -5 3 -3 5 -5 7","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str2","@d":"M-2420 4022l2 3 6 1 6 -1 5 -3 5 -3 5 -3 5 -3 5 -3 6 -2 5 -2 6 -2 5 -2 5 -3 5 -3 5 -3 5 -3 5 -4 4 -3 5 -4 4 -4 4 -5 7 -8","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str2","@d":"M-2391 4081l1 -7 1 -5 4 -3 6 -2 6 -1 6 1 4 5 5 3 5 2 6 1 6 0 6 0 6 -1 5 -2 6 -3 4 -3 5 -3 6 0 6 0 6 0 6 0 6 0 5 0 6 -1 6 -1 5 -2 6 -2 5 -4 4 -3 6 -2 6 2 4 3 0 5 -3 6 -1 6 -1 6 2 5 4 5 4 4 4 4 5 4 5 2 6 3 5 1 6 2 4 4 4 5 3 6 0 5 -5 5 -5 0 -5 -2 -5 -3 -6 -3 -4 -3 -5 -5 -4 -4 -5 -2 -6 -2 -3 -5 -3 -5 -3 -5 -2 -5 -4 -5 -4 -4 -6 -2 -5 -1 -6 0 -6 1 -6 0 -6 1 -6 0 -5 1 -6 1 -6 1 -4 4 -5 3 -6 1 -6 0 -6 0 -6 0 -5 -1 -6 -2 -6 -2 -5 -1 -6 -1 -6 -1 -6 0 -5 1 -7 0","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str2","@d":"M-858 4621l4 -3 5 -4 4 -4 4 -5 3 -5 3 -5 3 -5 5 -3 3 5 -1 6 -4 4 -4 4 -4 5 -4 4 -4 4 -3 5 -3 5 -1 6 1 5 3 6 2 5 3 6 0 5 -3 5 -4 5 -4 4 -4 4 -9 3","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str2","@d":"M-867 4683l-1 -5 1 -6 2 -6 2 -5 2 -5 2 -6 1 -5 1 -6 1 -6 -1 -6 -1 -6","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str2","@d":"M3405 6355l-6 -2 -5 -2 -6 -1 -5 -2 -7 -2 -5 0 -2 4 0 6 0 7 0 6 -1 6 -2 6 -1 6 -1 5 2 6 4 5 5 2 6 0 6 -1 6 1 5 2 7 4","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str2","@d":"M369 6486l6 -2 5 -2 6 -2 5 -2 6 -2 5 -2 6 -2 5 -2 6 -2 5 -2 6 -3 5 -2 6 -1 5 -1 6 0 6 2 5 4 4 4 2 5 -1 6 -2 6 -2 6 -3 5 -3 5 -4 5 -4 3 -5 2 -6 2 -6 1 -6 1 -5 1 -6 0 -6 0 -6 1 -6 1 -5 1 -6 1 -6 1 -6 2 -5 1 -6 3 -5 2 -4 4 -4 4 -4 5 -5 4 -4 3 -6 2 -5 2 -6 1 -6 0 -5 -1 -6 -2 -6 -2 -6 -1 -5 0 -6 1 -6 1 -6 1 -5 1 -6 1 -6 1 -6 0 -6 0 -6 0 -4 -3 -1 -6 2 -6 5 -3 5 -3 5 -3 5 -4 5 -3 4 -4 5 -4 4 -4 5 -3 5 -3 5 -3 5 -2 6 -2 6 -2 5 -2 6 -1 6 0 5 1 5 4 5 3 5 -1 5 -3 6 -4 5 -2 5 -2 10 -4","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str2","@d":"M2860 6683l2 -5 2 -6 1 -6 2 -5 2 -6 2 -5 2 -5 3 -6 2 -5 3 -5 3 -5 3 -5 3 -5 4 -5 3 -5 3 -5 3 -4 3 -5 4 -5 2 -5 3 -6 3 -5 3 -5 4 -5 3 -5 4 -4 4 -3 5 -3 6 -2 5 -1 6 -2 6 -1 6 -2 6 -1 5 -2 5 -3 5 -3 4 -5 4 -4 5 -3 5 -2 6 -3 5 -2 6 -2 5 -3 6 -3 6 -2 5 -1 5 0 5 3 4 5 3 5 2 6 1 6 0 6 -1 6 -2 5 -5 4 -5 3 -6 1 -5 0 -6 0 -6 0 -6 1 -6 2 -5 3 -5 3 -4 4 -3 5 -1 6 -3 5 -3 5 -3 5 -4 4 -4 4 -4 4 -5 4 -5 3 -5 2 -6 2 -6 1 -5 3 -5 3 -4 4 -5 3 -5 4 -4 4 -4 4 -5 4 -4 4 -4 4 -4 4 -4 4 -4 5 -4 4 -3 5 -4 5 -4 4 -5 3 -5 1 -12 1","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str2","@d":"M-3569 4591l5 -3 5 -3 4 -5 1 -5 2 -6 4 -4 5 -3 5 -3 5 -3 5 -3 5 -3 6 -2 5 -2 6 -1 6 0 6 -1 5 -3 4 -4 3 -5 2 -5 0 -7 1 -5 3 -5 5 -4 5 -3 5 -2 6 0 6 0 6 1 5 1 6 1 6 1 6 1 6 0 6 1 7 2 6 1 4 -1 3 -4 0 -7 -1 -6 -4 -5 -5 -3 -6 -2 -5 -1 -6 -1 -6 0 -6 0 -6 1 -5 1 -6 1 -6 1 -5 2 -6 1 -6 2 -6 2 -5 2 -6 2 -6 1 -5 1 -5 0 -6 -3 -3 -6 0 -5 1 -6 3 -6 2 -5 4 -5 3 -4 5 -4 3 -5 4 -4 3 -5 3 -5 3 -5 3 -6 2 -5 3 -5 4 -4 4 -4 6 -6","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str2","@d":"M-3415 4234l-6 3 -4 4 -3 5 -2 5 -2 6 2 6 0 5 -2 6 -1 6 -3 5 -5 4 -5 1 -6 -3 -6 -2 -6 -2 -3 2 -1 7 2 6 4 4 4 5 1 5 0 6 0 6 -1 6 0 6 -1 6 0 6 -2 5 -3 5 -3 5 -3 5 -4 5 -2 5 -2 5 -2 6 -2 5 -3 6 -2 5 -3 6 -3 5 -4 2 -6 0 -7 -1 -6 0 -6 0 -5 1 -5 3 -2 6 1 5 4 5 4 5 2 5 -1 6 -2 5 -1 6 -1 6 -1 6 -1 6 -1 5 -2 6 -2 5 -2 6 -2 5 -2 6 -2 5 -3 6 -2 6 -3 4 -4 -1 -3 -6 -3 -5 -2 -6 -2 -5 -4 -5 -3 -5 -4 -4 -4 -5 -4 -4 -3 -5 -2 -5 -2 -5 -1 -6 -1 -7 -2 -6 -3 -3 -6 1 -6 4 -2 4 0 6 1 6 1 6 2 6 1 5 0 6 -1 6 3 5 5 2 6 2 5 3 5 4 4 4 2 5 2 6 1 6 0 6 0 6 -1 5 -3 5 -1 6 1 5 2 6 3 5 5 7","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str2","@d":"M-2748 3125l-6 -1 -6 -1 -5 -2 -3 -5 1 -6 1 -6 1 -6 2 -4 5 -5 3 -4 4 -5 4 -4 2 -5 1 -6 -1 -6 -3 -5 -5 -4 -5 -2 -6 -1 -6 1 -5 1 -7 2 -6 0 -1 -3 3 -7 4 -5 5 -2 6 0 6 1 5 2 6 0 4 -3 5 -4 4 -4 5 -4 4 -4 4 -4 4 -5 3 -5 4 -4 7 -3","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str2","@d":"M-856 2935l4 -1 4 -4 4 -4 1 -6 0 -6 0 -5 3 -6 3 -5 5 -3 3 -5 2 -6 -1 -5 -4 -3 -6 -3 -3 -5 -2 -6 0 -6 1 -6 2 -5 2 -6 3 -5 4 -4 4 -5 4 -3 5 -3 7 -1 5 -2 2 -5 2 -9","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str2","@d":"M-802 2802l-6 0 -6 0 -6 1 -6 2 -5 2 -4 3 -4 5 -3 5 -2 6 -2 5 -3 5 -2 6 -2 5 -2 6 -1 5 -3 6 -2 5 0 6 2 5 4 5 3 5 -1 5 -3 6 -1 5 0 6 -1 6 -3 5 0 6 5 6","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str2","@d":"M572 2328l4 3 5 2 6 1 6 1 6 1 5 1 6 2 5 3 6 2 5 -1 6 -2 5 -3 4 -5 2 -5 2 -6 2 -5 3 -5 3 -5 5 -4 5 -1 6 -1 6 -3 5 -3 4 -3 5 -4 3 -4 4 -5 3 -5 2 -6 2 -5 2 -6 1 -6 1 -6 2 -5 2 -5 5 -4 5 -2 6 -2 6 -2 6 0 6 1 5 1 5 3 5 4 4 4 4 5 4 3 5 2 6 0 11 0","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str2","@d":"M794 2248l-2 -5 -3 -6 -3 -4 -5 -4 -5 -3 -4 -4 -5 -3 -7 -4","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str2","@d":"M1514 7287l-1 -6 -1 -6 0 -6 -1 -6 -1 -5 0 -6 -1 -6 0 -6 1 -6 1 -5 3 -5 4 -5 3 -5 4 -5 3 -4 4 -4 4 -5 4 -4 5 -4 4 -4 5 -4 4 -4 5 -4 4 -4 3 -5 2 -4 1 -6 -1 -6 -1 -6 -2 -6 -2 -6 -4 -6 -3 -3 -5 0 -6 4 -4 4 -4 4 -4 5 -3 5 -4 5 -3 4 -3 6 -2 5 -3 5 -4 4 -4 4 -5 3 -6 2 -5 2 -6 3 -5 2 -6 1 -5 2 -6 2 -6 1 -5 1 -6 1 -7 0 -6 -1 -5 -1 -4 -3 -3 -5 -1 -6 0 -7 0 -6 2 -6 1 -5 -1 -5 -6 -3 -5 1 -5 2 -6 4 -4 3 -5 3 -5 4 -3 5 -4 5 -3 5 -2 6 -2 5 0 5 3 5 4 5 5 4 3 5 4 5 2 5 -1 6 -1 6 -2 6 -3 5 -4 4 -6 0 -6 0 -6 0 -6 -1 -6 1 -4 3 -5 3 -4 5 -5 4 -5 3 -5 2 -5 2 -6 2 -5 2 -6 2 -5 3 -8 5","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str2","@d":"M2600 6812l5 -4 5 -3 4 -4 5 -4 4 -5 4 -4 4 -4 2 -5 0 -7 -3 -4 -6 -1 -6 0 -6 1 -6 0 -6 1 -6 1 -5 0 -6 2 -6 1 -6 0 -6 2 -4 3 -4 4 -3 5 -4 5 -5 3 -5 2 -6 2 -6 1 -6 1 -6 0 -6 -1 -6 0 -5 2 -4 3 -5 4 -3 5 -3 5 -2 6 -1 6 -2 5 -4 5 -5 1 -5 -3 -5 -4 -6 -2 -5 -1 -6 0 -6 0 -6 1 -5 3 -2 5 1 7 3 4 5 4 5 3 5 3 6 3 5 2 5 2 6 0 6 0 6 0 6 0 6 0 5 0 6 2 6 1 6 1 5 0 6 -2 6 -2 5 -2 5 -3 4 -5 3 -5 3 -5 4 -3 6 -1 6 1 6 1 6 -1 5 -4 4 -4 4 -5 3 -4 2 -6 3 -5 2 -6","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str2","@d":"M-2710 2997l3 5 -1 6 -4 5 -3 4 -4 4 -4 5","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str2","@d":"M-2041 3748l4 -3 -1 -6 -3 -5 -4 -4 -5 -3 -5 -3 -6 -2 -5 -1 -6 -1 -6 0 -6 1 -8 1","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str2","@d":"M-2100 3724l-5 1 -6 1 -6 2 -5 2 -5 3 -5 4 -4 4 -4 4 -2 9","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str2","@d":"M-2092 3722l-8 2","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str2","@d":"M-728 2977l-6 0 -5 -3 -4 -5 -1 -6 -2 -5 -4 -5 -5 -2 -6 0 -6 1 -5 2 -6 2 -5 2 -6 2 -5 1 -6 1 -6 1 -6 0 -6 0 -5 0 -6 2 -5 3 -5 2 -5 3 -6 2 -5 3 -4 4 -4 5","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str2","@d":"M-863 2987l-4 5 -4 4 -4 5 0 5 5 4 5 3 6 3 4 4 2 5 1 6 1 6 0 5 0 6 0 6 2 6 2 6 3 4 6 2 6 1 6 0 5 -2 2 -5 1 -6 1 -6 1 -6 -1 -6 -3 -5 -2 -5 -4 -4 -4 -5 -4 -5 -2 -5 -1 -6 0 -6 1 -5 3 -5 4 -4 3 -5 5 -3 5 -3 6 -2 6 0 5 -1 6 -1 6 0 6 0 6 1 5 0 6 1 6 1 5 3 5 3 5 3 6 2 5 2 5 2 6 1 6 1 6 -1 5 -5 -1 -4 -5 -4 -5 -3 -6 1 -7 1","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str2","@d":"M760 2215l-5 -3 -5 -3 -5 -2 -6 -1 -6 0 -6 1 -6 2 -4 3 -5 4 -4 4 -4 4 -5 4 -4 5 -3 4 -4 5 -2 5 -3 5 -1 6 -2 7","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str2","@d":"M-2840 2347l5 -3 5 -3 5 -3 4 -4 5 -4 4 -5 3 -5 4 -4 5 1 6 3 4 5 1 5 -1 6 0 6 1 6 1 7 2 5 4 2 6 0 7 0 4 3 4 4 4 5 3 6 3 6 3 5 3 5 3 3 5 0 5 -4 6 -5 5 -1 3 4 6 7","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str2","@d":"M-2712 2400l5 3 4 4 4 4 4 5 4 4 4 4 3 5 4 4 4 5 3 5 4 4 3 5 2 6 3 5 2 6 1 6 -1 5 -5 4 -5 -1 -5 -4 -5 -4 -4 -4 -3 -5 -1 -6 -2 -6 -1 -6 -2 -5 -3 -4 -5 -3 -6 -2 -6 0 -6 1 -5 3 0 8 -2 1 -4 -4 -3 -7 -1 -5 2 -6 0 -6 -3 -5 -5 -5 -4 -3 -6 0 -6 1 -5 -3 -4 -5 -4 -3 -6 -2 -5 -2 -5 -3 -5 -5 -5 -4 -4 -1 -3 3 -3 6 -3 6 -3 5 -5 5 -5 2 -4 -2 -3 -6 -1 -6 2 -5 2 -6 2 -6 1 -6 0 -5 -4 -5 -4 -4 -6 -6","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str2","@d":"M-3453 4399l5 -4 3 -5 4 -5 3 -5 1 -5 0 -6 -1 -6 -1 -6 0 -6 -1 -5 0 -6 0 -6 2 -6 1 -5 2 -6 2 -5 3 -5 4 -4 4 -5 4 -4 4 -5 3 -4 3 -6 2 -5 1 -6 1 -6 0 -5 -1 -6 -2 -6 -3 -4 -5 -7","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str2","@d":"M-1493 1087l4 3 4 5 3 5 1 5 -1 7 -2 5 -4 4 -6 -1 -6 -2 -6 -1 -5 -2 -6 0 -6 0 -9 2","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil7 str3","@d":"M-3176 3467l-5 3 -4 3 -5 4 -5 3 -5 4 -4 3 -5 3 -5 3 -5 3 -6 2 -6 1 -5 1 -6 1 -10 1","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str3","@d":"M-3544 3500l-6 0 -6 1 -6 0 -5 2 -5 2 -5 3 -5 4 -5 3 -5 3 -6 2 -5 0 -6 -2 -6 -1 -5 -2 -6 -2 -6 1 -5 2 -5 4 -4 4 -4 4 -4 4 -4 4 -4 4 -5 4 -4 4 -4 4 -5 4 -4 3 -5 4 -5 4 -4 3 -5 4 -4 3 -5 4 -4 4 -4 4 -4 4 -4 5 -3 4 -4 5 -4 5 -4 4 -4 4 -5 2 -6 1 -6 0 -6 -2 -5 -2 -6 -1 -6 -1 -6 -1 -5 1 -6 2 -5 2 -6 2 -6 1 -6 1 -5 1 -6 1 -6 0 -6 -1 -6 -1 -5 -1 -5 -3 -6 -2 -5 -2 -6 -1 -6 -1 -5 1 -6 2 -5 3 -5 4 -4 4 -5 3 -6 2 -6 1 -5 0 -5 -3 -5 -3 -5 -4 -5 -3 -5 -2 -6 -1 -6 0 -6 1 -5 -1 -6 0 -7 -1","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str3","@d":"M-3997 3618l-4 4 -5 3 -5 2 -6 1 -6 0 -6 0 -5 0 -6 0 -6 0 -6 1 -6 1 -5 2 -4 4 -3 5 -2 6 -2 5 -2 6 -2 5 -4 5 -4 4 -4 4 -4 4 -4 5 -4 4 -4 4 -4 4 -4 5 -4 3 -5 4 -5 3 -5 4 -4 3 -5 3 -5 3 -5 4 -5 3 -4 4 -4 4 -3 5 -3 5 -1 6 -1 6 -3 4 -5 4 -5 3 -4 4 -3 5 -4 5 -4 4 -3 5 -2 5 -2 6 -1 6 0 6 0 5 -2 6 -2 6 -2 5 -2 5 -3 5 -4 5 -3 5 -4 4 -3 5 -4 5 -3 4 -4 5 -4 4 -4 4 -4 4 -5 4 -5 3 -4 4 -5 3 -5 4 -5 3 -5 3 -5 2 -5 1 -6 0 -6 0 -6 0 -6 0 -6 0 -6 1 -5 1 -6 2 -5 3 -5 3 -4 5 -3 4 -1 6 -2 6 -2 5 -2 6 -2 5 -3 5 -2 5 -3 6 -3 5 -3 5 -3 5 -3 6","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str3","@d":"M-3252 3502l-6 1 -5 1 -6 1 -11 2","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str3","@d":"M-3280 3507l-6 0 -6 1 -6 1 -5 1 -6 1 -6 0 -6 -1 -6 0 -5 -1 -6 0 -6 -1 -6 0 -6 -1 -5 -1 -6 0 -6 -2 -6 -1 -5 -1 -6 0 -6 2 -5 2 -6 1 -5 2 -6 2 -5 3 -5 2 -6 2 -6 -1 -5 -1 -6 -2 -6 -1 -6 -1 -5 -1 -6 -1 -6 0 -6 -1 -5 -2 -6 -2 -5 -1 -6 -2 -6 -2 -5 0 -6 -1 -6 0 -6 1 -7 0","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str3","@d":"M-2869 5541l6 -3 5 -2 5 -4 4 -4 4 -5","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str3","@d":"M1155 2704l-6 1 -6 1 -5 1 -6 1 -6 1 -6 1 -5 1 -6 1 -6 1 -6 0 -5 0 -6 -2 -6 -2 -5 -1 -6 -1 -6 -1 -6 -1 -6 0 -5 -1 -6 0 -6 0 -6 0 -6 0 -6 0 -5 1 -6 2 -5 3 -6 1 -5 -1 -5 -3 -5 -4 -4 -3 -5 -4 -5 -3 -5 -4 -4 -3 -5 -3 -6 -3 -5 -3 -4 -4 -3 -4 -3 -6 -1 -6 0 -5 2 -6 1 -6 2 -6 0 -5 0 -6 0 -6 0 -6 -1 -6 0 -5 -2 -6 -1 -6 -2 -5 -2 -6 -1 -6 -2 -5 -1 -6 -1 -6 -1 -6 0 -5 0 -6 1 -6 2 -5 2 -6 3 -5 4 -4 4 -4 5 -3 5 -3 6 -3 5 -2 6 -2 5 -2 6 -3 4 -3 3 -5 3 -5 2 -5 3 -6 2 -5 3 -6 2 -5 2 -6 1 -5 1 -6 1 -6 1 -6 0 -5 -1 -6 -1 -6 -2 -6 -3 -5 -4 -4 -5 -3 -4 -4 -5 -3 -4 -4 -5 -4 -4 -5 -2 -5 -2 -5 -1 -6 0 -6 -1 -6 -3 -5 -5 -3 -6 -3 -5 -2 -6 -1 -6 -1 -5 -1 -6 1 -6 2 -5 2 -6 1 -6 2 -5 2 -6 1 -6 1 -5 1 -6 0 -6 0 -6 0 -6 -1","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str3","@d":"M-3921 2460l-6 2 -5 2 -4 4 -5 4 -4 3 -6 2 -6 1 -5 -1 -6 -2 -5 -3 -6 -1 -5 1 -6 1 -6 -1 -6 -2 -5 -2 -3 -5 -3 -5 -5 -2 -6 -2 -6 -1 -5 -2 -5 -3 -5 -4 -3 -5 -3 -5 -3 -5 -4 -4 -3 -5 -4 -4 -5 -5 -4 -3 -5 -3 -5 -2 -6 -2 -6 -2 -5 -2 -6 -1 -5 -2 -6 -1 -11 -2","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str3","@d":"M847 2333l-6 -1 -7 -1 -4 -3 -3 -5 -2 -5 -1 -6 -1 -6 0 -6 2 -6 1 -5 1 -6 1 -6 1 -6 0 -6 -3 -4 -6 -4 -5 -2 -8 -3","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str3","@d":"M794 2248l4 0 9 4","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str3","@d":"M3001 367l0 6 0 6 0 6 0 5 1 6 0 6 1 6 2 5 2 6 2 5 3 5 2 6 2 5 3 5 2 6 2 5 3 5 2 6 3 5 3 5 2 5 3 6 3 5 3 5 2 5 3 5 3 5 3 5 3 5 3 5 3 5 3 5 4 5 3 4 4 5 3 4 4 5 4 4 4 5 4 4 4 4 4 5 4 4 4 4 4 5 3 6","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil7 str4","@d":"M1184 367l2 5 3 5 3 5 3 5 4 5 3 5 3 5 3 5 2 5 3 5 2 6 3 5 3 5 4 4 4 4 4 5 4 4 4 4 2 6 2 5 1 6 2 5 3 5 3 5 4 5 4 4 4 5 3 4 4 5 4 4 3 5 4 5 3 5 2 5 3 5 2 5 3 6 2 5 3 5 3 5 4 4 5 4 7 5","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str4","@d":"M-2665 3406l-5 -2 -6 -2 -10 -1","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str4","@d":"M-2686 3401l-6 2 -5 2 -10 4","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str4","@d":"M-2463 3452l-5 2 -6 2 -5 0 -6 -1 -6 -1 -5 -2 -6 -1 -7 -1","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str4","@d":"M-3569 4591l-6 1 -5 1 -6 1 -6 -1 -6 -1 -5 -1 -6 0 -6 0 -6 2 -4 3 -4 5 -3 5 -3 5 -4 4 -4 4 -4 5 -3 5 -3 5 -2 5 -1 6 -1 6 -1 6 0 5 0 6 0 6 1 6 1 6 1 6 2 5 1 6 0 6 -1 5 -3 5 -3 5 -3 5 -3 5 -4 5 -3 5 -1 6 -1 6 1 6 1 5 3 6 2 5 2 5 0 6 1 6 0 6 0 6 0 6 0 5 1 6 2 6 1 6 1 5 2 6 0 6 0 5 -1 6 -2 6 -1 5 -1 6 0 6 1 6 2 6 -1 5 -1 6 -3 5 -2 6 -2 5 -2 6 -2 5 -2 6 -1 5 -1 6 -1 6 0 6 0 6 1 5 2 6 2 6 3 5 3 5 4 4 5 3 5 3 4 4 5 4 4 4 4 4 4 4 5 4 4 4 5 3 5 1 6 1 6 2 8 6","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str4","@d":"M-3592 5050l3 5 4 4 4 5 4 4 4 5 3 5 2 5 2 5 1 6 1 6 0 5 0 6 0 6 0 6 1 6 0 6 0 6 1 6 0 6 1 5 0 6 1 6 0 6 1 6 0 5 1 6 0 6 0 6 1 6 0 5 1 6 0 6 0 6 1 6 0 6 1 5 0 7","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str4","@d":"M-2224 3903l-4 4 -5 4 -4 3 -5 3 -6 3 -5 2 -6 2 -5 2 -5 2 -6 3 -5 3 -4 3 -5 4 -4 4 -4 4 -4 4 -5 5 -4 4","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str4","@d":"M-2420 4022l-6 2 -6 1 -5 0 -6 -2 -6 -2 -5 -2 -5 -3 -5 -3 -5 -3 -5 -3 -6 -1 -6 -1 -5 1 -6 0 -6 0 -6 0 -6 0 -6 0 -6 0 -5 -1 -6 0 -6 -1 -6 0 -6 -1 -5 -1 -10 -2","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str4","@d":"M-2571 4000l-6 0 -6 -1 -6 -1 -6 0 -6 0 -5 2 -6 1 -5 2 -6 3 -5 2 -5 3 -6 2 -5 3 -4 3 -5 4 -5 4 -4 4 -4 4 -4 5 -4 4 -4 4 -4 4 -5 3 -6 1 -6 -1 -6 0 -6 0 -5 0 -6 -2 -5 -3 -5 -3 -5 -3 -6 -2 -5 -1 -6 1 -6 0 -6 2 -6 1 -5 2 -6 2 -4 3 -4 5 -3 5 -3 5 -2 5 -2 6 -1 6 -1 5 -1 6 -1 6 -2 6 -3 4 -5 4 -5 3 -5 3 -6 2 -5 2 -6 2 -6 0 -5 -1 -6 -1 -6 -3 -5 -3 -5 -3 -4 -4 -3 -5 -1 -6 -2 -6 0 -5 0 -6 0 -6 -2 -6 -3 -5 -4 -4 -5 -3 -5 -2 -6 -2 -6 -1 -6 0 -6 1 -5 1 -6 2 -5 3 -6 2 -4 4 -5 3 -4 4 -4 5 -4 4 -5 2 -6 2 -6 2 -6 1 -5 0 -6 0 -6 1 -6 0 -6 0 -6 0 -5 0 -6 0 -6 0 -6 0 -6 0 -6 -1 -5 0 -6 -1 -6 0 -6 -1 -5 -2 -6 -1 -6 -2 -5 -2 -5 -3 -5 -3 -4 -4 -5 -4 -5 -3 -5 -3 -5 -3 -5 -3 -5 -2 -6 -1 -6 -1 -6 0 -6 1 -5 1 -6 1 -6 1 -6 1 -5 2 -6 1 -6 2 -5 1 -6 2 -5 3 -5 2 -6 2 -5 2 -6 2 -5 3 -5 2 -6 3 -5 2 -10 5","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str4","@d":"M-3286 4091l-5 3 -4 4 -4 3 -5 4 -4 4 -4 4 -5 4 -4 4 -5 3 -4 4 -5 4 -5 3 -4 3 -5 4 -5 3 -5 3 -5 4 -4 3 -5 3 -5 3 -5 4 -4 4 -4 4 -5 4 -4 4 -4 4 -4 4 -4 4 -3 5 1 6 -1 6 0 6 0 6 0 6 0 6","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str4","@d":"M-2310 4959l5 -3 5 -3 5 -3 5 -1 6 -2 6 -1 6 -1 4 -3 4 -5 3 -5 3 -5 3 -5 4 -5 4 -3 6 -2 6 -1 5 -1 6 -1 6 -2 5 -3 5 -2 6 -2 5 -2 6 -1 6 -1 6 -1 5 0 6 0 6 1 6 1 5 1 6 0 6 -1 6 -1 6 -1 5 -1 6 -2 5 -1 6 -2 6 -2 5 -2 6 -2 5 -2 6 -1 5 -2 6 -2 5 -2 6 -2 5 -1 6 -2 5 -3 6 -2 5 -3 5 -3 5 -3 5 -3 5 -2 5 -2 6 -2 6 -2 5 -3 6 -2 5 -2 5 -3 5 -2 3 -5 3 -5 4 -5 4 -4 5 -3 5 -3 5 -4 5 -2 5 -1 6 1 6 1 6 1 6 1 5 -1 6 -1 6 -1 6 -1 5 -2 6 -1 6 -2 5 -2 6 -1 5 -3 5 -2 6 -3 5 -3 4 -3 5 -4 3 -5 3 -5 3 -5 2 -6 2 -5 3 -5 5 -3 5 -3 6 -2 6 -1 5 -1 6 0 6 1 6 1 5 1 6 2 6 1 5 2 6 2 4 4 6 1 6 0 8 0","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str4","@d":"M-2481 5030l5 0 6 -1 6 -1 5 -2 5 -3 6 -3 5 -3 5 -3 5 -3 4 -3 5 -3 6 -3 5 -1 6 -1 6 -2 5 -1 6 -2 5 -3 5 -2 10 -6","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str4","@d":"M-2845 5523l2 -6 3 -5 2 -5 2 -5 2 -6 2 -6 1 -5 2 -6 2 -5 3 -6 2 -5 3 -5 3 -5 3 -5 4 -4 6 -2 6 -2 5 -3 4 -3 5 -4 4 -4 3 -5 3 -5 1 -6 1 -6 0 -6 -1 -6 0 -5 -2 -6 -1 -6 -1 -6 -2 -5 -1 -6 -1 -6 -1 -5 0 -6 1 -6 2 -6 1 -5 3 -5 3 -5 3 -5 3 -5 3 -6 2 -5 1 -6 1 -6 1 -5 2 -6 3 -5 2 -5 3 -5 3 -5 3 -5 4 -5 4 -4 4 -5 3 -4 3 -5 2 -6 1 -6 1 -5 1 -6 1 -6 1 -6 2 -5 1 -6 1 -6 1 -6 0 -5 -1 -6 -1 -6 -2 -6 -1 -5 0 -6 1 -6 1 -6 2 -5 2 -6 3 -5 4 -4 4 -4 5 -4 5 -3 5 -2 6 -2 5 -2 5 -3 5 -4 4 -3 5 -4 4 -4 4 -4 5 -4 4 -4 4 -4 5 -3 5 -2 6 -2 6 -2 5 -2 6 -1 5 -3 5 -2 6 -3 5 -2 6 -1 6 -1 5 0 6 0 6 0 6 1 5 2 6 3 5 2 6 2 5 0 6 0 6 -1 6 0 6 -1 5 0 7 -1","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str4","@d":"M-2845 5523l5 0 6 1 6 1 6 2 5 2 5 3 4 5 3 5 4 3 6 -1 4 -5 1 -6 2 -5 2 -5 4 -5 4 -4 5 -4 4 -3 5 -4 5 -3 4 -4 5 -3 5 -3 5 -3 5 -4 4 -3 5 -3 5 -4 5 -2 5 -3 6 -3 5 -2 6 -1 6 -1 6 0 5 3 5 3 5 -1 5 -4 5 -3 4 -4 4 -5 3 -5 2 -6 2 -5 0 -6 0 -6 0 -6 0 -6 2 -5 3 -5 3 -5 2 -6 0 -5 0 -6 0 -6 -1 -6 -2 -6 -2 -5 -3 -5 -4 -5 -4 -4 -5 -2 -5 -3 -6 -2 -5 -2 -6 -2 -5 -2 -5 -3 -5 -4 -5 -3 -3 -4 -3 -6 -2 -5 -2 -6 -1 -6 -1 -5 1 -6 0 -6 2 -6 1 -5 1 -6 1 -6 2 -6 1 -5 2 -6 3 -5 3 -5 3 -4 5 -4 5 -3 5 -3 5 -2 3 -5 2 -6 2 -5 2 -6 2 -5 2 -6 1 -6 1 -5 2 -6 1 -6 1 -6 0 -5 -1 -6 0 -6 0 -6 0 -6 1 -5 2 -6 3 -5 3 -5 3 -5 3 -5 4 -4 5 -4 5 -3 5 -3 5 -3 5 -3 5 -3 5 -2 6 -2 5 -2 6 -2 5 -2 6 -1 6 -1 6 0 6 0 5 0 6 0 6 0 6 1 6 0 5 -1 6 -2 5 -2 6 -3 5 -2 5 -3 7 -9","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str4","@d":"M-2370 4984l5 -2 6 -1 5 -2 6 -2 5 -3 5 -2 5 -3 6 -2 5 -3 5 -2 7 -3","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str4","@d":"M-141 1874l-3 -5 -4 -5 -5 -3 -4 -3 -5 -3 -5 -4 -5 -3 -4 -4 -5 -4 -4 -4 -4 -4 -5 -3 -5 -4 -5 -2 -5 -3 -5 -3 -5 -3 -4 -5 -2 -5 0 -6 1 -6 -1 -5 -4 -3 -6 -2 -6 -3 -4 -3 -4 -5 -3 -5 -2 -6 1 -5 2 -6 1 -6 -1 -6 -1 -5 -3 -6 -3 -5 -4 -4 -4 -4 -5 -4 -5 -3 -5 -3 -4 -4 -5 -3 -6 -2 -5 -3 -9 -5","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str4","@d":"M572 2328l-5 -3 -5 -2 -5 -3 -6 -3 -5 -2 -5 -2 -6 -2 -6 -1 -6 -1 -5 0 -6 0 -6 0 -5 2 -6 3 -5 2 -6 2 -5 1 -6 1 -6 1 -6 1 -6 1 -6 1 -6 1 -5 0 -5 -4 -3 -5 1 -4 5 -4 6 -4 3 -4 4 -5 2 -6 1 -5 -3 -6 -5 -2 -6 0 -5 3 -5 4 -5 3 -5 0 -5 -3 -6 -2 -6 -2 -5 -3 -3 -4 -3 -5 -2 -6 -2 -6 -4 -5 -3 -4 -3 -5 -4 -5 -4 -4 -4 -4 -4 -5 -4 -4 -4 -4 -4 -4 -3 -5 -4 -5 -3 -4 -3 -5 -3 -5 -3 -6 -2 -5 -1 -6 -3 -6 -3 -4 -4 -3 -6 -1 -7 -1 -5 0 -6 0 -6 1 -6 -1 -6 -1 -5 -2 -5 -2 -5 -3 -6 -3 -5 -3 -5 -3 -5 -3 -5 -3 -4 -3 -5 -3 -5 -4 -5 -3 -5 -3 -5 -3 -5 -3 -5 -3 -5 -3 -5 -3 -5 -3 -5 -3 -5 -3 -5 -3 -5 -3 -5 -3 -5 -3 -5 -3 -5 -3 -5 -3 -5 -3 -5 -2 -5 -3 -5 -3 -5 -3 -5 -3 -5 -3 -5 -4 -5 -3 -5 -3 -5 -3 -5 -4 -4 -3 -5 -3 -5 -4 -5 -3 -5 -2 -5 -3 -6 -2 -5 -2 -6 -3 -5 -2 -4 -4 -5 -3 -5 -3 -5 -4 -4 -3 -5 -4 -4 -4 -5 -3 -5 -4 -4 -3 -5 -4 -4 -4 -5 -3 -5 -4 -4 -3 -5 -3 -5 -3 -5 -3 -5 -3 -5 -4 -4 -4 -4 -4 -4 -4 -4 -5 -4 -4 -4 -5 -4 -4 -4 -4 -4 -4 -5 -3 -5 -3 -5 -3 -5 -4 -4 -4 -4 -3 -6 -6","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str4","@d":"M-473 1564l-5 -1 -6 0 -6 0 -6 0 -6 0 -6 1 -5 -2 -4 -4 -4 -5 -3 -5 -4 -4 -3 -5 -3 -5 -5 -3 -5 -1 -6 -2 -6 0 -6 1 -6 0 -5 -1 -6 -1 -5 -3 -5 -3 -5 -3 -6 -3 -5 -2 -5 -3 -5 -2 -6 -2 -5 -3 -6 -2 -5 -1 -6 -1 -6 -1 -5 -1 -6 0 -6 -1 -6 -1 -5 -2 -6 -1 -6 -1 -5 -2 -6 -1 -6 -2 -5 -1 -6 -1 -6 -2 -5 -1 -6 -3","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str4","@d":"M-3298 2439l-6 1 -5 1 -6 0 -6 -1 -6 -1 -5 -2 -6 -1 -6 -1 -5 -1 -6 -1 -6 -1 -6 0 -6 -1 -5 -1 -6 -2 -5 -2 -5 -4 -4 -4 -5 -4 -4 -4 -4 -4 -3 -5 -3 -5 -4 -4 -5 -4 -4 -4 -5 -3 -5 -2 -6 -1 -6 0 -6 1 -6 1 -6 1 -5 2 -6 2 -5 2 -5 2 -6 3 -5 3 -5 3 -5 3 -5 2 -6 2 -5 1 -6 0 -6 0 -6 -1 -6 0 -5 -1 -6 1 -6 1 -6 2 -5 2 -6 1 -5 3 -5 4 -5 0 -5 -2 -6 -4 -5 -2 -6 -2 -5 -1 -6 -1 -6 -1 -6 0 -6 0 -5 -1 -6 0 -6 0 -6 0 -6 0 -6 1 -5 1 -6 2 -5 2 -6 2 -5 3 -5 2 -5 3 -5 3 -5 3 -5 4 -4 4 -5 2 -6 3 -5 1 -6 2 -6 1 -6 1 -5 1 -6 0 -6 0 -6 0 -6 0 -5 0 -6 0 -6 0 -6 1 -6 1 -5 1 -6 1 -6 -1 -6 -1 -5 0 -6 0 -6 1 -6 1 -6 1 -5 2 -6 1 -6 1 -5 2 -6 2 -6 2","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str4","@d":"M-3146 2517l-6 -1 -6 -2 -5 0 -6 1 -5 2 -6 2 -6 2 -5 2 -6 2 -5 1 -6 -1 -6 -2 -5 -3 -4 -4 -4 -4 -4 -4 -3 -6 -3 -4 -6 -3 -4 -3 -5 -4 -5 -4 -4 -4 -2 -4 1 -6 2 -5 2 -6 0 -7 0 -6 -4 -3 -5 -3 -6 -1 -6 -1 -6 -1 -6 1 -7 1","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str4","@d":"M-2917 2335l-4 5 -4 4 -6 2 -6 0 -5 2 -4 4 -4 5 -4 4 -5 3 -5 2 -6 1 -6 0 -6 0 -6 1 -6 1 -5 1 -6 1 -5 2 -5 4 -4 4 -4 4 -5 4 -4 4 -4 4 -4 5 -4 4 -4 4 -3 5 -3 5 -3 5 -3 5 -3 5 -3 5 -3 5 -3 5 -2 5 -3 6 -2 5 -2 6 -2 5 -2 5 -2 6 -3 5 -2 5 -4 5 -4 4 -5 3 -4 4 -6 2 -6 1 -5 2 -6 0 -6 -1 -8 -1","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str4","@d":"M-310 1686l-5 -3 -5 -3 -5 -4 -5 -2 -5 -3 -5 -3 -6 -2 -5 -3 -5 -2 -5 -3 -5 -3 -6 -2 -5 -2 -6 -2 -6 -1 -6 -2 -4 -3 -3 -5 -1 -6 0 -6 -3 -6 -7 -8 -4 -4 -4 -4 -4 -5 -4 -4 -5 -4 -4 -4 -4 -3 -5 -4 -4 -4 -5 -4 -5 -2 -10 -5","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil7 str5","@d":"M2998 367l0 6 -3 5 -5 2 -6 -1 -6 -1 -6 -1 -5 -1 -6 0 -6 1 -6 2 -5 2 -6 2 -4 3 -5 4 -4 4 -4 5 -2 5 -2 5 -2 6 -1 6 -1 5 -1 6 0 6 0 7 2 5 6 1 6 0 2 6 -2 5 -4 4 -5 4 -5 4 -4 3 -4 5 -4 4 -5 3 -4 4 -5 4 -4 4 -2 6 -1 5 1 6 1 6 1 6 1 5 2 6 2 5 3 6 2 5 4 9","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M1321 577l6 1 4 4 5 3 3 5 3 5 3 5 3 5 2 6 3 5 3 5 3 5 3 5 2 5 3 6 3 5 4 4 3 5 4 4 4 4 5 4 4 3 5 4 5 3 5 3 5 3 5 4 5 3 4 3 5 3 5 3 5 4 5 3 4 4 5 4 4 3 5 3 5 3 5 3 5 3 5 3 6 3 5 2 5 3 6 2 5 2 5 2 6 2 5 2 6 2 5 2 6 1 6 2 5 2 6 2 5 2 6 1 5 2 6 3 5 2 6 1 5 2 6 0 6 0 6 1 5 2 6 2 5 3 5 2 6 2 5 3 5 2 6 2 5 2 6 3 5 2 6 1 5 2 6 2 5 1 6 2 5 2 6 2 6 2 5 1 6 2 5 1 6 1 6 0 6 1 6 0 5 0 6 0 6 0 6 0 6 2 5 2 6 3 5 2 5 2 6 0 5 -2 5 -3 6 -2 6 -2 5 -1 6 1 6 1 6 1 5 1 6 -1 6 -1 6 0 5 1 6 3 5 2 6 2 5 1 6 0 6 -2 5 -2 5 -4 4 -4 4 -4 4 -4 4 -5 3 -5 4 -4 4 -4 5 -4 5 -3 5 -3 5 -3 5 -3 5 -2 5 -3 6 -2 5 -2 6 -2 6 -1 6 0 5 2 5 3 5 4 5 3 5 3 5 2 6 1 6 0 5 0 6 -1 6 -1 6 -1 6 -1 5 -1 5 -3 4 -4 4 -5 3 -5 3 -5 3 -5 3 -5 3 -5 4 -4 4 -5 5 -3 5 -3 5 -2 6 -2 6 -2 5 -1 6 -2 6 -1 5 -1 6 -1 6 0 6 1 5 2 6 2 5 2 6 -2 5 -2 6 -2 5 -1 6 -1 6 0 6 -1 6 -1 5 -1 6 -1 6 -1 6 1 5 2 6 1 5 2 6 2 6 1 5 0 6 0 6 0 6 1 5 2 6 2 6 1 6 1 6 1 5 1 6 0 6 0 5 0 5 -4 4 -4 3 -5 2 -6 2 -6 3 -5 4 -4 6 -1 5 0 6 1 6 0 6 -2 4 -3 5 -5 3 -4 3 -5 2 -6 2 -6 1 -5 3 -5 3 -6 3 -4 3 -5 4 -5 4 -4 4 -4 4 -4 4 -4 4 -5 5 -4 5 -3 5 2 5 3 6 1 6 0 6 -1 5 -1 6 -2 6 -1 5 -2 6 -2 5 -3 4 -3 5 -4 4 -4 5 -4 4 -4 4 -4 4 -4 4 -5 4 -4 4 -4 4 -4 4 -5 4 -4 4 -4 4 -4 5 -4 4 -4 5 -4 4 -3 5 -3 5 -3 6 -2 5 -3 5 -2 6 -1 6 -2 5 -2 6 -1 5 -2 6 -2 6 -1 5 -2 6 -2 5 -4 4 -4 5 -3 5 -1 6 1 6 2 5 2 6 2 6 1 5 -1 6 -3 4 -3 4 -5 4 -4 3 -5 4 -4 4 -5 4 -4 4 -4 4 -5 4 -4 5 -3 4 -4 5 -4 5 -3 5 -2 5 -2 6 1 6 0 6 1 6 1 6 1 6 -1 6 -1 5 -3 2 -4 2 -6 1 -6 1 -6 1 -6 2 -5 4 -5 3 -4 3 -5 3 -11","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M1321 367l3 5 3 5 2 5 3 5 4 5 3 5 4 4 4 4 5 4 4 4 5 3 5 4 5 3 5 3 5 3 5 2 5 2 6 2 6 1 6 1 5 1 6 0 6 0 6 -1 6 -1 5 -1 6 -3 5 -2 5 -3 4 -4 5 -3 5 -4 5 -3 5 -3 5 -2 6 -2 5 -2 5 -3 5 -4 3 -4 4 -5 3 -5 4 -5 4 -4 4 -3 6 -2 10 -2","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M770 1225l-1 -5 -1 -6 -1 -6 0 -6 -1 -6 -1 -5 0 -6 -1 -6 -1 -6 0 -6 1 -5 2 -6 1 -6 2 -5 1 -6 0 -6 1 -6 1 -5 1 -6 0 -6 1 -6 0 -6 1 -5 0 -6 0 -6 -1 -6 0 -6 -1 -6 0 -5 -1 -6 0 -6 0 -6 0 -6 0 -6 1 -6 1 -5 2 -6 4 -4 4 -5 5 -3 5 -1 6 0 6 1 6 1 6 0 6 -1 6 0 6 -1 5 0 6 -1 6 -1 6 -1 5 -1 6 -1 6 -2 5 -1 6 -2 6 -1 5 -2 5 -2 6 -3 5 -3 5 -2 6 -2 5 -1 6 0 6 0 6 0 6 0 6 0 5 1 6 0 6 0 6 -1 6 0 6 0 5 -1 6 -1 6 0 6 -1 5 -1 6 -2 6 -1 5 -2 6 -2 5 -3 5 -3 4 -4 5 -4 4 -4 4 -4 3 -5 2 -6 3 -5 3 -5 4 -4 4 -4 4 -5 4 -3 5 -4 4 -4 5 -3 5 -3 5 -3 5 -3 6 -2 5 -2 6 -2 5 -1 6 -2 6 -2 4 -3 5 -3 4 -4 4 -5 4 -4 4 -4 4 -5 4 -4 3 -5 4 -4 5 -4 4 -4 4 -4 4 -4 4 -4 4 -5 3 -5 4 -4 3 -5 3 -5 3 -5 3 -5 3 -5 1 -6 2 -5 0 -6 1 -6 1 -6 1 -6 2 -5 1 -6 2 -6 1 -5 2 -6 1 -6 2 -5 2 -5 3 -6 2 -5 3 -5 3 -5 3 -5 4 -4 4 -5 4 -4 5 -4 4 -4 4 -4 5 -4 2 -5 3 -5 2 -5 1 -6 2 -6 0 -6 1 -6 -1 -5 -1 -6 -1 -10","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M706 1099l1 -5 1 -6 -2 -6 -3 -5 -4 -4 -5 -4 -4 -3 -5 -3 -5 -4 -5 -3 -3 -5 -4 -5 -3 -5 -2 -5 -2 -5 0 -6 0 -6 -1 -6 -2 -5 -2 -6 -2 -5 -3 -5 -3 -6 -2 -5 -3 -5 -2 -5 -3 -6 -3 -5 -3 -5 -2 -5 -2 -6 -2 -5 -1 -6 -2 -6 -1 -5 -1 -6 -2 -6 -1 -5 -1 -6 -1 -6 -1 -6 -1 -5 0 -6 -1 -6 0 -6 0 -6 1 -5 0 -6 0 -6 1 -6 0 -6 1 -6 0 -5 0 -6 1 -6 0 -6 0 -6 0 -6 0 -5 0 -6 -1 -6 0 -6 -1 -6 -1 -5 -2 -6 -2 -5 -3 -5 -3 -5 -3 -5 -4 -5 -3 -5 -2 -5 -1 -6 -1 -6 -1 -6 0 -5 0 -6 -1 -6 -1 -6 -1 -6 -1 -5 -2 -6 -2 -5 -2 -6 -3 -5 -2 -5 -3 -6 -2 -5 -3 -5 -2 -5 -3 -6 -3 -5 -2 -5 -3 -5 -4 -5 -4 -4 -5 -2 -6 -2 -6 0 -6 -1 -6 1 -5 0 -6 1 -6 1 -6 1 -6 0 -5 0 -6 -1 -6 -2 -5 -2 -5 -3 -5 -3 -5 -3 -5 -3 -5 -4 -4 -3 -5 -4 -4 -4 -4 -5 -4 -4 -3 -5 -4 -4 -4 -4 -4 -5 -4 -4 -4 -4 -5 -4 -5 -2 -5 -2 -6 -2 -6 -1 -6 0 -6 -1 -5 1 -6 0 -6 1 -6 0 -6 -1 -5 0 -6 0 -6 0 -6 0 -6 -1 -6 0 -5 -1 -6 0 -6 -1 -6 0 -6 0 -5 1 -6 1 -6 2 -5 2 -6 1 -5 3 -5 3 -5 3 -6 2 -5 1 -6 0 -6 0 -6 0 -6 0 -6 1 -6 0 -5 -1 -6 0 -6 -2 -5 -1 -6 -2 -5 -2 -6 -2 -5 -3 -5 -3 -5 -4 -5 -3 -5 -2 -6 -2 -5 -2 -6 0 -6 2 -4 3 -4 5 -4 4 -5 3 -5 4 -3 5 -2 6 -2 5 -3 5 -4 3 -6 3 -5 2 -5 2 -6 3 -5 2 -5 3 -5 3 -5 2 -6 2 -6 2 -5 2 -5 2 -5 4 -3 5 -4 4 -4 5 -3 5 -3 5 -4 4 -4 4 -5 3 -6 2 -5 2 -6 1 -5 2 -5 4 -3 5 -4 4 -3 6 -2 5 -1 6 2 5 2 6 3 5 2 5 1 6 1 6 0 6 -1 5 -1 6 -2 6 -3 5 -4 4 -5 3 -5 3 -5 3 -5 3 -5 3 -5 3 -5 3 -6 1 -6 0 -6 -1 -6 0 -5 0 -6 0 -6 0 -6 1 -6 0 -5 1 -6 0 -6 2 -5 3 -6 1 -5 -2 -6 -2 -4 -4 -3 -5 -4 -5 -4 -4 -4 -5 -4 -5","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M3405 5687l-5 2 -6 3 -5 2 -5 3 -4 5 -3 5 -3 5 -3 4 -4 6 -3 4 -4 4 -5 3 -6 2 -6 2 -5 1 -6 0 -6 1 -6 0 -6 -1 -5 0 -6 0 -6 0 -6 0 -6 -1 -6 1 -5 1 -6 2 -5 2 -6 2 -6 1 -5 0 -6 0 -6 -1 -6 -1 -6 -1 -5 -1 -6 -1 -6 0 -6 -1 -5 0 -6 1 -6 1 -6 1 -6 1 -5 0 -6 0 -6 1 -6 0 -6 -1 -5 0 -6 0 -6 0 -6 -1 -6 0 -6 -1 -5 0 -6 -1 -7 -1 -6 -1 -5 0 -6 1 -4 2 -4 5 -3 6 -2 5 0 6 0 6 0 6","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M2442 6139l2 -6 2 -6 1 -5 1 -6 2 -6 2 -6 1 -6 1 -5 -1 -6 -2 -4 -5 -4 -5 -4 -5 -3 -6 -1 -6 -2 -5 -1 -6 -1 -6 -2 -5 -2 -6 -2 -6 -2 -6 -2 -5 -3 -4 -3 -2 -5 0 -6 0 -6 1 -6 -1 -6 -1 -6 -2 -6 -2 -5 -2 -6 -2 -5 -2 -6 -2 -5 -2 -6 -3 -4 -4 -5 -3 -4 -4 -5 -4 -4 -4 -4 -5 -4 -4 -4 -4 -4 -4 -5 -4 -4 -4 -4 -5 -4 -4 -4 -4 -4 -5 -4 -4 -3 -5 -3 -6 -3 -5 -1 -6 -1 -6 0 -6 0 -6 2 -5 2 -5 3 -5 3 -5 3 -5 2 -6 2 -6 1 -6 0 -5 0 -6 0 -6 -1 -6 0 -6 -1 -6 0 -5 -1 -6 -1 -6 -1 -6 -1 -5 -1 -6 -2 -6 -1 -5 -1 -6 -2 -6 -2 -5 -1 -6 -2 -5 -1 -6 -2 -6 -1 -5 -2 -6 -1 -6 -2 -5 -1 -6 -2 -6 -1 -5 -1 -6 -1 -6 -1 -6 0 -5 0 -6 -1 -6 0 -6 0 -6 -1 -6 0 -5 -1 -6 -1 -6 0 -6 -1 -6 0 -5 0 -6 0 -6 1 -6 1 -5 1 -6 2 -6 1 -5 2 -6 2 -5 2 -6 2 -5 2 -6 2 -5 3 -5 3 -5 2 -6 2 -5 1 -6 1 -6 1 -6 1 -5 1 -6 2 -6 1 -5 2 -6 1 -6 2 -5 0 -6 1 -6 0 -6 0 -6 1 -5 0 -6 1 -6 1 -6 1 -5 1 -6 1 -6 1 -6 1 -5 1 -6 1 -6 1 -6 1 -6 1 -5 1 -6 1 -5 2 -6 2 -5 3 -5 2 -6 2 -5 2 -6 2 -5 2 -6 2 -5 2 -6 2 -5 2 -6 2 -5 3 -5 3 -5 3 -4 4 -5 3 -5 3 -5 3 -5 3 -6 2 -5 2 -5 3 -6 2 -5 3 -5 2 -5 4 -5 3 -5 2 -6 2 -6 0 -6 -1 -5 0 -6 1 -6 2 -5 2 -6 3 -5 2 -5 3 -5 3 -2 5 -1 6 -2 6 -3 5 -5 3 -5 2 -6 2 -6 1 -5 1 -6 1 -6 1 -6 1 -5 2 -6 2 -5 3 -4 3 -4 5 -4 4 -3 5 -4 5 -4 4 -4 4 -4 4 -4 4 -5 4 -4 4 -4 4 -5 4 -5 2 -6 2 -5 1 -6 2 -6 1 -5 2 -4 4 -4 5 -5 4 -5 2 -5 1 -6 2 -6 1 -6 1 -6 1 -5 1 -6 0 -6 0 -6 0 -5 -1 -6 -1 -6 -1 -6 -1 -5 -2 -6 -1 -6 -1 -6 0 -5 1 -6 1 -6 0 -6 1 -6 0 -5 0 -6 0 -6 1 -6 1 -6 1 -5 1 -6 1 -6 0 -6 0 -6 -2 -4 -4 -3 -5 -2 -6 -4 -4 -5 -3 -5 -3 -5 -2 -6 -2 -5 -2 -6 -1 -6 -2 -6 -1 -5 0 -6 1 -6 1 -6 1 -6 2 -5 1 -6 2 -5 1 -6 2 -6 0 -6 1 -5 0 -6 0 -6 0 -6 0 -6 1 -6 0 -6 0 -5 0 -6 0 -6 0 -6 0 -6 0 -5 -1 -6 -1 -6 -1 -6 -1 -5 0 -6 -1 -6 0 -6 1","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M-556 6840l-5 2 -5 3 -6 3 -5 2 -5 3 -5 4 -4 3 -4 5 -4 5 -2 5 -2 5 -1 6 0 6 -1 6 0 6 -1 5 -2 6 -2 5 -2 6 -2 5 -3 6 -3 5 -3 4 -4 5 -4 4 -5 3 -5 3 -6 2 -5 2 -6 1 -6 1 -5 1 -6 1 -6 1 -6 2 -5 1 -6 3 -5 2 -5 3 -5 3 -5 2 -5 3 -6 3 -5 3 -5 3 -5 3 -4 4 -3 5 -4 4 -4 5 -4 4 -4 4 -4 4 -5 4 -4 4 -4 4 -4 4 -4 4 -4 5 -4 4 -4 4 -4 5 -4 4 -3 5 -3 5 -2 5 -2 6 -2 5 -2 6 -2 5 -3 6 -3 5 -3 5 -3 4 -4 5 -4 4 -4 4 -5 4 -5 3 -5 3 -5 2 -6 2 -5 0 -6 1 -6 2 -6 2 -5 2 -5 3 -4 4 -3 5 -2 6 -1 5 2 6 2 6 0 5 0 6 -2 6 -2 5 -2 6 -3 5 -4 5 -4 4 -4 3 -6 3 -5 2 -6 2 -5 3 -5 3 -4 4 -4 4 -3 5 -4 4 -4 5 -5 8","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M648 6287l0 6 0 6 0 6 1 6 2 5 1 6 2 6 2 5 3 5 1 6 0 5 -2 6 -3 5 -2 6 -4 5 -3 4 -4 5 -4 4 -3 5 -4 4 -4 5 -4 4 -5 3 -4 4 -5 3 -5 4 -4 4 -3 5 -2 5 -1 6 -4 5 -4 4 -4 4 -4 4 -5 4 -4 4 -3 4 -2 6 0 6 2 5 2 6 3 5 4 4 4 5 3 5 2 5 3 5 2 6 2 5 3 6 2 5 1 6 -1 5 -1 6 -1 6 -1 6 -1 5 -1 6 0 6 -1 6 -1 6 -1 5 -2 6 -1 6 -2 5 -2 6 -2 5 -2 6 -3 5 -3 5 -3 4 -4 5 -4 4 -5 4 -4 4 -5 3 -4 4 -5 4 -5 3 -5 3 -5 3 -4 3 -5 4 -4 4 -3 5 -4 4 -4 5 -3 5 -4 4 -3 5 -4 4 -3 5 -4 5 -3 5 -3 5 -3 5 -3 5 -3 5 -3 5 -3 4 -4 5 -4 4 -4 5 -3 4 -4 5 -3 5 -4 4 -4 5 -4 5 -3 4 -3 5 -3 5 -2 5 -2 6 -1 6 0 6 0 6 -1 5 0 6 0 6 0 6 1 6 0 6 0 5 1 6 0 6 1 6 0 6 1 5 0 6 1 6 0 6 1 6 0 6 1 5 0 6 -1 6 -1 6 -1 5 -1 6 -1 6 0 6 -1 5 0 6 -1 6 -1 6 -2 5 -1 6 -1 6 -1 5 -2 6 -1 6 -1 6 0 5 0 6 0 6 1 6 1 6 2 5 0 6 1 6 0 6 -1 6 0 6 -1 5 -2 6 -2 5 -3 5 -3 5 -4 5 -4 4 -4 5 -3 5 -2 5 -2 5 -2 6 -2 5 -2 6 -1 6 -2 5 -2 5 -3 6 -2 5 -4 5 -3 5 -3 4 -4 5 -4 4 -4 5 -3 4 -4 5 -3 5 -2 5 -5 10","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M-2705 7287l-4 -5 -3 -5 -3 -5 0 -6 -1 -6 0 -6 1 -6 0 -5 -2 -6 -3 -5 -5 -2 -6 -1 -6 -1 -6 -1 -6 0 -5 -1 -6 0 -6 -1 -6 -1 -5 -2 -6 -2 -5 -2 -6 -2 -5 -2 -6 -1 -5 -2 -6 -1 -6 -1 -6 -1 -6 -1 -5 -1 -6 0 -6 2 -5 2 -5 2 -5 3 -5 4 -4 4 -4 4 -4 5 -4 4 -5 4 -4 4 -4 4 -5 3 -4 4 -5 3 -5 2 -6 3 -5 3 -4 4 -5 3 -6 1 -6 0 -6 -1 -4 -4 -2 -6 -5 -2 -6 0 -6 1 -5 3 -3 5 -2 6 -1 11","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M-3947 3399l-5 -4 -4 -3 -2 -6 0 -6 0 -6 1 -5 2 -6 2 -6 3 -5 4 -3 6 -2 5 -1 6 -1 6 -1 5 -2 5 -3 5 -3 5 -4 5 -3 4 -3 5 -4 4 -4 4 -5 4 -4 3 -5 3 -5 3 -5 3 -5 3 -5 4 -4 4 -4 5 -4 5 -3 5 -3 5 -2 5 -3 5 -3 6 -3 5 -2 6 -1 5 -1 6 -1 6 0 6 0 6 -1 6 -1 5 -1 6 -1 6 -2 5 -1 6 -2 4 -4 5 -4 5 -2 6 0 6 1 6 0 6 1 5 -1 4 -3 4 -6 3 -4 3 -5 3 -6 1 -5 1 -6 3 -5 3 -5 5 -4 5 -3 5 -3 4 -3 5 -4 5 -4 4 -3 5 -4 5 -3 5 -3 5 -3 5 -3 5 -3 5 -3 4 -3 5 -4 5 -3 5 -2 6 -2 6 -1 5 0 6 -2 6 -1 6 -1 5 -2 6 -1 5 -2 6 -3 5 -3 4 -3 5 -4 4 -4 4 -5 3 -4 3 -5 4 -5 3 -4 4 -5 4 -4 5 -4 4 -4 5 -3 5 -4 4 -3 4 -4 4 -5 2 -5 2 -6 3 -5 3 -5 3 -5 4 -4","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M-4270 3123l5 2 6 2 5 1 6 2 6 2 5 0 6 -1 6 -2 5 -2 6 -2 5 -2 5 -3 4 -4 5 -4 5 -2 6 -2 5 -2 6 -1 6 -2 5 -1 6 -2 5 -2 6 -1 6 -2 5 -2 6 -2 5 -1 6 -2 5 -2 6 -2 5 -2 6 -2 5 -1 6 -2 6 -1 6 -1 5 -1 6 0 6 -1 6 1 6 1 5 2 5 4 3 5 3 5 4 4 5 4 5 3 5 2 5 -2 5 -4 5 -4 4 -4 5 -3 4 -4 5 -4 4 -4 5 -3 4 -4 4 -4 5 -4 4 -4 4 -5 3 -4 3 -5 3 -6 2 -5 2 -6 3 -5 3 -5 3 -4 5 -4 4 -4 5 -3 6 -3 5 -3 5 -2 6 -1 6 -1 5 0 6 0 6 0 6 1 6 0 6 0 6 -1 5 -1 5 -3 4 -4 5 -4 4 -4 5 -3 5 -3 6 -3 5 -2 5 -2 5 -3 6 -2 5 -2 6 -2 5 -3 6 -2 5 -2 5 -4 4 -3 4 -5 3 -4 4 -5 4 -4 4 -4 5 -4 4 -4 4 -4 5 -4 5 -3 4 -4 5 -2 6 -3 5 -1 6 -2 6 0 6 -1 6 -1 5 -2 5 -3 5 -3 5 -3 5 -2 6 -3 5 -2 5 -3 5 -2 6 -2 5 -2 6 -2 5 -1 6 -1 6 -1 6 -1 5 -2 6 -2 5 -2 5 -3 6 -3 5 -2 5 -3 5 -3 5 -3 5 -3 5 -3 5 -3 5 -3 5 -3 5 -4 4 -3 5 -3 5 -4 4 -3 5 -3 5 -3 6 -3 5 -3 5 -2 6 -1 6 0 6 0 6 0 6 1 6 1 5 1 5 3 4 4 3 5","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M-3997 3618l-1 -6 0 -6 -1 -6 -1 -5 -2 -6 -1 -5 1 -6 4 -5 4 -4 5 -4","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M-2994 3305l6 -3 4 -3 5 -5 5 -2 6 -1 5 0 6 -1 6 0 6 2 4 3 5 4 5 4 5 3 5 1 6 1 6 1 6 1 5 2 6 1 5 3 6 2 5 1 6 -1 5 -3 6 -1 6 0 6 0 5 -1 5 -4 1 -5 -3 -6 -3 -5 -3 -5 -4 -4 -2 -6 -1 -5 -1 -6 0 -6 0 -6 -1 -6 1 -6 3 -4 5 -4 4 -4 4 -4 5 -4 4 -4 4 -5 4 -4 3 -4 4 -5 4 -4 4 -5 3 -5 3 -5 3 -5 4 -4 4 -3 5 -4 5 -3 5 -3 5 -3 5 -4 4 -4 4 -4 3 -5 2 -6 2 -9","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M-3280 3507l4 3 4 4 4 5 3 5 3 5 3 5 2 5 2 6 1 5 2 6 2 6 2 5 2 6 2 5 2 5 3 6 2 5 3 5 4 5 3 4 4 5 4 4 4 4 4 4 5 4 4 4 4 4 5 4 5 3 4 4 5 3 5 3 5 3 5 3 5 3 5 3 6 2 5 3 5 2 6 2 6 1 5 0 6 -1 5 -3 6 -2 5 -2 6 -2 6 -2 5 0 6 1 6 2 4 4 4 4 4 4 4 5 4 4 2 6 4 5 4 3 5 3 5 2 6 2 6 1 5 2 6 1 6 0 6 1 5 1 6 0 6 1 6 0 6 0 6 1 5 0 6 0 6 1 6 1 5 2 6 1 6 2 5 1 6 2 6 1 5 2 6 1 5 2 6 2 5 2 6 1 6 2 5 2 6 1 5 2 6 2 6 1 5 2","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M-2668 3397l-6 0 -6 1 -6 3","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M-1483 3350l-4 4 -6 3 -5 2 -5 3 -5 4 -4 3 -5 3 -5 4 -5 3 -4 4 -5 3 -5 2 -6 1 -6 -1 -6 0 -6 0 -6 0 -5 0 -6 0 -6 0 -6 0 -6 0 -6 0 -5 -1 -6 -2 -5 -2 -6 -2 -5 -2 -6 -1 -6 -1 -6 0 -6 1 -5 1 -6 2 -5 2 -5 3 -6 3 -4 3 -5 3 -6 3 -5 2 -5 3 -4 4 -4 5 -3 5 -3 4 -4 5 -5 4 -5 1 -6 -1 -6 -2 -4 -4 -4 -4 -4 -4 -6 -2 -5 -2 -6 -1 -6 -2 -5 -1 -6 -2 -6 -1 -5 -2 -5 -3 -4 -4 -4 -5 -4 -4 -4 -4 -4 -4 -5 -4 -4 -4 -5 -3 -5 -3 -6 -2 -5 -3 -5 -2 -6 -3 -5 -2 -5 -2 -6 -3 -5 -2 -5 -2 -5 -3 -6 -3 -5 -3 -5 -2 -5 -3 -5 -3 -5 -2 -6 -3 -5 -2 -6 -2 -5 -1 -6 -1 -6 -1 -6 0 -5 -1 -6 0 -6 -1 -6 0 -6 0 -5 1 -6 2 -6 2 -5 3 -4 3 -5 4 -4 4 -4 5 -4 4 -4 4 -4 4 -5 4 -4 4 -4 4 -4 4 -4 4 -3 5 -3 5 -3 5 -3 5 -3 5 -2 6 -3 5 -3 5 -2 5 -3 5 -3 6 -3 5 -3 5 -3 5 -4 4 -4 4 -5 3 -5 2 -6 1 -6 0 -6 0 -6 0 -6 -1 -5 -1 -6 -1 -6 -2 -5 -2 -6 -1 -5 -2 -6 -1 -6 0","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M-2299 3456l-4 -5 -8 -5","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M-2208 3444l-6 0 -6 0 -6 1 -5 1 -6 2 -5 3 -5 3 -4 4 -3 5 -4 5 -4 3 -6 0 -5 1 -6 -2 -6 -2 -5 -2 -4 -4 -5 -6","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M-856 2935l-6 2 -6 1 -5 1 -4 5 -3 5 -4 4 -3 5 -3 5 -2 5 -2 6 -2 5 -2 6 -2 5 -2 6 -3 5 -3 5 -3 5 -3 5 -4 4 -4 4 -5 4 -4 4 -5 3 -5 3 -5 3 -5 3 -3 5 -1 6 -1 6 -3 5 -4 4 -4 5 -4 4 -4 4 -4 4 -3 5 -3 5 -3 5 -3 5 -2 6 -2 5 -2 5 -3 6 -3 5 -3 5 -3 5 -3 5 -3 4 -4 5 -4 4 -4 4 -5 4 -7 5","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M-1039 3175l-4 4 -5 3 -5 3 -5 4 -5 3 -4 3 -5 4 -5 3 -4 4 -5 3 -5 4 -4 4 -5 3 -4 4 -5 3 -5 4 -4 3 -5 3 -5 3 -5 3 -6 3 -5 2 -5 3 -5 3 -10 4","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M-1278 3261l-6 0 -5 0 -6 0 -6 -1 -6 0 -6 0 -6 -1 -5 0 -6 0 -6 0 -6 0 -7 1","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M-1349 3260l-6 0 -5 3 -5 3 -4 4 -5 3 -4 4 -5 4 -4 4 -5 3 -4 4 -4 5 -4 4 -1 6 -2 6 -4 2 -6 0 -6 1 -6 1 -5 2 -5 3 -6 2 -5 3 -5 2 -5 3 -5 3 -5 3 -4 4 -5 4 -4 4","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M-2391 4081l-6 0 -6 0 -6 0 -5 -1 -6 -2 -5 -2 -6 -2 -5 -3 -4 -4 -5 -4 -3 -4 -3 -5 -4 -5 -4 -4 -4 -4 -5 -3 -5 -3 -5 -3 -5 -3 -6 -2 -5 -2 -6 -1 -6 -1 -6 1 -6 0 -6 1 -6 0 -5 -1 -5 -2 -5 -3 -5 -3 -5 -4 -5 -3 -5 -4 -6 -5","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M-1958 3866l-4 -3 -5 -3 -6 -2 -5 -3 -5 -2 -6 -2 -5 -3 -5 -3 -5 -3 -5 -3 -8 -6","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M-904 3767l-6 1 -5 1 -6 1 -6 1 -6 1 -5 0 -6 0 -6 0 -6 -1 -6 0 -6 0 -5 0 -6 -1 -6 0 -6 0 -6 0 -6 -1 -6 0 -5 0 -6 1 -6 0 -5 3 -5 3 -5 3 -6 2 -5 3 -5 3 -5 2 -6 2 -5 2 -6 2 -6 0 -5 1 -6 0 -6 0 -6 1 -6 0 -6 0 -5 1 -6 0 -6 0 -6 0 -6 0 -6 1 -5 0 -6 0 -6 1 -6 0 -6 1 -5 1 -6 2 -5 2 -6 3 -5 3 -4 4 -3 5 -2 5 -2 6 -3 5 -3 4 -5 5 -4 3 -5 4 -5 3 -5 3 -6 2 -5 2 -6 2 -5 1 -6 1 -6 2 -5 1 -6 2 -6 1 -5 2 -6 1 -5 2 -6 3 -5 2 -5 2 -5 3 -5 3 -5 3 -5 4 -5 3 -5 3 -5 3 -5 4 -4 3 -5 4 -4 4 -4 4 -4 4 -5 3 -5 3 -5 3 -5 3 -5 3 -5 3 -6 2 -5 3 -5 3 -5 3 -5 3 -4 4 -5 3 -5 4 -5 2 -5 3 -6 2 -5 1 -6 1 -6 1 -6 0 -6 1 -6 -2 -5 -1 -6 -2 -6 0 -6 0 -6 1 -5 2 -5 2 -5 4 -4 4 -4 4 -4 5 -4 4 -3 5 -1 6 1 6 3 5 3 5 2 5 3 6 2 5 1 6 1 6 1 6 0 6 0 6 -1 5 -3 5 -5 3 -6 3 -5 3 -5 3 -6 2 -5 1 -5 0 -6 -3 -5 -3 -5 -3 -5 -3 -5 -4 -5 -3 -5 -1 -6 -1 -6 -1 -6 -1 -6 -1 -5 -2 -5 -3 -4 -4 -5 -4 -4 -4 -6 -2 -5 -2 -5 -3 -5 -4 -5 -3 -4 -4 -5 -3 -5 -3 -5 -2 -6 0 -6 1 -6 0 -6 0 -6 0 -6 1 -6 0 -5 0 -6 -1 -6 -1 -5 -2 -6 -2 -5 -3 -5 -3 -5 -3 -5 -3 -4 -4 -5 -3 -4 -4 -4 -5 -3 -5 -3 -5 -4 -4 -5 -3 -5 -3 -6 -2 -5 -2 -6 -2 -5 -3 -4 -3 -5 -4 -5 -3 -4 -4 -5 -4 -4 -4 -4 -4 -4 -4 -4 -4 -3 -5 -3 -6 -2 -5 0 -6 1 -6 1 -6 -1 -5 -2 -6 -1 -6 -3 -5 -3 -5 -5 -3 -5 -4 -5 -3 -6 -4","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M-847 3785l-6 0 -5 -2 -5 -3 -5 -4 -5 -4 -4 -3 -5 -3 -6 -1 -6 1 -7 1","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M-721 3304l-1 6 -1 6 0 6 -1 6 0 6 0 5 -1 6 -2 6 -3 5 -4 4 -5 3 -6 1 -5 2 -5 4 -3 5 -2 6 -2 5 -1 6 0 6 0 6 1 6 0 5 -2 6 -4 5 -3 4 -3 5 -3 5 -3 5 -2 6 -3 5 -2 6 -1 5 0 6 0 6 1 6 0 6 1 5 1 6 2 6 1 5 2 6 2 5 2 6 3 5 3 5 4 4 3 5 3 5 4 5 3 5 2 5 1 6 1 6 0 5 0 6 -1 6 -2 5 -2 6 -3 5 -1 6 -1 6 -1 6 0 5 0 6 1 6 1 6 1 5 2 6 0 6 1 6 0 6 0 5 1 6 0 6 1 6 0 6 1 6 0 5 0 6 0 6 0 6 -1 6 -1 5 -3 6 -3 5 -4 5 -4 3 -5 2 -6 1 -6 2 -6 1 -7 1","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M-45 3270l-1 -5 -2 -6 -1 -6 -1 -5 0 -6 0 -6 1 -6 0 -6 1 -5 1 -6 1 -6 1 -6 1 -5 2 -6 1 -6 2 -5 1 -6 2 -6 2 -5 3 -7","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M10 3325l-4 -4 -5 -4 -4 -4 -4 -4 -4 -4 -4 -4 -5 -4 -4 -4 -4 -4 -5 -4 -4 -4 -4 -4 -4 -7","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M512 3668l-5 -1 -6 -1 -6 -1 -5 -2 -6 -1 -6 -2 -5 -2 -4 -4 -5 -4 -4 -4 -4 -4 -4 -5 -4 -4 -5 -3 -4 -4 -5 -4 -4 -3 -5 -3 -5 -4 -5 -3 -5 -3 -5 -4 -4 -3 -5 -3 -5 -3 -5 -3 -5 -3 -5 -3 -5 -3 -6 -2 -5 -3 -5 -3 -5 -3 -5 -3 -5 -3 -4 -4 -5 -4 -4 -3 -6 -1 -6 0 -6 1 -6 0 -6 0 -5 -1 -6 0 -6 1 -6 1 -5 1 -6 1 -6 1 -6 1 -6 1 -5 1 -6 1 -6 0 -6 -1 -5 -1 -6 -2 -5 -3 -5 -4 -4 -4 -3 -5 -2 -5 -2 -6 -2 -5 -1 -6 -2 -6 -1 -6 -1 -5 -2 -6 -2 -5 -2 -6 -3 -4 -4 -5 -4 -5 -4 -4 -4 -3 -6 -1 -6 -1 -6 0 -6 0 -6 0 -5 1 -6 1 -6 1 -6 0 -6 1 -5 0 -7 0 -5 -2 -4 -3 -4 -5 -3 -5 -4 -5 -3 -4 -3 -6 -3 -5 -4 -4 -4 -5 -4 -4 -4 -4 -3 -5 -3 -5 0 -5 1 -6 1 -6 -1 -6 -1 -6 -1 -6 -2 -5 -1 -6 -2 -6 -2 -5 -3 -5 -3 -5 -4 -4 -8 -8","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M-477 3749l-1 -6 0 -6 -1 -5 0 -6 0 -6 0 -6 0 -6 0 -6 1 -5 0 -6 1 -6 1 -6 1 -5 2 -6 3 -5 2 -6 2 -5 1 -6 1 -6 -1 -6 -1 -5 -1 -6 -3 -5 -3 -5 -3 -5 -5 -6","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M39 3854l-6 -2 -6 -1 -6 -1 -5 0 -6 0 -6 -1 -6 0 -6 0 -5 1 -6 0 -6 0 -6 0 -6 0 -6 0 -5 1 -6 0 -6 1 -6 0 -6 1 -6 0 -5 1 -6 1 -6 2 -5 1 -6 2 -6 1 -5 2 -6 2 -5 3 -5 3 -5 3 -4 4 -5 3 -6 2 -5 2 -6 1 -6 2 -5 1 -6 1 -6 1 -5 2 -6 1 -6 1 -6 1 -5 1 -6 0 -6 0 -6 0 -6 0 -6 0 -5 0 -6 0 -6 0 -6 0 -6 0 -6 0 -5 0 -6 -1 -6 0 -6 -2 -5 -1 -6 -1 -6 -2 -5 -1 -6 -1 -6 -2 -5 -1 -6 -1 -6 -1 -6 0 -6 0 -6 1 -5 0 -6 0 -6 0 -6 -2 -5 -1 -6 -2 -5 -3 -5 -3 -5 -3 -4 -4 -4 -4 -4 -5 -4 -4 -3 -5 -4 -5 -3 -4 -3 -5 -3 -5 -4 -10","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M577 3867l-5 -3 -5 -3 -5 -3 -5 -3 -5 -3 -5 -3 -5 -3 -5 -4 -5 -3 -5 -3 -5 -2 -5 -3 -6 -1 -6 1 -6 0 -6 2 -5 1 -6 3 -5 3 -4 3 -5 4 -4 4 -4 4 -4 5 -3 4 -4 5 -3 5 -4 4 -3 5 -4 5 -4 4 -3 5 -3 5 -4 4 -2 6 -2 6 -3 5 -3 4 -5 3 -5 2 -6 2 -6 0 -6 0 -6 -1 -5 -3 -4 -4 -3 -5 -3 -5 -2 -6 -2 -5 -1 -6 -1 -6 -2 -5 -4 -5 -3 -4 -4 -5 -4 -4 -4 -5 -4 -4 -4 -4 -4 -4 -5 -4 -4 -3 -5 -4 -4 -4 -4 -4 -4 -5 -3 -4 -4 -5 -4 -4 -4 -4 -4 -4 -5 -4 -5 -3 -5 -3 -6 -2 -5 -2 -6 -2 -5 -2 -6 -1 -6 -1 -5 -2 -6 0 -6 -1 -6 0 -5 1 -6 1 -6 2 -5 1 -6 2 -5 3 -5 2 -6 3 -5 2 -6 2 -5 1 -6 1 -6 1 -6 1 -5 1 -6 1 -6 2 -5 2 -4 5 -2 5 -3 5 -3 5 -4 5 -4 4 -5 3 -5 3 -5 3 -6 1 -5 0 -6 1 -6 0 -9 0","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M-353 3088l-3 5 -3 5 -4 4 -3 5 -4 5 -4 4 -3 4 -5 5 -4 4 -5 3 -5 1 -6 0 -6 -1 -5 -2 -5 -3 -5 -3 -5 -4 -4 -4 -4 -4 -5 -4 -5 -3 -5 -1 -6 -1 -6 0 -6 0 -6 0 -6 0 -5 1 -6 2 -5 2 -5 3 -5 4 -4 4 -4 5 -3 5 -2 5 -2 6 -1 5 -2 6 -1 6 -1 6 0 5 -1 6 0 6 -1 6 -1 6 -2 5 -2 6 -2 5 -3 5 -3 5 -4 4 -5 3 -5 4 -3 4 -4 5 -3 5 -4 5 -3 5 -3 5 -2 5 -2 5 -2 6 -2 6 -2 5 -1 6 -1 5 -1 6 0 6 0 6 0 6 0 6 0 5 0 6 -1 6 -2 6 -2 5 -4 5 -4 4 -3 5 -2 5 -2 6 -1 6 -1 5 1 6 1 6 1 6 2 5 1 6 1 6 1 6 0 5 0 6 0 6 0 6 -1 7","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M-31 3155l2 -5 3 -6 3 -5 3 -5 3 -4 3 -5 3 -5 4 -5 3 -5 3 -5 4 -4 3 -5 4 -4 4 -4 4 -4 4 -5 4 -4 3 -5 3 -5 3 -5 3 -5 3 -6 2 -5 2 -5 1 -6 1 -6 -1 -6 -4 -3 -5 -3 -6 -2 -5 -2 -6 -1 -6 -1 -6 -1 -5 -1 -6 -2 -6 -1 -5 -2 -6 -1 -6 -2 -5 -1 -6 -2 -5 -2 -6 -3 -4 -3 -5 -3 -5 -4 -4 -4 -5 -3 -6 -2 -5 -2 -6 -1 -5 -2 -6 -1 -6 -2 -5 -1 -6 -1 -6 -1 -6 1 -5 2 -6 2 -5 3 -5 3 -6 1 -5 0","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M-797 3779l-6 1 -5 2 -6 1 -6 1 -5 1 -6 0 -6 0 -10 0","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M-457 3819l-2 -6 -2 -5 -2 -5 -2 -6 -1 -5 -2 -6 -2 -6 -1 -5 -1 -6 -1 -6 -2 -5 -2 -9","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M-272 4462l-6 -1 -6 -1 -6 0 -5 0 -6 0 -6 -1 -5 -2 -6 -2 -5 -2 -6 -1 -6 -2 -5 -2 -6 -1 -6 0 -6 0 -6 0 -5 0 -6 1 -6 2 -5 1 -6 0 -5 -3 -6 -2 -5 -2 -6 -2 -5 -1 -6 -1 -6 -1 -6 -1 -6 0 -5 -1 -6 0 -6 0 -6 0 -6 0 -6 1 -5 0 -6 0 -6 1 -6 1 -6 1 -5 1 -6 1 -5 2 -6 2 -5 3 -6 2 -5 3 -5 3 -5 3 -4 4 -5 3 -4 4 -5 3 -5 4 -5 3 -4 3 -5 4 -5 3 -5 4 -5 3 -4 3 -5 3 -6 2 -6 1 -6 0 -5 2 -5 3 -4 4 -4 4 -4 5 -3 5 -4 9","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M380 4634l-4 3 -5 4 -5 3 -5 3 -5 2 -6 2 -6 2 -5 1 -6 2 -6 1 -5 1 -6 1 -6 1 -6 1 -5 0 -6 0 -6 0 -6 -2 -5 -1 -6 -1 -6 0 -6 0 -6 0 -5 0 -6 0 -6 0 -6 0 -6 1 -6 0 -5 1 -6 0 -6 1 -6 2 -5 1 -6 2 -5 2 -6 3 -5 2 -5 4","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M162 4676l-5 3 -4 5 -4 4 -4 4 -4 4 -5 4 -5 3 -4 4 -5 3 -4 4 -4 4 -5 4 -5 3 -4 4 -5 3 -5 3 -5 3 -5 3 -6 2 -5 0 -6 0 -6 -1 -6 -1 -5 -3 -3 -5 -2 -6 -1 -6 -1 -6 0 -5 0 -6 -1 -6 0 -6 -2 -6 -1 -5 -1 -6 -1 -6 -2 -5 -1 -6 -2 -6 -1 -5 -2 -6 -1 -5 -2 -6 -2 -5 -3 -6 -2 -5 -2 -6 -4 -5 -3 -4 -4 -4 -4 -4 -5 -4 -4 -4 -5 -3 -5 -4 -5 -3 -5 -3 -5 -3 -5 -2 -6 -2 -5 -2 -6 -2 -5 -2 -6 -1 -6 -1 -5 -1 -6 -1 -6 0 -6 -1 -6 0 -6 -1 -5 0 -6 0 -6 -1 -6 0 -6 0 -5 -1 -6 -1 -6 0 -6 -1 -6 -1 -5 0 -6 -1 -6 0 -6 0 -6 0 -6 0 -5 -1 -6 0 -6 -1 -6 -1 -6 -2 -5 -2 -4 -3 -2 -6 0 -6 0 -6 1 -6 2 -5 2 -6 2 -5 1 -6 1 -6 0 -6 -2 -5 -5 -4 -5 -3 -6 -1 -5 -1 -6 -1 -9 0","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M-1708 4748l5 -1 6 -1 6 -2 5 -2 5 -3 5 -4 4 -4 3 -5 3 -5 4 -4 5 -3 6 -2 6 0 6 0 5 2 6 2 5 2 6 2 5 1 6 2 6 1 5 1 6 2 6 1 5 2 6 2 5 2 5 3 6 2 5 2 6 1 6 0 6 0 6 1 5 0 6 0 6 -2 5 -2 4 -4 3 -6 3 -4 6 -1 6 1 5 1 6 2 5 2 6 3 5 2 5 3 4 4 3 5 3 5 3 5 5 3 5 3 5 3 5 3 6 3 5 2 5 3 5 2 6 2 5 3 6 2 5 2 6 2 5 1 6 1 6 0 6 -1 6 0 5 -2 6 -1 6 -1 5 -1 6 -1 6 -1 6 1 5 1 6 1 6 1 6 1 5 1 6 2 6 2 5 2 5 2 6 2 5 2 6 3 5 2 5 3 6 1 5 1 6 0 6 -1 6 -1 6 -1 5 -2 6 -1 6 -2 5 -1 6 -2 5 -2 6 -1 6 -2 5 -1 6 -1 6 0 6 0 6 1 5 -2 5 -3 5 -3 5 -3 5 -4 4 -4 5 -4 4 -4 3 -5 3 -5 2 -5 2 -6 2 -5 3 -5 2 -6 4 -4 4 -5 4 -3 6 -2 5 -2 6 -2 5 -2 5 -3 4 -4 5 -4 5 -3 5 -3 5 -3 4 -4 4 -4 4 -5 3 -4 4 -5 3 -5 3 -5 3 -5 3 -5 3 -5 3 -5 3 -5 3 -5 4 -4 5 -4 4 -4 5 -2 6 -2 6 -2 5 -1 6 0 6 0 6 1 6 1 5 0 6 1 6 2 6 1 5 2 8 3","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M1576 1466l-6 2 -5 1 -6 1 -6 1 -6 1 -5 1 -6 2 -6 1 -5 1 -6 0 -6 0 -6 0 -6 0 -5 0 -6 0 -6 0 -6 0 -6 0 -6 0 -5 0 -6 0 -6 0 -6 1 -6 0 -6 1 -5 1 -6 1 -6 1 -6 0 -5 2 -6 1 -6 2 -5 2 -6 2 -5 2 -6 2 -5 3 -4 3 -4 5 -4 4 -3 5 -3 5 -4 5 -3 5 -3 5 -2 5 -1 6 -1 6 -1 6 0 5 0 6 1 6 -1 6 -2 5 -3 6 -2 5 -2 5 -2 6 -2 6 -1 5 -2 6 -2 5 -1 6 -2 6 -1 5 0 6 0 6 0 6 0 6 1 5 0 6 1 6 1 6 1 6 1 5 0 6 -1 6 0 6 -2 5 -1 6 -3 5 -3 5 -3 5 -4 5 -4 4 -4 4 -5 3 -5 4 -4 3 -5 3 -5 3 -5 4 -5 3 -5 3 -5 3 -4 4 -5 3 -5 4 -4 4 -3 4 -5 4 -5 4 -5 3 -5 3 -5 3 -5 2 -6 1 -6 1 -5 -1 -6 -1 -6 -2 -5 -1 -6 -1 -6 0 -6 -1 -6 -1 -6 1 -6 0 -5 3 -3 3 -4 6 -3 5 -3 5 -4 4 -4 5 -4 4 -4 4 -4 5 -3 5 -2 5 -3 5 -2 6 -2 5 -2 5 -2 6 -2 6 -1 5 -1 6 -2 6 -2 5 -2 5 -3 6 -2 5 -3 5 -2 5 -3 6 -3 5 -3 4 -4 5 -3 5 -4 5 -3 4 -4 4 -4 5 -4 4 -4 5 -4 4 -4 4 -4 5 -3 4 -4 4 -4 5 -4 4 -4 4 -4 4 -5 4 -4 5 -4 4 -4 4 -4 4 -4 4 -4 4 -4 4 -5 4 -4 4 -4 4 -4 4 -4 5 -4 4 -5 4 -4 4 -3 4 -4 5 -4 4 -3 5 -3 5 -4 5 -4 4 -3 5 -4 4 -4 4 -4 5 -4 4 -4 4 -4 5 -4 4 -4 4 -4 4 -5 4 -4 3 -5 4 -8 7","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M812 2230l-2 5 -1 6 -2 11","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M823 2208l-6 6","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M817 2214l-5 16","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M-1461 1230l-6 -2 -6 -1 -6 -1 -5 0 -6 0 -6 0 -6 2 -5 1 -5 3 -5 4 -4 4 -4 4 -5 4 -4 4 -5 4 -5 2 -6 1 -6 0 -6 -2 -5 -2 -3 -5 -3 -5 -3 -6 -2 -5 -1 -6 -1 -5 -2 -6 -1 -6 -1 -6 -1 -5 -1 -6 -1 -6 -1 -6 -1 -5 0 -6 0 -6 0 -6 0 -6 1 -6 0 -5 1 -12","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M-1084 1281l-6 1 -6 1 -6 -1 -5 -1 -6 -2 -5 -2 -6 -3 -5 -2 -6 -2 -5 -2 -6 -2 -5 0 -4 5 -4 3 -6 1 -6 -1 -6 -1 -6 -1 -5 0 -6 -1 -6 -1 -6 -2 -5 -3 -4 -5 -5 -4 -4 -1 -5 2 -5 4 -5 4 -4 5 -4 5 -4 1 -6 0 -6 -1 -6 -1 -6 -1 -6 0 -6 -2 -5 -1 -5 -3 -5 -3 -5 -4 -4 -4 -4 -4 -5 -4 -4 -4 -4 -4 -4 -5 -4 -4 -4 -5 -3 -4 -3 -5 -1 -6 1 -6 1 -6 -2 -6 -3 -5 -4 -3 -6 -2 -5 -2 -6 -1 -6 -1 -6 0 -6 0 -5 2 -6 3 -6 1 -6 1 -4 4 -3 5 -2 6 -1 5 1 6 1 6 -3 5 -4 4 -5 4 -6 2 -5 0 -6 0 -6 -1 -6 -2","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M-856 1458l-6 -2 -4 -4 -5 -3 -5 -3 -6 -1 -5 -1 -5 -3 -5 -4 -5 -3 -4 -4 -8 -6","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M-941 1370l-1 -6 -3 -5 -2 -5 -3 -5 -3 -5 -4 -4 -4 -4 -5 -4 -4 -4 -6 -1 -5 -2 -6 -2 -6 -1 -5 -2 -6 -2 -5 -2 -5 -3 -4 -4 -5 -4 -4 -4 -4 -4 -4 -5 -4 -4 -4 -5 -4 -3 -5 -2 -6 0 -6 0 -6 0 -6 2 -8 1","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M-914 1424l-3 -4 -4 -5 -3 -5 -3 -5 -3 -5 -3 -5 -3 -5 -2 -5 -1 -6 -2 -9","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M-734 1478l-6 -2 -5 -2 -6 -2 -5 -1 -6 1 -6 1 -5 1 -6 1 -6 2 -5 3 -5 1 -6 0 -6 0 -6 0 -6 -1 -5 -1 -4 -4 -4 -5 -4 -4 -4 -3 -6 -2 -10 -3","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M-2142 1626l-4 4 -5 4 -4 3 -5 3 -5 4 -5 3 -5 3 -5 3 -5 3 -5 2 -5 3 -5 3 -5 3 -5 3 -5 3 -5 3 -5 4 -5 3 -5 3 -5 3 -4 4 -5 3 -5 4 -4 3 -5 4 -4 4 -5 4 -4 3 -5 3 -5 3 -6 3 -5 3 -5 3","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M-2302 1733l-5 2 -5 3 -5 3 -5 4 -4 4 -4 4 -4 4 -4 4 -4 4 -4 4 -5 5 -4 4 -4 4 -4 4 -5 4","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M-2368 1790l-5 4 -4 4 -4 4 -5 4 -5 3 -4 3 -5 3 -6 3 -5 3 -5 3 -5 3 -5 3 -5 3 -5 3 -5 2 -5 3 -6 2 -6 1 -5 2 -5 3 -4 4 -3 5 -4 5 -3 5 -3 5 -4 5 -3 4 -3 5 -3 5 -2 6 -2 6 -2 5 -2 5 -4 5 -4 4 -4 4 -4 4 -3 5 -3 5 -4 8","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M-1248 2119l-5 -3 -5 -3 -5 -2 -5 -3 -6 -2 -5 -2 -6 -1 -5 -1 -6 -1 -6 -1 -6 -2 -5 -1 -6 -1 -6 -1 -5 -2 -6 -1 -6 -1 -5 -2 -6 -1 -6 -2 -5 -1 -6 -2 -5 -2 -6 -2 -5 -2 -6 -2 -6 -1 -5 0 -6 1 -6 1 -6 0 -6 0 -5 -1 -6 -2 -5 -2 -6 -2 -6 -2 -5 -2 -5 -2 -6 -3 -5 -2 -6 -1 -5 -1 -6 0 -6 0 -6 1 -6 2 -5 2 -4 4 -4 5 -2 5 -3 5 -3 6 -3 4 -4 5 -3 5 -4 4 -4 5 -3 4 -5 5","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M-2635 2170l-1 5 -2 6 -2 6 -2 5 -4 4 -5 2 -6 2 -6 1 -6 0 -5 3 -7 5","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M-2286 2213l-3 -5 -3 -6 -3 -5 -5 -2 -5 -2 -6 0 -6 -1 -6 0 -6 -1 -6 0 -6 -1 -5 0 -6 1 -6 0 -6 1 -6 0 -6 0 -6 0 -5 -1 -5 -4 -4 -4 -4 -4 -6 -1 -5 3 -5 3 -5 4 -4 3 -6 2 -6 1 -6 -1 -5 -2 -5 -3 -6 -1 -6 -1 -6 0 -5 1 -6 1 -6 1 -5 2 -6 1 -6 1 -5 2 -6 1 -6 1 -6 1 -5 1 -6 1 -6 1 -6 1 -5 -1 -3 -6 -4 -4 -5 -3 -6 -1 -5 3 -4 4 -4 4 -3 5 -2 6 0 6 -2 6 -2 5 -3 5 -5 4 -5 1 -6 -1 -6 -2 -5 -2 -6 -2 -5 -2 -5 -2 -6 -3 -5 -2 -5 -3 -6 -2 -5 -2 -6 -2 -6 -2","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M-1558 2118l-5 3 -6 3 -5 1 -6 -1 -6 0 -6 -1 -5 -1 -6 -2 -6 -1 -5 -2 -6 -3 -5 -3 -5 -3 -5 -2 -5 0 -6 3 -5 2 -6 0 -6 -1 -6 0 -6 -1 -5 0 -6 0 -6 0 -6 0 -6 -1 -5 -1 -6 -1 -6 -1 -6 0 -6 0 -5 0 -6 1 -6 1 -5 2 -6 2 -5 3 -6 2 -5 3 -5 3 -5 2 -6 1 -6 0 -6 0 -5 -1 -6 0 -6 0 -6 0 -6 0 -6 1 -5 0 -6 2 -6 1 -5 2 -6 2 -5 1 -6 2 -5 2 -6 2 -5 3 -6 2 -5 3 -5 2 -5 3 -6 2 -5 2 -6 2 -5 2 -6 1 -6 1 -5 1 -6 0 -6 0 -6 0 -6 0 -5 -1 -6 -1 -6 -1 -6 -1 -6 0 -5 1 -6 1 -5 3 -5 4 -4 3 -5 4 -4 4 -5 4 -4 4 -4 4 -5 3 -5 4 -4 3 -6 2 -5 1 -6 0 -6 1 -6 1 -6 1 -5 1 -6 1 -6 1 -6 1 -6 1 -5 1 -6 1 -5 2 -6 3 -5 3 -5 2 -5 3 -6 1 -6 1 -5 1 -6 0 -6 1 -6 2 -5 2 -5 3 -4 4 -4 4 -4 5 -4 5 -4 4 -4 1 -6 -2 -5 -4 -4 -4 -3 -5 -4 -4 -4 -5 -4 -4 -4 -4 -4 -4 -4 -5 -5 -7","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M-2114 1350l-1 6 -1 5 -1 6 -1 6 -1 5 -2 6 -2 5 -3 6 -2 5 -2 6 -2 5 -1 6 -1 6 -1 5 1 6 2 6 1 6 2 5 1 6 2 6 1 5 1 6 1 6 0 5 0 6 1 6 0 6 0 6 0 6 0 5 0 6 0 6 0 6 0 6 0 6 0 5 0 6 -1 6 0 6 -1 6 0 6 -1 6 -1 5 -1 6 -1 6 -2 5 -3 5 -5 4 -4 4","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M-872 1910l5 2 5 3 5 3 6 1 5 2 6 2 6 1 5 1 6 0 6 0 6 -1 6 -2 6 -1 5 1 3 5 2 6 4 4 4 4 5 3 6 2 5 2 6 2 5 2 6 2 5 2 6 2 5 3 5 2 6 3 4 4 3 5 1 5 1 6 1 6 0 6 0 6 0 6 -2 6 -2 5 -2 5 -1 6 0 6 2 6 3 5 3 4 4 5 4 4 4 5 4 4 4 4 3 5 2 5 1 6 1 6 0 6 -1 6 -1 5 -2 6 -2 5 -4 5 -4 4 -5 3 -6 2 -5 2 -6 1 -6 2 -4 4 -3 4 -2 6 -3 5 -2 6 -2 6 -2 5 -1 6 -3 5 -3 5 -4 4 -5 2 -6 2 -5 2 -6 2 -6 2 -5 1 -6 1 -6 0 -6 0 -6 -1 -5 0 -6 0 -6 1 -6 -1 -5 -3 -5 -3 -6 -1 -5 0 -6 0 -6 0 -6 0 -6 0 -6 -1 -5 -2 -6 -2 -5 -3 -5 -3 -6 -2 -5 -3 -5 -1 -6 0 -5 2 -6 3 -5 2 -6 3 -5 3 -5 2 -5 3 -6 2 -5 1 -6 0 -6 1 -6 -1 -6 0 -6 0 -6 -1 -6 -1 -3 -4 0 -7 -3 -4 -6 -3 -5 -1 -6 2 -5 3 -6 0 -5 -2 -6 -3 -5 -2 -6 -2 -5 -2 -5 -3 -4 -5 -3 -5 -4 -2 -6 2 -6 2 -4 -3 -3 -6 -3 -5 -4 -3 -6 -2 -6 -1 -5 -2 -6 -2 -5 -2 -6 -2 -6 0 -5 0 -6 1 -6 1 -6 0 -6 -1 -5 -2 -6 -2 -5 -2 -6 -2 -5 -2 -6 -2 -5 -2 -6 -2 -5 -3 -9 -5","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M-3441 1901l1 6 0 6 0 6 0 6 0 6 -1 5 0 6 -1 6 -1 6 -1 6 -2 5 -2 6 -2 5 -3 5 -3 5 -3 5 -4 4 -4 5 -4 4 -4 4 -5 4 -4 4 -5 3 -4 4 -5 4 -5 3 -4 3 -5 3 -5 4 -5 3 -4 4 -4 4 -4 5 -4 4 -4 4 -4 4 -5 4 -4 3 -5 4 -5 3 -6 2 -5 2 -5 2 -6 2 -6 1 -5 2 -6 2 -5 2 -6 2 -5 3 -4 3 -5 4 -5 3 -5 4 -4 3 -5 4 -4 4 -5 3 -4 4 -4 4 -5 4 -5 3 -5 3 -5 2 -6 2 -5 3 -5 2 -6 3 -5 3 -5 3 -4 4 -5 4 -3 4 -2 5 -2 6 -2 6 -1 5 -2 6 -1 6 0 6 -2 5 -1 6 -3 5 -2 6 -2 5 -3 5 -3 5 -3 5 -3 5 -3 5 -3 5 -4 5 -4 4 -4 4 -4 4 -4 4 -4 4 -4 5 -4 4 -3 5 -2 6 -3 5 -4 4 -4 4 -4 5 -4 4 -4 4 -5 4 -4 4 -4 4 -4 4 -4 4 -4 5 -4 4 -4 4 -4 4 -4 5 -4 4 -3 5 -4 4 -4 4 -4 5 -3 4 -4 5 -3 5 -3 5 -4 4 -3 5 -3 5 -3 5 -4 5 -4 7","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M-3720 1802l5 -4 4 -3 5 -4 5 -3 5 -3 5 -3 5 -2 6 -2 5 -2 6 -1 6 -2 5 -1 6 -1 6 -2 5 -2 5 -3 5 -3 5 -4 5 -3 5 -3 5 -1 6 -1 6 1 6 1 5 1 6 0 6 0 6 0 6 0 6 0 5 -1 6 0 6 0 6 -1 6 -1 5 -1 6 -2 5 -3 5 -4 4 -3 5 -3 5 -3 5 -4 5 -3 5 -2 6 -1 6 1 5 3 4 4 3 5 3 5 3 5 3 5 3 5 3 5 3 6 2 5 2 5 1 6 1 6 1 6 1 5 1 6 0 6 0 6 -1 6 -2 5 -2 6 -2 5 -1 6 -1 5 -1 6 -1 6 -1 6 -1 6 0 5 -1 6 0 6 1 6 0 6","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M-3032 1971l3 5 3 5 2 5 3 6 2 5 3 5 1 6 2 5 2 6 1 6 1 6 1 5 1 6 1 6 0 6 0 5 0 6 0 6 -1 6 0 6 -1 6 -1 5 -1 6 -1 6 -1 5 -2 6 -1 6 -2 5 -1 6 -1 6 -1 6 0 5 -1 6 0 6 -1 6 -1 6 -1 5 -2 6 -2 6 -2 5 -3 5 -4 4 -5 3 -5 4 -6 2 -5 2 -6 1 -5 2 -6 1 -6 2 -5 2 -6 2 -6 3 -5 2 -5 3 -4 4 -3 5 -2 5 0 5 0 7 -1 6 0 6 -1 6 -2 5 -2 5 -3 5 -3 5 -4 5 -3 5 -2 6 -3 5 -2 5 -3 6 -2 5 -3 5 -4 4 -5 3 -5 3 -6 2 -5 3 -5 2 -6 2 -5 2 -6 3 -5 2 -5 4 -5 3 -4 3 -6 3 -5 2 -5 1 -6 1 -6 0 -6 0 -6 2 -4 3 -5 4 -4 4 -4 5 -4 4 -3 5 -3 5 -4 5 -3 5 -2 5 -5 8","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M-2763 2143l-5 4 -4 4 -4 5 -3 4 -3 5 -4 5 -3 5 -3 5 -3 5 -3 5 -3 5 -3 5 -3 5 -3 5 -3 5 -3 5 -3 5 -3 5 -3 5 -1 6 -2 5 -1 6 0 6 -3 4 -5 3 -5 3 -6 0 -6 1 -6 1 -3 4 -4 5 -1 6 -2 5 -3 5 -3 5 -4 5 -4 4 -5 3 -4 3 -5 4 -5 3 -5 4 -4 3 -5 6","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M-2840 2347l-5 -2 -6 -2 -5 -2 -6 -2 -5 -1 -6 -1 -6 0 -6 0 -6 0 -5 0 -6 -1 -6 0 -9 -1","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M-3565 1344l0 6 0 6 -1 5 0 6 0 6 0 6 1 6 3 5 2 6 -1 5 0 6 -1 6 0 6 -1 6 0 6 0 5 0 6 -1 6 0 6 -1 6 -3 4 -9 5","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M-3264 1528l-5 -1 -5 -3 -6 -3 -4 -3 -4 -4 -4 -5 -2 -5 -3 -6 -2 -5 -2 -6 -3 -4 -4 -5 -5 -3 -5 -3 -5 -2 -6 -1 -6 0 -6 0 -6 0 -6 0 -5 0 -6 0 -6 1 -6 1 -5 1 -6 2 -5 3 -5 3 -4 4 -4 4 -5 4 -5 3 -5 3 -5 3 -5 3 -6 2 -5 1 -6 2 -6 0 -6 1 -5 -1 -6 -2 -6 -1 -6 -2 -5 0 -6 2 -5 3 -6 0 -6 -1 -5 -1 -6 -2 -5 -2 -6 -2 -5 -3 -5 -3 -5 -3 -4 -4 -5 -3 -5 -4 -5 -3 -4 -4 -7 -5","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M-3090 1460l1 5 1 6 0 6 -1 6 -3 5 -3 5 -3 5 -4 5 -4 4 -4 3 -6 2 -6 -1 -6 -1 -5 -1 -6 -2 -6 -2 -5 -1 -6 0 -6 1 -5 1 -6 2 -6 2 -5 2 -6 2 -5 3 -5 2 -6 2 -5 2 -6 2 -5 1 -6 2 -6 1 -6 1 -5 1 -6 0 -6 -1 -7 -2","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M-3577 1469l-5 3 -5 3 -6 3 -5 3 -5 2 -4 4 -3 5 -3 5 -3 5 -4 5 -4 4 -4 4 -3 5 -4 5 -3 4 -4 5 -5 4 -5 1 -6 0 -6 0 -5 2 -6 3 -5 2 -6 3 -5 -1 -5 -4 -5 -1 -6 -1 -6 0 -6 0 -6 1 -6 1 -6 0 -5 1 -5 3 -5 4 -5 2 -6 1 -6 2 -5 1 -6 1 -6 1 -6 0 -5 3 -4 4 -3 5 -3 5 -3 5 -1 6 -2 6 -1 5 -2 6 -2 8","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M-3818 1613l-2 5 -1 6 1 6 0 6 1 6 1 5 -1 6 -2 5 -3 5 -4 4 -6 3","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M-2681 2209l-4 -4 -5 -4 -3 -4 -3 -5 -3 -5 -3 -6 -2 -5 -1 -6 1 -6 1 -6 -1 -5 -2 -5 -4 -5 -4 -4 -5 -3 -6 -2 -6 -1 -5 -1 -6 -1 -6 0 -6 2 -4 4 -5 6","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M-3834 1670l-5 3 -5 3 -5 3 -6 1 -6 1 -5 2 -5 2 -5 3 -5 4 -5 3 -5 3 -5 4 -4 3 -5 3 -5 3 -6 2 -5 2 -6 2 -6 1 -5 0 -6 0 -6 0 -6 1 -6 0 -6 0 -5 -1 -6 -1 -6 -1 -6 -1 -5 0 -6 2 -6 1 -4 4 -5 3 -4 4 -5 3 -6 2 -5 2 -6 -2 -6 -1 -5 -1 -5 3 -6 3 -5 3 -5 2 -5 3 -5 4 -4 3 -4 5 -3 5 -3 5 -3 5 -4 4 -5 4 -4 4 -4 4 -4 4 -4 4 -4 4 -5 5","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M-1164 3258l-6 3 -5 1 -6 0 -6 0 -6 0 -6 0 -5 0 -12 -1 -6 0 -5 0 -6 0 -6 0 -6 0 -6 0 -6 0 -5 0 -6 0 -10 0","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M-402 2846l-3 -5 -3 -5 -4 -5 -3 -5 -3 -4 -4 -5 -4 -4 -5 -3 -5 -3 -5 -3 -5 -3 -5 -3 -5 -2 -5 -4 -5 -3 -4 -4 -5 -3 -5 -4 -5 -3 -5 -3 -4 -4 -4 -4 -4 -5 -2 -5 -2 -5 -2 -6 -2 -6 -1 -6 -1 -5 -2 -5 -4 -4 -5 -4 -5 -3 -5 -3 -6 -2 -6 -1 -5 -1 -6 -1 -6 0 -6 1 -6 1 -6 0 -5 1 -6 1 -6 1 -6 1 -5 0 -6 0 -6 0 -6 0 -6 -1 -6 0 -5 0 -6 1 -6 2 -5 3 -5 3 -4 4 -3 5 -2 6 -2 5 -3 5 -2 6 -3 5 -4 5 -4 3 -5 2 -6 2 -6 1 -6 1 -5 1 -6 1 -6 1 -6 2 -5 1 -6 1 -6 1 -5 1 -6 0 -6 1 -6 0 -6 1 -5 2 -5 3 -3 5 -3 6 -2 9","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str5","@d":"M-336 2989l-5 -3 -5 -3 -1 -1 -4 -2 -3 -5 -3 -5 -4 -5 -3 -5 -3 -4 -4 -5 -3 -5 -1 -6 -1 -6 -1 -5 -1 -6 -2 -6 -1 -5 -1 -6 -2 -6 -2 -5 -1 -6 -2 -5 -2 -6 -2 -5 -2 -6 -2 -5 -2 -6 -3 -10","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil7 str6","@d":"M774 1248l0 -6 -1 -6 -2 -5 -1 -6","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str6","@d":"M692 1118l5 -4 3 -5 4 -4 2 -6","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str6","@d":"M3058 5776l-3 5 -3 5 -3 5 -3 5 -2 6 -3 5 -2 5 -2 6 -2 5 0 6 1 6 1 6 1 5","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str6","@d":"M2501 6261l-3 -6 -2 -5 -3 -5 -2 -6 -3 -5 -3 -5 -3 -4 -4 -5 -3 -5 -4 -4 -4 -5 -3 -4 -3 -5 -4 -5 -3 -5 -4 -5 -3 -5 -3 -5 -3 -5 -1 -6 -1 -5 0 -5 1 -6 2 -6","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str6","@d":"M-2298 7095l-6 -3 -5 -3 -5 -3 -5 -2 -5 -3 -6 -2 -5 -2 -6 -1 -6 0 -6 1 -5 1 -6 1 -6 1 -6 1 -6 2 -4 3 -4 5 -2 5 -2 6 -2 5 -3 6 -2 5 -3 5 -4 5 -3 4 -5 4 -4 4 -5 3 -6 3 -5 2 -6 1 -5 1 -6 1 -6 2 -5 2 -5 4 -3 5 -2 5 -1 6 0 6 0 6 0 6 0 6 0 6 0 5 -2 6 -2 6 -3 5 -4 4 -4 4 -5 4 -5 2 -6 2 -6 1 -6 0 -5 -1 -5 -3 -5 -4 -5 -3 -6 -1 -6 0 -5 1 -6 1 -6 2 -5 1 -6 0 -7 0 -5 1 -5 2 -4 4 -3 6 -3 4 -4 4 -5 4 -4 4 -4 4 -4 5 -4 4 -5 8","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str6","@d":"M-3441 3011l4 -4 5 -4 4 -5 2 -5 2 -6 1 -5 -2 -6 -4 -4 -6 -2 -5 -3 -6 -1 -5 -1 -6 -1 -6 -1 -6 -1 -6 0 -5 0 -6 0 -6 0 -6 0 -6 0 -6 0 -5 2 -5 3 -4 4 -4 5","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str6","@d":"M-3398 2795l3 5 3 6 2 5 1 6 1 6 -1 6 -1 6 -1 5 -1 6 -2 6 -2 5 -3 6 -2 5 -4 4 -3 5 -4 5 -4 4 -4 4 -4 4 -5 4 -4 4 -5 3 -5 3 -5 3 -5 3 -5 3","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str6","@d":"M-2710 2997l5 -4 4 -4 4 -4 4 -5 3 -4 4 -5 3 -5 4 -4 4 -5 3 -5 4 -4 3 -5 4 -4 4 -4 5 -4 5 -3 5 -3 5 -2 6 -2 5 -2 5 -3 6 -2 6 -2 4 -3 4 -4 3 -5 2 -6 2 -5 0 -6 1 -6 1 -6 2 -6 1 -5 2 -6 3 -5 3 -5 5 -4 5 -3 5 -1 6 -2 6 -1","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str6","@d":"M-2831 3750l6 1 6 1 6 1 5 0 6 1 6 1 6 1 5 2 5 3 5 4 3 5 3 5 2 6 0 6 0 6 0 5 -1 6 -1 6","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str6","@d":"M-285 3037l-4 -4 -4 -4 -4 -4 -4 -5 -3 -4 -4 -5 -3 -5 -4 -4 -4 -4 -5 -3 -5 -3 -7 -3","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str6","@d":"M-654 3268l-6 0 -6 0 -6 1 -6 0 -6 1 -6 1 -5 3 -5 3 -4 3 -4 5 -4 4 -4 5 -3 5 -2 5","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str6","@d":"M-160 2973l-6 0 -6 0 -6 -1 -6 -1 -5 -2 -6 -1 -6 -1 -5 2 -6 2 -5 2 -6 1 -6 2 -5 1 -6 1 -6 1 -6 1 -5 1 -6 1","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str6","@d":"M-358 3029l1 6 3 5 3 5 3 5 2 5 2 6 1 5 -2 6 -3 5 -2 5 -3 6","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str6","@d":"M-867 4683l-3 5 -3 5 -4 5 -3 5 -4 4 -3 5 -3 5 -4 4 -3 5 -4 5 -3 4 -4 5 -3 5 -4 4 -4 5 -4 4 -4 4 -3 5 -3 5 -3 5 -3 5 -3 5 -3 5 -2 5 -3 6 -3 5","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str6","@d":"M-663 4540l-3 5 -3 5 -3 5 -3 5 -4 5 -4 4 -5 3 -5 3 -5 3 -5 3 -5 3 -4 4 -5 3 -5 3 -5 4 -5 3","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str6","@d":"M1652 1411l-4 4 -5 3 -4 4 -5 3 -5 3 -5 3 -5 4 -4 4 -3 5 -4 4 -4 4 -5 4 -5 3 -5 3 -5 2 -8 2","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str6","@d":"M-2080 1229l0 6 0 5 -1 6 -1 6 -2 5 -3 6 -3 5 -3 4 -4 5 -3 5 -2 5 -3 6 -2 5 -2 6 -1 5 -1 6 -1 6 -1 5 0 6 -1 6 0 6 0 6","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str6","@d":"M-971 1874l3 5 3 5 4 5 4 4 5 3 5 3 5 2 6 2 5 1 6 2 6 1 6 1 6 1 5 1 6 0 6 0 6 -1 6 0 6 1","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str6","@d":"M-3798 1862l5 -3 5 -3 5 -3 5 -3 4 -4 4 -4 4 -4 4 -4 5 -4 4 -4 5 -4 4 -3 5 -3 5 -4 5 -3 5 -3 4 -4","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str6","@d":"M-3066 1874l2 5 4 6 2 5 3 5 2 5 2 6 1 6 0 5 0 6 0 6 1 6 1 6 1 6 2 5 2 5 3 5 4 5 4 4","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str6","@d":"M-2970 1415l-5 3 -5 3 -5 3 -6 2 -5 2 -6 1 -6 0 -6 1 -5 -1 -6 0 -6 -1 -6 -1 -6 0 -5 0 -6 1 -6 2 -5 2 -5 3 -5 3 -5 3 -4 4 -3 5 -3 10","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil7 str7","@d":"M775 1260l-1 -6 0 -6","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str7","@d":"M688 1122l4 -4","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str7","@d":"M3038 5846l0 6 1 6 0 6 1 8","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str7","@d":"M2513 6287l-2 -5 -3 -6 -2 -5 -3 -5 -2 -5","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str7","@d":"M-3528 2976l-3 5 -3 5 -2 5 -2 6 -3 5 -4 4 -5 6","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str7","@d":"M-3458 2917l-5 3 -5 3 -5 2 -6 3 -5 2 -5 2 -9 3","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str7","@d":"M-2769 3810l-1 6 -1 5 -4 7","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str7","@d":"M-2554 2833l5 -1 6 -1 6 -2 4 -3 4 -5 2 -5 2 -7","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str7","@d":"M-276 3045l-5 -4 -4 -4","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str7","@d":"M-637 3268l-6 0 -6 0 -5 0","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str7","@d":"M-263 2982l-6 2 -5 1 -6 1 -8 2","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str7","@d":"M-358 3017l-1 6 1 6","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str7","@d":"M-953 4808l-2 5 -2 6 -1 5 -2 6 -1 6 -1 5 -1 10","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str7","@d":"M-732 4601l-4 3 -5 4 -5 3 -5 3 -4 4 -5 3 -8 6","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str7","@d":"M1680 1389l-5 3 -4 4 -5 3 -5 4 -4 4 -5 4","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str7","@d":"M-2084 1171l-1 6 -1 6 0 5 0 6 0 6 1 6 1 6 1 5 2 6 1 6","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str7","@d":"M-963 1840l-2 6 -2 5 -2 6 -2 5 0 6 0 6","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str7","@d":"M-3827 1868l6 0 6 -1 6 -1 5 -2 6 -2","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str7","@d":"M-3061 1834l-1 6 -2 6 -1 6 -1 5 -1 6 0 6 1 5","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str7","@d":"M-2935 1394l-5 3 -6 2 -5 3 -5 3 -5 3 -5 3 -4 4","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@id":"rivers_lakes","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil7 str8","@d":"M-3511 537l35 -6 9 37 12 6 19 -31 45 2 -4 15 51 19 39 63 33 24 103 11 -4 48","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str8","@d":"M-3173 725l20 -27 -4 -27 40 -8 80 20 23 -9 14 14 48 -14 70 17 89 -4 56 -19 66 20 45 -21 32 10 30 -34 38 -13 70 54 6 21 150 -4 69 21 34 36 47 -8 30 17 290 54","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str8","@d":"M-374 834l16 -17 43 -4 42 -41 35 -69 42 -81 -2 -73 33 -182","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str8","@d":"M-1830 821l157 3 222 -74 18 18 -31 18 2 16 13 4 39 -38 81 -31 77 36 1 13 -16 1 18 23 51 -6 4 12 50 3 40 32","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str8","@d":"M-1104 851l27 -9 39 21 -3 -30 46 -26 2 -17 75 3 21 -19 34 33 102 23 49 37","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str8","@d":"M-712 867l50 18 63 -12 39 16 127 -40 48 -38 11 23","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str8","@d":"M2316 1366l-27 -35 2 -24 -51 -23 -16 -218 -5 -2 -9 44 -21 -2 -13 -22 20 -44 20 -9 0 -14 -18 -15 2 -8 13 1 17 -67 -16 -10 1 -6 15 2 26 -57 80 -92 61 -29 42 7 72 -90 191 -142 47 2 7 40 32 20 39 0 5 -7 -15 -12 21 -15 16 7 7 24 35 -4 60 -8 42 2 35 22 36 13 17 2 35 5 0 -2 2 -22 25 -1 23 23 18 20 41 4 35 -7 33 3 19 -19 -18 -10 12 -10 53 2 25 -5 16 -6","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str8","@d":"M-4107 1294l-22 11 -37 -18 -4 26 -7 3 -6 -13 -16 3 -9 34 -48 35 -10 -5 1 -29 -19 -1 -3 -17 33 -73 37 -26 1 -2 -14 -23 -41 -8 -15 36 -28 -45 21 -20 -20 -30 6 -33 -3 -4 -22 -11 0 8 -24 -12 -17 25 -18 -26 20 -29 -8 -51 19 -37 49 -15 -1 -16 -19 10 -3 -26 41 -27 39 13 28 -32 20 2 7 -14 -10 -26 74 -34 68 38 58 -19 33 8 61 -46 29 19 13 -5 1 -21 17 -11 31 32 29 -6 5 -32 -25 0 -47 -33 8 -43 18 -7 -5 -10 16 -13 17 -1 35 -43 14 8 28 -27 22 5 6 -44 39 1 47 -39 21 2 1 33 -5 7 9 10 13 2 7 -22 67 -39 11 7 -18 29","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str8","@d":"M-4136 1806l-4 2 -71 39 -2 -158 25 -15 7 4 4 -9 -5 -14 42 -46 86 -43 6 -41 -9 -5 -29 48 -70 14 1 -52 20 -5 53 -62 -8 -9 -40 29 -42 0 -18 -48 -25 -6 3 -9 26 -18 12 13 -5 9 11 10 12 -1 -4 -20 13 -6 -12 -51 34 -17 18 -45","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str8","@d":"M2316 1366l-1 55 19 13 39 -5 19 20 -10 41 -38 22 -27 -19 -23 37 12 63 31 12 20 31 -8 34 22 39 -10 50 -55 39 -21 45 -55 52 -59 25 -24 30","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str8","@d":"M2147 1950l-274 164 -68 128 -261 87","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str8","@d":"M1544 2329l-229 77 -24 40 -29 -12 -79 32 -139 177 24 26 32 -4 58 37 -3 2 -65 48 -50 64 -33 1 -5 -14 43 -12 -5 -28 -45 15 -41 70","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str8","@d":"M3085 3222l-165 -75 -83 15 -8 -7 -1 -47 -24 -15 21 -31 123 -10 17 -10 -2 -11 2 0 12 24 17 -7 0 0 1 -2 1 -6 14 0 25 42 37 4 11 53 24 24 0 4 -18 -4 -2 6 18 21 -20 32","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str8","@d":"M954 2848l-84 172 -88 101 -19 61 -56 40 -19 80 -58 69 -42 83","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str8","@d":"M2511 3605l2 -3 27 -37 0 0 9 -12 12 -67 53 -61 -6 -33 22 -8 15 -60 -10 -22 -61 -24 -53 46 -71 -33 -8 -35 34 -8 6 -28 -8 -4 -42 21 -15 -30 62 -41 0 -5 -18 0 -57 34 -67 9 -53 45 -36 9 -106 115 -113 80 -9 27 14 30 52 -1 28 44 7 1 11 -47 72 -31 46 37 -13 26 33 70 30 11 76 -12 53 59 11 3 63 -53 0 0 8 -12","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str8","@d":"M1501 4056l-14 -26 -6 -3 -58 2 -8 -4 -7 -52 3 -8 40 -9 4 -9 -6 -35 35 -31 94 -41 43 17 -5 20 14 18 1 10 -42 36 -20 42 -43 21 -3 45 -22 7","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str8","@d":"M588 3454l-9 46 -61 111 -6 57 0 8 24 81 50 86 -9 24 -3 7 37 82 90 103","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str8","@d":"M1520 4191l-7 -55 24 -29 6 -1 35 47 22 9 20 -11 4 1 4 7 -2 8 -26 12 -33 -18 -14 0 -33 30","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str8","@d":"M701 4059l131 50 -2 18 27 33 -68 49 -14 31 -61 12 -35 68 -32 -6 -115 65 -25 29 -8 51 -23 -5 -27 17 -1 94 -65 33 -3 36 -6 90 -25 16 -35 91","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str8","@d":"M314 4831l6 29 -5 8 -12 -7 -13 9 -29 59 33 41 40 13 6 -4 -3 -17 4 -1 19 26 -19 22 -114 40 -38 -25 -49 8 -25 17 3 10 -10 2 -52 -24 -23 16 -41 -1 -72 55 -15 48 -25 -1 -60 34","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str8","@d":"M-3554 5258l6 48 -14 10 -20 -4 -59 20 -127 87 -111 4 -112 -66 -63 12 -50 -26 -58 8 -29 -15 -1 -18 -5 -1 -5 11 -45 -17 -31 38 -95 9 -70 45 -24 -19 52 -97 -6 -29 38 -52 -7 -38 55 -103 -11 -107 20 -69 11 -7 1 -7 -22 -11 12 -129 -46 -30 36 -57 36 -123 -11 -125 -31 -50 4 -3 19 20 5 -1 1 -11 51 17 6 -6 -17 -16 20 -38 -3 -11 -11 -6 -9 1 -11 37 -65 -35 -109 56 -57 -2 -18 10 -6 -5 22 -76 -34 -83 7 -13 42 -13 13 1 12 23 -7 4 3 3 23 2 9 13 3 -3 -10 -29 22 -8 15 11 6 0 2 -15 16 -5 -1 -3 -36 2 -3 -16 70 -33 3 -12 -28 -53 -2 -47 -1 0 -11 -3 -36 51 -30 85 -21 11 -100 18 -79 -24 -6 -14 5 -18 -13 -29 55 -120 2 -90 53 -115 1 -44 -13 -24 7 -27 73 -35 96 -116 20 -102 121 -288 1 -3 -27 -41 39 -82 58 -214 10 -26 35 -3 18 -49 17 -3 0 -5 -24 -9 -1 -18 5 -11 21 -19 0 -8 -9 -10 -8 2 -21 78 -24 34 -3 -2 66 -249 -7 -86 -5 -8 -20 -32 -9 -104 -25 -62 10 -42 -23 -155 -22 -47 10 -82 72 -61","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str8","@d":"M-2870 5540l-20 -14 -30 8","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str8","@d":"M-2920 5534l-17 51 -11 7 -2 0 -18 -9 -23 -58 -59 -69 -215 -140 10 -27 -7 -5 -30 18 6 14 -9 5 -82 -32 -113 12 -25 14 -11 -5 -20 -37 -8 -15","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str8","@d":"M-1046 5663l-120 7 -22 23 -43 12 -90 -40 -73 16 -33 -10","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str8","@d":"M-180 5188l-76 98 -15 -8 -2 3 11 9 -65 219 -56 39 1 36 -35 21 -3 28 -34 31 -38 13 -57 -74 -45 -15 -36 22 -34 -13 -45 12 -43 79 -49 23 -35 -1 -22 -18 -28 7 -38 -39 -122 3","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str8","@d":"M-1427 5671l-31 -11 -77 21 -68 -18 -34 25 -154 -4 -65 91 -52 19 -22 43 -56 17 -128 -4 -133 55 -43 73","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str8","@d":"M-2290 5978l-42 60 -13 55","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str8","@d":"M-2345 6093l-6 24 -1 0 0 -24","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str8","@d":"M-2352 6093l-13 -15 -32 -2 -5 3 1 75 -90 44 -19 -3 -41 -37 -70 -14 -55 -69 -16 -7 -57 -3 -18 -12 -35 -65 -27 -14 -91 -171 16 -2 27 49 8 2 19 -27 -3 -6 -17 4 -7 -13 3 -38 -40 -31 -43 -2 -32 -72 10 -25 53 -29 14 -61 12 -13 30 1","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str8","@d":"M-2355 6320l30 -32 -3 -11 -56 -12","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str8","@d":"M-906 6736l-20 -40","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str8","@d":"M-926 6696l-13 -33 10 -41 -16 -7 -53 111 -33 0 -36 38 -82 33 -142 -19 -71 -49 -38 11 -14 39 -30 14 -49 -12 -18 -31 -36 19 -34 -5 -62 32 -66 5 -45 28 -219 -43 -217 -148 -66 -97 -43 -22 -16 -80 -26 -14 -14 -105","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str8","@d":"M-489 6865l-67 -25 -51 -21 -53 41 -98 -3 -56 -25 -68 -67 19 36 55 45 -19 6 -69 -33 -10 -83","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str8","@d":"M3405 5323l-36 -9 -278 41 -37 -17 -87 30 -49 53 -90 45 -100 -1 -51 -19 -9 43 -41 15 -29 -5 -41 -40 -69 13 -56 83 -125 82 -99 5 -11 -20 -32 -7 -185 66 -91 0 -222 49 -75 -11 -50 29 -49 0 -69 24 -66 29 -44 55 -66 36 -64 10 -106 80 -68 20 -23 45 -49 22 -48 47 -3 10 -41 118 -83 71 -114 -23 -1 -5 -8 -28 -40 -23 -66 18 -23 79 -30 8 -30 39 -38 0 -16 -20 -63 -16 -26 38 -38 -2 -58 34 -71 78 -20 2 -41 128 -27 38 -43 32 -53 2 -36 23 -140 119 -24 -3 -88 40 -54 3 -64 -19 -39 9 -1 -1","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str8","@d":"M-2384 6265l-45 4 -69 61 -61 -7 -48 35 -70 -13 -25 11 -62 211 -168 436 -144 284","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str8","@d":"M2383 3779l-21 -19 2 -4 22 -3 4 5 -7 21","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@id":"coastline","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil7 str9","@d":"M-5373 7287l0 -6920 8778 0 0 6920 -8778 0","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str10","@d":"M-5472 7385l0 -7117 8975 0 0 7117 -8975 0","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"text":[{"$":"10","@x":"-4756","@y":"344","@class":"fil8 fnt0","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"10","@x":"-5234","@y":"7357","@class":"fil8 fnt0","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"8","@x":"-3682","@y":"344","@class":"fil8 fnt0","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"8","@x":"-3999","@y":"7357","@class":"fil8 fnt0","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"6","@x":"-2627","@y":"344","@class":"fil8 fnt0","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"6","@x":"-2784","@y":"7357","@class":"fil8 fnt0","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"4","@x":"-1581","@y":"344","@class":"fil8 fnt0","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"4","@x":"-1580","@y":"7357","@class":"fil8 fnt0","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"2","@x":"1592","@y":"344","@class":"fil8 fnt0","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"2","@x":"2060","@y":"7357","@class":"fil8 fnt0","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"0","@x":"534","@y":"344","@class":"fil8 fnt0","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"0","@x":"841","@y":"7357","@class":"fil8 fnt0","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"2","@x":"-522","@y":"344","@class":"fil8 fnt0","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"2","@x":"-365","@y":"7357","@class":"fil8 fnt0","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"4","@x":"2648","@y":"344","@class":"fil8 fnt0","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"4","@x":"3274","@y":"7357","@class":"fil8 fnt0","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"36","@x":"3412","@y":"5999","@class":"fil8 fnt0","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"36","@x":"-5457","@y":"6096","@class":"fil8 fnt0","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"38","@x":"3412","@y":"4539","@class":"fil8 fnt0","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"38","@x":"-5457","@y":"4636","@class":"fil8 fnt0","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"40","@x":"3414","@y":"3065","@class":"fil8 fnt0","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"40","@x":"-5457","@y":"3176","@class":"fil8 fnt0","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"42","@x":"3415","@y":"1608","@class":"fil8 fnt0","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"42","@x":"-5460","@y":"1720","@class":"fil8 fnt0","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"switch":[{"text":[{"$":"westl. v. Greenwich","@x":"-146","@y":"344","@class":"fil8 fnt0","@systemLanguage":"de","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"west of Greenwich","@x":"-146","@y":"344","@class":"fil8 fnt0","@systemLanguage":"en","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"text":[{"$":"westl. v. Greenwich","@x":"161","@y":"7357","@class":"fil8 fnt0","@systemLanguage":"de","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"west of Greenwich","@x":"161","@y":"7357","@class":"fil8 fnt0","@systemLanguage":"en","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"text":[{"$":"\u00f6stl. v. Greenwich","@x":"664","@y":"344","@class":"fil8 fnt0","@systemLanguage":"de","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"east of Greenwich","@x":"664","@y":"344","@class":"fil8 fnt0","@systemLanguage":"en","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"text":[{"$":"\u00f6stl. v. Greenwich","@x":"950","@y":"7357","@class":"fil8 fnt0","@systemLanguage":"de","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"east of Greenwich","@x":"950","@y":"7357","@class":"fil8 fnt0","@systemLanguage":"en","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"text":[{"$":"Modifizierte Kegelprojektion nach Lambert","@x":"3500","@y":"7501","@class":"fil8 fnt0","@style":"text-anchor:end;","@systemLanguage":"de","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"Modified conic projection after Lambert","@x":"3500","@y":"7501","@class":"fil8 fnt0","@style":"text-anchor:end;","@systemLanguage":"en","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"text":[{"$":"Ber\u00fchrungsbreitenkreise: 38\u00b0 und 42\u00b0 n\u00f6rdl. Breite, (Kanarische Inseln: 28\u00b0 n\u00f6rdl. Breite)","@x":"3500","@y":"7585","@class":"fil8 fnt0","@style":"text-anchor:end;","@systemLanguage":"de","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"Touching latitudes: 38\u00b0 and 42\u00b0 north latitude (Canary Islands: 28\u00b0 north latitude)","@x":"3500","@y":"7585","@class":"fil8 fnt0","@style":"text-anchor:end;","@systemLanguage":"en","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"text":[{"$":"Zentralmeridian: 4\u00b0 westl. L\u00e4nge, (Kanarische Inseln: 16\u00b0 westl. L\u00e4nge)","@x":"3500","@y":"7669","@class":"fil8 fnt0","@style":"text-anchor:end;","@systemLanguage":"de","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"Central meridian: 4\u00b0 west longitude, (Canary Islands: 16\u00b0 west longitude)","@x":"3500","@y":"7669","@class":"fil8 fnt0","@style":"text-anchor:end;","@systemLanguage":"en","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@id":"gridline_lettering","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"g":[{"path":[{"@class":"fil9 str11","@d":"M-1010 3230l0 -663 -663 0 0 663 663 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil10 str11","@d":"M-1150 3230l0 -523 -523 0 0 523 523 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil11 str11","@d":"M1893 2362l0 -644 -647 0 0 644 647 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil10 str11","@d":"M1639 2362l0 -393 -393 0 0 393 393 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil10 str11","@d":"M-791 977l0 -334 -334 0 0 334 334 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil10 str11","@d":"M-919 977l0 -210 -206 0 0 210 206 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil10 str11","@d":"M-387 1045l0 -264 -264 0 0 264 264 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil10 str11","@d":"M-491 1045l0 -164 -160 0 0 164 160 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil11 str11","@d":"M450 4025l0 -440 -437 0 0 440 437 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil12 str11","@d":"M290 4025l0 -274 -277 0 0 274 277 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str11","@d":"M0 3748l0 0","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil11 str11","@d":"M-2287 5402l0 -384 -383 0 0 384 383 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil12 str11","@d":"M-2407 5402l0 -260 -263 0 0 260 263 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil10 str11","@d":"M-2519 1022l0 -327 -327 0 0 327 327 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil12 str11","@d":"M-2682 1022l0 -164 -164 0 0 164 164 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil10 str11","@d":"M-1537 1059l0 -237 -240 0 0 237 240 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil12 str11","@d":"M-1610 1059l0 -163 -167 0 0 163 167 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil10 str11","@d":"M-195 1467l0 -237 -237 0 0 237 237 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil12 str11","@d":"M-272 1467l0 -160 -160 0 0 160 160 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil13 str11","@d":"M-2737 2807l0 -207 -207 0 0 207 207 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil12 str11","@d":"M-2788 2807l0 -153 -156 0 0 153 156 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil11 str11","@d":"M-2488 6003l0 -320 -320 0 0 320 320 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil12 str11","@d":"M-2655 6003l0 -153 -153 0 0 153 153 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil13 str11","@d":"M-2811 4508l0 -260 -260 0 0 260 260 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil12 str11","@d":"M-2927 4508l0 -143 -144 0 0 143 144 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil10 str11","@d":"M1303 1629l0 -203 -203 0 0 203 203 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil12 str11","@d":"M1237 1629l0 -137 -137 0 0 137 137 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil13 str11","@d":"M-3308 1106l0 -213 -214 0 0 213 214 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil12 str11","@d":"M-3396 1106l0 -127 -126 0 0 127 126 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil13 str11","@d":"M-2695 2041l0 -174 -173 0 0 174 173 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil12 str11","@d":"M-2752 2041l0 -117 -116 0 0 117 116 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil13 str11","@d":"M-353 3592l0 -170 -170 0 0 170 170 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil12 str11","@d":"M-419 3592l0 -104 -104 0 0 104 104 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil13 str11","@d":"M534 1659l0 -170 -170 0 0 170 170 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil12 str11","@d":"M467 1659l0 -103 -103 0 0 103 103 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil11 str11","@d":"M-1904 2272l0 -233 -233 0 0 233 233 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil14 str11","@d":"M-1937 2272l0 -200 -200 0 0 200 200 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil15 str11","@d":"M2541 3567l0 -273 -277 0 0 273 277 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil14 str11","@d":"M2461 3567l0 -196 -197 0 0 196 197 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil11 str11","@d":"M-14 4970l0 -320 -317 0 0 320 317 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil14 str11","@d":"M-134 4970l0 -194 -197 0 0 194 197 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil10 str11","@d":"M-1860 4895l0 -277 -273 0 0 277 273 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil14 str11","@d":"M-1940 4895l0 -194 -193 0 0 194 193 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil10 str11","@d":"M-1100 5523l0 -283 -284 0 0 283 284 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil14 str11","@d":"M-1200 5523l0 -183 -184 0 0 183 184 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil15 str11","@d":"M599 4608l0 -344 -343 0 0 344 343 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil14 str11","@d":"M439 4608l0 -184 -183 0 0 184 183 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil10 str11","@d":"M-3800 1072l0 -326 -327 0 0 326 327 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil14 str11","@d":"M-3947 1072l0 -180 -180 0 0 180 180 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil10 str11","@d":"M-1245 1681l0 -203 -207 0 0 203 207 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil14 str11","@d":"M-1299 1681l0 -157 -153 0 0 157 153 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil10 str11","@d":"M-663 1315l0 -204 -206 0 0 204 206 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil14 str11","@d":"M-715 1315l0 -156 -154 0 0 156 154 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil11 str11","@d":"M-458 5475l0 -224 -227 0 0 224 227 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil14 str11","@d":"M-532 5475l0 -156 -153 0 0 156 153 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil13 str11","@d":"M-2517 1522l0 -237 -237 0 0 237 237 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil14 str11","@d":"M-2608 1522l0 -146 -146 0 0 146 146 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil11 str11","@d":"M640 3226l0 -223 -223 0 0 223 223 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil14 str11","@d":"M564 3226l0 -143 -147 0 0 143 147 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil10 str11","@d":"M-312 4250l0 -200 -200 0 0 200 200 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil14 str11","@d":"M-369 4250l0 -143 -143 0 0 143 143 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil10 str11","@d":"M-723 1705l0 -183 -184 0 0 183 184 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil14 str11","@d":"M-767 1705l0 -143 -140 0 0 143 140 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil11 str11","@d":"M1148 2597l0 -240 -240 0 0 240 240 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil14 str11","@d":"M1044 2597l0 -137 -136 0 0 137 136 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil10 str11","@d":"M-1200 4922l0 -260 -257 0 0 260 257 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil14 str11","@d":"M-1320 4922l0 -137 -137 0 0 137 137 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil13 str11","@d":"M-1802 1675l0 -163 -164 0 0 163 164 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil14 str11","@d":"M-1842 1675l0 -123 -124 0 0 123 124 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil13 str11","@d":"M-2401 3769l0 -216 -216 0 0 216 216 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil14 str11","@d":"M-2493 3769l0 -120 -124 0 0 120 124 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil11 str11","@d":"M2259 1720l0 -237 -233 0 0 237 233 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil14 str11","@d":"M2146 1720l0 -123 -120 0 0 123 120 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil11 str11","@d":"M-3825 1565l0 -297 -300 0 0 297 300 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil14 str11","@d":"M-4005 1565l0 -120 -120 0 0 120 120 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil10 str11","@d":"M-1662 3525l0 -230 -230 0 0 230 230 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil14 str11","@d":"M-1775 3525l0 -117 -117 0 0 117 117 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil13 str11","@d":"M-1157 4308l0 -230 -230 0 0 230 230 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil14 str11","@d":"M-1274 4308l0 -113 -113 0 0 113 113 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil13 str11","@d":"M-1612 2535l0 -150 -153 0 0 150 153 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil14 str11","@d":"M-1652 2535l0 -113 -113 0 0 113 113 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil16 str11","@d":"M-803 2148l0 -130 -130 0 0 130 130 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil14 str11","@d":"M-837 2148l0 -96 -96 0 0 96 96 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil13 str11","@d":"M234 2837l0 -150 -150 0 0 150 150 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil14 str11","@d":"M177 2837l0 -93 -93 0 0 93 93 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil15 str11","@d":"M-1810 5814l0 -337 -337 0 0 337 337 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil17 str11","@d":"M-1904 5814l0 -243 -243 0 0 243 243 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil11 str11","@d":"M-933 1247l0 -186 -183 0 0 186 183 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil17 str11","@d":"M-946 1247l0 -166 -170 0 0 166 170 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil10 str11","@d":"M-3130 5156l0 -223 -223 0 0 223 223 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil17 str11","@d":"M-3203 5156l0 -147 -150 0 0 147 150 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil10 str11","@d":"M-3291 1785l0 -220 -220 0 0 220 220 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil17 str11","@d":"M-3374 1785l0 -136 -137 0 0 136 137 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil13 str11","@d":"M-1987 2939l0 -160 -160 0 0 160 160 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil17 str11","@d":"M-2041 2939l0 -106 -106 0 0 106 106 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil15 str11","@d":"M25 2378l0 -303 -300 0 0 303 300 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil14 str11","@d":"M12 2378l0 -286 -287 0 0 286 287 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil18 str11","@d":"M-723 2722l0 -150 -154 0 0 150 154 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil9 str11","@d":"M-760 2722l0 -116 -117 0 0 116 117 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@id":"rects_for_legend","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@id":"textPathAtlantic","@style":"visibility:hidden;","@d":"M -4900,5300 C -4950,4300 -4950,1800 -4900,800","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@id":"textPathMiddle","@style":"visibility:hidden;","@d":"M -1900,6500 C -1400,6400 -600,6150 -100,6000","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@id":"textPathMiddleSea","@style":"visibility:hidden;","@d":"M 1200,5500 C 2200,5100 2400,4950 3400,4500","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@id":"textPathBalearic","@style":"visibility:hidden;","@d":"M 1500,3600 C 2000,3200 2100,3150 2600,2900","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@id":"textPathMorocco","@style":"visibility:hidden;","@d":"M -2700,7120 C -2200,7070 -1000,7070 -500,7120","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@id":"textPathPortugal","@style":"visibility:hidden;","@d":"M -3900,4600 C -3850,4000 -3700,2900 -3500,2300","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@id":"textPathFranceText","@style":"visibility:hidden;","@d":"M 50,650 C 500,850 1400,1020 1850,1050","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@id":"textPathEbro","@style":"visibility:hidden;","@d":"M 30,1960 C 50,1970 170,2050 200,2065","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@id":"textPathGuadalquivir","@style":"visibility:hidden;","@d":"M -2860,5500 C -2850,5350 -2800,5200 -2700,5000","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@id":"textPathGuadiana","@style":"visibility:hidden;","@d":"M -3725,4950 C -3710,4800 -3700,4720 -3670,4570","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"switch":[{"text":[{"textPath":{"$":"Atlantischer Ozean","@xlink:href":"#textPathAtlantic","@startOffset":"5%","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@systemLanguage":"de","@class":"fil19 fnt1","@style":"letter-spacing:150px;","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"textPath":{"$":"Atlantic Ocean","@xlink:href":"#textPathAtlantic","@startOffset":"10%","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@systemLanguage":"en","@class":"fil19 fnt1","@style":"letter-spacing:200px;","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"text":[{"textPath":{"$":"Mittel-","@xlink:href":"#textPathMiddle","@startOffset":"25%","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@systemLanguage":"de","@class":"fil19 fnt1","@style":"letter-spacing:70px;","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"textPath":{"$":"Mediter-","@xlink:href":"#textPathMiddle","@startOffset":"5%","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@systemLanguage":"en","@class":"fil19 fnt1","@style":"letter-spacing:130px;","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"text":[{"textPath":{"$":"l\u00e4ndisches Meer","@xlink:href":"#textPathMiddleSea","@startOffset":"0%","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@systemLanguage":"de","@class":"fil19 fnt1","@style":"letter-spacing:70px;","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"textPath":{"$":"ranean Sea","@xlink:href":"#textPathMiddleSea","@startOffset":"5%","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@systemLanguage":"en","@class":"fil19 fnt1","@style":"letter-spacing:130px;","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"text":[{"textPath":{"$":"Balearen","@xlink:href":"#textPathBalearic","@startOffset":"5%","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@systemLanguage":"de","@class":"fil8 fnt2","@style":"letter-spacing:85px;","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"textPath":{"$":"Balearics","@xlink:href":"#textPathBalearic","@startOffset":"5%","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@systemLanguage":"en","@class":"fil8 fnt2","@style":"letter-spacing:80px;","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"text":[{"textPath":{"$":"Marokko","@xlink:href":"#textPathMorocco","@startOffset":"5%","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@systemLanguage":"de","@class":"fil8 fnt4","@style":"letter-spacing:220px;","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"textPath":{"$":"Morocco","@xlink:href":"#textPathMorocco","@startOffset":"5%","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@systemLanguage":"en","@class":"fil8 fnt4","@style":"letter-spacing:220px;","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"text":[{"textPath":{"$":"Frankreich","@xlink:href":"#textPathFranceText","@startOffset":"10%","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@systemLanguage":"de","@class":"fil8 fnt4","@style":"letter-spacing:70px;","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"textPath":{"$":"France","@xlink:href":"#textPathFranceText","@startOffset":"5%","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@systemLanguage":"en","@class":"fil8 fnt4","@style":"letter-spacing:190px;","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"text":[{"$":"Sevilla","@x":"-2247","@y":"5318","@class":"fil8 fnt5","@systemLanguage":"de","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"Seville","@x":"-2247","@y":"5318","@class":"fil8 fnt5","@systemLanguage":"en","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"text":[{"$":"Lissabon","@x":"-4885","@y":"4076","@class":"fil8 fnt5","@systemLanguage":"de","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"Lisbon","@x":"-4806","@y":"4076","@class":"fil8 fnt5","@systemLanguage":"en","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"text":[{"$":"Algier","@x":"2298","@y":"5447","@class":"fil8 fnt5","@systemLanguage":"de","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"Algiers","@x":"2298","@y":"5447","@class":"fil8 fnt5","@systemLanguage":"en","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"text":[{"$":"Mallorca","@x":"2488","@y":"3766","@class":"fil8 fnt3","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"Menorca","@x":"2928","@y":"3006","@class":"fil8 fnt3","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"textPath":{"$":"Portugal","@xlink:href":"#textPathPortugal","@startOffset":"5%","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@class":"fil8 fnt4","@style":"letter-spacing:200px;","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"Barcelona","@x":"1998","@y":"2171","@class":"fil8 fnt5","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"Valencia","@x":"619","@y":"3777","@class":"fil8 fnt5","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"Madrid","@x":"-966","@y":"3255","@class":"fil8 fnt5","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"Bilbao","@x":"-1400","@y":"715","@class":"fil8 fnt5","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"La Coru\u00f1a","@x":"-4377","@y":"663","@class":"fil8 fnt5","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"Marseille","@x":"3035","@y":"484","@class":"fil8 fnt5","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"Montpellier","@x":"2125","@y":"485","@class":"fil8 fnt5","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"Perpignan","@x":"1710","@y":"1200","@class":"fil8 fnt5","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"Porto","@x":"-4225","@y":"3046","@class":"fil8 fnt5","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"textPath":{"$":"Ebro","@xlink:href":"#textPathEbro","@startOffset":"0%","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@class":"fil19 fnt6","@style":"letter-spacing:5px;","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"textPath":{"$":"Guadalquivir","@xlink:href":"#textPathGuadalquivir","@startOffset":"0%","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@class":"fil19 fnt6","@style":"letter-spacing:0px;","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"textPath":{"$":"Guadiana","@xlink:href":"#textPathGuadiana","@startOffset":"0%","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@class":"fil19 fnt6","@style":"letter-spacing:0px;","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"Ibiza","@x":"1598","@y":"4068","@class":"fil8 fnt7","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"ellipse":[{"@class":"fil20 str12","@cx":"-4524","@cy":"4115","@rx":"20","@ry":"20","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil20 str12","@cx":"2539","@cy":"5508","@rx":"20","@ry":"20","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil20 str12","@cx":"-4248","@cy":"3087","@rx":"20","@ry":"20","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil20 str12","@cx":"3344","@cy":"541","@rx":"20","@ry":"20","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil20 str12","@cx":"2602","@cy":"516","@rx":"20","@ry":"20","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil20 str12","@cx":"2139","@cy":"1235","@rx":"20","@ry":"20","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"g":[{"text":{"$":"Tajo","@x":"0","@y":"3748","@class":"fil19 fnt6","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@transform":"matrix(0.999514 -0.0311582 0.0311582 0.999514 -774.816 -1079.23)","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"text":{"$":"Tejo","@x":"0","@y":"3748","@class":"fil19 fnt6","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@transform":"matrix(0.788941 -0.614468 0.614468 0.788941 -6525.95 784.685)","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"text":{"$":"Duero","@x":"0","@y":"3748","@class":"fil19 fnt6","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@transform":"matrix(0.974789 0.22313 -0.22313 0.974789 -642.438 -1622.51)","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@id":"lettering","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"g":{"path":[{"@class":"fil7 str13","@d":"M-5373 1689l93 8 103 7 103 8 103 7 103 8 53 3 50 4 104 6 103 7 103 6 103 6 103 6 104 6 103 5 103 5 104 5 103 5 3 0 100 5 103 4 104 4 103 4 103 3 104 4 103 3 104 3 103 3 103 2 56 2 48 1 103 2 103 2 104 1 103 2 104 1 103 1 103 1 104 0 103 1 104 0 5 0 98 0 103 -1 104 0 103 -1 104 -1 103 -1 103 -1 104 -2 103 -2 104 -2 58 -1 45 -1 103 -3 104 -3 103 -3 103 -3 104 -3 103 -4 104 -4 103 -4 103 -4 103 -5 9 0 95 -4 103 -5 103 -5 104 -6 103 -5 103 -6 103 -6 104 -7 103 -6 103 -7 61 -4 42 -3 103 -7 103 -7 104 -8 103 -8 103 -8 103 -8 103 -8 103 -9 103 -9 103 -9 11 -1 92 -9 103 -9 103 -10 103 -10 103 -10 103 -11 11 -1","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str13","@d":"M-5373 3150l87 7 106 8 106 7 107 8 54 3 52 4 106 7 107 7 106 6 106 6 106 6 107 6 106 6 107 5 106 5 106 5 3 0 104 5 106 4 107 5 106 3 107 4 106 4 106 3 107 3 106 3 107 3 57 1 49 1 107 2 106 2 107 2 106 1 107 2 106 1 107 0 106 1 107 0 106 1 6 0 101 -1 107 0 106 0 107 -1 106 -1 107 -1 106 -2 107 -2 106 -2 107 -2 60 -1 46 -1 107 -3 106 -2 106 -4 107 -3 106 -3 107 -4 106 -4 107 -4 106 -5 107 -4 8 -1 98 -4 106 -5 107 -6 106 -5 106 -6 107 -6 106 -6 106 -7 107 -6 106 -7 63 -5 43 -2 107 -8 106 -7 106 -8 106 -8 107 -9 106 -8 106 -9 106 -9 106 -9 106 -9 12 -1 94 -9 106 -10 106 -10 106 -10 75 -8","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str13","@d":"M-5373 4611l87 6 110 8 109 8 56 3 53 4 110 7 109 7 110 7 109 6 110 6 109 6 109 6 110 6 109 5 110 5 3 0 107 5 109 4 110 5 109 4 110 4 109 3 110 4 109 3 110 3 110 2 59 2 50 1 110 2 109 2 110 2 110 1 109 2 110 1 109 1 110 0 110 1 109 0 6 0 104 0 110 -1 109 0 110 -1 109 -1 110 -1 110 -2 109 -2 110 -2 109 -2 63 -1 47 -1 110 -3 109 -3 110 -3 109 -3 110 -4 110 -4 109 -4 110 -4 109 -5 110 -5 8 0 101 -5 110 -5 109 -5 110 -6 109 -6 110 -6 109 -7 109 -6 110 -7 109 -7 65 -5 45 -3 109 -7 109 -8 110 -8 109 -8 109 -9 110 -9 109 -9 109 -9 109 -9 109 -10 12 -1 98 -9 109 -10 109 -10 41 -4","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str13","@d":"M-5373 6072l94 7 112 8 58 3 55 4 112 7 113 8 112 6 113 7 113 6 112 7 113 6 112 5 113 6 113 5 3 0 109 5 113 4 112 5 113 4 113 4 112 4 113 3 113 4 112 3 113 2 61 2 52 1 113 2 112 2 113 2 113 2 112 1 113 1 113 1 113 1 112 0 113 0 6 0 107 0 113 0 112 -1 113 -1 113 -1 113 -1 112 -2 113 -1 113 -3 112 -2 64 -1 49 -1 113 -3 113 -3 112 -3 113 -4 113 -3 112 -4 113 -5 113 -4 112 -5 113 -5 9 0 103 -5 113 -5 113 -6 112 -6 113 -6 112 -6 113 -7 112 -7 113 -7 112 -7 67 -5 46 -3 112 -7 113 -8 112 -9 113 -8 112 -9 112 -9 113 -9 112 -10 112 -9 113 -10 12 -2 100 -9 112 -10 14 -1","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str13","@d":"M-5189 7287l1 -17 9 -139 9 -138 10 -139 9 -138 9 -139 10 -139 9 -138 9 -138 5 -72 5 -67 9 -138 9 -139 10 -138 9 -138 9 -139 10 -138 9 -138 9 -138 10 -139 9 -138 0 -4 9 -134 10 -138 9 -139 9 -138 10 -138 9 -138 9 -138 10 -139 9 -138 9 -138 5 -75 4 -63 10 -138 9 -138 9 -139 10 -138 9 -138 9 -138 10 -139 9 -138 9 -138 10 -138 0 -8 9 -131 9 -138 10 -139 9 -138 9 -138 10 -139 9 -138 9 -139 10 -138 8 -125","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str13","@d":"M-3976 7287l4 -88 6 -139 6 -138 6 -139 7 -139 6 -139 6 -138 6 -139 4 -71 3 -68 6 -138 6 -139 6 -138 6 -139 7 -138 6 -139 6 -138 6 -139 7 -138 6 -138 0 -4 6 -135 6 -138 6 -138 7 -139 6 -138 6 -139 6 -138 6 -138 7 -139 6 -138 3 -75 3 -63 6 -139 7 -138 6 -138 6 -139 6 -138 6 -139 7 -138 6 -139 6 -138 6 -138 1 -8 5 -131 7 -139 6 -138 6 -139 6 -138 7 -139 6 -139 6 -138 6 -139 7 -139 2 -45","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str13","@d":"M-2765 7287l1 -47 3 -139 3 -139 3 -139 3 -139 3 -138 3 -139 3 -139 2 -71 2 -68 3 -138 3 -139 3 -139 3 -138 3 -139 3 -138 3 -139 3 -138 4 -139 3 -139 0 -3 3 -135 3 -139 3 -138 3 -138 3 -139 3 -138 3 -139 4 -138 3 -139 3 -138 1 -75 2 -64 3 -138 3 -139 3 -138 3 -139 3 -138 4 -139 3 -138 3 -139 3 -138 3 -139 0 -7 3 -132 3 -138 3 -139 3 -138 4 -139 3 -139 3 -139 3 -138 3 -139 3 -139 2 -79 0 -2","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str13","@d":"M-1556 7287l0 -34 0 -139 0 -139 0 -138 0 -139 0 -139 0 -139 0 -139 0 -71 0 -67 0 -139 0 -139 0 -138 0 -139 0 -139 0 -138 0 -139 0 -138 0 -139 0 -139 0 -3 0 -135 0 -139 0 -138 0 -139 0 -138 0 -139 0 -138 0 -139 0 -138 0 -139 0 -74 0 -64 0 -139 0 -138 0 -139 0 -138 0 -139 0 -138 0 -139 0 -138 0 -139 0 -139 0 -7 0 -131 0 -139 0 -139 0 -138 0 -139 0 -139 0 -139 0 -139 0 -138 0 -139 0 -79 0 -14","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str13","@d":"M-346 7287l-1 -47 -3 -139 -4 -139 -3 -139 -3 -139 -3 -138 -3 -139 -3 -139 -2 -71 -1 -68 -3 -138 -3 -139 -4 -139 -3 -138 -3 -139 -3 -138 -3 -139 -3 -138 -3 -139 -3 -139 0 -3 -3 -135 -4 -139 -3 -138 -3 -138 -3 -139 -3 -138 -3 -139 -3 -138 -3 -139 -3 -138 -2 -75 -2 -64 -3 -138 -3 -139 -3 -138 -3 -139 -3 -138 -3 -139 -3 -138 -3 -139 -4 -138 -3 -139 0 -7 -3 -132 -3 -138 -3 -139 -3 -138 -3 -139 -3 -139 -3 -139 -4 -138 -3 -139 -3 -139 -2 -79 0 -2","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str13","@d":"M865 7287l-4 -88 -7 -139 -6 -138 -6 -139 -6 -139 -7 -139 -6 -138 -6 -139 -3 -71 -3 -68 -6 -138 -7 -139 -6 -138 -6 -139 -6 -138 -7 -139 -6 -138 -6 -139 -6 -138 -6 -138 -1 -4 -6 -135 -6 -138 -6 -138 -6 -139 -6 -138 -7 -139 -6 -138 -6 -138 -6 -139 -7 -138 -3 -75 -3 -63 -6 -139 -6 -138 -6 -138 -7 -139 -6 -138 -6 -139 -6 -138 -6 -139 -7 -138 -6 -138 0 -8 -6 -131 -6 -139 -7 -138 -6 -139 -6 -138 -6 -139 -7 -139 -6 -138 -6 -139 -6 -139 -2 -45","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str13","@d":"M2078 7287l-1 -17 -10 -139 -9 -138 -9 -139 -10 -138 -9 -139 -9 -139 -10 -138 -9 -138 -5 -72 -4 -67 -10 -138 -9 -139 -9 -138 -10 -138 -9 -139 -9 -138 -10 -138 -9 -138 -9 -139 -10 -138 0 -4 -9 -134 -9 -138 -10 -139 -9 -138 -9 -138 -10 -138 -9 -138 -9 -139 -10 -138 -9 -138 -5 -75 -4 -63 -9 -138 -10 -138 -9 -139 -9 -138 -10 -138 -9 -138 -9 -139 -10 -138 -9 -138 -9 -138 -1 -8 -9 -131 -9 -138 -9 -139 -10 -138 -9 -138 -9 -139 -10 -138 -9 -139 -9 -138 -9 -125","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str13","@d":"M3295 7287l-10 -112 -13 -138 -12 -139 -13 -138 -12 -139 -13 -138 -12 -138 -12 -138 -13 -139 -6 -71 -6 -67 -13 -138 -12 -138 -13 -138 -12 -138 -13 -138 -12 -138 -12 -138 -13 -138 -12 -138 -13 -138 0 -4 -12 -134 -12 -138 -13 -138 -12 -138 -13 -138 -12 -138 -13 -138 -12 -138 -12 -138 -13 -138 -6 -74 -6 -64 -13 -138 -12 -138 -12 -138 -13 -138 -12 -138 -13 -138 -12 -138 -13 -138 -12 -138 -12 -138 -1 -7 -12 -131 -12 -138 -13 -138 -12 -138 -13 -138 -12 -139 -12 -138 -13 -138 -12 -138 -4 -42","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@id":"gridlines","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil20 str14","@d":"M-12 7218l0 0 0 -1637 3344 0 0 1637 -3344 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str15","@d":"M85 7122l0 -1444 3149 0 0 1444 -3149 0","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@id":"textPathCanary","@style":"visibility:hidden;","@d":"M 700,6300 C 1200,6125 2100,6000 2600,6000","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"image":{"@transform":"matrix(0.930151 0 0 0.929032 86.3544 3637.68)","@x":"0","@y":"2198","@width":"3383","@height":"1550","@xlink:href":"tests\/resources\/images\/canaryRelief.png","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"g":[{"g":[{"path":[{"@class":"fil4","@d":"M3152 5774l-14 0 0 -3 -3 -3 3 -4 4 -6 10 -7 6 0 4 3 0 7 0 3 -7 4 0 3 -3 3z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil4","@d":"M3138 5898l-3 0 -3 -4 0 -3 -4 -3 4 0 3 -4 7 -6 0 -4 0 -3 0 -3 6 -20 4 0 3 0 7 3 6 3 4 4 0 6 0 4 -4 0 -3 3 -7 10 0 3 -3 7 -7 0 -6 3 -4 4z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil4","@d":"M2988 6178l-6 0 0 -4 -4 -3 0 -3 -6 0 -7 0 -3 -4 -4 0 -10 0 -13 0 -3 4 -4 0 -3 -7 0 -7 -3 -3 0 -3 0 -4 0 -6 3 0 7 -4 3 -6 7 -4 3 -3 0 -3 3 -4 0 -6 0 -10 4 -17 -4 -13 0 -4 4 -6 0 -4 6 -10 0 -3 7 -7 3 -3 4 -10 3 0 7 -3 6 -7 10 -10 17 0 7 -3 6 3 4 -3 3 -4 7 -3 3 -7 7 -3 3 -3 7 -10 6 0 4 0 3 0 3 0 7 -4 3 -3 7 -3 3 0 4 -4 3 4 3 0 4 3 3 3 3 4 4 0 3 0 3 0 7 -4 3 -3 4 -7 0 -3 3 -3 0 -4 0 -6 3 -4 0 -3 4 -7 0 -3 0 -3 3 -7 3 -13 14 -17 3 -3 3 3 7 3 7 4 10 10 3 6 3 4 -3 6 0 14 0 3 0 7 -3 3 -7 3 -10 7 -3 7 0 3 0 7 3 6 0 7 3 3 0 7 0 3 0 4 -3 6 -3 7 -4 33 0 4 -6 0 0 10 -4 3 -6 3 0 4 -4 0 -3 3 -3 3 -7 4 -3 0 -7 3 0 3 0 7 -3 0 -4 0 -10 0 -6 -3 -4 3 -6 3 0 4 -4 0 -6 10 0 3 -17 3 -13 7 -4 0 -10 -3 -6 0 -7 0 -10 6 -3 0 -4 4 -6 3 -4 10 -3 13 -3 0 -4 7 -3 3 -7 4 0 10z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil4","@d":"M2638 6761l-10 -3 -13 0 -3 0 -10 0 -7 -7 -7 -3 -3 0 -10 -4 -10 0 -20 0 -7 0 -3 4 -3 0 -4 0 -3 0 -3 -4 6 -6 4 -7 0 -7 0 -3 6 0 4 0 3 3 10 0 10 4 17 -4 3 -3 10 -3 7 -4 3 -3 17 -7 20 -10 6 -3 4 -3 6 -10 4 0 6 -7 7 -3 3 -4 4 0 6 -6 10 -14 4 -6 10 -10 3 -4 3 -10 0 -10 -3 -20 3 -6 4 -10 3 -10 0 -4 7 -6 6 -7 4 -7 3 -6 0 -4 3 -13 0 -7 4 -3 0 -3 0 -4 0 -10 0 -3 6 -7 4 -3 3 -3 3 -7 4 -7 10 -10 3 -6 3 -10 4 -10 0 -4 3 -3 3 -3 4 -7 0 -7 3 -3 3 -7 4 -3 0 -3 6 -7 7 -10 3 -3 -3 -17 3 -3 0 -7 4 -3 3 -17 3 -3 0 -10 0 -14 0 -10 4 -3 0 -3 10 -4 3 0 3 -3 4 -3 6 0 7 -7 3 0 7 -3 3 -4 7 -3 3 0 7 0 3 0 7 -3 7 3 3 0 3 3 4 7 0 3 10 4 6 10 4 3 0 3 3 14 -3 13 3 17 0 6 3 7 0 3 0 14 4 10 0 10 -4 3 0 7 0 20 -3 3 -3 13 -4 7 -3 7 -3 3 -4 7 0 6 0 4 4 10 0 3 -4 7 0 6 4 7 3 7 3 3 0 3 -6 7 0 3 -4 7 -6 3 -4 17 -3 7 0 3 -3 10 0 3 -7 7 -3 3 0 7 0 3 0 10 -7 4 0 3 -3 10 -4 7 -3 6 -10 7 -3 3 -4 0 -3 -3 -3 0 -4 0 -10 7 -3 3 -13 0 -7 3 -7 0 -10 0 -13 4 -7 3 -13 3 -10 4 -7 3 -10 7 -10 6 -10 4 -16 0 -7 6 -7 10 -3 4 -10 16 -3 4 -7 6 -3 4 -4 3 -10 10 -3 7 -3 3 -4 0 -10 10 -3 3 -3 4 -4 3z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil4","@d":"M1835 6994l-10 -3 -7 -7 -3 0 -10 -3 -27 0 -6 0 0 -3 -14 -14 -10 -3 -3 -3 0 -4 -13 -10 -4 -3 -3 -7 -7 -6 -10 -4 -3 -3 -3 0 0 -3 -7 -20 -7 -4 0 -6 -3 -10 -10 -17 0 -3 3 -10 0 -4 0 -6 0 -4 0 -3 0 -3 0 -14 0 -13 4 -7 3 0 3 -3 10 0 4 0 3 0 3 -7 7 -6 3 -7 7 0 3 0 4 -3 3 -4 3 -3 0 -3 0 -4 4 -3 3 0 3 -3 0 -4 4 -3 0 -7 -4 -6 4 -7 3 -3 -3 -4 3 -6 0 -7 3 -3 -3 -7 -3 -7 0 -6 13 3 10 0 3 0 10 0 4 0 3 7 10 3 7 0 3 3 3 0 17 0 10 0 7 0 3 4 3 -4 7 -3 3 0 4 3 6 4 4 -4 3 4 10 6 7 0 3 4 3 -4 7 -3 7 0 3 0 3 -3 0 -4 0 -3 0 -3 -6 -7 3 -7 10 0 3 -6 4 3 6 3 4 4 -4 3 -10 13 0 4 -3 6 0 7 3 3 7 7 0 3 0 7 0 7 -3 3 0 3 0 7 0 3 0 4 3 10 0 3 7 3 3 7 7 0 0 3 6 4 4 3 0 3 -4 7 -3 10 -3 3 0 7 3 3 3 7 0 3 0 7 7 3 0 7 -10 0 -3 3 0 4 -4 6 -3 7 3 7 0 3 4 3 6 7 4 3 -4 4 0 3 -10 7 -6 3 0 3 -4 4 -3 0 -3 6 -4 7 -3 3 -3 10 -10 7 -4 0 -16 7 -7 0 -7 3 -3 3 -3 0 -7 0 -7 4 -3 0 -3 3 -14 7 0 3 -3 3 -3 7 -4 3 -3 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil4","@d":"M415 6408l0 6 0 7 -3 3 -4 4 -3 3 -7 3 -3 4 0 6 -7 7 -3 10 -3 0 0 -3 -7 -4 -7 -6 -3 -4 0 -3 0 -7 0 -3 0 -3 -3 -4 -4 -3 0 -17 0 -6 0 -4 0 -3 0 -3 -3 -4 -13 -13 -7 -10 0 -3 0 -14 -3 -6 0 -7 -4 -3 -6 -7 0 -3 -4 -7 -6 -3 0 -7 0 -3 0 -4 -4 -6 0 -4 0 -3 -3 -7 -3 -3 -4 -3 -3 -10 -7 -4 -3 0 -7 -10 0 -3 0 -7 4 -6 0 -4 10 -10 3 -3 0 -7 0 -3 3 0 10 -3 7 -7 13 -7 7 -6 3 -4 4 -3 3 3 7 4 3 3 3 0 4 0 6 0 7 3 7 0 13 -3 7 -3 3 0 7 0 3 0 7 3 10 10 3 7 0 3 0 3 0 4 0 3 3 3 7 10 0 4 0 6 3 4 10 6 4 4 0 6 -4 7 0 3 -10 7 -6 13 -4 7 -3 10 0 10 0 3 3 7 4 13 3 10 0 7 -3 10 -4 3 0 4 -3 3 0 3 -3 7 -14 20 0 3 -3 4z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil4","@d":"M1128 6811l-3 0 -3 -3 -7 -4 0 -3 -3 -3 3 -14 0 -6 -3 -4 -4 -3 -3 -3 -3 0 -4 -4 -3 -3 0 -7 0 -6 -3 0 -7 -10 -10 -14 -7 -6 -3 -7 -7 -3 0 -4 -3 -3 -3 -7 -4 -16 -3 -7 -7 -3 -3 -4 -3 0 0 -3 -7 -7 0 -3 -3 -7 0 -13 -4 -17 0 -3 -3 -7 -10 -16 0 -4 -7 -10 -3 -3 -7 -3 -3 -4 -3 -6 -4 -4 -3 -6 3 -4 0 -3 10 0 7 -3 3 0 4 -4 6 -3 4 0 6 -3 10 -4 4 0 3 4 3 0 10 6 20 0 10 0 4 0 13 -6 10 0 10 3 10 -10 3 -3 4 0 3 -4 7 0 13 0 3 4 20 0 4 -4 16 0 4 -3 3 -3 3 -4 7 -6 7 -4 3 0 10 4 3 0 4 0 3 -4 3 -6 7 -4 7 -3 0 -3 3 -4 3 -6 4 -4 0 -3 6 -3 4 -4 3 0 3 -3 4 -3 3 -7 3 -13 4 -7 3 -3 7 0 6 -7 0 -3 10 3 10 -3 7 -7 7 -3 3 0 0 -4 3 -6 7 0 7 3 3 0 7 -3 3 -4 7 4 3 0 7 0 3 0 13 6 7 0 3 0 7 -3 10 0 3 0 7 -7 7 0 3 -6 3 -4 10 4 4 0 0 3 3 10 3 3 0 4 0 13 0 3 -3 7 0 3 -3 4 -7 3 -10 3 -3 0 -14 7 -13 7 -3 3 -4 0 -6 3 -7 4 -3 6 -10 10 -4 4 -3 3 -7 7 -6 10 -7 10 -7 6 -10 4 -3 3 -7 3 -6 7 -4 3 -3 4 0 13 0 3 0 14 3 6 0 4 -3 6 -3 4 -4 3 0 3 -3 4 0 6 -7 10 0 4 -10 20 -3 6 -3 10 -4 10 0 4 -6 16 0 10 0 4 0 3 -17 10 -7 3 0 4 -6 13 -7 10 -7 7 -3 3 -3 10 -4 3 -3 0 -7 10 -6 4 0 3 -4 3 -10 0 -10 0 -6 0 -20 7 -7 7 -3 3 -4 0 -10 0 -6 0 -4 3 -3 0 -7 7z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil4","@d":"M768 6788l-10 0 -10 -7 -13 -17 -7 0 -3 -3 -7 -7 -3 -10 -7 -6 -3 -4 0 -6 -3 -17 3 -3 0 -7 0 -10 7 -10 0 -3 0 -4 0 -3 3 -3 7 -4 3 -3 10 -7 17 -10 3 0 3 4 4 0 6 6 4 0 3 0 17 7 3 0 10 7 10 10 3 0 10 6 0 4 10 0 7 3 7 7 0 3 6 10 0 3 0 10 0 10 -3 4 0 3 -3 0 -7 10 -7 3 -3 7 -3 3 -4 0 -6 7 -7 7 -3 0 -7 3 -3 3 -4 0 -3 0 -13 -3 -4 3 -6 4 -4 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil4","@d":"M278 7051l-10 0 -3 0 -7 -7 -3 -3 -3 -3 -10 -20 -4 0 -3 -4 -3 0 -10 -3 -4 3 -6 -3 -10 0 -10 -3 -7 -4 -13 0 -4 -3 -3 0 -3 -10 -4 -10 0 -3 0 -4 0 -6 7 -7 10 -7 7 -3 3 3 7 7 3 0 7 0 6 0 7 0 7 3 3 0 7 0 6 -3 4 0 3 -3 7 -10 6 -7 4 0 10 -7 0 -3 -4 -3 -3 -4 3 -3 4 -3 3 0 10 0 3 0 4 -7 3 0 7 0 3 -3 3 -4 4 -3 3 -3 13 3 7 3 3 10 4 4 0 3 3 3 0 4 0 6 -3 4 -10 10 -4 3 -3 3 -3 7 0 3 0 4 -4 6 0 4 -3 16 -7 4 -3 3 -7 7 0 3 -3 3 -3 4 -4 3 0 7 0 6 0 4 -3 3 0 3 0 4 0 3 -7 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"path":{"@class":"fil5","@d":"M85 7121l0 -1443 3150 0 0 1443 -3150 0m3053 -1223l4 -4 6 -3 7 0 3 -7 0 -3 7 -10 3 -3 4 0 0 -4 0 -6 -4 -4 -6 -3 -7 -3 -3 0 -4 0 -6 20 0 3 0 3 0 4 -7 6 -3 4 -4 0 4 3 0 3 3 4 3 0m-150 280l0 -10 7 -4 3 -3 4 -7 3 0 3 -13 4 -10 6 -3 4 -4 3 0 10 -6 7 0 6 0 10 3 4 0 13 -7 17 -3 0 -3 6 -10 4 0 0 -4 6 -3 4 -3 6 3 10 0 4 0 3 0 0 -7 0 -3 7 -3 3 0 7 -4 3 -3 3 -3 4 0 0 -4 6 -3 4 -3 0 -10 6 0 0 -4 4 -33 3 -7 3 -6 0 -4 0 -3 0 -7 -3 -3 0 -7 -3 -6 0 -7 0 -3 3 -7 10 -7 7 -3 3 -3 0 -7 0 -3 0 -14 3 -6 -3 -4 -3 -6 -10 -10 -7 -4 -7 -3 -3 -3 -3 3 -14 17 -3 13 -3 7 0 3 0 3 -4 7 0 3 -3 4 0 6 0 4 -3 3 0 3 -4 7 -3 3 -7 4 -3 0 -3 0 -4 0 -3 -4 -3 -3 -4 -3 -3 0 -3 -4 -4 4 -3 0 -7 3 -3 3 -7 4 -3 0 -3 0 -4 0 -6 0 -7 10 -3 3 -7 3 -3 7 -7 3 -3 4 -4 3 -6 -3 -7 3 -17 0 -10 10 -6 7 -7 3 -3 0 -4 10 -3 3 -7 7 0 3 -6 10 0 4 -4 6 0 4 4 13 -4 17 0 10 0 6 -3 4 0 3 -3 3 -7 4 -3 6 -7 4 -3 0 0 6 0 4 0 3 3 3 0 7 3 7 4 0 3 -4 13 0 10 0 4 0 3 4 7 0 6 0 0 3 4 3 0 4 6 0m-2573 230l3 -4 0 -3 14 -20 3 -7 0 -3 3 -3 0 -4 4 -3 3 -10 0 -7 -3 -10 -4 -13 -3 -7 0 -3 0 -10 3 -10 4 -7 6 -13 10 -7 0 -3 4 -7 0 -6 -4 -4 -10 -6 -3 -4 0 -6 0 -4 -7 -10 -3 -3 0 -3 0 -4 0 -3 0 -3 -3 -7 -10 -10 -7 -3 -3 0 -7 0 -3 0 -7 3 -13 3 -7 0 -7 -3 -6 0 -4 0 -3 0 -3 -3 -7 -4 -3 -3 -4 3 -3 4 -7 6 -13 7 -7 7 -10 3 -3 0 0 3 0 7 -3 3 -10 10 0 4 -4 6 0 7 0 3 7 10 3 0 7 4 3 10 4 3 3 3 3 7 0 3 0 4 4 6 0 4 0 3 0 7 6 3 4 7 0 3 6 7 4 3 0 7 3 6 0 14 0 3 7 10 13 13 3 4 0 3 0 3 0 4 0 6 0 17 4 3 3 4 0 3 0 3 0 7 0 3 3 4 7 6 7 4 0 3 3 0 3 -10 7 -7 0 -6 3 -4 7 -3 3 -3 4 -4 3 -3 0 -7 0 -6m2223 353l4 -3 3 -4 3 -3 10 -10 4 0 3 -3 3 -7 10 -10 4 -3 3 -4 7 -6 3 -4 10 -16 3 -4 7 -10 7 -6 16 0 10 -4 10 -6 10 -7 7 -3 10 -4 13 -3 7 -3 13 -4 10 0 7 0 7 -3 13 0 3 -3 10 -7 4 0 3 0 3 3 4 0 3 -3 10 -7 3 -6 4 -7 3 -10 0 -3 7 -4 0 -10 0 -3 0 -7 3 -3 7 -7 0 -3 3 -10 0 -3 3 -7 4 -17 6 -3 4 -7 0 -3 6 -7 0 -3 -3 -3 -3 -7 -4 -7 0 -6 4 -7 0 -3 -4 -10 0 -4 0 -6 4 -7 3 -3 3 -7 4 -7 3 -13 3 -3 0 -20 0 -7 4 -3 0 -10 -4 -10 0 -14 0 -3 -3 -7 0 -6 -3 -17 3 -13 -3 -14 0 -3 -4 -3 -6 -10 -10 -4 0 -3 -4 -7 -3 -3 -3 0 -7 -3 -7 3 -3 0 -7 0 -3 0 -7 3 -3 4 -7 3 -3 0 -7 7 -6 0 -4 3 -3 3 -3 0 -10 4 0 3 -4 3 0 10 0 14 0 10 -3 3 -3 17 -4 3 0 7 -3 3 3 17 -3 3 -7 10 -6 7 0 3 -4 3 -3 7 -3 3 0 7 -4 7 -3 3 -3 3 0 4 -4 10 -3 10 -3 6 -10 10 -4 7 -3 7 -3 3 -4 3 -6 7 0 3 0 10 0 4 0 3 -4 3 0 7 -3 13 0 4 -3 6 -4 7 -6 7 -7 6 0 4 -3 10 -4 10 -3 6 3 20 0 10 -3 10 -3 4 -10 10 -4 6 -10 14 -6 6 -4 0 -3 4 -7 3 -6 7 -4 0 -6 10 -4 3 -6 3 -20 10 -17 7 -3 3 -7 4 -10 3 -3 3 -17 4 -10 -4 -10 0 -3 -3 -4 0 -6 0 0 3 0 7 -4 7 -6 6 3 4 3 0 4 0 3 0 3 -4 7 0 20 0 10 0 10 4 3 0 7 3 7 7 10 0 3 0 13 0 10 3m-1870 27l4 0 6 -4 4 -3 13 3 3 0 4 0 3 -3 7 -3 3 0 7 -7 6 -7 4 0 3 -3 3 -7 7 -3 7 -10 3 0 0 -3 3 -4 0 -10 0 -10 0 -3 -6 -10 0 -3 -7 -7 -7 -3 -10 0 0 -4 -10 -6 -3 0 -10 -10 -10 -7 -3 0 -17 -7 -3 0 -4 0 -6 -6 -4 0 -3 -4 -3 0 -17 10 -10 7 -3 3 -7 4 -3 3 0 3 0 4 0 3 -7 10 0 10 0 7 -3 3 3 17 0 6 3 4 7 6 3 10 7 7 3 3 7 0 13 17 10 7 10 0m360 23l7 -7 3 0 4 -3 6 0 10 0 4 0 3 -3 7 -7 20 -7 6 0 10 0 10 0 4 -3 0 -3 6 -4 7 -10 3 0 4 -3 3 -10 3 -3 7 -7 7 -10 6 -13 0 -4 7 -3 17 -10 0 -3 0 -4 0 -10 6 -16 0 -4 4 -10 3 -10 3 -6 10 -20 0 -4 7 -10 0 -6 3 -4 0 -3 4 -3 3 -4 3 -6 0 -4 -3 -6 0 -14 0 -3 0 -13 3 -4 4 -3 6 -7 7 -3 3 -3 10 -4 7 -6 7 -10 6 -10 7 -7 3 -3 4 -4 10 -10 3 -6 7 -4 6 -3 4 0 3 -3 13 -7 14 -7 3 0 10 -3 7 -3 3 -4 0 -3 3 -7 0 -3 0 -13 0 -4 -3 -3 -3 -10 0 -3 -4 0 -10 -4 -3 4 -3 6 -7 0 -7 7 -3 0 -10 0 -7 3 -3 0 -7 0 -13 -6 -3 0 -7 0 -3 0 -7 -4 -3 4 -7 3 -3 0 -7 -3 -7 0 -3 6 0 4 -3 0 -7 3 -7 7 -10 3 -10 -3 0 3 -6 7 -7 0 -3 3 -4 7 -3 13 -3 7 -4 3 -3 3 -3 0 -4 4 -6 3 0 3 -4 4 -3 6 -3 4 0 3 -7 3 -7 4 -3 6 -3 4 -4 0 -3 0 -10 -4 -3 0 -7 4 -7 6 -3 4 -3 3 -4 3 -16 0 -4 4 -20 0 -3 -4 -13 0 -7 0 -3 4 -4 0 -3 3 -10 10 -10 -3 -10 0 -13 6 -4 0 -10 0 -20 0 -10 -6 -3 0 -3 -4 -4 0 -10 4 -6 3 -4 0 -6 3 -4 4 -3 0 -7 3 -10 0 0 3 -3 4 3 6 4 4 3 6 3 4 7 3 3 3 7 10 0 4 10 16 3 7 0 3 4 17 0 13 3 7 0 3 7 7 0 3 3 0 3 4 7 3 3 7 4 16 3 7 3 3 0 4 7 3 3 7 7 6 10 14 7 10 3 0 0 6 0 7 3 3 4 4 3 0 3 3 4 3 3 4 0 6 -3 14 3 3 0 3 7 4 3 3 3 0m707 183l3 0 4 -3 3 -7 3 -3 0 -3 14 -7 3 -3 3 0 7 -4 7 0 3 0 3 -3 7 -3 7 0 16 -7 4 0 10 -7 3 -10 3 -3 4 -7 3 -6 3 0 4 -4 0 -3 6 -3 10 -7 0 -3 4 -4 -4 -3 -6 -7 -4 -3 0 -3 -3 -7 3 -7 4 -6 0 -4 3 -3 10 0 0 -7 -7 -3 0 -7 0 -3 -3 -7 -3 -3 0 -7 3 -3 3 -10 4 -7 0 -3 -4 -3 -6 -4 0 -3 -7 0 -3 -7 -7 -3 0 -3 -3 -10 0 -4 0 -3 0 -7 0 -3 3 -3 0 -7 0 -7 0 -3 -7 -7 -3 -3 0 -7 3 -6 0 -4 10 -13 4 -3 -4 -4 -6 -3 -4 -3 -3 6 -10 0 -3 7 6 7 0 3 0 3 0 4 -3 3 -3 0 -7 0 -7 3 -3 4 -3 -4 -7 0 -10 -6 -3 -4 -4 4 -6 -4 -4 -3 -3 0 -7 3 -3 4 -3 -4 -7 0 -10 0 -17 0 -3 0 -3 -3 -7 0 -10 -3 -3 -7 -4 0 -10 0 -3 0 -10 0 -13 -3 0 6 3 7 3 7 -3 3 0 7 -3 6 3 4 -3 3 -4 7 4 6 0 7 -4 3 0 4 -3 3 -3 0 -4 3 0 4 0 3 -3 3 -3 4 -4 3 -3 0 -7 0 -3 7 -7 6 -3 7 -3 0 -4 0 -10 0 -3 3 -3 0 -4 7 0 13 0 14 0 3 0 3 0 4 0 6 0 4 -3 10 0 3 10 17 3 10 0 6 7 4 7 20 0 3 3 0 3 3 10 4 7 6 3 7 4 3 13 10 0 4 3 3 10 3 14 14 0 3 6 0 27 0 10 3 3 0 7 7 10 3m-1557 57l7 0 0 -3 0 -4 0 -3 3 -3 0 -4 0 -6 0 -7 4 -3 3 -4 3 -3 0 -3 7 -7 3 -3 7 -4 3 -16 0 -4 4 -6 0 -4 0 -3 3 -7 3 -3 4 -3 10 -10 3 -4 0 -6 0 -4 -3 -3 0 -3 -4 -4 -3 -10 -7 -3 -13 -3 -3 3 -4 3 -3 4 -3 3 -7 0 -3 0 -4 7 -3 0 -10 0 -3 0 -4 3 -3 3 3 4 4 3 0 3 -10 7 -4 0 -6 7 -7 10 -3 3 -4 0 -6 3 -7 0 -3 0 -7 -3 -7 0 -6 0 -7 0 -3 0 -7 -7 -3 -3 -7 3 -10 7 -7 7 0 6 0 4 0 3 4 10 3 10 3 0 4 3 13 0 7 4 10 3 10 0 6 3 4 -3 10 3 3 0 3 4 4 0 10 20 3 3 3 3 7 7 3 0 10 0m2874 -1277l3 -3 0 -3 7 -4 0 -3 0 -7 -4 -3 -6 0 -10 7 -4 6 -3 4 3 3 0 3 14 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"text":[{"$":"18","@x":"242","@y":"5654","@class":"fil8 fnt8","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"16","@x":"1525","@y":"5654","@class":"fil8 fnt8","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"14","@x":"2797","@y":"5654","@class":"fil8 fnt8","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"18","@x":"222","@y":"7192","@class":"fil8 fnt8","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"16","@x":"1517","@y":"7192","@class":"fil8 fnt8","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"14","@x":"2834","@y":"7192","@class":"fil8 fnt8","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"28","@x":"3244","@y":"6808","@class":"fil8 fnt8","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"28","@x":"-2","@y":"6812","@class":"fil8 fnt8","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"switch":{"text":[{"$":"westl. v. Greenwich","@x":"377","@y":"5654","@class":"fil8 fnt8","@systemLanguage":"de","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"west of Greenwich","@x":"377","@y":"5654","@class":"fil8 fnt8","@systemLanguage":"en","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil7 str8","@d":"M3152 5776l2 -4 2 -3 5 -5 2 -3 0 -5 -4 -5 -6 0 -2 3 -11 3 -3 7 -1 5 1 4 2 1 13 2","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str8","@d":"M3140 5897l-4 0 -4 -2 -1 -2 -1 -3 2 -3 3 -2 5 -5 0 -4 1 -4 1 -3 6 -19 4 -2 3 1 8 3 5 2 5 6 -1 4 -2 3 -3 2 -2 3 -6 10 0 4 -6 5 -4 0 -6 5 -3 1","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str8","@d":"M2987 6178l-5 -1 -2 -3 -1 -3 -2 -3 -4 -1 -9 1 -3 -2 -4 -1 -9 1 -12 0 -3 2 -4 -1 -3 -5 -2 -7 -2 -3 -2 -4 0 -4 2 -4 3 -2 8 -1 3 -8 5 -5 3 -2 2 -3 1 -3 0 -8 0 -10 3 -17 -3 -11 0 -5 3 -7 1 -4 6 -9 2 -3 5 -6 4 -6 3 -7 3 -2 6 -3 9 -7 10 -10 14 0 9 -1 4 0 4 -1 6 -4 5 -4 4 -7 6 -3 3 -3 6 -8 3 -3 4 0 3 2 5 1 4 -1 6 -4 3 -2 6 -4 4 -1 4 -1 3 0 3 2 4 5 3 1 2 3 4 2 4 0 4 -2 6 -3 2 -3 4 -6 1 -5 2 -3 1 -3 0 -5 2 -4 1 -4 4 -5 1 -5 0 -5 1 -3 2 -3 3 -13 12 -18 4 0 2 3 7 3 9 2 8 11 5 5 1 4 -2 8 -2 13 1 4 -1 5 -2 3 -5 5 -10 6 -3 7 -1 4 -1 5 3 7 2 8 2 4 1 4 0 3 -1 5 -5 6 -3 6 -1 35 -2 3 -4 1 -2 9 -2 2 -6 4 -3 2 -3 2 -2 3 -3 2 -7 3 -3 3 -6 3 -3 3 0 5 -2 2 -4 -1 -9 -2 -5 0 -4 1 -6 3 -3 3 -3 2 -4 11 -3 2 -15 2 -12 8 -5 0 -11 -4 -5 -1 -8 3 -10 4 -4 1 -3 2 -5 5 -5 10 -3 12 -3 3 -4 6 -2 3 -6 4 -2 8","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str8","@d":"M416 6407l2 -3 1 -4 13 -17 3 -7 0 -5 2 -4 1 -3 2 -3 5 -11 1 -4 -5 -11 -2 -12 -3 -7 -1 -4 0 -9 2 -12 4 -7 8 -12 8 -7 2 -3 2 -8 0 -4 -4 -4 -9 -7 -2 -2 0 -9 -2 -4 -7 -8 -2 -3 -1 -4 0 -5 2 -3 -1 -3 -4 -6 -10 -10 -7 -3 -4 -1 -5 0 -3 1 -7 4 -12 3 -8 -2 -8 -3 -5 0 -4 1 -4 -1 -4 -1 -5 -5 -3 -2 -3 2 -5 5 -7 4 -13 6 -7 9 -8 1 -3 3 -1 3 0 4 -2 4 -2 3 -8 7 -2 3 -3 7 -1 9 1 4 8 7 3 1 5 4 4 10 2 3 4 2 3 7 0 4 1 4 4 5 0 5 -1 5 2 3 3 6 6 5 1 4 4 6 4 6 2 3 1 8 2 14 0 4 7 8 12 14 2 3 0 3 1 4 1 4 0 5 1 19 2 2 2 3 1 4 -1 4 0 5 2 4 4 5 4 5 6 4 2 3 2 -1 4 -10 5 -5 3 -7 3 -3 6 -4 3 -2 4 -6 1 -3 2 -4 1 -10","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str8","@d":"M2637 6761l3 -2 6 -4 3 -3 10 -9 3 -2 2 -3 5 -6 8 -11 3 -3 6 -4 5 -4 4 -6 10 -17 2 -2 6 -9 8 -7 18 -2 8 -1 10 -6 2 -2 9 -6 8 -2 10 -5 12 -3 7 -3 12 -3 13 -1 3 -1 9 -1 12 -2 4 -2 9 -6 3 -1 3 0 6 4 2 0 2 -3 3 -2 8 -7 4 -6 4 -7 2 -8 1 -4 5 -5 1 -9 0 -4 1 -5 1 -3 8 -8 1 -4 2 -8 2 -3 2 -9 5 -14 4 -7 4 -6 1 -3 5 -5 0 -5 -2 -4 -2 -7 -4 -6 -1 -4 2 -8 1 -4 -2 -9 0 -5 0 -4 2 -7 5 -6 4 -6 0 -5 6 -14 1 -3 1 -19 1 -8 1 -4 1 -10 -2 -8 0 -15 -1 -4 -3 -7 0 -4 -3 -18 2 -14 -3 -12 -1 -3 -2 -3 -5 -11 -11 -4 -2 -2 -1 -8 -3 -3 -4 -1 -7 -2 -7 3 -4 1 -5 0 -4 0 -7 3 -4 1 -5 5 -5 0 -4 6 -9 1 -3 2 -2 3 -3 2 -11 4 -2 3 -2 3 -1 9 2 13 -1 10 -2 3 -4 16 -4 7 -1 3 -1 4 1 18 -1 4 -7 8 -7 9 -1 3 -3 3 -4 6 -1 4 0 4 -6 9 -2 4 -2 3 -2 3 -2 8 -2 3 -2 8 -3 7 -9 11 -5 5 -4 6 -2 4 -5 4 -4 6 -1 4 -2 9 1 5 -1 4 -1 4 -1 4 -2 13 -2 3 -4 7 -2 8 -8 7 -5 5 -1 4 -3 12 -3 7 -2 9 2 18 -1 10 -3 12 -2 3 -10 11 -4 6 -11 13 -6 5 -3 2 -2 3 -7 3 -9 6 -3 2 -6 9 -3 2 -7 3 -19 11 -17 7 -3 2 -8 3 -9 6 -3 1 -17 4 -11 -4 -9 0 -5 -1 -3 -1 -5 0 -2 3 1 8 -4 6 -5 6 2 3 3 2 4 -1 4 -1 2 -2 9 -2 19 0 9 0 12 4 3 2 7 3 6 4 9 1 4 -1 13 3 9 1","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str8","@d":"M767 6789l4 -1 6 -4 4 -1 13 2 4 0 5 -1 3 -1 6 -5 4 1 4 -6 3 -3 6 -3 3 -3 1 -3 5 -6 7 -3 6 -8 3 -3 2 -3 1 -4 1 -9 1 -9 -2 -3 -4 -11 -2 -3 -8 -8 -6 -2 -8 -2 -2 -1 -7 -8 -5 -1 -11 -9 -9 -6 -3 -2 -17 -4 -5 0 -3 -2 -6 -4 -2 -2 -4 -2 -5 0 -16 11 -10 5 -3 2 -6 4 -2 2 -2 4 -1 4 0 5 -5 10 0 10 -1 4 -2 4 1 18 3 7 2 4 7 6 4 10 5 6 3 2 7 3 15 15 9 6 9 1","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str8","@d":"M1128 6811l6 -4 3 -3 4 -1 8 -2 8 1 4 -2 2 -2 10 -6 17 -7 9 -1 9 1 10 -1 3 -1 2 -4 5 -5 6 -9 4 -1 2 -3 5 -10 2 -3 8 -7 6 -9 6 -14 3 -3 5 -5 15 -9 2 -3 0 -4 1 -9 5 -16 0 -4 2 -8 5 -10 2 -9 10 -20 1 -4 5 -10 1 -4 5 -6 1 -3 2 -3 2 -2 4 -7 1 -4 -4 -7 -1 -13 0 -4 2 -11 1 -4 5 -5 7 -7 7 -3 3 -2 10 -5 6 -4 5 -10 8 -12 5 -5 3 -2 3 -2 3 -3 8 -12 5 -4 6 -4 7 -3 3 -2 4 -1 12 -8 14 -7 3 -1 12 -3 6 -4 3 -2 1 -5 1 -4 2 -3 0 -14 -1 -4 -2 -2 -3 -12 -1 -3 -4 0 -11 -3 -2 4 -5 5 -4 1 -9 6 -3 1 -9 1 -8 3 -4 -1 -4 -1 -14 -4 -4 -1 -5 1 -4 -1 -7 -3 -3 1 -6 4 -5 0 -7 -3 -4 0 -3 2 -1 4 -2 3 -2 3 -8 2 -7 8 -9 1 -8 -2 -3 2 -5 6 -6 3 -4 2 -4 6 -3 13 -3 6 -5 5 -4 2 -3 2 -2 3 -5 4 -2 3 -2 4 -5 5 -2 3 -1 4 -7 2 -6 5 -2 7 -3 2 -5 1 -4 -1 -8 -2 -5 1 -7 2 -6 5 -4 6 -2 3 -3 2 -18 2 -3 1 -19 -1 -4 -1 -15 0 -4 1 -3 1 -5 1 -3 2 -10 9 -9 -1 -13 0 -10 5 -5 1 -9 -1 -20 0 -11 -4 -3 -2 -3 -2 -5 0 -9 1 -6 4 -3 2 -6 4 -4 1 -4 1 -7 3 -8 1 -3 2 -2 3 -1 2 4 6 2 3 4 6 3 2 7 3 2 3 1 3 6 10 2 3 9 16 3 7 2 3 4 16 -1 14 2 8 1 3 6 6 1 3 3 2 3 2 6 4 5 5 3 17 4 6 2 3 1 3 4 5 6 5 7 8 9 14 8 8 2 3 1 4 0 9 2 4 3 2 4 1 3 2 2 3 3 5 2 4 -2 13 1 4 2 3 5 5 3 2 4 0","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str8","@d":"M1833 6995l4 -1 3 -2 6 -8 1 -4 3 -3 10 -4 6 -4 4 -1 4 -1 7 -3 4 0 3 -2 6 -3 9 -2 16 -3 4 -2 8 -7 5 -10 1 -4 3 -6 6 -5 3 -2 2 -3 2 -3 5 -5 9 -6 2 -3 1 -4 -2 -3 -5 -5 -5 -6 -1 -3 -1 -5 2 -7 3 -7 2 -3 2 -3 8 -1 1 -4 -5 -4 -1 -7 -1 -3 -3 -7 -1 -4 0 -5 2 -3 5 -11 1 -7 0 -4 -3 -2 -5 -5 -3 -2 -4 -2 -6 -4 -4 -6 -1 -3 -2 -8 -1 -5 1 -5 -1 -4 0 -4 2 -3 2 -8 0 -5 -1 -3 -8 -8 -1 -4 0 -5 2 -8 1 -4 10 -11 1 -4 -2 -3 -5 -5 -3 -2 -4 6 -10 0 -3 2 0 4 4 6 2 4 -1 5 -1 3 -2 3 -4 1 -5 0 -7 4 -4 0 -4 0 -7 -3 -9 -7 -4 -1 -4 1 -4 -1 -6 -4 -3 0 -6 5 -5 0 -3 -1 -4 -1 -13 2 -14 -1 -5 -1 -3 -2 -5 0 -10 -5 -6 -5 -3 -1 -9 1 -5 0 -8 -2 -14 -2 0 5 2 3 3 6 1 5 -1 4 -2 8 -1 5 1 4 -2 2 -4 7 2 8 0 5 -1 5 -1 3 -2 3 -4 1 -2 3 -1 4 -2 3 -2 3 -3 2 -3 2 -3 2 -9 1 -4 7 -4 5 -5 5 -3 2 -4 1 -10 1 -4 0 -2 3 -2 4 1 14 -3 13 0 4 1 4 0 4 1 5 0 3 -4 12 1 3 10 16 1 8 2 8 5 5 6 18 2 3 4 2 3 1 7 3 8 8 4 6 5 5 11 9 2 3 2 3 10 5 12 13 2 2 5 0 29 2 7 2 4 1 9 7 7 2","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str8","@d":"M277 7053l7 -2 2 -2 -1 -3 1 -4 2 -3 1 -4 0 -8 0 -4 2 -4 2 -2 2 -3 2 -3 2 -2 4 -6 6 -4 6 -2 1 -3 1 -15 1 -3 4 -6 1 -5 0 -4 1 -4 2 -3 3 -3 3 -2 11 -9 1 -3 1 -9 -1 -3 -1 -3 -3 -3 -1 -4 -5 -10 -5 -4 -14 -1 -4 1 -2 3 -4 6 -4 1 -5 0 -4 1 -5 5 -3 2 -9 0 -4 1 -3 2 -2 4 4 1 1 3 0 5 -9 5 -4 2 -8 7 -5 11 -2 2 -4 2 -9 2 -4 1 -5 -1 -6 -4 -5 0 -9 1 -5 -1 -3 -1 -9 -7 -4 -1 -7 3 -9 5 -5 6 -2 8 0 4 1 4 4 10 3 8 2 2 4 2 14 1 8 3 8 2 10 0 7 3 5 0 10 0 3 1 3 2 2 3 12 19 2 2 2 3 9 7 3 2 8 0","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil15 str11","@d":"M2977 6617l0 -283 -283 0 0 283 283 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil14 str11","@d":"M2901 6617l0 -206 -207 0 0 206 207 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil7 str16","@d":"M85 7121l0 -1443 3150 0 0 1443 -3150 0","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str16","@d":"M271 6790l0 -8 1 -37 0 -36 1 -37 0 -37 1 -36 1 -37 0 -36 1 -37 0 -36 1 -37 1 -36 0 -37 1 -37 0 -36 1 -37 1 -36 0 -37 1 -36 0 -37 1 -36 1 -37 0 -37 1 -36 0 -37 1 -36 1 -37 0 -36 1 -37 0 -37 1 -36 0 -7","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str16","@d":"M85 6786l27 1 33 0 32 1 32 1 33 0 29 1","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str16","@d":"M2852 6790l18 -1 32 0 33 -1 32 0 33 -1 32 -1 33 0 32 -1 32 0 33 -1 32 -1 33 0 8 -1","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str16","@d":"M2852 6790l0 -8 -1 -37 0 -36 -1 -37 0 -37 -1 -36 -1 -37 0 -36 -1 -37 0 -36 -1 -37 -1 -36 0 -37 -1 -37 0 -36 -1 -37 -1 -36 0 -37 -1 -36 0 -37 -1 -36 -1 -37 0 -37 -1 -36 0 -37 -1 -36 -1 -37 0 -36 -1 -37 0 -37 -1 -36 0 -7","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str16","@d":"M1561 6800l11 0 33 0 32 0 32 0 33 0 32 0 33 0 32 0 33 0 32 0 33 0 32 -1 32 0 33 0 32 0 33 0 32 -1 33 0 32 0 33 0 32 -1 32 0 33 0 32 0 33 -1 32 0 33 0 32 -1 33 0 32 -1 32 0 33 0 32 -1 33 0 32 -1 33 0 32 -1 33 0 32 -1 32 0 15 0","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str16","@d":"M1561 6800l0 -8 0 -36 0 -37 0 -36 0 -37 0 -37 0 -36 0 -37 0 -36 0 -37 0 -36 0 -37 0 -36 0 -37 0 -37 0 -36 0 -37 0 -36 0 -37 0 -36 0 -37 0 -37 0 -36 0 -37 0 -36 0 -37 0 -36 0 -37 0 -37 0 -36 0 -37 0 -17","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str16","@d":"M271 6790l3 0 33 0 32 1 33 0 32 1 33 0 32 1 32 0 33 1 32 0 33 0 32 1 33 0 32 0 33 1 32 0 32 0 33 1 32 0 33 0 32 1 33 0 32 0 33 0 32 1 32 0 33 0 32 0 33 0 32 0 33 1 32 0 33 0 32 0 32 0 33 0 32 0 33 0 32 0 33 0 21 0","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str16","@d":"M1561 7121l0 -36 0 -37 0 -36 0 -37 0 -37 0 -36 0 -37 0 -36 0 -29","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str16","@d":"M2857 7121l0 -10 0 -37 -1 -37 0 -36 -1 -37 -1 -36 0 -37 -1 -36 0 -37 -1 -28","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str16","@d":"M265 7121l1 -10 0 -37 1 -37 0 -36 1 -37 1 -36 0 -37 1 -36 0 -37 1 -28","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil15 str11","@d":"M1248 6705l0 -273 -276 0 0 273 276 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil17 str11","@d":"M1145 6705l0 -173 -173 0 0 173 173 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"switch":{"text":[{"textPath":{"$":"Kanarische Inseln","@xlink:href":"#textPathCanary","@startOffset":"5%","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@systemLanguage":"de","@class":"fil8 fnt9","@style":"letter-spacing:40px;","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"textPath":{"$":"Canary Islands","@xlink:href":"#textPathCanary","@startOffset":"5%","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@systemLanguage":"en","@class":"fil8 fnt9","@style":"letter-spacing:60px;","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"text":[{"$":"Teneriffa","@x":"1221","@y":"6344","@class":"fil8 fnt7","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"Gran Canaria","@x":"1893","@y":"7067","@class":"fil8 fnt7","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@id":"islands","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"switch":[{"g":[{"text":[{"$":"Spanien - Bev\u00f6lkerung","@x":"-5481","@y":"166","@class":"fil8 fnt10","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"1970 - 1990","@x":"3500","@y":"157","@class":"fil8 fnt10","@style":"text-anchor:end;","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"Erstellt v. Andreas Neumann im Rahmen d. Kartenentwurfspraktikums, Sommersemester 1998,","@x":"-5483","@y":"7499","@class":"fil8 fnt8","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"geleitet v. Prof. Ingrid Kretschmer, Institut f\u00fcr Geographie der Universit\u00e4t Wien.","@x":"-5483","@y":"7583","@class":"fil8 fnt8","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"Verwendete Software: Arc\/Info und Module, CorelDRAW und div. Perl-Scripts.","@x":"-5483","@y":"7666","@class":"fil8 fnt8","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"Bev\u00f6lkerungsdichte","@x":"3665","@y":"363","@class":"fil8 fnt11","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"Bev\u00f6lkerungsver\u00e4nderung","@x":"3665","@y":"4063","@class":"fil8 fnt11","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"Bev\u00f6lkerung absolut","@x":"3665","@y":"1815","@class":"fil8 fnt11","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"Einwohner\/km\u00b2 auf Provinzebene","@x":"3665","@y":"510","@class":"fil8 fnt7","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"Prozentuelle Ver\u00e4nderung der","@x":"3665","@y":"4210","@class":"fil8 fnt7","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"Provinzen gegen\u00fcber Stand 1970","@x":"3665","@y":"4344","@class":"fil8 fnt7","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"Prozentuelle Ver\u00e4nderung der","@x":"3665","@y":"5750","@class":"fil8 fnt7","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"Hauptst\u00e4dte gegen\u00fcber Stand 1970","@x":"3665","@y":"5884","@class":"fil8 fnt7","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"Auf Provinzebene und in den","@x":"3665","@y":"1962","@class":"fil8 fnt7","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"Hauptst\u00e4dten (inneres Quadrat)","@x":"3665","@y":"2096","@class":"fil8 fnt7","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@systemLanguage":"de","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"text":[{"$":"Spain - Population","@x":"-5481","@y":"166","@class":"fil8 fnt10","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"1970 - 1990","@x":"3500","@y":"157","@class":"fil8 fnt10","@style":"text-anchor:end;","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"Created by Andreas Neumann for the map design course, summer semester 1998,","@x":"-5483","@y":"7499","@class":"fil8 fnt8","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"led by Prof. Ingrid Kretschmer, Geography Institute of Vienna University.","@x":"-5483","@y":"7583","@class":"fil8 fnt8","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"Used software: Arc\/Info and Modules, CorelDRAW and various Perl scripts.","@x":"-5483","@y":"7666","@class":"fil8 fnt8","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"Population density","@x":"3665","@y":"363","@class":"fil8 fnt11","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"Population change","@x":"3665","@y":"4063","@class":"fil8 fnt11","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"Population absolute","@x":"3665","@y":"1815","@class":"fil8 fnt11","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"Inhab. per km\u00b2 at province level","@x":"3665","@y":"510","@class":"fil8 fnt7","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"Percentual change of the","@x":"3665","@y":"4210","@class":"fil8 fnt7","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"province vs situation 1970","@x":"3665","@y":"4344","@class":"fil8 fnt7","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"Percentual change of the","@x":"3665","@y":"5750","@class":"fil8 fnt7","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"capitals vs situation 1970","@x":"3665","@y":"5884","@class":"fil8 fnt7","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"At provincial level and in the","@x":"3665","@y":"1962","@class":"fil8 fnt7","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"capitals (inner square)","@x":"3665","@y":"2096","@class":"fil8 fnt7","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@systemLanguage":"en","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"text":[{"$":"Angaben in tausend","@x":"4151","@y":"3193","@class":"fil8 fnt41","@systemLanguage":"de","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"Indications in thousands","@x":"4151","@y":"3193","@class":"fil8 fnt41","@systemLanguage":"en","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"text":[{"$":"Massstab 1 : 6.000.000","@x":"-1325","@y":"7682","@class":"fil8 fnt41","@systemLanguage":"de","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"Scale 1 : 6.000.000","@x":"-1325","@y":"7682","@class":"fil8 fnt41","@systemLanguage":"en","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"text":[{"$":"Quelle: Spanisches Statistisches Zentralamt","@x":"3665","@y":"7280","@class":"fil8 fnt41","@systemLanguage":"de","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"Source: Spanish Central Office for Statistics","@x":"3665","@y":"7280","@class":"fil8 fnt41","@systemLanguage":"en","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"text":[{"$":"Minimum (Provinz): Soria - 97.268","@x":"3665","@y":"3331","@class":"fil8 fnt41","@systemLanguage":"de","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"Minimum (Province): Soria - 97.268","@x":"3665","@y":"3331","@class":"fil8 fnt41","@systemLanguage":"en","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"text":[{"$":"Maximum (Provinz): Madrid - 5.028.120","@x":"3665","@y":"3432","@class":"fil8 fnt41","@systemLanguage":"de","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"Maximum (Province): Madrid - 5.028.120","@x":"3665","@y":"3432","@class":"fil8 fnt41","@systemLanguage":"en","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"text":[{"$":"Minimum (Hauptstadt): Teruel - 28.488","@x":"3665","@y":"3532","@class":"fil8 fnt41","@systemLanguage":"de","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"Minimum (capital): Teruel - 28.488","@x":"3665","@y":"3532","@class":"fil8 fnt41","@systemLanguage":"en","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"text":[{"$":"Maximum (Hauptstadt): Madrid - 3.120.732","@x":"3665","@y":"3633","@class":"fil8 fnt41","@systemLanguage":"de","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"Maximum (capital): Madrid - 3.120.732","@x":"3665","@y":"3633","@class":"fil8 fnt41","@systemLanguage":"en","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"text":[{"$":"Stand 1990","@x":"4779","@y":"1362","@class":"fil8 fnt41","@systemLanguage":"de","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"Situation 1990","@x":"4779","@y":"1362","@class":"fil8 fnt41","@systemLanguage":"en","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"text":[{"$":"Stand 1990","@x":"5063","@y":"3022","@class":"fil8 fnt41","@systemLanguage":"de","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"Sit. 1990","@x":"5063","@y":"3022","@class":"fil8 fnt41","@systemLanguage":"en","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"g":[{"path":[{"@class":"fil0 str11","@d":"M3665 634l196 0 0 98 -196 0 0 -98z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str11","@d":"M3665 634l196 0 0 98 -196 0 0 -98z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil1 str11","@d":"M3665 791l196 0 0 99 -196 0 0 -99z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str11","@d":"M3665 791l196 0 0 99 -196 0 0 -99z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil2 str11","@d":"M3665 949l196 0 0 98 -196 0 0 -98z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str11","@d":"M3665 949l196 0 0 98 -196 0 0 -98z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil3 str11","@d":"M3665 1106l196 0 0 99 -196 0 0 -99z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str11","@d":"M3665 1106l196 0 0 99 -196 0 0 -99z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"path":[{"@class":"fil4 str11","@d":"M3665 1264l196 0 0 98 -196 0 0 -98z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str11","@d":"M3665 1264l196 0 0 98 -196 0 0 -98z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"rect":{"@class":"fil7 str11","@x":"-2090","@y":"7529","@width":"2295","@height":"39","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"path":[{"@class":"fil7 str11","@d":"M-2090 7568l0 -48","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str11","@d":"M-2024 7568l0 -40","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str11","@d":"M-1959 7568l0 -40","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str11","@d":"M-1893 7568l0 -40","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str11","@d":"M-1827 7568l0 -40","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str11","@d":"M-1762 7568l0 -48","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str11","@d":"M-1434 7568l0 -40","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str11","@d":"M-1106 7568l0 -48","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str11","@d":"M-778 7568l0 -40","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str11","@d":"M-450 7568l0 -48","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str11","@d":"M-121 7568l0 -40","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str11","@d":"M206 7567l0 -47","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str11","@d":"M-1434 7547l328 0","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str11","@d":"M-1828 7547l66 0","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str11","@d":"M-1959 7547l65 0","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str11","@d":"M-2090 7547l65 0","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str11","@d":"M-778 7547l328 0","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str11","@d":"M-122 7547l328 0","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"text":[{"$":"0","@x":"-1783","@y":"7500","@class":"fil8 fnt42","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"100","@x":"-1167","@y":"7500","@class":"fil8 fnt42","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"200","@x":"-511","@y":"7500","@class":"fil8 fnt42","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"300 km","@x":"146","@y":"7500","@class":"fil8 fnt42","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"50","@x":"-2131","@y":"7500","@class":"fil8 fnt42","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"rect":[{"@class":"fil16 str11","@x":"3665","@y":"4473","@width":"197","@height":"98","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil10 str11","@x":"3665","@y":"6014","@width":"197","@height":"98","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil13 str11","@x":"3665","@y":"4631","@width":"197","@height":"98","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil12 str11","@x":"3665","@y":"6172","@width":"197","@height":"98","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil10 str11","@x":"3665","@y":"4788","@width":"197","@height":"98","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil14 str11","@x":"3665","@y":"6329","@width":"197","@height":"98","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil11 str11","@x":"3665","@y":"4946","@width":"197","@height":"98","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil17 str11","@x":"3665","@y":"6487","@width":"197","@height":"98","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil15 str11","@x":"3665","@y":"5103","@width":"197","@height":"98","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil15 str11","@x":"3665","@y":"6644","@width":"197","@height":"98","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"text":[{"$":"<","@x":"4250","@y":"723","@class":"fil8 fnt12","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":" 25","@x":"4304","@y":"723","@class":"fil8 fnt13","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"<","@x":"4338","@y":"4563","@class":"fil8 fnt14","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":" 85 %","@x":"4392","@y":"4563","@class":"fil8 fnt15","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"<","@x":"4338","@y":"6104","@class":"fil8 fnt16","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":" 115 %","@x":"4392","@y":"6104","@class":"fil8 fnt17","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"25 ","@x":"4111","@y":"881","@class":"fil8 fnt17","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":" 45","@x":"4304","@y":"881","@class":"fil8 fnt17","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"<","@x":"4250","@y":"881","@class":"fil8 fnt18","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"85 % ","@x":"4086","@y":"4720","@class":"fil8 fnt19","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":" 100 %","@x":"4392","@y":"4720","@class":"fil8 fnt19","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"<","@x":"4338","@y":"4720","@class":"fil8 fnt20","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"115 % ","@x":"4030","@y":"6261","@class":"fil8 fnt21","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":" 130 %","@x":"4392","@y":"6261","@class":"fil8 fnt21","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"<","@x":"4338","@y":"6261","@class":"fil8 fnt22","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"45 ","@x":"4111","@y":"1038","@class":"fil8 fnt23","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":" 75","@x":"4304","@y":"1038","@class":"fil8 fnt23","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"<","@x":"4250","@y":"1038","@class":"fil8 fnt24","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"100 % ","@x":"4030","@y":"4878","@class":"fil8 fnt25","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":" 115 %","@x":"4392","@y":"4878","@class":"fil8 fnt25","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"<","@x":"4338","@y":"4878","@class":"fil8 fnt26","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"130 % ","@x":"4030","@y":"6417","@class":"fil8 fnt27","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":" 145 %","@x":"4391","@y":"6417","@class":"fil8 fnt27","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"<","@x":"4337","@y":"6417","@class":"fil8 fnt28","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"75 ","@x":"4111","@y":"1196","@class":"fil8 fnt29","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":" 150","@x":"4304","@y":"1196","@class":"fil8 fnt29","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"<","@x":"4251","@y":"1196","@class":"fil8 fnt30","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"115 % ","@x":"4030","@y":"5035","@class":"fil8 fnt31","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":" 130 %","@x":"4392","@y":"5035","@class":"fil8 fnt31","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"<","@x":"4338","@y":"5035","@class":"fil8 fnt32","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"145 % ","@x":"4030","@y":"6576","@class":"fil8 fnt33","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":" 160 %","@x":"4392","@y":"6576","@class":"fil8 fnt33","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"<","@x":"4338","@y":"6576","@class":"fil8 fnt34","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"150 ","@x":"4054","@y":"1353","@class":"fil8 fnt35","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"<","@x":"4249","@y":"1353","@class":"fil8 fnt36","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"130 % ","@x":"4035","@y":"5193","@class":"fil8 fnt37","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"<","@x":"4343","@y":"5193","@class":"fil8 fnt38","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"160 % ","@x":"4035","@y":"6734","@class":"fil8 fnt39","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"<","@x":"4343","@y":"6734","@class":"fil8 fnt40","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"5.000","@x":"4712","@y":"2359","@class":"fil8 fnt41","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"1.000","@x":"4709","@y":"2484","@class":"fil8 fnt41","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"500","@x":"4769","@y":"2608","@class":"fil8 fnt41","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"200","@x":"4770","@y":"2733","@class":"fil8 fnt41","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"100","@x":"4770","@y":"2857","@class":"fil8 fnt41","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"50","@x":"4809","@y":"2982","@class":"fil8 fnt41","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"Min.: Soria - 9,46, Max.: Madrid - 628,91","@x":"3665","@y":"1543","@class":"fil8 fnt41","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"Minimum: Soria - 84,61 %,","@x":"3665","@y":"5400","@class":"fil8 fnt41","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"Maximum: Las Palmas - 141,24 %","@x":"3665","@y":"5500","@class":"fil8 fnt41","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"Minimum: Vizcaya - 93,50 %,","@x":"3665","@y":"6939","@class":"fil8 fnt41","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"$":"Maximum: Guadalajara - 199,18 %","@x":"3665","@y":"7040","@class":"fil8 fnt41","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"path":[{"@class":"fil7 str17","@d":"M4451 3032l0 -783 -786 0 0 783 786 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str17","@d":"M4022 3032l0 -357 -357 0 0 357 357 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str17","@d":"M3928 3032l0 -263 -263 0 0 263 263 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str17","@d":"M3851 3032l0 -184 -186 0 0 184 186 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str17","@d":"M3812 3032l0 -143 -147 0 0 143 147 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str17","@d":"M3778 3032l0 -114 -113 0 0 114 113 0z","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str18","@d":"M4680 2334l-232 0","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str18","@d":"M4680 2460l-331 0 -327 277","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str18","@d":"M4738 2576l-389 0 -424 263","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str18","@d":"M4738 2706l-389 0 -498 209","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str18","@d":"M4738 2832l-389 0 -536 137","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},{"@class":"fil7 str18","@d":"M4779 2952l-430 0 -570 51","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@id":"text_legend","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}],"@xml:space":"preserve","@x":"25","@y":"25","@width":"550","@height":"382.36","@style":"shape-rendering:geometricPrecision; text-rendering:auto; image-rendering:optimizeSpeed","@viewBox":"-5483 0 11053 7684","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}},"@viewBox":"0 0 600 420","@width":"600","@height":"420","@xmlns":{"xlink":"http:\/\/www.w3.org\/1999\/xlink","$":"http:\/\/www.w3.org\/2000\/svg"}}}
diff --git a/1.9.10/samples/ns-invoice100.xml.jsn b/1.9.10/samples/ns-invoice100.xml.jsn new file mode 100644 index 0000000..0743265 --- /dev/null +++ b/1.9.10/samples/ns-invoice100.xml.jsn
@@ -0,0 +1 @@ +{"ns1:invoice":{"Header":{"IssueDateTime":{"$":"2003-03-13T13:13:32-08:00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Identifier":{"$":"15570720","@schemeAgencyName":"ISO","@schemeName":"Invoice","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"POIdentifier":{"$":"691","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"BuyerParty":{"PartyID":{"$":"1","@schemeName":"SpiderMarkExpress","@schemeAgencyName":"SUNW","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Name":{"$":"IDES Retail INC US","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Address":{"Street":{"$":"Hill St.","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"HouseID":{"$":"5555","@schemeName":"HouseID","@schemeAgencyName":"house","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"RoomID":{"$":"Suite 3","@schemeName":"RoomID","@schemeAgencyName":"room","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"CityName":{"$":"Boston","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PostalZoneID":{"$":"01234","@schemeName":"Zipcode","@schemeAgencyName":"USPS","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"StateName":{"$":"MA","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"CountryIdentificationCode":{"$":"US","@listAgencyId":"ISO","@listId":"3166","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Contact":{"Name":{"$":"Joe Buyer","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Communication":[{"Value":{"$":"313-555-1212","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ChannelID":{"$":"phone","@schemeName":"SpiderMarkExpress","@schemeAgencyName":"SUNW","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"Value":{"$":"313-555-1213","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ChannelID":{"$":"fax","@schemeName":"SpiderMarkExpress","@schemeAgencyName":"SUNW","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}}],"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"SellerParty":{"PartyID":{"$":"10","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Name":{"$":"1YvMdIkxZRXszgQfmoKqkit","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Address":{"Street":{"$":"ZNk","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"HouseID":{"$":"1234","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"RoomID":{"$":"Ste 301","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"CityName":{"$":"tzFMMtlE1lxdag","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PostalZoneID":{"$":"992292786","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"StateName":{"$":"FL","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"CountryIdentificationCode":{"$":"SY","@listAgencyId":"ISO","@listId":"3166","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Contact":{"Name":{"$":"jjzxxgwwqgwqjf","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Communication":[{"Value":{"$":"jjzxxgwwqgwqjf@1YvMdIkxZRXszgQfmoKqkit.com","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ChannelID":{"$":"email","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"Value":{"$":"9433593740064593","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ChannelID":{"$":"phone","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"Value":{"$":"38667976759785","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ChannelID":{"$":"fax","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}}],"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Shipment":{"ShipDate":{"$":"2003-03-13T13:13:32-08:00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TransportModeID":{"$":"sea","@schemeAgencyName":"ISO","@schemeName":"TransportMode","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"CarrierID":{"$":"UPS","@schemeAgencyName":"ISO","@schemeName":"Carrier","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PaymentMeans":{"PaymentDate":{"$":"2003-04-13","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PayeeFinancialAccount":{"Identifier":{"$":"312098283","@schemeAgencyName":"ISO","@schemeName":"Account","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"FinancialInstitution":{"Identifier":{"$":"33747420","@schemeAgencyName":"UN","@schemeName":"Financial Institution","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Name":{"$":"Caaco","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Address":{"Street":{"$":"H9LHLljO Street","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"HouseID":{"$":"15","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"CityName":{"$":"Yigmnvii","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PostalZoneID":{"$":"48839","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"StateName":{"$":"CT","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"CountryIdentificationCode":{"$":"US","@listAgencyId":"ISO","@listId":"3166","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TypeID":{"$":"vozbix","@schemeAgencyName":"ISO","@schemeName":"Account Type","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"AccountName":{"$":"Adrvgrri","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"LineItem":[{"LineID":{"$":"0","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"1","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"2","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"3","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"4","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"5","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"6","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"7","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"8","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"9","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"10","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"11","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"12","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"13","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"14","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"15","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"16","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"17","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"18","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"19","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"21","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"22","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"23","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"24","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"25","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"26","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"27","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"28","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"29","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"30","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"31","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"32","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"33","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"34","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"35","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"36","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"37","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"38","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"39","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"40","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"41","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"42","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"43","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"44","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"45","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"46","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"47","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"48","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"49","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"50","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"51","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"52","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"53","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"54","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"55","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"56","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"57","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"58","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"59","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"60","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"61","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"62","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"63","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"64","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"65","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"66","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"67","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"68","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"69","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"70","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"71","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"72","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"73","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"74","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"75","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"76","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"77","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"78","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"79","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"80","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"81","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"82","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"83","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"84","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"85","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"86","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"87","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"88","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"89","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"90","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"91","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"92","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"93","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"94","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"95","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"96","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"97","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"98","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},{"LineID":{"$":"99","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Item":{"StandardItemIdentifier":{"$":"20","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Description":{"$":"vZCwLwz1AGtbQT7t0diKccyB0rm0DXS5JFUWZyFcDFW7t","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Quantity":{"$":"10","@unitCode":"number","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"OrderStatus":{"$":"FULFILLED","@listId":"OrderStatus","@listAgencyId":"Sun","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Pricing":{"GrossUnitPriceAmount":{"$":"437.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"NetUnitPriceAmount":{"$":"367.08","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"discount","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"allowance","@schemeName":"Generic","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"Rate":{"$":"16.00","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"TotalAmount":{"$":"3670.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}}],"Summary":{"LineItemCountValue":{"$":"2","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"SubtotalAmount":{"$":"18215.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PricingVariation":{"ServiceID":{"$":"shipping and handling","@schemeName":"Variations","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"ConditionID":{"$":"charge","@schemeName":"Conditions","@schemeAgencyName":"ISO","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"LumpSumAmount":{"$":"7.00","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PriceAmount":{"$":"18222.80","@currencyId":"USD","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"PackingSlipIdentifier":{"$":"156263","@schemeAgencyName":"ISO","@schemeName":"Packing Slip","@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}},"@xmlns":{"ns1":"http:\/\/www.sun.com\/schema\/spidermarkexpress\/sm-inv"}}}
diff --git a/1.9.10/samples/ns-soap.xml.jsn b/1.9.10/samples/ns-soap.xml.jsn new file mode 100644 index 0000000..63973a2 --- /dev/null +++ b/1.9.10/samples/ns-soap.xml.jsn
@@ -0,0 +1 @@ +{"soapenv:Envelope":{"soapenv:Body":{"ns1:reverseResponse":{"reverseReturn":{"@href":"#id0","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns1":"urn:axis.sosnoski.com"}},"@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns1":"urn:axis.sosnoski.com"}},"multiRef":[{"routes":{"item":[{"@href":"#id1","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns3":"urn:axis.sosnoski.com"}},{"@href":"#id2","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns3":"urn:axis.sosnoski.com"}},{"@href":"#id3","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns3":"urn:axis.sosnoski.com"}},{"@href":"#id4","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns3":"urn:axis.sosnoski.com"}},{"@href":"#id5","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns3":"urn:axis.sosnoski.com"}},{"@href":"#id6","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns3":"urn:axis.sosnoski.com"}},{"@href":"#id7","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns3":"urn:axis.sosnoski.com"}},{"@href":"#id8","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns3":"urn:axis.sosnoski.com"}},{"@href":"#id9","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns3":"urn:axis.sosnoski.com"}},{"@href":"#id10","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns3":"urn:axis.sosnoski.com"}},{"@href":"#id11","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns3":"urn:axis.sosnoski.com"}},{"@href":"#id12","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns3":"urn:axis.sosnoski.com"}},{"@href":"#id13","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns3":"urn:axis.sosnoski.com"}},{"@href":"#id14","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns3":"urn:axis.sosnoski.com"}},{"@href":"#id15","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns3":"urn:axis.sosnoski.com"}},{"@href":"#id16","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns3":"urn:axis.sosnoski.com"}},{"@href":"#id17","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns3":"urn:axis.sosnoski.com"}},{"@href":"#id18","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns3":"urn:axis.sosnoski.com"}},{"@href":"#id19","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns3":"urn:axis.sosnoski.com"}},{"@href":"#id20","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns3":"urn:axis.sosnoski.com"}},{"@href":"#id21","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns3":"urn:axis.sosnoski.com"}},{"@href":"#id22","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns3":"urn:axis.sosnoski.com"}},{"@href":"#id23","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns3":"urn:axis.sosnoski.com"}},{"@href":"#id24","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns3":"urn:axis.sosnoski.com"}},{"@href":"#id25","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns3":"urn:axis.sosnoski.com"}},{"@href":"#id26","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns3":"urn:axis.sosnoski.com"}},{"@href":"#id27","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns3":"urn:axis.sosnoski.com"}},{"@href":"#id28","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns3":"urn:axis.sosnoski.com"}},{"@href":"#id29","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns3":"urn:axis.sosnoski.com"}},{"@href":"#id30","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns3":"urn:axis.sosnoski.com"}},{"@href":"#id31","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns3":"urn:axis.sosnoski.com"}},{"@href":"#id32","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns3":"urn:axis.sosnoski.com"}},{"@href":"#id33","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns3":"urn:axis.sosnoski.com"}},{"@href":"#id34","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns3":"urn:axis.sosnoski.com"}},{"@href":"#id35","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns3":"urn:axis.sosnoski.com"}},{"@href":"#id36","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns3":"urn:axis.sosnoski.com"}},{"@href":"#id37","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns3":"urn:axis.sosnoski.com"}},{"@href":"#id38","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns3":"urn:axis.sosnoski.com"}},{"@href":"#id39","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns3":"urn:axis.sosnoski.com"}},{"@href":"#id40","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns3":"urn:axis.sosnoski.com"}},{"@href":"#id41","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns3":"urn:axis.sosnoski.com"}},{"@href":"#id42","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns3":"urn:axis.sosnoski.com"}},{"@href":"#id43","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns3":"urn:axis.sosnoski.com"}},{"@href":"#id44","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns3":"urn:axis.sosnoski.com"}},{"@href":"#id45","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns3":"urn:axis.sosnoski.com"}},{"@href":"#id46","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns3":"urn:axis.sosnoski.com"}},{"@href":"#id47","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns3":"urn:axis.sosnoski.com"}},{"@href":"#id48","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns3":"urn:axis.sosnoski.com"}},{"@href":"#id49","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns3":"urn:axis.sosnoski.com"}},{"@href":"#id50","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns3":"urn:axis.sosnoski.com"}},{"@href":"#id51","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns3":"urn:axis.sosnoski.com"}},{"@href":"#id52","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns3":"urn:axis.sosnoski.com"}},{"@href":"#id53","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns3":"urn:axis.sosnoski.com"}},{"@href":"#id54","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns3":"urn:axis.sosnoski.com"}},{"@href":"#id55","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns3":"urn:axis.sosnoski.com"}},{"@href":"#id56","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns3":"urn:axis.sosnoski.com"}}],"@xsi:type":"soapenc:Array","@soapenc:arrayType":"ns2:RouteBean[56]","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns3":"urn:axis.sosnoski.com"}},"airports":{"item":[{"@href":"#id57","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns4":"urn:axis.sosnoski.com"}},{"@href":"#id58","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns4":"urn:axis.sosnoski.com"}},{"@href":"#id59","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns4":"urn:axis.sosnoski.com"}},{"@href":"#id60","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns4":"urn:axis.sosnoski.com"}},{"@href":"#id61","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns4":"urn:axis.sosnoski.com"}},{"@href":"#id62","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns4":"urn:axis.sosnoski.com"}},{"@href":"#id63","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns4":"urn:axis.sosnoski.com"}},{"@href":"#id64","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns4":"urn:axis.sosnoski.com"}}],"@xsi:type":"soapenc:Array","@soapenc:arrayType":"ns2:AirportBean[8]","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns4":"urn:axis.sosnoski.com"}},"carriers":{"item":[{"@href":"#id65","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns5":"urn:axis.sosnoski.com"}},{"@href":"#id66","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns5":"urn:axis.sosnoski.com"}},{"@href":"#id67","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns5":"urn:axis.sosnoski.com"}},{"@href":"#id68","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns5":"urn:axis.sosnoski.com"}},{"@href":"#id69","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns5":"urn:axis.sosnoski.com"}},{"@href":"#id70","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns5":"urn:axis.sosnoski.com"}},{"@href":"#id71","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns5":"urn:axis.sosnoski.com"}},{"@href":"#id72","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns5":"urn:axis.sosnoski.com"}}],"@xsi:type":"soapenc:Array","@soapenc:arrayType":"ns2:CarrierBean[8]","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns5":"urn:axis.sosnoski.com"}},"@id":"id0","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns2:TimeTableBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","ns2":"http:\/\/flightsraw","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/"}},{"flights":{"item":[{"@href":"#id73","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns6":"http:\/\/flightsraw","ns7":"urn:axis.sosnoski.com"}},{"@href":"#id74","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns6":"http:\/\/flightsraw","ns7":"urn:axis.sosnoski.com"}},{"@href":"#id75","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns6":"http:\/\/flightsraw","ns7":"urn:axis.sosnoski.com"}}],"@xsi:type":"soapenc:Array","@soapenc:arrayType":"ns6:FlightBean[3]","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns6":"http:\/\/flightsraw","ns7":"urn:axis.sosnoski.com"}},"from":{"@href":"#id61","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns6":"http:\/\/flightsraw"}},"to":{"@href":"#id64","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns6":"http:\/\/flightsraw"}},"@id":"id49","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns6:RouteBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns6":"http:\/\/flightsraw"}},{"flights":{"item":[{"@href":"#id76","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns8":"http:\/\/flightsraw","ns9":"urn:axis.sosnoski.com"}},{"@href":"#id77","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns8":"http:\/\/flightsraw","ns9":"urn:axis.sosnoski.com"}},{"@href":"#id78","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns8":"http:\/\/flightsraw","ns9":"urn:axis.sosnoski.com"}},{"@href":"#id79","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns8":"http:\/\/flightsraw","ns9":"urn:axis.sosnoski.com"}},{"@href":"#id80","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns8":"http:\/\/flightsraw","ns9":"urn:axis.sosnoski.com"}}],"@xsi:type":"soapenc:Array","@soapenc:arrayType":"ns8:FlightBean[5]","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns8":"http:\/\/flightsraw","ns9":"urn:axis.sosnoski.com"}},"from":{"@href":"#id60","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns8":"http:\/\/flightsraw"}},"to":{"@href":"#id59","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns8":"http:\/\/flightsraw"}},"@id":"id28","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns8:RouteBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns8":"http:\/\/flightsraw"}},{"location":{"$":"Chicago, IL","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns10":"http:\/\/flightsraw"}},"name":{"$":"O'Hare International Airport","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns10":"http:\/\/flightsraw"}},"ident":{"$":"ORD","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns10":"http:\/\/flightsraw"}},"@id":"id61","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns10:AirportBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns10":"http:\/\/flightsraw"}},{"flights":{"item":[{"@href":"#id81","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns11":"http:\/\/flightsraw","ns12":"urn:axis.sosnoski.com"}},{"@href":"#id82","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns11":"http:\/\/flightsraw","ns12":"urn:axis.sosnoski.com"}},{"@href":"#id83","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns11":"http:\/\/flightsraw","ns12":"urn:axis.sosnoski.com"}},{"@href":"#id84","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns11":"http:\/\/flightsraw","ns12":"urn:axis.sosnoski.com"}},{"@href":"#id85","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns11":"http:\/\/flightsraw","ns12":"urn:axis.sosnoski.com"}},{"@href":"#id86","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns11":"http:\/\/flightsraw","ns12":"urn:axis.sosnoski.com"}},{"@href":"#id87","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns11":"http:\/\/flightsraw","ns12":"urn:axis.sosnoski.com"}},{"@href":"#id88","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns11":"http:\/\/flightsraw","ns12":"urn:axis.sosnoski.com"}}],"@xsi:type":"soapenc:Array","@soapenc:arrayType":"ns11:FlightBean[8]","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns11":"http:\/\/flightsraw","ns12":"urn:axis.sosnoski.com"}},"from":{"@href":"#id60","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns11":"http:\/\/flightsraw"}},"to":{"@href":"#id61","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns11":"http:\/\/flightsraw"}},"@id":"id37","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns11:RouteBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns11":"http:\/\/flightsraw"}},{"flights":{"item":[{"@href":"#id89","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns13":"http:\/\/flightsraw","ns14":"urn:axis.sosnoski.com"}},{"@href":"#id90","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns13":"http:\/\/flightsraw","ns14":"urn:axis.sosnoski.com"}},{"@href":"#id91","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns13":"http:\/\/flightsraw","ns14":"urn:axis.sosnoski.com"}},{"@href":"#id92","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns13":"http:\/\/flightsraw","ns14":"urn:axis.sosnoski.com"}},{"@href":"#id93","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns13":"http:\/\/flightsraw","ns14":"urn:axis.sosnoski.com"}}],"@xsi:type":"soapenc:Array","@soapenc:arrayType":"ns13:FlightBean[5]","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns13":"http:\/\/flightsraw","ns14":"urn:axis.sosnoski.com"}},"from":{"@href":"#id63","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns13":"http:\/\/flightsraw"}},"to":{"@href":"#id60","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns13":"http:\/\/flightsraw"}},"@id":"id42","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns13:RouteBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns13":"http:\/\/flightsraw"}},{"flights":{"item":[{"@href":"#id94","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns15":"http:\/\/flightsraw","ns16":"urn:axis.sosnoski.com"}},{"@href":"#id95","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns15":"http:\/\/flightsraw","ns16":"urn:axis.sosnoski.com"}}],"@xsi:type":"soapenc:Array","@soapenc:arrayType":"ns15:FlightBean[2]","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns15":"http:\/\/flightsraw","ns16":"urn:axis.sosnoski.com"}},"from":{"@href":"#id61","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns15":"http:\/\/flightsraw"}},"to":{"@href":"#id59","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns15":"http:\/\/flightsraw"}},"@id":"id30","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns15:RouteBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns15":"http:\/\/flightsraw"}},{"flights":{"item":[{"@href":"#id96","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns17":"http:\/\/flightsraw","ns18":"urn:axis.sosnoski.com"}},{"@href":"#id97","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns17":"http:\/\/flightsraw","ns18":"urn:axis.sosnoski.com"}},{"@href":"#id98","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns17":"http:\/\/flightsraw","ns18":"urn:axis.sosnoski.com"}},{"@href":"#id99","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns17":"http:\/\/flightsraw","ns18":"urn:axis.sosnoski.com"}},{"@href":"#id100","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns17":"http:\/\/flightsraw","ns18":"urn:axis.sosnoski.com"}}],"@xsi:type":"soapenc:Array","@soapenc:arrayType":"ns17:FlightBean[5]","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns17":"http:\/\/flightsraw","ns18":"urn:axis.sosnoski.com"}},"from":{"@href":"#id58","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns17":"http:\/\/flightsraw"}},"to":{"@href":"#id61","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns17":"http:\/\/flightsraw"}},"@id":"id19","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns17:RouteBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns17":"http:\/\/flightsraw"}},{"flights":{"item":[{"@href":"#id101","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns19":"http:\/\/flightsraw","ns20":"urn:axis.sosnoski.com"}},{"@href":"#id102","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns19":"http:\/\/flightsraw","ns20":"urn:axis.sosnoski.com"}},{"@href":"#id103","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns19":"http:\/\/flightsraw","ns20":"urn:axis.sosnoski.com"}},{"@href":"#id104","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns19":"http:\/\/flightsraw","ns20":"urn:axis.sosnoski.com"}},{"@href":"#id105","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns19":"http:\/\/flightsraw","ns20":"urn:axis.sosnoski.com"}},{"@href":"#id106","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns19":"http:\/\/flightsraw","ns20":"urn:axis.sosnoski.com"}}],"@xsi:type":"soapenc:Array","@soapenc:arrayType":"ns19:FlightBean[6]","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns19":"http:\/\/flightsraw","ns20":"urn:axis.sosnoski.com"}},"from":{"@href":"#id64","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns19":"http:\/\/flightsraw"}},"to":{"@href":"#id62","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns19":"http:\/\/flightsraw"}},"@id":"id54","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns19:RouteBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns19":"http:\/\/flightsraw"}},{"flights":{"item":[{"@href":"#id107","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns21":"http:\/\/flightsraw","ns22":"urn:axis.sosnoski.com"}},{"@href":"#id108","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns21":"http:\/\/flightsraw","ns22":"urn:axis.sosnoski.com"}},{"@href":"#id109","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns21":"http:\/\/flightsraw","ns22":"urn:axis.sosnoski.com"}},{"@href":"#id110","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns21":"http:\/\/flightsraw","ns22":"urn:axis.sosnoski.com"}}],"@xsi:type":"soapenc:Array","@soapenc:arrayType":"ns21:FlightBean[4]","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns21":"http:\/\/flightsraw","ns22":"urn:axis.sosnoski.com"}},"from":{"@href":"#id59","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns21":"http:\/\/flightsraw"}},"to":{"@href":"#id58","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns21":"http:\/\/flightsraw"}},"@id":"id16","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns21:RouteBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns21":"http:\/\/flightsraw"}},{"flights":{"item":[{"@href":"#id111","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns23":"http:\/\/flightsraw","ns24":"urn:axis.sosnoski.com"}},{"@href":"#id112","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns23":"http:\/\/flightsraw","ns24":"urn:axis.sosnoski.com"}},{"@href":"#id113","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns23":"http:\/\/flightsraw","ns24":"urn:axis.sosnoski.com"}},{"@href":"#id114","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns23":"http:\/\/flightsraw","ns24":"urn:axis.sosnoski.com"}},{"@href":"#id115","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns23":"http:\/\/flightsraw","ns24":"urn:axis.sosnoski.com"}},{"@href":"#id116","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns23":"http:\/\/flightsraw","ns24":"urn:axis.sosnoski.com"}}],"@xsi:type":"soapenc:Array","@soapenc:arrayType":"ns23:FlightBean[6]","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns23":"http:\/\/flightsraw","ns24":"urn:axis.sosnoski.com"}},"from":{"@href":"#id64","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns23":"http:\/\/flightsraw"}},"to":{"@href":"#id58","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns23":"http:\/\/flightsraw"}},"@id":"id26","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns23:RouteBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns23":"http:\/\/flightsraw"}},{"URL":{"$":"http:\/\/www.northleft.com","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns25":"http:\/\/flightsraw"}},"name":{"$":"Northleft Airlines","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns25":"http:\/\/flightsraw"}},"rating":{"$":"4","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns25":"http:\/\/flightsraw"}},"ident":{"$":"NL","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns25":"http:\/\/flightsraw"}},"@id":"id70","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns25:CarrierBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns25":"http:\/\/flightsraw"}},{"flights":{"item":[{"@href":"#id117","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns26":"http:\/\/flightsraw","ns27":"urn:axis.sosnoski.com"}},{"@href":"#id118","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns26":"http:\/\/flightsraw","ns27":"urn:axis.sosnoski.com"}}],"@xsi:type":"soapenc:Array","@soapenc:arrayType":"ns26:FlightBean[2]","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns26":"http:\/\/flightsraw","ns27":"urn:axis.sosnoski.com"}},"from":{"@href":"#id59","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns26":"http:\/\/flightsraw"}},"to":{"@href":"#id61","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns26":"http:\/\/flightsraw"}},"@id":"id29","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns26:RouteBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns26":"http:\/\/flightsraw"}},{"flights":{"item":{"@href":"#id119","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns28":"http:\/\/flightsraw","ns29":"urn:axis.sosnoski.com"}},"@xsi:type":"soapenc:Array","@soapenc:arrayType":"ns28:FlightBean[1]","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns28":"http:\/\/flightsraw","ns29":"urn:axis.sosnoski.com"}},"from":{"@href":"#id57","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns28":"http:\/\/flightsraw"}},"to":{"@href":"#id63","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns28":"http:\/\/flightsraw"}},"@id":"id11","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns28:RouteBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns28":"http:\/\/flightsraw"}},{"flights":{"item":{"@href":"#id120","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns30":"http:\/\/flightsraw","ns31":"urn:axis.sosnoski.com"}},"@xsi:type":"soapenc:Array","@soapenc:arrayType":"ns30:FlightBean[1]","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns30":"http:\/\/flightsraw","ns31":"urn:axis.sosnoski.com"}},"from":{"@href":"#id64","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns30":"http:\/\/flightsraw"}},"to":{"@href":"#id57","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns30":"http:\/\/flightsraw"}},"@id":"id14","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns30:RouteBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns30":"http:\/\/flightsraw"}},{"location":{"$":"San Francisco, CA","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns32":"http:\/\/flightsraw"}},"name":{"$":"San Francisco International Airport","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns32":"http:\/\/flightsraw"}},"ident":{"$":"SFO","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns32":"http:\/\/flightsraw"}},"@id":"id63","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns32:AirportBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns32":"http:\/\/flightsraw"}},{"flights":{"item":[{"@href":"#id121","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns33":"http:\/\/flightsraw","ns34":"urn:axis.sosnoski.com"}},{"@href":"#id122","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns33":"http:\/\/flightsraw","ns34":"urn:axis.sosnoski.com"}},{"@href":"#id123","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns33":"http:\/\/flightsraw","ns34":"urn:axis.sosnoski.com"}},{"@href":"#id124","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns33":"http:\/\/flightsraw","ns34":"urn:axis.sosnoski.com"}},{"@href":"#id125","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns33":"http:\/\/flightsraw","ns34":"urn:axis.sosnoski.com"}},{"@href":"#id126","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns33":"http:\/\/flightsraw","ns34":"urn:axis.sosnoski.com"}},{"@href":"#id127","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns33":"http:\/\/flightsraw","ns34":"urn:axis.sosnoski.com"}}],"@xsi:type":"soapenc:Array","@soapenc:arrayType":"ns33:FlightBean[7]","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns33":"http:\/\/flightsraw","ns34":"urn:axis.sosnoski.com"}},"from":{"@href":"#id62","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns33":"http:\/\/flightsraw"}},"to":{"@href":"#id60","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns33":"http:\/\/flightsraw"}},"@id":"id40","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns33:RouteBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns33":"http:\/\/flightsraw"}},{"flights":{"item":{"@href":"#id128","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns35":"http:\/\/flightsraw","ns36":"urn:axis.sosnoski.com"}},"@xsi:type":"soapenc:Array","@soapenc:arrayType":"ns35:FlightBean[1]","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns35":"http:\/\/flightsraw","ns36":"urn:axis.sosnoski.com"}},"from":{"@href":"#id57","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns35":"http:\/\/flightsraw"}},"to":{"@href":"#id64","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns35":"http:\/\/flightsraw"}},"@id":"id13","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns35:RouteBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns35":"http:\/\/flightsraw"}},{"URL":{"$":"http:\/\/www.arcticairlines.com","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns37":"http:\/\/flightsraw"}},"name":{"$":"Arctic Airlines","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns37":"http:\/\/flightsraw"}},"rating":{"$":"9","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns37":"http:\/\/flightsraw"}},"ident":{"$":"AR","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns37":"http:\/\/flightsraw"}},"@id":"id65","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns37:CarrierBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns37":"http:\/\/flightsraw"}},{"URL":{"$":"http:\/\/www.classyskylines.com","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns38":"http:\/\/flightsraw"}},"name":{"$":"Classy Skylines","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns38":"http:\/\/flightsraw"}},"rating":{"$":"9","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns38":"http:\/\/flightsraw"}},"ident":{"$":"CL","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns38":"http:\/\/flightsraw"}},"@id":"id69","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns38:CarrierBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns38":"http:\/\/flightsraw"}},{"flights":{"item":[{"@href":"#id129","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns39":"http:\/\/flightsraw","ns40":"urn:axis.sosnoski.com"}},{"@href":"#id130","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns39":"http:\/\/flightsraw","ns40":"urn:axis.sosnoski.com"}},{"@href":"#id131","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns39":"http:\/\/flightsraw","ns40":"urn:axis.sosnoski.com"}},{"@href":"#id132","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns39":"http:\/\/flightsraw","ns40":"urn:axis.sosnoski.com"}},{"@href":"#id133","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns39":"http:\/\/flightsraw","ns40":"urn:axis.sosnoski.com"}},{"@href":"#id134","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns39":"http:\/\/flightsraw","ns40":"urn:axis.sosnoski.com"}},{"@href":"#id135","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns39":"http:\/\/flightsraw","ns40":"urn:axis.sosnoski.com"}},{"@href":"#id136","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns39":"http:\/\/flightsraw","ns40":"urn:axis.sosnoski.com"}}],"@xsi:type":"soapenc:Array","@soapenc:arrayType":"ns39:FlightBean[8]","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns39":"http:\/\/flightsraw","ns40":"urn:axis.sosnoski.com"}},"from":{"@href":"#id63","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns39":"http:\/\/flightsraw"}},"to":{"@href":"#id64","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns39":"http:\/\/flightsraw"}},"@id":"id55","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns39:RouteBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns39":"http:\/\/flightsraw"}},{"flights":{"item":[{"@href":"#id137","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns41":"http:\/\/flightsraw","ns42":"urn:axis.sosnoski.com"}},{"@href":"#id138","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns41":"http:\/\/flightsraw","ns42":"urn:axis.sosnoski.com"}},{"@href":"#id139","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns41":"http:\/\/flightsraw","ns42":"urn:axis.sosnoski.com"}},{"@href":"#id140","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns41":"http:\/\/flightsraw","ns42":"urn:axis.sosnoski.com"}},{"@href":"#id141","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns41":"http:\/\/flightsraw","ns42":"urn:axis.sosnoski.com"}},{"@href":"#id142","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns41":"http:\/\/flightsraw","ns42":"urn:axis.sosnoski.com"}}],"@xsi:type":"soapenc:Array","@soapenc:arrayType":"ns41:FlightBean[6]","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns41":"http:\/\/flightsraw","ns42":"urn:axis.sosnoski.com"}},"from":{"@href":"#id63","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns41":"http:\/\/flightsraw"}},"to":{"@href":"#id58","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns41":"http:\/\/flightsraw"}},"@id":"id24","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns41:RouteBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns41":"http:\/\/flightsraw"}},{"flights":{"item":[{"@href":"#id143","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns43":"http:\/\/flightsraw","ns44":"urn:axis.sosnoski.com"}},{"@href":"#id144","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns43":"http:\/\/flightsraw","ns44":"urn:axis.sosnoski.com"}},{"@href":"#id145","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns43":"http:\/\/flightsraw","ns44":"urn:axis.sosnoski.com"}},{"@href":"#id146","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns43":"http:\/\/flightsraw","ns44":"urn:axis.sosnoski.com"}}],"@xsi:type":"soapenc:Array","@soapenc:arrayType":"ns43:FlightBean[4]","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns43":"http:\/\/flightsraw","ns44":"urn:axis.sosnoski.com"}},"from":{"@href":"#id64","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns43":"http:\/\/flightsraw"}},"to":{"@href":"#id59","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns43":"http:\/\/flightsraw"}},"@id":"id36","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns43:RouteBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns43":"http:\/\/flightsraw"}},{"flights":{"item":[{"@href":"#id147","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns45":"http:\/\/flightsraw","ns46":"urn:axis.sosnoski.com"}},{"@href":"#id148","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns45":"http:\/\/flightsraw","ns46":"urn:axis.sosnoski.com"}},{"@href":"#id149","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns45":"http:\/\/flightsraw","ns46":"urn:axis.sosnoski.com"}},{"@href":"#id150","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns45":"http:\/\/flightsraw","ns46":"urn:axis.sosnoski.com"}},{"@href":"#id151","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns45":"http:\/\/flightsraw","ns46":"urn:axis.sosnoski.com"}}],"@xsi:type":"soapenc:Array","@soapenc:arrayType":"ns45:FlightBean[5]","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns45":"http:\/\/flightsraw","ns46":"urn:axis.sosnoski.com"}},"from":{"@href":"#id60","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns45":"http:\/\/flightsraw"}},"to":{"@href":"#id63","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns45":"http:\/\/flightsraw"}},"@id":"id41","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns45:RouteBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns45":"http:\/\/flightsraw"}},{"flights":{"item":[{"@href":"#id152","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns47":"http:\/\/flightsraw","ns48":"urn:axis.sosnoski.com"}},{"@href":"#id153","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns47":"http:\/\/flightsraw","ns48":"urn:axis.sosnoski.com"}},{"@href":"#id154","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns47":"http:\/\/flightsraw","ns48":"urn:axis.sosnoski.com"}},{"@href":"#id155","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns47":"http:\/\/flightsraw","ns48":"urn:axis.sosnoski.com"}},{"@href":"#id156","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns47":"http:\/\/flightsraw","ns48":"urn:axis.sosnoski.com"}},{"@href":"#id157","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns47":"http:\/\/flightsraw","ns48":"urn:axis.sosnoski.com"}}],"@xsi:type":"soapenc:Array","@soapenc:arrayType":"ns47:FlightBean[6]","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns47":"http:\/\/flightsraw","ns48":"urn:axis.sosnoski.com"}},"from":{"@href":"#id63","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns47":"http:\/\/flightsraw"}},"to":{"@href":"#id59","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns47":"http:\/\/flightsraw"}},"@id":"id34","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns47:RouteBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns47":"http:\/\/flightsraw"}},{"flights":{"item":[{"@href":"#id158","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns49":"http:\/\/flightsraw","ns50":"urn:axis.sosnoski.com"}},{"@href":"#id159","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns49":"http:\/\/flightsraw","ns50":"urn:axis.sosnoski.com"}},{"@href":"#id160","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns49":"http:\/\/flightsraw","ns50":"urn:axis.sosnoski.com"}},{"@href":"#id161","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns49":"http:\/\/flightsraw","ns50":"urn:axis.sosnoski.com"}},{"@href":"#id162","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns49":"http:\/\/flightsraw","ns50":"urn:axis.sosnoski.com"}},{"@href":"#id163","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns49":"http:\/\/flightsraw","ns50":"urn:axis.sosnoski.com"}},{"@href":"#id164","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns49":"http:\/\/flightsraw","ns50":"urn:axis.sosnoski.com"}},{"@href":"#id165","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns49":"http:\/\/flightsraw","ns50":"urn:axis.sosnoski.com"}},{"@href":"#id166","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns49":"http:\/\/flightsraw","ns50":"urn:axis.sosnoski.com"}},{"@href":"#id167","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns49":"http:\/\/flightsraw","ns50":"urn:axis.sosnoski.com"}}],"@xsi:type":"soapenc:Array","@soapenc:arrayType":"ns49:FlightBean[10]","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns49":"http:\/\/flightsraw","ns50":"urn:axis.sosnoski.com"}},"from":{"@href":"#id62","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns49":"http:\/\/flightsraw"}},"to":{"@href":"#id58","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns49":"http:\/\/flightsraw"}},"@id":"id22","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns49:RouteBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns49":"http:\/\/flightsraw"}},{"flights":{"item":[{"@href":"#id168","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns51":"http:\/\/flightsraw","ns52":"urn:axis.sosnoski.com"}},{"@href":"#id169","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns51":"http:\/\/flightsraw","ns52":"urn:axis.sosnoski.com"}},{"@href":"#id170","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns51":"http:\/\/flightsraw","ns52":"urn:axis.sosnoski.com"}},{"@href":"#id171","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns51":"http:\/\/flightsraw","ns52":"urn:axis.sosnoski.com"}},{"@href":"#id172","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns51":"http:\/\/flightsraw","ns52":"urn:axis.sosnoski.com"}},{"@href":"#id173","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns51":"http:\/\/flightsraw","ns52":"urn:axis.sosnoski.com"}},{"@href":"#id174","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns51":"http:\/\/flightsraw","ns52":"urn:axis.sosnoski.com"}},{"@href":"#id175","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns51":"http:\/\/flightsraw","ns52":"urn:axis.sosnoski.com"}}],"@xsi:type":"soapenc:Array","@soapenc:arrayType":"ns51:FlightBean[8]","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns51":"http:\/\/flightsraw","ns52":"urn:axis.sosnoski.com"}},"from":{"@href":"#id64","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns51":"http:\/\/flightsraw"}},"to":{"@href":"#id63","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns51":"http:\/\/flightsraw"}},"@id":"id56","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns51:RouteBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns51":"http:\/\/flightsraw"}},{"URL":{"$":"http:\/\/www.bumblingint.com","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns53":"http:\/\/flightsraw"}},"name":{"$":"Bumbling International","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns53":"http:\/\/flightsraw"}},"rating":{"$":"2","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns53":"http:\/\/flightsraw"}},"ident":{"$":"BI","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns53":"http:\/\/flightsraw"}},"@id":"id67","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns53:CarrierBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns53":"http:\/\/flightsraw"}},{"URL":{"$":"http:\/\/www.combinedlines.com","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns54":"http:\/\/flightsraw"}},"name":{"$":"Combined Airlines","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns54":"http:\/\/flightsraw"}},"rating":{"$":"7","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns54":"http:\/\/flightsraw"}},"ident":{"$":"CA","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns54":"http:\/\/flightsraw"}},"@id":"id66","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns54:CarrierBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns54":"http:\/\/flightsraw"}},{"location":{"$":"Miami, FL","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns55":"http:\/\/flightsraw"}},"name":{"$":"Miami International Airport","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns55":"http:\/\/flightsraw"}},"ident":{"$":"MIA","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns55":"http:\/\/flightsraw"}},"@id":"id58","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns55:AirportBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns55":"http:\/\/flightsraw"}},{"flights":{"item":[{"@href":"#id176","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns56":"http:\/\/flightsraw","ns57":"urn:axis.sosnoski.com"}},{"@href":"#id177","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns56":"http:\/\/flightsraw","ns57":"urn:axis.sosnoski.com"}},{"@href":"#id178","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns56":"http:\/\/flightsraw","ns57":"urn:axis.sosnoski.com"}},{"@href":"#id179","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns56":"http:\/\/flightsraw","ns57":"urn:axis.sosnoski.com"}},{"@href":"#id180","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns56":"http:\/\/flightsraw","ns57":"urn:axis.sosnoski.com"}}],"@xsi:type":"soapenc:Array","@soapenc:arrayType":"ns56:FlightBean[5]","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns56":"http:\/\/flightsraw","ns57":"urn:axis.sosnoski.com"}},"from":{"@href":"#id58","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns56":"http:\/\/flightsraw"}},"to":{"@href":"#id57","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns56":"http:\/\/flightsraw"}},"@id":"id2","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns56:RouteBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns56":"http:\/\/flightsraw"}},{"flights":{"item":[{"@href":"#id181","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns58":"http:\/\/flightsraw","ns59":"urn:axis.sosnoski.com"}},{"@href":"#id182","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns58":"http:\/\/flightsraw","ns59":"urn:axis.sosnoski.com"}},{"@href":"#id183","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns58":"http:\/\/flightsraw","ns59":"urn:axis.sosnoski.com"}},{"@href":"#id184","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns58":"http:\/\/flightsraw","ns59":"urn:axis.sosnoski.com"}}],"@xsi:type":"soapenc:Array","@soapenc:arrayType":"ns58:FlightBean[4]","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns58":"http:\/\/flightsraw","ns59":"urn:axis.sosnoski.com"}},"from":{"@href":"#id61","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns58":"http:\/\/flightsraw"}},"to":{"@href":"#id63","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns58":"http:\/\/flightsraw"}},"@id":"id47","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns58:RouteBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns58":"http:\/\/flightsraw"}},{"flights":{"item":[{"@href":"#id185","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns60":"http:\/\/flightsraw","ns61":"urn:axis.sosnoski.com"}},{"@href":"#id186","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns60":"http:\/\/flightsraw","ns61":"urn:axis.sosnoski.com"}},{"@href":"#id187","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns60":"http:\/\/flightsraw","ns61":"urn:axis.sosnoski.com"}}],"@xsi:type":"soapenc:Array","@soapenc:arrayType":"ns60:FlightBean[3]","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns60":"http:\/\/flightsraw","ns61":"urn:axis.sosnoski.com"}},"from":{"@href":"#id61","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns60":"http:\/\/flightsraw"}},"to":{"@href":"#id57","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns60":"http:\/\/flightsraw"}},"@id":"id8","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns60:RouteBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns60":"http:\/\/flightsraw"}},{"flights":{"item":[{"@href":"#id188","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns62":"http:\/\/flightsraw","ns63":"urn:axis.sosnoski.com"}},{"@href":"#id189","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns62":"http:\/\/flightsraw","ns63":"urn:axis.sosnoski.com"}},{"@href":"#id190","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns62":"http:\/\/flightsraw","ns63":"urn:axis.sosnoski.com"}},{"@href":"#id191","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns62":"http:\/\/flightsraw","ns63":"urn:axis.sosnoski.com"}},{"@href":"#id192","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns62":"http:\/\/flightsraw","ns63":"urn:axis.sosnoski.com"}},{"@href":"#id193","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns62":"http:\/\/flightsraw","ns63":"urn:axis.sosnoski.com"}},{"@href":"#id194","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns62":"http:\/\/flightsraw","ns63":"urn:axis.sosnoski.com"}},{"@href":"#id195","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns62":"http:\/\/flightsraw","ns63":"urn:axis.sosnoski.com"}}],"@xsi:type":"soapenc:Array","@soapenc:arrayType":"ns62:FlightBean[8]","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns62":"http:\/\/flightsraw","ns63":"urn:axis.sosnoski.com"}},"from":{"@href":"#id61","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns62":"http:\/\/flightsraw"}},"to":{"@href":"#id60","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns62":"http:\/\/flightsraw"}},"@id":"id38","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns62:RouteBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns62":"http:\/\/flightsraw"}},{"flights":{"item":[{"@href":"#id196","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns64":"http:\/\/flightsraw","ns65":"urn:axis.sosnoski.com"}},{"@href":"#id197","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns64":"http:\/\/flightsraw","ns65":"urn:axis.sosnoski.com"}},{"@href":"#id198","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns64":"http:\/\/flightsraw","ns65":"urn:axis.sosnoski.com"}},{"@href":"#id199","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns64":"http:\/\/flightsraw","ns65":"urn:axis.sosnoski.com"}},{"@href":"#id200","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns64":"http:\/\/flightsraw","ns65":"urn:axis.sosnoski.com"}},{"@href":"#id201","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns64":"http:\/\/flightsraw","ns65":"urn:axis.sosnoski.com"}},{"@href":"#id202","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns64":"http:\/\/flightsraw","ns65":"urn:axis.sosnoski.com"}},{"@href":"#id203","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns64":"http:\/\/flightsraw","ns65":"urn:axis.sosnoski.com"}},{"@href":"#id204","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns64":"http:\/\/flightsraw","ns65":"urn:axis.sosnoski.com"}}],"@xsi:type":"soapenc:Array","@soapenc:arrayType":"ns64:FlightBean[9]","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns64":"http:\/\/flightsraw","ns65":"urn:axis.sosnoski.com"}},"from":{"@href":"#id61","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns64":"http:\/\/flightsraw"}},"to":{"@href":"#id62","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns64":"http:\/\/flightsraw"}},"@id":"id45","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns64:RouteBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns64":"http:\/\/flightsraw"}},{"flights":{"item":[{"@href":"#id205","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns66":"http:\/\/flightsraw","ns67":"urn:axis.sosnoski.com"}},{"@href":"#id206","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns66":"http:\/\/flightsraw","ns67":"urn:axis.sosnoski.com"}},{"@href":"#id207","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns66":"http:\/\/flightsraw","ns67":"urn:axis.sosnoski.com"}},{"@href":"#id208","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns66":"http:\/\/flightsraw","ns67":"urn:axis.sosnoski.com"}}],"@xsi:type":"soapenc:Array","@soapenc:arrayType":"ns66:FlightBean[4]","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns66":"http:\/\/flightsraw","ns67":"urn:axis.sosnoski.com"}},"from":{"@href":"#id59","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns66":"http:\/\/flightsraw"}},"to":{"@href":"#id57","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns66":"http:\/\/flightsraw"}},"@id":"id4","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns66:RouteBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns66":"http:\/\/flightsraw"}},{"flights":{"item":[{"@href":"#id209","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns68":"http:\/\/flightsraw","ns69":"urn:axis.sosnoski.com"}},{"@href":"#id210","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns68":"http:\/\/flightsraw","ns69":"urn:axis.sosnoski.com"}},{"@href":"#id211","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns68":"http:\/\/flightsraw","ns69":"urn:axis.sosnoski.com"}},{"@href":"#id212","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns68":"http:\/\/flightsraw","ns69":"urn:axis.sosnoski.com"}}],"@xsi:type":"soapenc:Array","@soapenc:arrayType":"ns68:FlightBean[4]","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns68":"http:\/\/flightsraw","ns69":"urn:axis.sosnoski.com"}},"from":{"@href":"#id62","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns68":"http:\/\/flightsraw"}},"to":{"@href":"#id59","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns68":"http:\/\/flightsraw"}},"@id":"id32","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns68:RouteBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns68":"http:\/\/flightsraw"}},{"URL":{"$":"http:\/\/www.serenityflights.com","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns70":"http:\/\/flightsraw"}},"name":{"$":"Serenity Flights, Inc.","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns70":"http:\/\/flightsraw"}},"rating":{"$":"7","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns70":"http:\/\/flightsraw"}},"ident":{"$":"SF","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns70":"http:\/\/flightsraw"}},"@id":"id72","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns70:CarrierBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns70":"http:\/\/flightsraw"}},{"flights":{"item":[{"@href":"#id213","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns71":"http:\/\/flightsraw","ns72":"urn:axis.sosnoski.com"}},{"@href":"#id214","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns71":"http:\/\/flightsraw","ns72":"urn:axis.sosnoski.com"}},{"@href":"#id215","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns71":"http:\/\/flightsraw","ns72":"urn:axis.sosnoski.com"}},{"@href":"#id216","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns71":"http:\/\/flightsraw","ns72":"urn:axis.sosnoski.com"}}],"@xsi:type":"soapenc:Array","@soapenc:arrayType":"ns71:FlightBean[4]","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns71":"http:\/\/flightsraw","ns72":"urn:axis.sosnoski.com"}},"from":{"@href":"#id59","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns71":"http:\/\/flightsraw"}},"to":{"@href":"#id64","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns71":"http:\/\/flightsraw"}},"@id":"id35","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns71:RouteBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns71":"http:\/\/flightsraw"}},{"flights":{"item":[{"@href":"#id217","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns73":"http:\/\/flightsraw","ns74":"urn:axis.sosnoski.com"}},{"@href":"#id218","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns73":"http:\/\/flightsraw","ns74":"urn:axis.sosnoski.com"}},{"@href":"#id219","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns73":"http:\/\/flightsraw","ns74":"urn:axis.sosnoski.com"}}],"@xsi:type":"soapenc:Array","@soapenc:arrayType":"ns73:FlightBean[3]","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns73":"http:\/\/flightsraw","ns74":"urn:axis.sosnoski.com"}},"from":{"@href":"#id57","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns73":"http:\/\/flightsraw"}},"to":{"@href":"#id61","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns73":"http:\/\/flightsraw"}},"@id":"id7","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns73:RouteBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns73":"http:\/\/flightsraw"}},{"flights":{"item":[{"@href":"#id220","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns75":"http:\/\/flightsraw","ns76":"urn:axis.sosnoski.com"}},{"@href":"#id221","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns75":"http:\/\/flightsraw","ns76":"urn:axis.sosnoski.com"}},{"@href":"#id222","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns75":"http:\/\/flightsraw","ns76":"urn:axis.sosnoski.com"}},{"@href":"#id223","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns75":"http:\/\/flightsraw","ns76":"urn:axis.sosnoski.com"}}],"@xsi:type":"soapenc:Array","@soapenc:arrayType":"ns75:FlightBean[4]","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns75":"http:\/\/flightsraw","ns76":"urn:axis.sosnoski.com"}},"from":{"@href":"#id58","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns75":"http:\/\/flightsraw"}},"to":{"@href":"#id59","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns75":"http:\/\/flightsraw"}},"@id":"id15","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns75:RouteBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns75":"http:\/\/flightsraw"}},{"flights":{"item":[{"@href":"#id224","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns77":"http:\/\/flightsraw","ns78":"urn:axis.sosnoski.com"}},{"@href":"#id225","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns77":"http:\/\/flightsraw","ns78":"urn:axis.sosnoski.com"}},{"@href":"#id226","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns77":"http:\/\/flightsraw","ns78":"urn:axis.sosnoski.com"}}],"@xsi:type":"soapenc:Array","@soapenc:arrayType":"ns77:FlightBean[3]","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns77":"http:\/\/flightsraw","ns78":"urn:axis.sosnoski.com"}},"from":{"@href":"#id63","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns77":"http:\/\/flightsraw"}},"to":{"@href":"#id62","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns77":"http:\/\/flightsraw"}},"@id":"id52","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns77:RouteBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns77":"http:\/\/flightsraw"}},{"flights":{"item":[{"@href":"#id227","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns79":"http:\/\/flightsraw","ns80":"urn:axis.sosnoski.com"}},{"@href":"#id228","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns79":"http:\/\/flightsraw","ns80":"urn:axis.sosnoski.com"}}],"@xsi:type":"soapenc:Array","@soapenc:arrayType":"ns79:FlightBean[2]","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns79":"http:\/\/flightsraw","ns80":"urn:axis.sosnoski.com"}},"from":{"@href":"#id57","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns79":"http:\/\/flightsraw"}},"to":{"@href":"#id62","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns79":"http:\/\/flightsraw"}},"@id":"id9","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns79:RouteBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns79":"http:\/\/flightsraw"}},{"flights":{"item":[{"@href":"#id229","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns81":"http:\/\/flightsraw","ns82":"urn:axis.sosnoski.com"}},{"@href":"#id230","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns81":"http:\/\/flightsraw","ns82":"urn:axis.sosnoski.com"}},{"@href":"#id231","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns81":"http:\/\/flightsraw","ns82":"urn:axis.sosnoski.com"}},{"@href":"#id232","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns81":"http:\/\/flightsraw","ns82":"urn:axis.sosnoski.com"}},{"@href":"#id233","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns81":"http:\/\/flightsraw","ns82":"urn:axis.sosnoski.com"}}],"@xsi:type":"soapenc:Array","@soapenc:arrayType":"ns81:FlightBean[5]","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns81":"http:\/\/flightsraw","ns82":"urn:axis.sosnoski.com"}},"from":{"@href":"#id59","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns81":"http:\/\/flightsraw"}},"to":{"@href":"#id60","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns81":"http:\/\/flightsraw"}},"@id":"id27","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns81:RouteBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns81":"http:\/\/flightsraw"}},{"location":{"$":"New York, NY","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns83":"http:\/\/flightsraw"}},"name":{"$":"John F. Kennedy International Airport","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns83":"http:\/\/flightsraw"}},"ident":{"$":"JFK","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns83":"http:\/\/flightsraw"}},"@id":"id62","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns83:AirportBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns83":"http:\/\/flightsraw"}},{"URL":{"$":"http:\/\/www.classyskylines.com","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns84":"http:\/\/flightsraw"}},"name":{"$":"Worldwide Airlines","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns84":"http:\/\/flightsraw"}},"rating":{"$":"7","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns84":"http:\/\/flightsraw"}},"ident":{"$":"WA","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns84":"http:\/\/flightsraw"}},"@id":"id68","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns84:CarrierBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns84":"http:\/\/flightsraw"}},{"flights":{"item":[{"@href":"#id234","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns85":"http:\/\/flightsraw","ns86":"urn:axis.sosnoski.com"}},{"@href":"#id235","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns85":"http:\/\/flightsraw","ns86":"urn:axis.sosnoski.com"}},{"@href":"#id236","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns85":"http:\/\/flightsraw","ns86":"urn:axis.sosnoski.com"}},{"@href":"#id237","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns85":"http:\/\/flightsraw","ns86":"urn:axis.sosnoski.com"}},{"@href":"#id238","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns85":"http:\/\/flightsraw","ns86":"urn:axis.sosnoski.com"}},{"@href":"#id239","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns85":"http:\/\/flightsraw","ns86":"urn:axis.sosnoski.com"}},{"@href":"#id240","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns85":"http:\/\/flightsraw","ns86":"urn:axis.sosnoski.com"}},{"@href":"#id241","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns85":"http:\/\/flightsraw","ns86":"urn:axis.sosnoski.com"}},{"@href":"#id242","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns85":"http:\/\/flightsraw","ns86":"urn:axis.sosnoski.com"}}],"@xsi:type":"soapenc:Array","@soapenc:arrayType":"ns85:FlightBean[9]","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns85":"http:\/\/flightsraw","ns86":"urn:axis.sosnoski.com"}},"from":{"@href":"#id60","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns85":"http:\/\/flightsraw"}},"to":{"@href":"#id58","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns85":"http:\/\/flightsraw"}},"@id":"id18","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns85:RouteBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns85":"http:\/\/flightsraw"}},{"flights":{"item":[{"@href":"#id243","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns87":"http:\/\/flightsraw","ns88":"urn:axis.sosnoski.com"}},{"@href":"#id244","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns87":"http:\/\/flightsraw","ns88":"urn:axis.sosnoski.com"}},{"@href":"#id245","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns87":"http:\/\/flightsraw","ns88":"urn:axis.sosnoski.com"}},{"@href":"#id246","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns87":"http:\/\/flightsraw","ns88":"urn:axis.sosnoski.com"}},{"@href":"#id247","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns87":"http:\/\/flightsraw","ns88":"urn:axis.sosnoski.com"}},{"@href":"#id248","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns87":"http:\/\/flightsraw","ns88":"urn:axis.sosnoski.com"}},{"@href":"#id249","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns87":"http:\/\/flightsraw","ns88":"urn:axis.sosnoski.com"}},{"@href":"#id250","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns87":"http:\/\/flightsraw","ns88":"urn:axis.sosnoski.com"}},{"@href":"#id251","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns87":"http:\/\/flightsraw","ns88":"urn:axis.sosnoski.com"}},{"@href":"#id252","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns87":"http:\/\/flightsraw","ns88":"urn:axis.sosnoski.com"}}],"@xsi:type":"soapenc:Array","@soapenc:arrayType":"ns87:FlightBean[10]","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns87":"http:\/\/flightsraw","ns88":"urn:axis.sosnoski.com"}},"from":{"@href":"#id58","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns87":"http:\/\/flightsraw"}},"to":{"@href":"#id62","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns87":"http:\/\/flightsraw"}},"@id":"id21","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns87:RouteBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns87":"http:\/\/flightsraw"}},{"flights":{"item":[{"@href":"#id253","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns89":"http:\/\/flightsraw","ns90":"urn:axis.sosnoski.com"}},{"@href":"#id254","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns89":"http:\/\/flightsraw","ns90":"urn:axis.sosnoski.com"}},{"@href":"#id255","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns89":"http:\/\/flightsraw","ns90":"urn:axis.sosnoski.com"}},{"@href":"#id256","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns89":"http:\/\/flightsraw","ns90":"urn:axis.sosnoski.com"}},{"@href":"#id257","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns89":"http:\/\/flightsraw","ns90":"urn:axis.sosnoski.com"}},{"@href":"#id258","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns89":"http:\/\/flightsraw","ns90":"urn:axis.sosnoski.com"}}],"@xsi:type":"soapenc:Array","@soapenc:arrayType":"ns89:FlightBean[6]","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns89":"http:\/\/flightsraw","ns90":"urn:axis.sosnoski.com"}},"from":{"@href":"#id62","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns89":"http:\/\/flightsraw"}},"to":{"@href":"#id64","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns89":"http:\/\/flightsraw"}},"@id":"id53","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns89:RouteBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns89":"http:\/\/flightsraw"}},{"flights":{"item":[{"@href":"#id259","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns91":"http:\/\/flightsraw","ns92":"urn:axis.sosnoski.com"}},{"@href":"#id260","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns91":"http:\/\/flightsraw","ns92":"urn:axis.sosnoski.com"}},{"@href":"#id261","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns91":"http:\/\/flightsraw","ns92":"urn:axis.sosnoski.com"}},{"@href":"#id262","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns91":"http:\/\/flightsraw","ns92":"urn:axis.sosnoski.com"}}],"@xsi:type":"soapenc:Array","@soapenc:arrayType":"ns91:FlightBean[4]","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns91":"http:\/\/flightsraw","ns92":"urn:axis.sosnoski.com"}},"from":{"@href":"#id59","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns91":"http:\/\/flightsraw"}},"to":{"@href":"#id62","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns91":"http:\/\/flightsraw"}},"@id":"id31","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns91:RouteBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns91":"http:\/\/flightsraw"}},{"flights":{"item":[{"@href":"#id263","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns93":"http:\/\/flightsraw","ns94":"urn:axis.sosnoski.com"}},{"@href":"#id264","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns93":"http:\/\/flightsraw","ns94":"urn:axis.sosnoski.com"}},{"@href":"#id265","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns93":"http:\/\/flightsraw","ns94":"urn:axis.sosnoski.com"}}],"@xsi:type":"soapenc:Array","@soapenc:arrayType":"ns93:FlightBean[3]","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns93":"http:\/\/flightsraw","ns94":"urn:axis.sosnoski.com"}},"from":{"@href":"#id62","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns93":"http:\/\/flightsraw"}},"to":{"@href":"#id63","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns93":"http:\/\/flightsraw"}},"@id":"id51","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns93:RouteBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns93":"http:\/\/flightsraw"}},{"flights":{"item":[{"@href":"#id266","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns95":"http:\/\/flightsraw","ns96":"urn:axis.sosnoski.com"}},{"@href":"#id267","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns95":"http:\/\/flightsraw","ns96":"urn:axis.sosnoski.com"}},{"@href":"#id268","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns95":"http:\/\/flightsraw","ns96":"urn:axis.sosnoski.com"}},{"@href":"#id269","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns95":"http:\/\/flightsraw","ns96":"urn:axis.sosnoski.com"}},{"@href":"#id270","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns95":"http:\/\/flightsraw","ns96":"urn:axis.sosnoski.com"}}],"@xsi:type":"soapenc:Array","@soapenc:arrayType":"ns95:FlightBean[5]","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns95":"http:\/\/flightsraw","ns96":"urn:axis.sosnoski.com"}},"from":{"@href":"#id57","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns95":"http:\/\/flightsraw"}},"to":{"@href":"#id58","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns95":"http:\/\/flightsraw"}},"@id":"id1","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns95:RouteBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns95":"http:\/\/flightsraw"}},{"flights":{"item":[{"@href":"#id271","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns97":"http:\/\/flightsraw","ns98":"urn:axis.sosnoski.com"}},{"@href":"#id272","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns97":"http:\/\/flightsraw","ns98":"urn:axis.sosnoski.com"}},{"@href":"#id273","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns97":"http:\/\/flightsraw","ns98":"urn:axis.sosnoski.com"}},{"@href":"#id274","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns97":"http:\/\/flightsraw","ns98":"urn:axis.sosnoski.com"}},{"@href":"#id275","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns97":"http:\/\/flightsraw","ns98":"urn:axis.sosnoski.com"}},{"@href":"#id276","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns97":"http:\/\/flightsraw","ns98":"urn:axis.sosnoski.com"}}],"@xsi:type":"soapenc:Array","@soapenc:arrayType":"ns97:FlightBean[6]","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns97":"http:\/\/flightsraw","ns98":"urn:axis.sosnoski.com"}},"from":{"@href":"#id64","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns97":"http:\/\/flightsraw"}},"to":{"@href":"#id60","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns97":"http:\/\/flightsraw"}},"@id":"id44","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns97:RouteBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns97":"http:\/\/flightsraw"}},{"location":{"$":"Boston, MA","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns99":"http:\/\/flightsraw"}},"name":{"$":"Logan International Airport","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns99":"http:\/\/flightsraw"}},"ident":{"$":"BOS","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns99":"http:\/\/flightsraw"}},"@id":"id60","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns99:AirportBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns99":"http:\/\/flightsraw"}},{"flights":{"item":[{"@href":"#id277","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns100":"http:\/\/flightsraw","ns101":"urn:axis.sosnoski.com"}},{"@href":"#id278","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns100":"http:\/\/flightsraw","ns101":"urn:axis.sosnoski.com"}},{"@href":"#id279","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns100":"http:\/\/flightsraw","ns101":"urn:axis.sosnoski.com"}},{"@href":"#id280","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns100":"http:\/\/flightsraw","ns101":"urn:axis.sosnoski.com"}},{"@href":"#id281","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns100":"http:\/\/flightsraw","ns101":"urn:axis.sosnoski.com"}},{"@href":"#id282","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns100":"http:\/\/flightsraw","ns101":"urn:axis.sosnoski.com"}}],"@xsi:type":"soapenc:Array","@soapenc:arrayType":"ns100:FlightBean[6]","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns100":"http:\/\/flightsraw","ns101":"urn:axis.sosnoski.com"}},"from":{"@href":"#id60","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns100":"http:\/\/flightsraw"}},"to":{"@href":"#id64","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns100":"http:\/\/flightsraw"}},"@id":"id43","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns100:RouteBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns100":"http:\/\/flightsraw"}},{"flights":{"item":[{"@href":"#id283","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns102":"http:\/\/flightsraw","ns103":"urn:axis.sosnoski.com"}},{"@href":"#id284","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns102":"http:\/\/flightsraw","ns103":"urn:axis.sosnoski.com"}},{"@href":"#id285","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns102":"http:\/\/flightsraw","ns103":"urn:axis.sosnoski.com"}},{"@href":"#id286","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns102":"http:\/\/flightsraw","ns103":"urn:axis.sosnoski.com"}},{"@href":"#id287","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns102":"http:\/\/flightsraw","ns103":"urn:axis.sosnoski.com"}},{"@href":"#id288","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns102":"http:\/\/flightsraw","ns103":"urn:axis.sosnoski.com"}}],"@xsi:type":"soapenc:Array","@soapenc:arrayType":"ns102:FlightBean[6]","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns102":"http:\/\/flightsraw","ns103":"urn:axis.sosnoski.com"}},"from":{"@href":"#id59","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns102":"http:\/\/flightsraw"}},"to":{"@href":"#id63","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns102":"http:\/\/flightsraw"}},"@id":"id33","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns102:RouteBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns102":"http:\/\/flightsraw"}},{"flights":{"item":[{"@href":"#id289","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns104":"http:\/\/flightsraw","ns105":"urn:axis.sosnoski.com"}},{"@href":"#id290","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns104":"http:\/\/flightsraw","ns105":"urn:axis.sosnoski.com"}},{"@href":"#id291","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns104":"http:\/\/flightsraw","ns105":"urn:axis.sosnoski.com"}},{"@href":"#id292","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns104":"http:\/\/flightsraw","ns105":"urn:axis.sosnoski.com"}},{"@href":"#id293","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns104":"http:\/\/flightsraw","ns105":"urn:axis.sosnoski.com"}},{"@href":"#id294","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns104":"http:\/\/flightsraw","ns105":"urn:axis.sosnoski.com"}}],"@xsi:type":"soapenc:Array","@soapenc:arrayType":"ns104:FlightBean[6]","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns104":"http:\/\/flightsraw","ns105":"urn:axis.sosnoski.com"}},"from":{"@href":"#id58","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns104":"http:\/\/flightsraw"}},"to":{"@href":"#id63","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns104":"http:\/\/flightsraw"}},"@id":"id23","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns104:RouteBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns104":"http:\/\/flightsraw"}},{"flights":{"item":[{"@href":"#id295","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns106":"http:\/\/flightsraw","ns107":"urn:axis.sosnoski.com"}},{"@href":"#id296","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns106":"http:\/\/flightsraw","ns107":"urn:axis.sosnoski.com"}},{"@href":"#id297","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns106":"http:\/\/flightsraw","ns107":"urn:axis.sosnoski.com"}},{"@href":"#id298","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns106":"http:\/\/flightsraw","ns107":"urn:axis.sosnoski.com"}},{"@href":"#id299","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns106":"http:\/\/flightsraw","ns107":"urn:axis.sosnoski.com"}}],"@xsi:type":"soapenc:Array","@soapenc:arrayType":"ns106:FlightBean[5]","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns106":"http:\/\/flightsraw","ns107":"urn:axis.sosnoski.com"}},"from":{"@href":"#id61","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns106":"http:\/\/flightsraw"}},"to":{"@href":"#id58","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns106":"http:\/\/flightsraw"}},"@id":"id20","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns106:RouteBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns106":"http:\/\/flightsraw"}},{"flights":{"item":[{"@href":"#id300","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns108":"http:\/\/flightsraw","ns109":"urn:axis.sosnoski.com"}},{"@href":"#id301","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns108":"http:\/\/flightsraw","ns109":"urn:axis.sosnoski.com"}},{"@href":"#id302","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns108":"http:\/\/flightsraw","ns109":"urn:axis.sosnoski.com"}},{"@href":"#id303","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns108":"http:\/\/flightsraw","ns109":"urn:axis.sosnoski.com"}},{"@href":"#id304","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns108":"http:\/\/flightsraw","ns109":"urn:axis.sosnoski.com"}},{"@href":"#id305","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns108":"http:\/\/flightsraw","ns109":"urn:axis.sosnoski.com"}}],"@xsi:type":"soapenc:Array","@soapenc:arrayType":"ns108:FlightBean[6]","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns108":"http:\/\/flightsraw","ns109":"urn:axis.sosnoski.com"}},"from":{"@href":"#id58","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns108":"http:\/\/flightsraw"}},"to":{"@href":"#id64","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns108":"http:\/\/flightsraw"}},"@id":"id25","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns108:RouteBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns108":"http:\/\/flightsraw"}},{"flights":{"item":[{"@href":"#id306","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns110":"http:\/\/flightsraw","ns111":"urn:axis.sosnoski.com"}},{"@href":"#id307","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns110":"http:\/\/flightsraw","ns111":"urn:axis.sosnoski.com"}},{"@href":"#id308","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns110":"http:\/\/flightsraw","ns111":"urn:axis.sosnoski.com"}},{"@href":"#id309","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns110":"http:\/\/flightsraw","ns111":"urn:axis.sosnoski.com"}},{"@href":"#id310","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns110":"http:\/\/flightsraw","ns111":"urn:axis.sosnoski.com"}}],"@xsi:type":"soapenc:Array","@soapenc:arrayType":"ns110:FlightBean[5]","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns110":"http:\/\/flightsraw","ns111":"urn:axis.sosnoski.com"}},"from":{"@href":"#id60","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns110":"http:\/\/flightsraw"}},"to":{"@href":"#id57","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns110":"http:\/\/flightsraw"}},"@id":"id6","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns110:RouteBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns110":"http:\/\/flightsraw"}},{"flights":{"item":[{"@href":"#id311","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns112":"http:\/\/flightsraw","ns113":"urn:axis.sosnoski.com"}},{"@href":"#id312","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns112":"http:\/\/flightsraw","ns113":"urn:axis.sosnoski.com"}},{"@href":"#id313","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns112":"http:\/\/flightsraw","ns113":"urn:axis.sosnoski.com"}},{"@href":"#id314","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns112":"http:\/\/flightsraw","ns113":"urn:axis.sosnoski.com"}},{"@href":"#id315","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns112":"http:\/\/flightsraw","ns113":"urn:axis.sosnoski.com"}},{"@href":"#id316","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns112":"http:\/\/flightsraw","ns113":"urn:axis.sosnoski.com"}},{"@href":"#id317","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns112":"http:\/\/flightsraw","ns113":"urn:axis.sosnoski.com"}},{"@href":"#id318","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns112":"http:\/\/flightsraw","ns113":"urn:axis.sosnoski.com"}},{"@href":"#id319","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns112":"http:\/\/flightsraw","ns113":"urn:axis.sosnoski.com"}}],"@xsi:type":"soapenc:Array","@soapenc:arrayType":"ns112:FlightBean[9]","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns112":"http:\/\/flightsraw","ns113":"urn:axis.sosnoski.com"}},"from":{"@href":"#id58","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns112":"http:\/\/flightsraw"}},"to":{"@href":"#id60","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns112":"http:\/\/flightsraw"}},"@id":"id17","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns112:RouteBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns112":"http:\/\/flightsraw"}},{"flights":{"item":[{"@href":"#id320","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns114":"http:\/\/flightsraw","ns115":"urn:axis.sosnoski.com"}},{"@href":"#id321","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns114":"http:\/\/flightsraw","ns115":"urn:axis.sosnoski.com"}},{"@href":"#id322","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns114":"http:\/\/flightsraw","ns115":"urn:axis.sosnoski.com"}},{"@href":"#id323","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns114":"http:\/\/flightsraw","ns115":"urn:axis.sosnoski.com"}}],"@xsi:type":"soapenc:Array","@soapenc:arrayType":"ns114:FlightBean[4]","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns114":"http:\/\/flightsraw","ns115":"urn:axis.sosnoski.com"}},"from":{"@href":"#id63","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns114":"http:\/\/flightsraw"}},"to":{"@href":"#id61","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns114":"http:\/\/flightsraw"}},"@id":"id48","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns114:RouteBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns114":"http:\/\/flightsraw"}},{"flights":{"item":[{"@href":"#id324","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns116":"http:\/\/flightsraw","ns117":"urn:axis.sosnoski.com"}},{"@href":"#id325","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns116":"http:\/\/flightsraw","ns117":"urn:axis.sosnoski.com"}}],"@xsi:type":"soapenc:Array","@soapenc:arrayType":"ns116:FlightBean[2]","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns116":"http:\/\/flightsraw","ns117":"urn:axis.sosnoski.com"}},"from":{"@href":"#id62","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns116":"http:\/\/flightsraw"}},"to":{"@href":"#id57","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns116":"http:\/\/flightsraw"}},"@id":"id10","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns116:RouteBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns116":"http:\/\/flightsraw"}},{"location":{"$":"Los Angeles, CA","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns118":"http:\/\/flightsraw"}},"name":{"$":"Los Angeles International Airport","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns118":"http:\/\/flightsraw"}},"ident":{"$":"LAX","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns118":"http:\/\/flightsraw"}},"@id":"id59","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns118:AirportBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns118":"http:\/\/flightsraw"}},{"location":{"$":"Denver, CO","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns119":"http:\/\/flightsraw"}},"name":{"$":"Denver International Airport","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns119":"http:\/\/flightsraw"}},"ident":{"$":"DEN","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns119":"http:\/\/flightsraw"}},"@id":"id64","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns119:AirportBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns119":"http:\/\/flightsraw"}},{"URL":{"$":"http:\/\/www.tempusfugit.com","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns120":"http:\/\/flightsraw"}},"name":{"$":"Tempus Fugit Lines","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns120":"http:\/\/flightsraw"}},"rating":{"$":"7","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns120":"http:\/\/flightsraw"}},"ident":{"$":"TF","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns120":"http:\/\/flightsraw"}},"@id":"id71","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns120:CarrierBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns120":"http:\/\/flightsraw"}},{"flights":{"item":[{"@href":"#id326","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns121":"http:\/\/flightsraw","ns122":"urn:axis.sosnoski.com"}},{"@href":"#id327","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns121":"http:\/\/flightsraw","ns122":"urn:axis.sosnoski.com"}},{"@href":"#id328","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns121":"http:\/\/flightsraw","ns122":"urn:axis.sosnoski.com"}},{"@href":"#id329","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns121":"http:\/\/flightsraw","ns122":"urn:axis.sosnoski.com"}},{"@href":"#id330","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns121":"http:\/\/flightsraw","ns122":"urn:axis.sosnoski.com"}},{"@href":"#id331","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns121":"http:\/\/flightsraw","ns122":"urn:axis.sosnoski.com"}},{"@href":"#id332","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns121":"http:\/\/flightsraw","ns122":"urn:axis.sosnoski.com"}}],"@xsi:type":"soapenc:Array","@soapenc:arrayType":"ns121:FlightBean[7]","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns121":"http:\/\/flightsraw","ns122":"urn:axis.sosnoski.com"}},"from":{"@href":"#id60","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns121":"http:\/\/flightsraw"}},"to":{"@href":"#id62","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns121":"http:\/\/flightsraw"}},"@id":"id39","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns121:RouteBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns121":"http:\/\/flightsraw"}},{"flights":{"item":[{"@href":"#id333","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns123":"http:\/\/flightsraw","ns124":"urn:axis.sosnoski.com"}},{"@href":"#id334","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns123":"http:\/\/flightsraw","ns124":"urn:axis.sosnoski.com"}},{"@href":"#id335","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns123":"http:\/\/flightsraw","ns124":"urn:axis.sosnoski.com"}},{"@href":"#id336","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns123":"http:\/\/flightsraw","ns124":"urn:axis.sosnoski.com"}},{"@href":"#id337","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns123":"http:\/\/flightsraw","ns124":"urn:axis.sosnoski.com"}}],"@xsi:type":"soapenc:Array","@soapenc:arrayType":"ns123:FlightBean[5]","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns123":"http:\/\/flightsraw","ns124":"urn:axis.sosnoski.com"}},"from":{"@href":"#id57","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns123":"http:\/\/flightsraw"}},"to":{"@href":"#id60","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns123":"http:\/\/flightsraw"}},"@id":"id5","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns123:RouteBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns123":"http:\/\/flightsraw"}},{"flights":{"item":[{"@href":"#id338","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns125":"http:\/\/flightsraw","ns126":"urn:axis.sosnoski.com"}},{"@href":"#id339","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns125":"http:\/\/flightsraw","ns126":"urn:axis.sosnoski.com"}},{"@href":"#id340","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns125":"http:\/\/flightsraw","ns126":"urn:axis.sosnoski.com"}},{"@href":"#id341","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns125":"http:\/\/flightsraw","ns126":"urn:axis.sosnoski.com"}},{"@href":"#id342","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns125":"http:\/\/flightsraw","ns126":"urn:axis.sosnoski.com"}},{"@href":"#id343","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns125":"http:\/\/flightsraw","ns126":"urn:axis.sosnoski.com"}},{"@href":"#id344","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns125":"http:\/\/flightsraw","ns126":"urn:axis.sosnoski.com"}},{"@href":"#id345","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns125":"http:\/\/flightsraw","ns126":"urn:axis.sosnoski.com"}},{"@href":"#id346","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns125":"http:\/\/flightsraw","ns126":"urn:axis.sosnoski.com"}}],"@xsi:type":"soapenc:Array","@soapenc:arrayType":"ns125:FlightBean[9]","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns125":"http:\/\/flightsraw","ns126":"urn:axis.sosnoski.com"}},"from":{"@href":"#id62","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns125":"http:\/\/flightsraw"}},"to":{"@href":"#id61","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns125":"http:\/\/flightsraw"}},"@id":"id46","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns125:RouteBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns125":"http:\/\/flightsraw"}},{"flights":{"item":[{"@href":"#id347","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns127":"http:\/\/flightsraw","ns128":"urn:axis.sosnoski.com"}},{"@href":"#id348","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns127":"http:\/\/flightsraw","ns128":"urn:axis.sosnoski.com"}},{"@href":"#id349","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns127":"http:\/\/flightsraw","ns128":"urn:axis.sosnoski.com"}},{"@href":"#id350","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns127":"http:\/\/flightsraw","ns128":"urn:axis.sosnoski.com"}}],"@xsi:type":"soapenc:Array","@soapenc:arrayType":"ns127:FlightBean[4]","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns127":"http:\/\/flightsraw","ns128":"urn:axis.sosnoski.com"}},"from":{"@href":"#id57","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns127":"http:\/\/flightsraw"}},"to":{"@href":"#id59","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns127":"http:\/\/flightsraw"}},"@id":"id3","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns127:RouteBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns127":"http:\/\/flightsraw"}},{"flights":{"item":[{"@href":"#id351","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns129":"http:\/\/flightsraw","ns130":"urn:axis.sosnoski.com"}},{"@href":"#id352","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns129":"http:\/\/flightsraw","ns130":"urn:axis.sosnoski.com"}},{"@href":"#id353","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns129":"http:\/\/flightsraw","ns130":"urn:axis.sosnoski.com"}}],"@xsi:type":"soapenc:Array","@soapenc:arrayType":"ns129:FlightBean[3]","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns129":"http:\/\/flightsraw","ns130":"urn:axis.sosnoski.com"}},"from":{"@href":"#id64","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns129":"http:\/\/flightsraw"}},"to":{"@href":"#id61","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns129":"http:\/\/flightsraw"}},"@id":"id50","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns129:RouteBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns129":"http:\/\/flightsraw"}},{"flights":{"item":{"@href":"#id354","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns131":"http:\/\/flightsraw","ns132":"urn:axis.sosnoski.com"}},"@xsi:type":"soapenc:Array","@soapenc:arrayType":"ns131:FlightBean[1]","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns131":"http:\/\/flightsraw","ns132":"urn:axis.sosnoski.com"}},"from":{"@href":"#id63","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns131":"http:\/\/flightsraw"}},"to":{"@href":"#id57","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns131":"http:\/\/flightsraw"}},"@id":"id12","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns131:RouteBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns131":"http:\/\/flightsraw"}},{"location":{"$":"Seattle, WA","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns133":"http:\/\/flightsraw"}},"name":{"$":"Seattle-Tacoma International Airport","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns133":"http:\/\/flightsraw"}},"ident":{"$":"SEA","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns133":"http:\/\/flightsraw"}},"@id":"id57","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns133:AirportBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns133":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"7:57p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns134":"http:\/\/flightsraw"}},"departureTime":{"$":"5:08p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns134":"http:\/\/flightsraw"}},"number":{"$":"671","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns134":"http:\/\/flightsraw"}},"carrier":{"@href":"#id69","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns134":"http:\/\/flightsraw"}},"@id":"id102","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns134:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns134":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"3:58a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns135":"http:\/\/flightsraw"}},"departureTime":{"$":"1:46a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns135":"http:\/\/flightsraw"}},"number":{"$":"709","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns135":"http:\/\/flightsraw"}},"carrier":{"@href":"#id67","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns135":"http:\/\/flightsraw"}},"@id":"id301","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns135:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns135":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"3:54a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns136":"http:\/\/flightsraw"}},"departureTime":{"$":"11:08p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns136":"http:\/\/flightsraw"}},"number":{"$":"275","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns136":"http:\/\/flightsraw"}},"carrier":{"@href":"#id67","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns136":"http:\/\/flightsraw"}},"@id":"id125","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns136:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns136":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"3:15a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns137":"http:\/\/flightsraw"}},"departureTime":{"$":"3:11a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns137":"http:\/\/flightsraw"}},"number":{"$":"809","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns137":"http:\/\/flightsraw"}},"carrier":{"@href":"#id68","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns137":"http:\/\/flightsraw"}},"@id":"id319","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns137:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns137":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"1:46a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns138":"http:\/\/flightsraw"}},"departureTime":{"$":"1:45a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns138":"http:\/\/flightsraw"}},"number":{"$":"709","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns138":"http:\/\/flightsraw"}},"carrier":{"@href":"#id70","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns138":"http:\/\/flightsraw"}},"@id":"id201","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns138:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns138":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"1:56a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns139":"http:\/\/flightsraw"}},"departureTime":{"$":"1:46a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns139":"http:\/\/flightsraw"}},"number":{"$":"346","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns139":"http:\/\/flightsraw"}},"carrier":{"@href":"#id71","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns139":"http:\/\/flightsraw"}},"@id":"id148","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns139:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns139":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"3:49p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns140":"http:\/\/flightsraw"}},"departureTime":{"$":"11:46a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns140":"http:\/\/flightsraw"}},"number":{"$":"523","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns140":"http:\/\/flightsraw"}},"carrier":{"@href":"#id71","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns140":"http:\/\/flightsraw"}},"@id":"id306","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns140:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns140":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"2:42a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns141":"http:\/\/flightsraw"}},"departureTime":{"$":"3:05a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns141":"http:\/\/flightsraw"}},"number":{"$":"934","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns141":"http:\/\/flightsraw"}},"carrier":{"@href":"#id70","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns141":"http:\/\/flightsraw"}},"@id":"id206","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns141:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns141":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"2:46a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns142":"http:\/\/flightsraw"}},"departureTime":{"$":"3:17a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns142":"http:\/\/flightsraw"}},"number":{"$":"749","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns142":"http:\/\/flightsraw"}},"carrier":{"@href":"#id68","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns142":"http:\/\/flightsraw"}},"@id":"id128","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns142:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns142":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"3:43p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns143":"http:\/\/flightsraw"}},"departureTime":{"$":"1:43p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns143":"http:\/\/flightsraw"}},"number":{"$":"569","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns143":"http:\/\/flightsraw"}},"carrier":{"@href":"#id68","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns143":"http:\/\/flightsraw"}},"@id":"id278","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns143:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns143":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"9:31a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns144":"http:\/\/flightsraw"}},"departureTime":{"$":"6:08a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns144":"http:\/\/flightsraw"}},"number":{"$":"690","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns144":"http:\/\/flightsraw"}},"carrier":{"@href":"#id65","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns144":"http:\/\/flightsraw"}},"@id":"id152","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns144:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns144":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"8:42a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns145":"http:\/\/flightsraw"}},"departureTime":{"$":"4:07a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns145":"http:\/\/flightsraw"}},"number":{"$":"731","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns145":"http:\/\/flightsraw"}},"carrier":{"@href":"#id66","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns145":"http:\/\/flightsraw"}},"@id":"id169","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns145:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns145":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"9:03a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns146":"http:\/\/flightsraw"}},"departureTime":{"$":"4:24a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns146":"http:\/\/flightsraw"}},"number":{"$":"600","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns146":"http:\/\/flightsraw"}},"carrier":{"@href":"#id68","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns146":"http:\/\/flightsraw"}},"@id":"id326","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns146:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns146":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"6:15p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns147":"http:\/\/flightsraw"}},"departureTime":{"$":"3:11p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns147":"http:\/\/flightsraw"}},"number":{"$":"485","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns147":"http:\/\/flightsraw"}},"carrier":{"@href":"#id72","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns147":"http:\/\/flightsraw"}},"@id":"id251","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns147:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns147":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"2:48a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns148":"http:\/\/flightsraw"}},"departureTime":{"$":"11:28p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns148":"http:\/\/flightsraw"}},"number":{"$":"409","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns148":"http:\/\/flightsraw"}},"carrier":{"@href":"#id66","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns148":"http:\/\/flightsraw"}},"@id":"id316","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns148:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns148":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"2:05a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns149":"http:\/\/flightsraw"}},"departureTime":{"$":"1:49a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns149":"http:\/\/flightsraw"}},"number":{"$":"714","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns149":"http:\/\/flightsraw"}},"carrier":{"@href":"#id65","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns149":"http:\/\/flightsraw"}},"@id":"id273","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns149:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns149":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"3:57a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns150":"http:\/\/flightsraw"}},"departureTime":{"$":"1:15a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns150":"http:\/\/flightsraw"}},"number":{"$":"861","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns150":"http:\/\/flightsraw"}},"carrier":{"@href":"#id71","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns150":"http:\/\/flightsraw"}},"@id":"id303","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns150:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns150":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"9:53a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns151":"http:\/\/flightsraw"}},"departureTime":{"$":"8:04a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns151":"http:\/\/flightsraw"}},"number":{"$":"687","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns151":"http:\/\/flightsraw"}},"carrier":{"@href":"#id65","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns151":"http:\/\/flightsraw"}},"@id":"id80","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns151:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns151":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"4:42a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns152":"http:\/\/flightsraw"}},"departureTime":{"$":"3:08a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns152":"http:\/\/flightsraw"}},"number":{"$":"316","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns152":"http:\/\/flightsraw"}},"carrier":{"@href":"#id71","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns152":"http:\/\/flightsraw"}},"@id":"id168","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns152:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns152":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"9:52a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns153":"http:\/\/flightsraw"}},"departureTime":{"$":"6:52a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns153":"http:\/\/flightsraw"}},"number":{"$":"292","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns153":"http:\/\/flightsraw"}},"carrier":{"@href":"#id66","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns153":"http:\/\/flightsraw"}},"@id":"id249","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns153:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns153":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"4:43a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns154":"http:\/\/flightsraw"}},"departureTime":{"$":"2:04a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns154":"http:\/\/flightsraw"}},"number":{"$":"357","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns154":"http:\/\/flightsraw"}},"carrier":{"@href":"#id72","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns154":"http:\/\/flightsraw"}},"@id":"id131","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns154:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns154":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"8:22p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns155":"http:\/\/flightsraw"}},"departureTime":{"$":"5:12p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns155":"http:\/\/flightsraw"}},"number":{"$":"848","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns155":"http:\/\/flightsraw"}},"carrier":{"@href":"#id70","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns155":"http:\/\/flightsraw"}},"@id":"id165","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns155:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns155":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"1:33a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns156":"http:\/\/flightsraw"}},"departureTime":{"$":"2:47a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns156":"http:\/\/flightsraw"}},"number":{"$":"649","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns156":"http:\/\/flightsraw"}},"carrier":{"@href":"#id69","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns156":"http:\/\/flightsraw"}},"@id":"id342","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns156:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns156":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"1:15a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns157":"http:\/\/flightsraw"}},"departureTime":{"$":"3:08a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns157":"http:\/\/flightsraw"}},"number":{"$":"213","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns157":"http:\/\/flightsraw"}},"carrier":{"@href":"#id69","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns157":"http:\/\/flightsraw"}},"@id":"id107","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns157:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns157":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"4:00a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns158":"http:\/\/flightsraw"}},"departureTime":{"$":"1:06a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns158":"http:\/\/flightsraw"}},"number":{"$":"778","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns158":"http:\/\/flightsraw"}},"carrier":{"@href":"#id71","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns158":"http:\/\/flightsraw"}},"@id":"id333","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns158:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns158":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"11:14p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns159":"http:\/\/flightsraw"}},"departureTime":{"$":"6:34p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns159":"http:\/\/flightsraw"}},"number":{"$":"769","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns159":"http:\/\/flightsraw"}},"carrier":{"@href":"#id69","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns159":"http:\/\/flightsraw"}},"@id":"id297","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns159:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns159":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"2:25a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns160":"http:\/\/flightsraw"}},"departureTime":{"$":"1:01a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns160":"http:\/\/flightsraw"}},"number":{"$":"891","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns160":"http:\/\/flightsraw"}},"carrier":{"@href":"#id65","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns160":"http:\/\/flightsraw"}},"@id":"id325","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns160:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns160":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"6:51p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns161":"http:\/\/flightsraw"}},"departureTime":{"$":"2:48p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns161":"http:\/\/flightsraw"}},"number":{"$":"672","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns161":"http:\/\/flightsraw"}},"carrier":{"@href":"#id70","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns161":"http:\/\/flightsraw"}},"@id":"id309","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns161:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns161":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"3:25a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns162":"http:\/\/flightsraw"}},"departureTime":{"$":"2:49a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns162":"http:\/\/flightsraw"}},"number":{"$":"439","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns162":"http:\/\/flightsraw"}},"carrier":{"@href":"#id71","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns162":"http:\/\/flightsraw"}},"@id":"id287","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns162:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns162":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"11:27p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns163":"http:\/\/flightsraw"}},"departureTime":{"$":"8:05p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns163":"http:\/\/flightsraw"}},"number":{"$":"812","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns163":"http:\/\/flightsraw"}},"carrier":{"@href":"#id69","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns163":"http:\/\/flightsraw"}},"@id":"id157","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns163:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns163":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"3:56a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns164":"http:\/\/flightsraw"}},"departureTime":{"$":"1:06a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns164":"http:\/\/flightsraw"}},"number":{"$":"585","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns164":"http:\/\/flightsraw"}},"carrier":{"@href":"#id70","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns164":"http:\/\/flightsraw"}},"@id":"id336","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns164:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns164":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"10:22p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns165":"http:\/\/flightsraw"}},"departureTime":{"$":"5:42p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns165":"http:\/\/flightsraw"}},"number":{"$":"226","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns165":"http:\/\/flightsraw"}},"carrier":{"@href":"#id71","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns165":"http:\/\/flightsraw"}},"@id":"id134","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns165:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns165":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"1:57p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns166":"http:\/\/flightsraw"}},"departureTime":{"$":"12:19p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns166":"http:\/\/flightsraw"}},"number":{"$":"898","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns166":"http:\/\/flightsraw"}},"carrier":{"@href":"#id67","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns166":"http:\/\/flightsraw"}},"@id":"id289","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns166:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns166":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"3:45p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns167":"http:\/\/flightsraw"}},"departureTime":{"$":"2:39p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns167":"http:\/\/flightsraw"}},"number":{"$":"749","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns167":"http:\/\/flightsraw"}},"carrier":{"@href":"#id67","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns167":"http:\/\/flightsraw"}},"@id":"id223","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns167:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns167":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"4:16p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns168":"http:\/\/flightsraw"}},"departureTime":{"$":"1:10p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns168":"http:\/\/flightsraw"}},"number":{"$":"726","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns168":"http:\/\/flightsraw"}},"carrier":{"@href":"#id66","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns168":"http:\/\/flightsraw"}},"@id":"id162","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns168:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns168":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"1:37a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns169":"http:\/\/flightsraw"}},"departureTime":{"$":"1:26a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns169":"http:\/\/flightsraw"}},"number":{"$":"919","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns169":"http:\/\/flightsraw"}},"carrier":{"@href":"#id68","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns169":"http:\/\/flightsraw"}},"@id":"id197","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns169:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns169":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"6:20p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns170":"http:\/\/flightsraw"}},"departureTime":{"$":"2:47p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns170":"http:\/\/flightsraw"}},"number":{"$":"372","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns170":"http:\/\/flightsraw"}},"carrier":{"@href":"#id70","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns170":"http:\/\/flightsraw"}},"@id":"id212","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns170:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns170":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"4:54p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns171":"http:\/\/flightsraw"}},"departureTime":{"$":"3:04p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns171":"http:\/\/flightsraw"}},"number":{"$":"293","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns171":"http:\/\/flightsraw"}},"carrier":{"@href":"#id68","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns171":"http:\/\/flightsraw"}},"@id":"id79","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns171:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns171":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"3:10a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns172":"http:\/\/flightsraw"}},"departureTime":{"$":"1:56a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns172":"http:\/\/flightsraw"}},"number":{"$":"906","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns172":"http:\/\/flightsraw"}},"carrier":{"@href":"#id72","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns172":"http:\/\/flightsraw"}},"@id":"id166","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns172:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns172":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"1:46a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns173":"http:\/\/flightsraw"}},"departureTime":{"$":"1:13a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns173":"http:\/\/flightsraw"}},"number":{"$":"212","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns173":"http:\/\/flightsraw"}},"carrier":{"@href":"#id70","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns173":"http:\/\/flightsraw"}},"@id":"id199","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns173:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns173":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"2:57a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns174":"http:\/\/flightsraw"}},"departureTime":{"$":"3:44a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns174":"http:\/\/flightsraw"}},"number":{"$":"747","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns174":"http:\/\/flightsraw"}},"carrier":{"@href":"#id66","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns174":"http:\/\/flightsraw"}},"@id":"id247","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns174:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns174":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"4:35a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns175":"http:\/\/flightsraw"}},"departureTime":{"$":"1:47a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns175":"http:\/\/flightsraw"}},"number":{"$":"595","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns175":"http:\/\/flightsraw"}},"carrier":{"@href":"#id68","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns175":"http:\/\/flightsraw"}},"@id":"id174","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns175:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns175":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"4:08p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns176":"http:\/\/flightsraw"}},"departureTime":{"$":"12:42p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns176":"http:\/\/flightsraw"}},"number":{"$":"647","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns176":"http:\/\/flightsraw"}},"carrier":{"@href":"#id67","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns176":"http:\/\/flightsraw"}},"@id":"id286","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns176:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns176":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"12:20p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns177":"http:\/\/flightsraw"}},"departureTime":{"$":"10:50a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns177":"http:\/\/flightsraw"}},"number":{"$":"404","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns177":"http:\/\/flightsraw"}},"carrier":{"@href":"#id68","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns177":"http:\/\/flightsraw"}},"@id":"id291","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns177:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns177":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"3:42a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns178":"http:\/\/flightsraw"}},"departureTime":{"$":"1:31a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns178":"http:\/\/flightsraw"}},"number":{"$":"349","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns178":"http:\/\/flightsraw"}},"carrier":{"@href":"#id65","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns178":"http:\/\/flightsraw"}},"@id":"id183","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns178:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns178":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"3:46a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns179":"http:\/\/flightsraw"}},"departureTime":{"$":"1:57a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns179":"http:\/\/flightsraw"}},"number":{"$":"377","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns179":"http:\/\/flightsraw"}},"carrier":{"@href":"#id72","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns179":"http:\/\/flightsraw"}},"@id":"id181","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns179:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns179":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"10:37p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns180":"http:\/\/flightsraw"}},"departureTime":{"$":"7:49p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns180":"http:\/\/flightsraw"}},"number":{"$":"420","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns180":"http:\/\/flightsraw"}},"carrier":{"@href":"#id72","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns180":"http:\/\/flightsraw"}},"@id":"id106","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns180:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns180":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"12:37a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns181":"http:\/\/flightsraw"}},"departureTime":{"$":"10:35p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns181":"http:\/\/flightsraw"}},"number":{"$":"932","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns181":"http:\/\/flightsraw"}},"carrier":{"@href":"#id68","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns181":"http:\/\/flightsraw"}},"@id":"id149","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns181:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns181":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"4:37p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns182":"http:\/\/flightsraw"}},"departureTime":{"$":"12:52p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns182":"http:\/\/flightsraw"}},"number":{"$":"891","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns182":"http:\/\/flightsraw"}},"carrier":{"@href":"#id71","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns182":"http:\/\/flightsraw"}},"@id":"id354","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns182:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns182":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"6:30a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns183":"http:\/\/flightsraw"}},"departureTime":{"$":"4:49a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns183":"http:\/\/flightsraw"}},"number":{"$":"823","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns183":"http:\/\/flightsraw"}},"carrier":{"@href":"#id69","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns183":"http:\/\/flightsraw"}},"@id":"id200","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns183:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns183":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"4:31a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns184":"http:\/\/flightsraw"}},"departureTime":{"$":"1:16a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns184":"http:\/\/flightsraw"}},"number":{"$":"259","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns184":"http:\/\/flightsraw"}},"carrier":{"@href":"#id70","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns184":"http:\/\/flightsraw"}},"@id":"id295","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns184:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns184":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"1:39a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns185":"http:\/\/flightsraw"}},"departureTime":{"$":"2:23a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns185":"http:\/\/flightsraw"}},"number":{"$":"692","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns185":"http:\/\/flightsraw"}},"carrier":{"@href":"#id68","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns185":"http:\/\/flightsraw"}},"@id":"id345","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns185:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns185":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"8:21p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns186":"http:\/\/flightsraw"}},"departureTime":{"$":"5:25p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns186":"http:\/\/flightsraw"}},"number":{"$":"979","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns186":"http:\/\/flightsraw"}},"carrier":{"@href":"#id69","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns186":"http:\/\/flightsraw"}},"@id":"id347","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns186:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns186":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"2:57a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns187":"http:\/\/flightsraw"}},"departureTime":{"$":"3:20a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns187":"http:\/\/flightsraw"}},"number":{"$":"299","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns187":"http:\/\/flightsraw"}},"carrier":{"@href":"#id70","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns187":"http:\/\/flightsraw"}},"@id":"id250","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns187:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns187":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"11:46a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns188":"http:\/\/flightsraw"}},"departureTime":{"$":"7:45a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns188":"http:\/\/flightsraw"}},"number":{"$":"269","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns188":"http:\/\/flightsraw"}},"carrier":{"@href":"#id70","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns188":"http:\/\/flightsraw"}},"@id":"id263","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns188:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns188":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"7:23p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns189":"http:\/\/flightsraw"}},"departureTime":{"$":"4:03p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns189":"http:\/\/flightsraw"}},"number":{"$":"847","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns189":"http:\/\/flightsraw"}},"carrier":{"@href":"#id72","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns189":"http:\/\/flightsraw"}},"@id":"id144","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns189:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns189":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"3:35a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns190":"http:\/\/flightsraw"}},"departureTime":{"$":"2:52a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns190":"http:\/\/flightsraw"}},"number":{"$":"291","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns190":"http:\/\/flightsraw"}},"carrier":{"@href":"#id67","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns190":"http:\/\/flightsraw"}},"@id":"id211","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns190:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns190":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"7:56p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns191":"http:\/\/flightsraw"}},"departureTime":{"$":"4:49p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns191":"http:\/\/flightsraw"}},"number":{"$":"768","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns191":"http:\/\/flightsraw"}},"carrier":{"@href":"#id65","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns191":"http:\/\/flightsraw"}},"@id":"id238","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns191:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns191":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"7:14p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns192":"http:\/\/flightsraw"}},"departureTime":{"$":"4:24p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns192":"http:\/\/flightsraw"}},"number":{"$":"373","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns192":"http:\/\/flightsraw"}},"carrier":{"@href":"#id69","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns192":"http:\/\/flightsraw"}},"@id":"id188","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns192:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns192":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"1:36p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns193":"http:\/\/flightsraw"}},"departureTime":{"$":"8:54a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns193":"http:\/\/flightsraw"}},"number":{"$":"267","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns193":"http:\/\/flightsraw"}},"carrier":{"@href":"#id70","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns193":"http:\/\/flightsraw"}},"@id":"id96","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns193:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns193":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"4:44a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns194":"http:\/\/flightsraw"}},"departureTime":{"$":"3:26a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns194":"http:\/\/flightsraw"}},"number":{"$":"339","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns194":"http:\/\/flightsraw"}},"carrier":{"@href":"#id68","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns194":"http:\/\/flightsraw"}},"@id":"id328","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns194:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns194":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"10:53p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns195":"http:\/\/flightsraw"}},"departureTime":{"$":"7:39p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns195":"http:\/\/flightsraw"}},"number":{"$":"871","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns195":"http:\/\/flightsraw"}},"carrier":{"@href":"#id66","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns195":"http:\/\/flightsraw"}},"@id":"id158","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns195:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns195":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"10:38a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns196":"http:\/\/flightsraw"}},"departureTime":{"$":"6:50a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns196":"http:\/\/flightsraw"}},"number":{"$":"718","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns196":"http:\/\/flightsraw"}},"carrier":{"@href":"#id69","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns196":"http:\/\/flightsraw"}},"@id":"id74","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns196:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns196":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"8:52a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns197":"http:\/\/flightsraw"}},"departureTime":{"$":"5:46a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns197":"http:\/\/flightsraw"}},"number":{"$":"239","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns197":"http:\/\/flightsraw"}},"carrier":{"@href":"#id65","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns197":"http:\/\/flightsraw"}},"@id":"id267","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns197:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns197":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"4:38a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns198":"http:\/\/flightsraw"}},"departureTime":{"$":"1:45a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns198":"http:\/\/flightsraw"}},"number":{"$":"277","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns198":"http:\/\/flightsraw"}},"carrier":{"@href":"#id66","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns198":"http:\/\/flightsraw"}},"@id":"id299","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns198:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns198":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"8:48p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns199":"http:\/\/flightsraw"}},"departureTime":{"$":"4:08p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns199":"http:\/\/flightsraw"}},"number":{"$":"279","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns199":"http:\/\/flightsraw"}},"carrier":{"@href":"#id68","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns199":"http:\/\/flightsraw"}},"@id":"id136","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns199:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns199":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"4:45a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns200":"http:\/\/flightsraw"}},"departureTime":{"$":"3:09a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns200":"http:\/\/flightsraw"}},"number":{"$":"889","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns200":"http:\/\/flightsraw"}},"carrier":{"@href":"#id68","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns200":"http:\/\/flightsraw"}},"@id":"id126","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns200:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns200":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"3:16a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns201":"http:\/\/flightsraw"}},"departureTime":{"$":"3:05a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns201":"http:\/\/flightsraw"}},"number":{"$":"994","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns201":"http:\/\/flightsraw"}},"carrier":{"@href":"#id68","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns201":"http:\/\/flightsraw"}},"@id":"id312","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns201:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns201":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"2:50a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns202":"http:\/\/flightsraw"}},"departureTime":{"$":"1:57a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns202":"http:\/\/flightsraw"}},"number":{"$":"862","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns202":"http:\/\/flightsraw"}},"carrier":{"@href":"#id69","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns202":"http:\/\/flightsraw"}},"@id":"id81","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns202:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns202":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"1:27a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns203":"http:\/\/flightsraw"}},"departureTime":{"$":"9:25p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns203":"http:\/\/flightsraw"}},"number":{"$":"363","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns203":"http:\/\/flightsraw"}},"carrier":{"@href":"#id68","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns203":"http:\/\/flightsraw"}},"@id":"id310","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns203:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns203":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"1:41a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns204":"http:\/\/flightsraw"}},"departureTime":{"$":"2:25a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns204":"http:\/\/flightsraw"}},"number":{"$":"273","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns204":"http:\/\/flightsraw"}},"carrier":{"@href":"#id68","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns204":"http:\/\/flightsraw"}},"@id":"id204","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns204:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns204":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"12:28p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns205":"http:\/\/flightsraw"}},"departureTime":{"$":"10:20a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns205":"http:\/\/flightsraw"}},"number":{"$":"625","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns205":"http:\/\/flightsraw"}},"carrier":{"@href":"#id65","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns205":"http:\/\/flightsraw"}},"@id":"id89","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns205:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns205":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"9:20p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns206":"http:\/\/flightsraw"}},"departureTime":{"$":"6:22p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns206":"http:\/\/flightsraw"}},"number":{"$":"945","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns206":"http:\/\/flightsraw"}},"carrier":{"@href":"#id65","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns206":"http:\/\/flightsraw"}},"@id":"id252","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns206:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns206":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"1:47a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns207":"http:\/\/flightsraw"}},"departureTime":{"$":"3:20a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns207":"http:\/\/flightsraw"}},"number":{"$":"406","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns207":"http:\/\/flightsraw"}},"carrier":{"@href":"#id67","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns207":"http:\/\/flightsraw"}},"@id":"id77","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns207:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns207":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"3:08a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns208":"http:\/\/flightsraw"}},"departureTime":{"$":"2:18a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns208":"http:\/\/flightsraw"}},"number":{"$":"497","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns208":"http:\/\/flightsraw"}},"carrier":{"@href":"#id65","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns208":"http:\/\/flightsraw"}},"@id":"id177","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns208:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns208":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"3:33a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns209":"http:\/\/flightsraw"}},"departureTime":{"$":"4:19a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns209":"http:\/\/flightsraw"}},"number":{"$":"746","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns209":"http:\/\/flightsraw"}},"carrier":{"@href":"#id70","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns209":"http:\/\/flightsraw"}},"@id":"id262","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns209:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns209":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"11:17p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns210":"http:\/\/flightsraw"}},"departureTime":{"$":"8:24p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns210":"http:\/\/flightsraw"}},"number":{"$":"823","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns210":"http:\/\/flightsraw"}},"carrier":{"@href":"#id69","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns210":"http:\/\/flightsraw"}},"@id":"id191","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns210:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns210":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"5:48a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns211":"http:\/\/flightsraw"}},"departureTime":{"$":"1:02a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns211":"http:\/\/flightsraw"}},"number":{"$":"332","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns211":"http:\/\/flightsraw"}},"carrier":{"@href":"#id67","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns211":"http:\/\/flightsraw"}},"@id":"id122","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns211:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns211":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"7:30p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns212":"http:\/\/flightsraw"}},"departureTime":{"$":"2:49p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns212":"http:\/\/flightsraw"}},"number":{"$":"549","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns212":"http:\/\/flightsraw"}},"carrier":{"@href":"#id66","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns212":"http:\/\/flightsraw"}},"@id":"id100","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns212:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns212":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"5:18p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns213":"http:\/\/flightsraw"}},"departureTime":{"$":"2:33p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns213":"http:\/\/flightsraw"}},"number":{"$":"609","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns213":"http:\/\/flightsraw"}},"carrier":{"@href":"#id70","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns213":"http:\/\/flightsraw"}},"@id":"id256","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns213:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns213":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"2:03a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns214":"http:\/\/flightsraw"}},"departureTime":{"$":"9:19p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns214":"http:\/\/flightsraw"}},"number":{"$":"263","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns214":"http:\/\/flightsraw"}},"carrier":{"@href":"#id66","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns214":"http:\/\/flightsraw"}},"@id":"id132","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns214:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns214":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"9:08a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns215":"http:\/\/flightsraw"}},"departureTime":{"$":"7:03a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns215":"http:\/\/flightsraw"}},"number":{"$":"310","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns215":"http:\/\/flightsraw"}},"carrier":{"@href":"#id65","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns215":"http:\/\/flightsraw"}},"@id":"id279","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns215:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns215":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"1:56a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns216":"http:\/\/flightsraw"}},"departureTime":{"$":"2:41a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns216":"http:\/\/flightsraw"}},"number":{"$":"836","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns216":"http:\/\/flightsraw"}},"carrier":{"@href":"#id65","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns216":"http:\/\/flightsraw"}},"@id":"id147","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns216:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns216":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"6:40a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns217":"http:\/\/flightsraw"}},"departureTime":{"$":"3:53a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns217":"http:\/\/flightsraw"}},"number":{"$":"612","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns217":"http:\/\/flightsraw"}},"carrier":{"@href":"#id65","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns217":"http:\/\/flightsraw"}},"@id":"id194","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns217:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns217":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"10:07p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns218":"http:\/\/flightsraw"}},"departureTime":{"$":"8:28p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns218":"http:\/\/flightsraw"}},"number":{"$":"508","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns218":"http:\/\/flightsraw"}},"carrier":{"@href":"#id67","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns218":"http:\/\/flightsraw"}},"@id":"id231","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns218:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns218":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"2:53p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns219":"http:\/\/flightsraw"}},"departureTime":{"$":"10:12a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns219":"http:\/\/flightsraw"}},"number":{"$":"753","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns219":"http:\/\/flightsraw"}},"carrier":{"@href":"#id68","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns219":"http:\/\/flightsraw"}},"@id":"id135","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns219:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns219":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"3:15a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns220":"http:\/\/flightsraw"}},"departureTime":{"$":"3:08a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns220":"http:\/\/flightsraw"}},"number":{"$":"572","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns220":"http:\/\/flightsraw"}},"carrier":{"@href":"#id65","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns220":"http:\/\/flightsraw"}},"@id":"id315","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns220:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns220":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"3:07a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns221":"http:\/\/flightsraw"}},"departureTime":{"$":"2:28a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns221":"http:\/\/flightsraw"}},"number":{"$":"511","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns221":"http:\/\/flightsraw"}},"carrier":{"@href":"#id65","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns221":"http:\/\/flightsraw"}},"@id":"id176","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns221:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns221":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"4:01a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns222":"http:\/\/flightsraw"}},"departureTime":{"$":"3:25a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns222":"http:\/\/flightsraw"}},"number":{"$":"832","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns222":"http:\/\/flightsraw"}},"carrier":{"@href":"#id71","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns222":"http:\/\/flightsraw"}},"@id":"id265","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns222:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns222":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"3:29a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns223":"http:\/\/flightsraw"}},"departureTime":{"$":"12:33a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns223":"http:\/\/flightsraw"}},"number":{"$":"493","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns223":"http:\/\/flightsraw"}},"carrier":{"@href":"#id65","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns223":"http:\/\/flightsraw"}},"@id":"id349","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns223:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns223":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"4:38a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns224":"http:\/\/flightsraw"}},"departureTime":{"$":"2:10a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns224":"http:\/\/flightsraw"}},"number":{"$":"785","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns224":"http:\/\/flightsraw"}},"carrier":{"@href":"#id71","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns224":"http:\/\/flightsraw"}},"@id":"id172","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns224:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns224":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"4:51p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns225":"http:\/\/flightsraw"}},"departureTime":{"$":"2:10p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns225":"http:\/\/flightsraw"}},"number":{"$":"940","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns225":"http:\/\/flightsraw"}},"carrier":{"@href":"#id68","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns225":"http:\/\/flightsraw"}},"@id":"id253","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns225:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns225":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"7:24p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns226":"http:\/\/flightsraw"}},"departureTime":{"$":"6:14p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns226":"http:\/\/flightsraw"}},"number":{"$":"767","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns226":"http:\/\/flightsraw"}},"carrier":{"@href":"#id66","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns226":"http:\/\/flightsraw"}},"@id":"id222","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns226:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns226":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"7:57p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns227":"http:\/\/flightsraw"}},"departureTime":{"$":"3:16p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns227":"http:\/\/flightsraw"}},"number":{"$":"707","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns227":"http:\/\/flightsraw"}},"carrier":{"@href":"#id66","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns227":"http:\/\/flightsraw"}},"@id":"id99","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns227:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns227":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"3:29a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns228":"http:\/\/flightsraw"}},"departureTime":{"$":"3:21a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns228":"http:\/\/flightsraw"}},"number":{"$":"987","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns228":"http:\/\/flightsraw"}},"carrier":{"@href":"#id71","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns228":"http:\/\/flightsraw"}},"@id":"id119","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns228:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns228":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"7:20p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns229":"http:\/\/flightsraw"}},"departureTime":{"$":"2:42p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns229":"http:\/\/flightsraw"}},"number":{"$":"963","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns229":"http:\/\/flightsraw"}},"carrier":{"@href":"#id68","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns229":"http:\/\/flightsraw"}},"@id":"id331","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns229:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns229":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"1:44a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns230":"http:\/\/flightsraw"}},"departureTime":{"$":"3:00a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns230":"http:\/\/flightsraw"}},"number":{"$":"363","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns230":"http:\/\/flightsraw"}},"carrier":{"@href":"#id65","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns230":"http:\/\/flightsraw"}},"@id":"id141","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns230:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns230":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"1:40a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns231":"http:\/\/flightsraw"}},"departureTime":{"$":"2:23a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns231":"http:\/\/flightsraw"}},"number":{"$":"774","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns231":"http:\/\/flightsraw"}},"carrier":{"@href":"#id67","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns231":"http:\/\/flightsraw"}},"@id":"id137","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns231:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns231":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"3:15a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns232":"http:\/\/flightsraw"}},"departureTime":{"$":"2:39a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns232":"http:\/\/flightsraw"}},"number":{"$":"355","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns232":"http:\/\/flightsraw"}},"carrier":{"@href":"#id71","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns232":"http:\/\/flightsraw"}},"@id":"id159","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns232:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns232":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"12:48p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns233":"http:\/\/flightsraw"}},"departureTime":{"$":"11:11a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns233":"http:\/\/flightsraw"}},"number":{"$":"610","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns233":"http:\/\/flightsraw"}},"carrier":{"@href":"#id70","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns233":"http:\/\/flightsraw"}},"@id":"id343","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns233:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns233":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"4:03a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns234":"http:\/\/flightsraw"}},"departureTime":{"$":"4:11a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns234":"http:\/\/flightsraw"}},"number":{"$":"771","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns234":"http:\/\/flightsraw"}},"carrier":{"@href":"#id68","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns234":"http:\/\/flightsraw"}},"@id":"id335","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns234:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns234":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"3:18a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns235":"http:\/\/flightsraw"}},"departureTime":{"$":"1:48a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns235":"http:\/\/flightsraw"}},"number":{"$":"388","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns235":"http:\/\/flightsraw"}},"carrier":{"@href":"#id67","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns235":"http:\/\/flightsraw"}},"@id":"id145","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns235:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns235":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"11:54a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns236":"http:\/\/flightsraw"}},"departureTime":{"$":"7:15a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns236":"http:\/\/flightsraw"}},"number":{"$":"920","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns236":"http:\/\/flightsraw"}},"carrier":{"@href":"#id68","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns236":"http:\/\/flightsraw"}},"@id":"id123","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns236:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns236":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"12:42a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns237":"http:\/\/flightsraw"}},"departureTime":{"$":"9:59p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns237":"http:\/\/flightsraw"}},"number":{"$":"589","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns237":"http:\/\/flightsraw"}},"carrier":{"@href":"#id71","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns237":"http:\/\/flightsraw"}},"@id":"id217","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns237:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns237":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"4:55p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns238":"http:\/\/flightsraw"}},"departureTime":{"$":"2:55p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns238":"http:\/\/flightsraw"}},"number":{"$":"648","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns238":"http:\/\/flightsraw"}},"carrier":{"@href":"#id71","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns238":"http:\/\/flightsraw"}},"@id":"id276","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns238:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns238":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"3:20a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns239":"http:\/\/flightsraw"}},"departureTime":{"$":"3:38a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns239":"http:\/\/flightsraw"}},"number":{"$":"476","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns239":"http:\/\/flightsraw"}},"carrier":{"@href":"#id72","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns239":"http:\/\/flightsraw"}},"@id":"id154","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns239:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns239":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"10:49a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns240":"http:\/\/flightsraw"}},"departureTime":{"$":"7:05a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns240":"http:\/\/flightsraw"}},"number":{"$":"910","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns240":"http:\/\/flightsraw"}},"carrier":{"@href":"#id69","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns240":"http:\/\/flightsraw"}},"@id":"id75","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns240:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns240":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"3:14a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns241":"http:\/\/flightsraw"}},"departureTime":{"$":"2:13a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns241":"http:\/\/flightsraw"}},"number":{"$":"804","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns241":"http:\/\/flightsraw"}},"carrier":{"@href":"#id69","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns241":"http:\/\/flightsraw"}},"@id":"id160","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns241:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns241":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"2:55a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns242":"http:\/\/flightsraw"}},"departureTime":{"$":"3:18a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns242":"http:\/\/flightsraw"}},"number":{"$":"646","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns242":"http:\/\/flightsraw"}},"carrier":{"@href":"#id70","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns242":"http:\/\/flightsraw"}},"@id":"id86","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns242:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns242":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"2:59a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns243":"http:\/\/flightsraw"}},"departureTime":{"$":"1:37a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns243":"http:\/\/flightsraw"}},"number":{"$":"602","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns243":"http:\/\/flightsraw"}},"carrier":{"@href":"#id66","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns243":"http:\/\/flightsraw"}},"@id":"id180","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns243:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns243":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"3:08p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns244":"http:\/\/flightsraw"}},"departureTime":{"$":"11:52a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns244":"http:\/\/flightsraw"}},"number":{"$":"716","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns244":"http:\/\/flightsraw"}},"carrier":{"@href":"#id66","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns244":"http:\/\/flightsraw"}},"@id":"id314","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns244:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns244":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"1:34a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns245":"http:\/\/flightsraw"}},"departureTime":{"$":"2:07a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns245":"http:\/\/flightsraw"}},"number":{"$":"231","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns245":"http:\/\/flightsraw"}},"carrier":{"@href":"#id71","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns245":"http:\/\/flightsraw"}},"@id":"id290","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns245:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns245":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"2:09a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns246":"http:\/\/flightsraw"}},"departureTime":{"$":"2:13a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns246":"http:\/\/flightsraw"}},"number":{"$":"576","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns246":"http:\/\/flightsraw"}},"carrier":{"@href":"#id72","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns246":"http:\/\/flightsraw"}},"@id":"id95","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns246:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns246":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"4:12p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns247":"http:\/\/flightsraw"}},"departureTime":{"$":"2:32p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns247":"http:\/\/flightsraw"}},"number":{"$":"378","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns247":"http:\/\/flightsraw"}},"carrier":{"@href":"#id69","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns247":"http:\/\/flightsraw"}},"@id":"id196","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns247:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns247":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"2:30p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns248":"http:\/\/flightsraw"}},"departureTime":{"$":"12:18p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns248":"http:\/\/flightsraw"}},"number":{"$":"484","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns248":"http:\/\/flightsraw"}},"carrier":{"@href":"#id66","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns248":"http:\/\/flightsraw"}},"@id":"id94","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns248:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns248":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"10:35p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns249":"http:\/\/flightsraw"}},"departureTime":{"$":"8:52p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns249":"http:\/\/flightsraw"}},"number":{"$":"408","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns249":"http:\/\/flightsraw"}},"carrier":{"@href":"#id65","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns249":"http:\/\/flightsraw"}},"@id":"id198","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns249:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns249":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"3:15a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns250":"http:\/\/flightsraw"}},"departureTime":{"$":"2:38a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns250":"http:\/\/flightsraw"}},"number":{"$":"627","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns250":"http:\/\/flightsraw"}},"carrier":{"@href":"#id68","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns250":"http:\/\/flightsraw"}},"@id":"id318","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns250:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns250":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"9:19p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns251":"http:\/\/flightsraw"}},"departureTime":{"$":"8:09p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns251":"http:\/\/flightsraw"}},"number":{"$":"547","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns251":"http:\/\/flightsraw"}},"carrier":{"@href":"#id69","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns251":"http:\/\/flightsraw"}},"@id":"id220","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns251:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns251":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"3:23a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns252":"http:\/\/flightsraw"}},"departureTime":{"$":"3:11a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns252":"http:\/\/flightsraw"}},"number":{"$":"318","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns252":"http:\/\/flightsraw"}},"carrier":{"@href":"#id72","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns252":"http:\/\/flightsraw"}},"@id":"id216","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns252:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns252":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"3:03p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns253":"http:\/\/flightsraw"}},"departureTime":{"$":"11:52a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns253":"http:\/\/flightsraw"}},"number":{"$":"544","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns253":"http:\/\/flightsraw"}},"carrier":{"@href":"#id70","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns253":"http:\/\/flightsraw"}},"@id":"id161","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns253:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns253":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"1:38a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns254":"http:\/\/flightsraw"}},"departureTime":{"$":"3:41a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns254":"http:\/\/flightsraw"}},"number":{"$":"454","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns254":"http:\/\/flightsraw"}},"carrier":{"@href":"#id68","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns254":"http:\/\/flightsraw"}},"@id":"id232","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns254:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns254":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"3:30a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns255":"http:\/\/flightsraw"}},"departureTime":{"$":"1:45a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns255":"http:\/\/flightsraw"}},"number":{"$":"538","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns255":"http:\/\/flightsraw"}},"carrier":{"@href":"#id72","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns255":"http:\/\/flightsraw"}},"@id":"id214","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns255:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns255":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"4:42a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns256":"http:\/\/flightsraw"}},"departureTime":{"$":"3:13a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns256":"http:\/\/flightsraw"}},"number":{"$":"598","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns256":"http:\/\/flightsraw"}},"carrier":{"@href":"#id68","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns256":"http:\/\/flightsraw"}},"@id":"id127","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns256:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns256":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"10:42a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns257":"http:\/\/flightsraw"}},"departureTime":{"$":"7:31a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns257":"http:\/\/flightsraw"}},"number":{"$":"436","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns257":"http:\/\/flightsraw"}},"carrier":{"@href":"#id65","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns257":"http:\/\/flightsraw"}},"@id":"id266","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns257:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns257":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"3:58a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns258":"http:\/\/flightsraw"}},"departureTime":{"$":"3:33a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns258":"http:\/\/flightsraw"}},"number":{"$":"536","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns258":"http:\/\/flightsraw"}},"carrier":{"@href":"#id71","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns258":"http:\/\/flightsraw"}},"@id":"id264","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns258:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns258":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"10:39p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns259":"http:\/\/flightsraw"}},"departureTime":{"$":"6:48p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns259":"http:\/\/flightsraw"}},"number":{"$":"897","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns259":"http:\/\/flightsraw"}},"carrier":{"@href":"#id71","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns259":"http:\/\/flightsraw"}},"@id":"id225","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns259:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns259":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"3:37a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns260":"http:\/\/flightsraw"}},"departureTime":{"$":"2:53a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns260":"http:\/\/flightsraw"}},"number":{"$":"246","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns260":"http:\/\/flightsraw"}},"carrier":{"@href":"#id69","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns260":"http:\/\/flightsraw"}},"@id":"id353","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns260:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns260":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"7:51a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns261":"http:\/\/flightsraw"}},"departureTime":{"$":"3:17a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns261":"http:\/\/flightsraw"}},"number":{"$":"654","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns261":"http:\/\/flightsraw"}},"carrier":{"@href":"#id69","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns261":"http:\/\/flightsraw"}},"@id":"id296","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns261:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns261":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"3:43a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns262":"http:\/\/flightsraw"}},"departureTime":{"$":"1:26a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns262":"http:\/\/flightsraw"}},"number":{"$":"673","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns262":"http:\/\/flightsraw"}},"carrier":{"@href":"#id69","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns262":"http:\/\/flightsraw"}},"@id":"id352","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns262:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns262":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"4:38a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns263":"http:\/\/flightsraw"}},"departureTime":{"$":"2:52a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns263":"http:\/\/flightsraw"}},"number":{"$":"244","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns263":"http:\/\/flightsraw"}},"carrier":{"@href":"#id68","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns263":"http:\/\/flightsraw"}},"@id":"id175","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns263:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns263":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"8:35p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns264":"http:\/\/flightsraw"}},"departureTime":{"$":"5:37p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns264":"http:\/\/flightsraw"}},"number":{"$":"369","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns264":"http:\/\/flightsraw"}},"carrier":{"@href":"#id68","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns264":"http:\/\/flightsraw"}},"@id":"id88","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns264:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns264":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"10:13a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns265":"http:\/\/flightsraw"}},"departureTime":{"$":"7:08a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns265":"http:\/\/flightsraw"}},"number":{"$":"771","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns265":"http:\/\/flightsraw"}},"carrier":{"@href":"#id68","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns265":"http:\/\/flightsraw"}},"@id":"id235","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns265:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns265":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"6:05a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns266":"http:\/\/flightsraw"}},"departureTime":{"$":"3:09a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns266":"http:\/\/flightsraw"}},"number":{"$":"361","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns266":"http:\/\/flightsraw"}},"carrier":{"@href":"#id69","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns266":"http:\/\/flightsraw"}},"@id":"id245","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns266:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns266":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"3:05a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns267":"http:\/\/flightsraw"}},"departureTime":{"$":"1:28a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns267":"http:\/\/flightsraw"}},"number":{"$":"371","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns267":"http:\/\/flightsraw"}},"carrier":{"@href":"#id65","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns267":"http:\/\/flightsraw"}},"@id":"id178","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns267:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns267":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"5:33p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns268":"http:\/\/flightsraw"}},"departureTime":{"$":"1:52p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns268":"http:\/\/flightsraw"}},"number":{"$":"715","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns268":"http:\/\/flightsraw"}},"carrier":{"@href":"#id69","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns268":"http:\/\/flightsraw"}},"@id":"id182","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns268:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns268":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"5:36p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns269":"http:\/\/flightsraw"}},"departureTime":{"$":"2:41p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns269":"http:\/\/flightsraw"}},"number":{"$":"714","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns269":"http:\/\/flightsraw"}},"carrier":{"@href":"#id68","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns269":"http:\/\/flightsraw"}},"@id":"id85","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns269:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns269":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"8:27p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns270":"http:\/\/flightsraw"}},"departureTime":{"$":"3:45p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns270":"http:\/\/flightsraw"}},"number":{"$":"365","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns270":"http:\/\/flightsraw"}},"carrier":{"@href":"#id71","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns270":"http:\/\/flightsraw"}},"@id":"id133","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns270:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns270":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"10:53p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns271":"http:\/\/flightsraw"}},"departureTime":{"$":"7:12p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns271":"http:\/\/flightsraw"}},"number":{"$":"576","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns271":"http:\/\/flightsraw"}},"carrier":{"@href":"#id72","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns271":"http:\/\/flightsraw"}},"@id":"id351","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns271:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns271":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"1:42a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns272":"http:\/\/flightsraw"}},"departureTime":{"$":"3:26a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns272":"http:\/\/flightsraw"}},"number":{"$":"616","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns272":"http:\/\/flightsraw"}},"carrier":{"@href":"#id65","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns272":"http:\/\/flightsraw"}},"@id":"id233","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns272:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns272":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"4:01p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns273":"http:\/\/flightsraw"}},"departureTime":{"$":"1:59p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns273":"http:\/\/flightsraw"}},"number":{"$":"892","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns273":"http:\/\/flightsraw"}},"carrier":{"@href":"#id70","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns273":"http:\/\/flightsraw"}},"@id":"id277","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns273:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns273":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"3:42p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns274":"http:\/\/flightsraw"}},"departureTime":{"$":"12:08p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns274":"http:\/\/flightsraw"}},"number":{"$":"302","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns274":"http:\/\/flightsraw"}},"carrier":{"@href":"#id67","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns274":"http:\/\/flightsraw"}},"@id":"id259","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns274:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns274":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"3:21a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns275":"http:\/\/flightsraw"}},"departureTime":{"$":"3:19a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns275":"http:\/\/flightsraw"}},"number":{"$":"509","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns275":"http:\/\/flightsraw"}},"carrier":{"@href":"#id67","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns275":"http:\/\/flightsraw"}},"@id":"id155","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns275:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns275":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"3:26a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns276":"http:\/\/flightsraw"}},"departureTime":{"$":"1:35a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns276":"http:\/\/flightsraw"}},"number":{"$":"970","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns276":"http:\/\/flightsraw"}},"carrier":{"@href":"#id67","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns276":"http:\/\/flightsraw"}},"@id":"id153","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns276:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns276":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"12:26p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns277":"http:\/\/flightsraw"}},"departureTime":{"$":"9:27a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns277":"http:\/\/flightsraw"}},"number":{"$":"870","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns277":"http:\/\/flightsraw"}},"carrier":{"@href":"#id71","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns277":"http:\/\/flightsraw"}},"@id":"id244","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns277:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns277":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"1:34a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns278":"http:\/\/flightsraw"}},"departureTime":{"$":"1:49a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns278":"http:\/\/flightsraw"}},"number":{"$":"994","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns278":"http:\/\/flightsraw"}},"carrier":{"@href":"#id69","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns278":"http:\/\/flightsraw"}},"@id":"id338","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns278:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns278":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"3:26a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns279":"http:\/\/flightsraw"}},"departureTime":{"$":"11:24p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns279":"http:\/\/flightsraw"}},"number":{"$":"733","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns279":"http:\/\/flightsraw"}},"carrier":{"@href":"#id70","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns279":"http:\/\/flightsraw"}},"@id":"id302","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns279:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns279":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"3:57a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns280":"http:\/\/flightsraw"}},"departureTime":{"$":"3:40a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns280":"http:\/\/flightsraw"}},"number":{"$":"370","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns280":"http:\/\/flightsraw"}},"carrier":{"@href":"#id70","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns280":"http:\/\/flightsraw"}},"@id":"id300","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns280:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns280":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"10:16a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns281":"http:\/\/flightsraw"}},"departureTime":{"$":"9:04a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns281":"http:\/\/flightsraw"}},"number":{"$":"267","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns281":"http:\/\/flightsraw"}},"carrier":{"@href":"#id70","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns281":"http:\/\/flightsraw"}},"@id":"id108","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns281:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns281":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"2:26a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns282":"http:\/\/flightsraw"}},"departureTime":{"$":"1:22a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns282":"http:\/\/flightsraw"}},"number":{"$":"724","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns282":"http:\/\/flightsraw"}},"carrier":{"@href":"#id65","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns282":"http:\/\/flightsraw"}},"@id":"id324","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns282:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns282":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"2:03a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns283":"http:\/\/flightsraw"}},"departureTime":{"$":"2:03a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns283":"http:\/\/flightsraw"}},"number":{"$":"842","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns283":"http:\/\/flightsraw"}},"carrier":{"@href":"#id70","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns283":"http:\/\/flightsraw"}},"@id":"id271","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns283:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns283":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"1:03a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns284":"http:\/\/flightsraw"}},"departureTime":{"$":"1:49a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns284":"http:\/\/flightsraw"}},"number":{"$":"630","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns284":"http:\/\/flightsraw"}},"carrier":{"@href":"#id70","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns284":"http:\/\/flightsraw"}},"@id":"id221","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns284:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns284":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"2:42a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns285":"http:\/\/flightsraw"}},"departureTime":{"$":"1:52a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns285":"http:\/\/flightsraw"}},"number":{"$":"565","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns285":"http:\/\/flightsraw"}},"carrier":{"@href":"#id70","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns285":"http:\/\/flightsraw"}},"@id":"id104","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns285:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns285":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"7:36p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns286":"http:\/\/flightsraw"}},"departureTime":{"$":"6:01p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns286":"http:\/\/flightsraw"}},"number":{"$":"933","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns286":"http:\/\/flightsraw"}},"carrier":{"@href":"#id65","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns286":"http:\/\/flightsraw"}},"@id":"id293","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns286:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns286":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"12:20a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns287":"http:\/\/flightsraw"}},"departureTime":{"$":"9:16p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns287":"http:\/\/flightsraw"}},"number":{"$":"348","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns287":"http:\/\/flightsraw"}},"carrier":{"@href":"#id68","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns287":"http:\/\/flightsraw"}},"@id":"id242","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns287:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns287":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"9:37p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns288":"http:\/\/flightsraw"}},"departureTime":{"$":"5:34p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns288":"http:\/\/flightsraw"}},"number":{"$":"356","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns288":"http:\/\/flightsraw"}},"carrier":{"@href":"#id66","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns288":"http:\/\/flightsraw"}},"@id":"id305","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns288:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns288":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"7:23p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns289":"http:\/\/flightsraw"}},"departureTime":{"$":"4:00p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns289":"http:\/\/flightsraw"}},"number":{"$":"963","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns289":"http:\/\/flightsraw"}},"carrier":{"@href":"#id72","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns289":"http:\/\/flightsraw"}},"@id":"id146","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns289:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns289":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"1:39a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns290":"http:\/\/flightsraw"}},"departureTime":{"$":"11:25p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns290":"http:\/\/flightsraw"}},"number":{"$":"919","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns290":"http:\/\/flightsraw"}},"carrier":{"@href":"#id71","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns290":"http:\/\/flightsraw"}},"@id":"id92","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns290:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns290":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"3:15a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns291":"http:\/\/flightsraw"}},"departureTime":{"$":"2:06a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns291":"http:\/\/flightsraw"}},"number":{"$":"708","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns291":"http:\/\/flightsraw"}},"carrier":{"@href":"#id66","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns291":"http:\/\/flightsraw"}},"@id":"id164","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns291:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns291":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"8:35p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns292":"http:\/\/flightsraw"}},"departureTime":{"$":"6:18p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns292":"http:\/\/flightsraw"}},"number":{"$":"823","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns292":"http:\/\/flightsraw"}},"carrier":{"@href":"#id72","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns292":"http:\/\/flightsraw"}},"@id":"id118","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns292:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns292":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"1:59a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns293":"http:\/\/flightsraw"}},"departureTime":{"$":"2:45a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns293":"http:\/\/flightsraw"}},"number":{"$":"563","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns293":"http:\/\/flightsraw"}},"carrier":{"@href":"#id72","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns293":"http:\/\/flightsraw"}},"@id":"id281","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns293:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns293":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"4:45a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns294":"http:\/\/flightsraw"}},"departureTime":{"$":"3:31a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns294":"http:\/\/flightsraw"}},"number":{"$":"883","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns294":"http:\/\/flightsraw"}},"carrier":{"@href":"#id68","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns294":"http:\/\/flightsraw"}},"@id":"id121","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns294:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns294":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"2:46a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns295":"http:\/\/flightsraw"}},"departureTime":{"$":"2:35a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns295":"http:\/\/flightsraw"}},"number":{"$":"210","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns295":"http:\/\/flightsraw"}},"carrier":{"@href":"#id69","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns295":"http:\/\/flightsraw"}},"@id":"id205","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns295:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns295":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"4:11p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns296":"http:\/\/flightsraw"}},"departureTime":{"$":"12:41p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns296":"http:\/\/flightsraw"}},"number":{"$":"763","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns296":"http:\/\/flightsraw"}},"carrier":{"@href":"#id67","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns296":"http:\/\/flightsraw"}},"@id":"id215","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns296:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns296":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"9:39p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns297":"http:\/\/flightsraw"}},"departureTime":{"$":"6:13p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns297":"http:\/\/flightsraw"}},"number":{"$":"689","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns297":"http:\/\/flightsraw"}},"carrier":{"@href":"#id71","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns297":"http:\/\/flightsraw"}},"@id":"id156","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns297:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns297":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"5:39a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns298":"http:\/\/flightsraw"}},"departureTime":{"$":"1:46a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns298":"http:\/\/flightsraw"}},"number":{"$":"476","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns298":"http:\/\/flightsraw"}},"carrier":{"@href":"#id70","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns298":"http:\/\/flightsraw"}},"@id":"id111","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns298:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns298":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"1:38a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns299":"http:\/\/flightsraw"}},"departureTime":{"$":"1:22a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns299":"http:\/\/flightsraw"}},"number":{"$":"370","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns299":"http:\/\/flightsraw"}},"carrier":{"@href":"#id70","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns299":"http:\/\/flightsraw"}},"@id":"id292","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns299:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns299":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"2:42a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns300":"http:\/\/flightsraw"}},"departureTime":{"$":"1:37a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns300":"http:\/\/flightsraw"}},"number":{"$":"581","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns300":"http:\/\/flightsraw"}},"carrier":{"@href":"#id68","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns300":"http:\/\/flightsraw"}},"@id":"id257","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns300:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns300":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"2:09a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns301":"http:\/\/flightsraw"}},"departureTime":{"$":"3:10a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns301":"http:\/\/flightsraw"}},"number":{"$":"613","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns301":"http:\/\/flightsraw"}},"carrier":{"@href":"#id68","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns301":"http:\/\/flightsraw"}},"@id":"id91","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns301:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns301":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"2:42a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns302":"http:\/\/flightsraw"}},"departureTime":{"$":"3:01a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns302":"http:\/\/flightsraw"}},"number":{"$":"699","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns302":"http:\/\/flightsraw"}},"carrier":{"@href":"#id70","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns302":"http:\/\/flightsraw"}},"@id":"id219","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns302:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns302":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"3:06a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns303":"http:\/\/flightsraw"}},"departureTime":{"$":"3:14a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns303":"http:\/\/flightsraw"}},"number":{"$":"732","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns303":"http:\/\/flightsraw"}},"carrier":{"@href":"#id65","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns303":"http:\/\/flightsraw"}},"@id":"id167","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns303:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns303":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"3:29a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns304":"http:\/\/flightsraw"}},"departureTime":{"$":"2:35a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns304":"http:\/\/flightsraw"}},"number":{"$":"629","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns304":"http:\/\/flightsraw"}},"carrier":{"@href":"#id65","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns304":"http:\/\/flightsraw"}},"@id":"id260","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns304:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns304":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"11:05a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns305":"http:\/\/flightsraw"}},"departureTime":{"$":"8:15a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns305":"http:\/\/flightsraw"}},"number":{"$":"680","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns305":"http:\/\/flightsraw"}},"carrier":{"@href":"#id72","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns305":"http:\/\/flightsraw"}},"@id":"id83","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns305:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns305":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"12:50a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns306":"http:\/\/flightsraw"}},"departureTime":{"$":"10:01p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns306":"http:\/\/flightsraw"}},"number":{"$":"499","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns306":"http:\/\/flightsraw"}},"carrier":{"@href":"#id70","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns306":"http:\/\/flightsraw"}},"@id":"id348","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns306:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns306":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"7:15a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns307":"http:\/\/flightsraw"}},"departureTime":{"$":"3:55a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns307":"http:\/\/flightsraw"}},"number":{"$":"862","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns307":"http:\/\/flightsraw"}},"carrier":{"@href":"#id71","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns307":"http:\/\/flightsraw"}},"@id":"id313","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns307:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns307":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"2:29a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns308":"http:\/\/flightsraw"}},"departureTime":{"$":"11:03p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns308":"http:\/\/flightsraw"}},"number":{"$":"223","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns308":"http:\/\/flightsraw"}},"carrier":{"@href":"#id67","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns308":"http:\/\/flightsraw"}},"@id":"id261","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns308:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns308":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"1:35a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns309":"http:\/\/flightsraw"}},"departureTime":{"$":"1:47a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns309":"http:\/\/flightsraw"}},"number":{"$":"671","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns309":"http:\/\/flightsraw"}},"carrier":{"@href":"#id65","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns309":"http:\/\/flightsraw"}},"@id":"id340","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns309:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns309":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"4:43a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns310":"http:\/\/flightsraw"}},"departureTime":{"$":"1:17a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns310":"http:\/\/flightsraw"}},"number":{"$":"945","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns310":"http:\/\/flightsraw"}},"carrier":{"@href":"#id67","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns310":"http:\/\/flightsraw"}},"@id":"id327","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns310:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns310":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"2:52a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns311":"http:\/\/flightsraw"}},"departureTime":{"$":"11:36p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns311":"http:\/\/flightsraw"}},"number":{"$":"937","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns311":"http:\/\/flightsraw"}},"carrier":{"@href":"#id68","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns311":"http:\/\/flightsraw"}},"@id":"id317","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns311:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns311":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"10:09p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns312":"http:\/\/flightsraw"}},"departureTime":{"$":"6:15p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns312":"http:\/\/flightsraw"}},"number":{"$":"886","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns312":"http:\/\/flightsraw"}},"carrier":{"@href":"#id67","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns312":"http:\/\/flightsraw"}},"@id":"id112","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns312:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns312":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"1:58p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns313":"http:\/\/flightsraw"}},"departureTime":{"$":"11:13a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns313":"http:\/\/flightsraw"}},"number":{"$":"639","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns313":"http:\/\/flightsraw"}},"carrier":{"@href":"#id68","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns313":"http:\/\/flightsraw"}},"@id":"id120","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns313:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns313":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"11:17a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns314":"http:\/\/flightsraw"}},"departureTime":{"$":"7:11a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns314":"http:\/\/flightsraw"}},"number":{"$":"422","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns314":"http:\/\/flightsraw"}},"carrier":{"@href":"#id68","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns314":"http:\/\/flightsraw"}},"@id":"id308","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns314:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns314":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"11:17p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns315":"http:\/\/flightsraw"}},"departureTime":{"$":"9:34p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns315":"http:\/\/flightsraw"}},"number":{"$":"294","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns315":"http:\/\/flightsraw"}},"carrier":{"@href":"#id67","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns315":"http:\/\/flightsraw"}},"@id":"id229","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns315:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns315":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"3:06a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns316":"http:\/\/flightsraw"}},"departureTime":{"$":"3:48a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns316":"http:\/\/flightsraw"}},"number":{"$":"978","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns316":"http:\/\/flightsraw"}},"carrier":{"@href":"#id66","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns316":"http:\/\/flightsraw"}},"@id":"id163","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns316:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns316":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"11:44p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns317":"http:\/\/flightsraw"}},"departureTime":{"$":"10:10p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns317":"http:\/\/flightsraw"}},"number":{"$":"825","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns317":"http:\/\/flightsraw"}},"carrier":{"@href":"#id70","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns317":"http:\/\/flightsraw"}},"@id":"id344","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns317:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns317":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"1:37a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns318":"http:\/\/flightsraw"}},"departureTime":{"$":"3:52a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns318":"http:\/\/flightsraw"}},"number":{"$":"221","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns318":"http:\/\/flightsraw"}},"carrier":{"@href":"#id71","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns318":"http:\/\/flightsraw"}},"@id":"id294","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns318:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns318":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"4:47a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns319":"http:\/\/flightsraw"}},"departureTime":{"$":"3:09a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns319":"http:\/\/flightsraw"}},"number":{"$":"429","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns319":"http:\/\/flightsraw"}},"carrier":{"@href":"#id68","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns319":"http:\/\/flightsraw"}},"@id":"id203","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns319:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns319":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"2:54a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns320":"http:\/\/flightsraw"}},"departureTime":{"$":"1:26a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns320":"http:\/\/flightsraw"}},"number":{"$":"680","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns320":"http:\/\/flightsraw"}},"carrier":{"@href":"#id69","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns320":"http:\/\/flightsraw"}},"@id":"id84","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns320:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns320":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"1:50a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns321":"http:\/\/flightsraw"}},"departureTime":{"$":"1:24a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns321":"http:\/\/flightsraw"}},"number":{"$":"743","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns321":"http:\/\/flightsraw"}},"carrier":{"@href":"#id67","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns321":"http:\/\/flightsraw"}},"@id":"id76","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns321:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns321":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"1:15p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns322":"http:\/\/flightsraw"}},"departureTime":{"$":"9:31a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns322":"http:\/\/flightsraw"}},"number":{"$":"339","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns322":"http:\/\/flightsraw"}},"carrier":{"@href":"#id72","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns322":"http:\/\/flightsraw"}},"@id":"id323","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns322:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns322":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"4:11p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns323":"http:\/\/flightsraw"}},"departureTime":{"$":"12:49p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns323":"http:\/\/flightsraw"}},"number":{"$":"340","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns323":"http:\/\/flightsraw"}},"carrier":{"@href":"#id72","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns323":"http:\/\/flightsraw"}},"@id":"id285","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns323:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns323":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"1:43p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns324":"http:\/\/flightsraw"}},"departureTime":{"$":"9:59a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns324":"http:\/\/flightsraw"}},"number":{"$":"633","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns324":"http:\/\/flightsraw"}},"carrier":{"@href":"#id65","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns324":"http:\/\/flightsraw"}},"@id":"id322","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns324:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns324":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"1:56a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns325":"http:\/\/flightsraw"}},"departureTime":{"$":"2:03a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns325":"http:\/\/flightsraw"}},"number":{"$":"759","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns325":"http:\/\/flightsraw"}},"carrier":{"@href":"#id71","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns325":"http:\/\/flightsraw"}},"@id":"id150","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns325:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns325":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"2:51a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns326":"http:\/\/flightsraw"}},"departureTime":{"$":"2:14a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns326":"http:\/\/flightsraw"}},"number":{"$":"833","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns326":"http:\/\/flightsraw"}},"carrier":{"@href":"#id68","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns326":"http:\/\/flightsraw"}},"@id":"id192","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns326:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns326":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"2:50a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns327":"http:\/\/flightsraw"}},"departureTime":{"$":"3:53a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns327":"http:\/\/flightsraw"}},"number":{"$":"311","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns327":"http:\/\/flightsraw"}},"carrier":{"@href":"#id68","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns327":"http:\/\/flightsraw"}},"@id":"id101","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns327:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns327":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"3:50a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns328":"http:\/\/flightsraw"}},"departureTime":{"$":"2:48a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns328":"http:\/\/flightsraw"}},"number":{"$":"486","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns328":"http:\/\/flightsraw"}},"carrier":{"@href":"#id66","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns328":"http:\/\/flightsraw"}},"@id":"id116","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns328:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns328":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"1:02p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns329":"http:\/\/flightsraw"}},"departureTime":{"$":"9:30a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns329":"http:\/\/flightsraw"}},"number":{"$":"813","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns329":"http:\/\/flightsraw"}},"carrier":{"@href":"#id65","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns329":"http:\/\/flightsraw"}},"@id":"id210","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns329:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns329":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"3:48a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns330":"http:\/\/flightsraw"}},"departureTime":{"$":"2:49a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns330":"http:\/\/flightsraw"}},"number":{"$":"796","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns330":"http:\/\/flightsraw"}},"carrier":{"@href":"#id69","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns330":"http:\/\/flightsraw"}},"@id":"id321","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns330:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns330":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"2:08a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns331":"http:\/\/flightsraw"}},"departureTime":{"$":"2:29a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns331":"http:\/\/flightsraw"}},"number":{"$":"449","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns331":"http:\/\/flightsraw"}},"carrier":{"@href":"#id68","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns331":"http:\/\/flightsraw"}},"@id":"id272","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns331:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns331":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"3:18a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns332":"http:\/\/flightsraw"}},"departureTime":{"$":"2:43a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns332":"http:\/\/flightsraw"}},"number":{"$":"329","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns332":"http:\/\/flightsraw"}},"carrier":{"@href":"#id66","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns332":"http:\/\/flightsraw"}},"@id":"id143","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns332:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns332":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"3:48a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns333":"http:\/\/flightsraw"}},"departureTime":{"$":"2:40a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns333":"http:\/\/flightsraw"}},"number":{"$":"675","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns333":"http:\/\/flightsraw"}},"carrier":{"@href":"#id70","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns333":"http:\/\/flightsraw"}},"@id":"id224","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns333:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns333":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"9:01p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns334":"http:\/\/flightsraw"}},"departureTime":{"$":"7:20p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns334":"http:\/\/flightsraw"}},"number":{"$":"447","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns334":"http:\/\/flightsraw"}},"carrier":{"@href":"#id71","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns334":"http:\/\/flightsraw"}},"@id":"id138","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns334:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns334":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"4:48a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns335":"http:\/\/flightsraw"}},"departureTime":{"$":"4:06a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns335":"http:\/\/flightsraw"}},"number":{"$":"503","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns335":"http:\/\/flightsraw"}},"carrier":{"@href":"#id67","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns335":"http:\/\/flightsraw"}},"@id":"id124","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns335:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns335":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"4:43a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns336":"http:\/\/flightsraw"}},"departureTime":{"$":"1:01a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns336":"http:\/\/flightsraw"}},"number":{"$":"688","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns336":"http:\/\/flightsraw"}},"carrier":{"@href":"#id66","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns336":"http:\/\/flightsraw"}},"@id":"id130","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns336:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns336":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"10:56a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns337":"http:\/\/flightsraw"}},"departureTime":{"$":"7:43a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns337":"http:\/\/flightsraw"}},"number":{"$":"294","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns337":"http:\/\/flightsraw"}},"carrier":{"@href":"#id66","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns337":"http:\/\/flightsraw"}},"@id":"id311","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns337:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns337":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"2:19p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns338":"http:\/\/flightsraw"}},"departureTime":{"$":"11:54a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns338":"http:\/\/flightsraw"}},"number":{"$":"900","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns338":"http:\/\/flightsraw"}},"carrier":{"@href":"#id65","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns338":"http:\/\/flightsraw"}},"@id":"id227","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns338:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns338":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"2:13a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns339":"http:\/\/flightsraw"}},"departureTime":{"$":"11:08p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns339":"http:\/\/flightsraw"}},"number":{"$":"542","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns339":"http:\/\/flightsraw"}},"carrier":{"@href":"#id68","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns339":"http:\/\/flightsraw"}},"@id":"id241","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns339:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns339":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"3:41a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns340":"http:\/\/flightsraw"}},"departureTime":{"$":"4:02a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns340":"http:\/\/flightsraw"}},"number":{"$":"461","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns340":"http:\/\/flightsraw"}},"carrier":{"@href":"#id72","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns340":"http:\/\/flightsraw"}},"@id":"id184","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns340:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns340":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"2:32a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns341":"http:\/\/flightsraw"}},"departureTime":{"$":"12:27a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns341":"http:\/\/flightsraw"}},"number":{"$":"646","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns341":"http:\/\/flightsraw"}},"carrier":{"@href":"#id72","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns341":"http:\/\/flightsraw"}},"@id":"id275","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns341:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns341":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"11:53a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns342":"http:\/\/flightsraw"}},"departureTime":{"$":"7:13a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns342":"http:\/\/flightsraw"}},"number":{"$":"409","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns342":"http:\/\/flightsraw"}},"carrier":{"@href":"#id68","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns342":"http:\/\/flightsraw"}},"@id":"id332","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns342:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns342":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"3:01a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns343":"http:\/\/flightsraw"}},"departureTime":{"$":"3:30a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns343":"http:\/\/flightsraw"}},"number":{"$":"295","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns343":"http:\/\/flightsraw"}},"carrier":{"@href":"#id66","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns343":"http:\/\/flightsraw"}},"@id":"id243","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns343:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns343":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"4:00a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns344":"http:\/\/flightsraw"}},"departureTime":{"$":"3:17a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns344":"http:\/\/flightsraw"}},"number":{"$":"298","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns344":"http:\/\/flightsraw"}},"carrier":{"@href":"#id68","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns344":"http:\/\/flightsraw"}},"@id":"id334","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns344:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns344":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"4:41a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns345":"http:\/\/flightsraw"}},"departureTime":{"$":"2:32a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns345":"http:\/\/flightsraw"}},"number":{"$":"946","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns345":"http:\/\/flightsraw"}},"carrier":{"@href":"#id69","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns345":"http:\/\/flightsraw"}},"@id":"id98","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns345:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns345":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"2:05a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns346":"http:\/\/flightsraw"}},"departureTime":{"$":"3:08a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns346":"http:\/\/flightsraw"}},"number":{"$":"806","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns346":"http:\/\/flightsraw"}},"carrier":{"@href":"#id71","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns346":"http:\/\/flightsraw"}},"@id":"id282","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns346:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns346":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"2:16p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns347":"http:\/\/flightsraw"}},"departureTime":{"$":"10:53a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns347":"http:\/\/flightsraw"}},"number":{"$":"405","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns347":"http:\/\/flightsraw"}},"carrier":{"@href":"#id66","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns347":"http:\/\/flightsraw"}},"@id":"id213","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns347:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns347":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"1:50p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns348":"http:\/\/flightsraw"}},"departureTime":{"$":"10:45a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns348":"http:\/\/flightsraw"}},"number":{"$":"876","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns348":"http:\/\/flightsraw"}},"carrier":{"@href":"#id66","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns348":"http:\/\/flightsraw"}},"@id":"id270","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns348:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns348":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"6:59p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns349":"http:\/\/flightsraw"}},"departureTime":{"$":"4:16p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns349":"http:\/\/flightsraw"}},"number":{"$":"633","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns349":"http:\/\/flightsraw"}},"carrier":{"@href":"#id69","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns349":"http:\/\/flightsraw"}},"@id":"id255","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns349:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns349":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"10:27p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns350":"http:\/\/flightsraw"}},"departureTime":{"$":"8:44p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns350":"http:\/\/flightsraw"}},"number":{"$":"852","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns350":"http:\/\/flightsraw"}},"carrier":{"@href":"#id71","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns350":"http:\/\/flightsraw"}},"@id":"id142","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns350:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns350":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"4:39a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns351":"http:\/\/flightsraw"}},"departureTime":{"$":"4:05a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns351":"http:\/\/flightsraw"}},"number":{"$":"624","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns351":"http:\/\/flightsraw"}},"carrier":{"@href":"#id67","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns351":"http:\/\/flightsraw"}},"@id":"id330","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns351:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns351":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"8:19a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns352":"http:\/\/flightsraw"}},"departureTime":{"$":"4:16a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns352":"http:\/\/flightsraw"}},"number":{"$":"775","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns352":"http:\/\/flightsraw"}},"carrier":{"@href":"#id68","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns352":"http:\/\/flightsraw"}},"@id":"id307","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns352:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns352":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"1:39a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns353":"http:\/\/flightsraw"}},"departureTime":{"$":"9:01p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns353":"http:\/\/flightsraw"}},"number":{"$":"757","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns353":"http:\/\/flightsraw"}},"carrier":{"@href":"#id72","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns353":"http:\/\/flightsraw"}},"@id":"id170","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns353:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns353":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"2:36a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns354":"http:\/\/flightsraw"}},"departureTime":{"$":"1:03a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns354":"http:\/\/flightsraw"}},"number":{"$":"939","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns354":"http:\/\/flightsraw"}},"carrier":{"@href":"#id72","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns354":"http:\/\/flightsraw"}},"@id":"id258","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns354:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns354":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"3:09a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns355":"http:\/\/flightsraw"}},"departureTime":{"$":"2:42a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns355":"http:\/\/flightsraw"}},"number":{"$":"530","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns355":"http:\/\/flightsraw"}},"carrier":{"@href":"#id66","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns355":"http:\/\/flightsraw"}},"@id":"id239","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns355:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns355":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"3:43a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns356":"http:\/\/flightsraw"}},"departureTime":{"$":"2:09a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns356":"http:\/\/flightsraw"}},"number":{"$":"587","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns356":"http:\/\/flightsraw"}},"carrier":{"@href":"#id68","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns356":"http:\/\/flightsraw"}},"@id":"id346","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns356:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns356":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"1:38a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns357":"http:\/\/flightsraw"}},"departureTime":{"$":"2:12a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns357":"http:\/\/flightsraw"}},"number":{"$":"842","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns357":"http:\/\/flightsraw"}},"carrier":{"@href":"#id70","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns357":"http:\/\/flightsraw"}},"@id":"id202","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns357:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns357":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"1:14a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns358":"http:\/\/flightsraw"}},"departureTime":{"$":"3:30a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns358":"http:\/\/flightsraw"}},"number":{"$":"293","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns358":"http:\/\/flightsraw"}},"carrier":{"@href":"#id66","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns358":"http:\/\/flightsraw"}},"@id":"id109","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns358:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns358":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"4:52p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns359":"http:\/\/flightsraw"}},"departureTime":{"$":"2:28p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns359":"http:\/\/flightsraw"}},"number":{"$":"600","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns359":"http:\/\/flightsraw"}},"carrier":{"@href":"#id65","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns359":"http:\/\/flightsraw"}},"@id":"id228","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns359:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns359":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"8:50p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns360":"http:\/\/flightsraw"}},"departureTime":{"$":"6:07p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns360":"http:\/\/flightsraw"}},"number":{"$":"313","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns360":"http:\/\/flightsraw"}},"carrier":{"@href":"#id68","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns360":"http:\/\/flightsraw"}},"@id":"id105","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns360:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns360":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"2:28a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns361":"http:\/\/flightsraw"}},"departureTime":{"$":"3:34a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns361":"http:\/\/flightsraw"}},"number":{"$":"904","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns361":"http:\/\/flightsraw"}},"carrier":{"@href":"#id67","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns361":"http:\/\/flightsraw"}},"@id":"id186","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns361:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns361":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"2:27a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns362":"http:\/\/flightsraw"}},"departureTime":{"$":"2:06a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns362":"http:\/\/flightsraw"}},"number":{"$":"820","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns362":"http:\/\/flightsraw"}},"carrier":{"@href":"#id71","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns362":"http:\/\/flightsraw"}},"@id":"id185","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns362:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns362":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"2:37a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns363":"http:\/\/flightsraw"}},"departureTime":{"$":"3:34a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns363":"http:\/\/flightsraw"}},"number":{"$":"255","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns363":"http:\/\/flightsraw"}},"carrier":{"@href":"#id65","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns363":"http:\/\/flightsraw"}},"@id":"id208","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns363:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns363":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"3:29a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns364":"http:\/\/flightsraw"}},"departureTime":{"$":"4:19a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns364":"http:\/\/flightsraw"}},"number":{"$":"260","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns364":"http:\/\/flightsraw"}},"carrier":{"@href":"#id67","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns364":"http:\/\/flightsraw"}},"@id":"id209","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns364:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns364":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"6:01a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns365":"http:\/\/flightsraw"}},"departureTime":{"$":"4:15a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns365":"http:\/\/flightsraw"}},"number":{"$":"840","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns365":"http:\/\/flightsraw"}},"carrier":{"@href":"#id67","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns365":"http:\/\/flightsraw"}},"@id":"id230","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns365:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns365":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"2:49a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns366":"http:\/\/flightsraw"}},"departureTime":{"$":"2:36a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns366":"http:\/\/flightsraw"}},"number":{"$":"680","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns366":"http:\/\/flightsraw"}},"carrier":{"@href":"#id68","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns366":"http:\/\/flightsraw"}},"@id":"id195","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns366:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns366":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"4:35a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns367":"http:\/\/flightsraw"}},"departureTime":{"$":"2:07a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns367":"http:\/\/flightsraw"}},"number":{"$":"939","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns367":"http:\/\/flightsraw"}},"carrier":{"@href":"#id66","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns367":"http:\/\/flightsraw"}},"@id":"id171","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns367:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns367":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"2:44a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns368":"http:\/\/flightsraw"}},"departureTime":{"$":"4:04a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns368":"http:\/\/flightsraw"}},"number":{"$":"504","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns368":"http:\/\/flightsraw"}},"carrier":{"@href":"#id69","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns368":"http:\/\/flightsraw"}},"@id":"id254","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns368:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns368":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"4:28p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns369":"http:\/\/flightsraw"}},"departureTime":{"$":"11:48a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns369":"http:\/\/flightsraw"}},"number":{"$":"465","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns369":"http:\/\/flightsraw"}},"carrier":{"@href":"#id71","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns369":"http:\/\/flightsraw"}},"@id":"id129","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns369:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns369":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"3:25a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns370":"http:\/\/flightsraw"}},"departureTime":{"$":"3:11a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns370":"http:\/\/flightsraw"}},"number":{"$":"270","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns370":"http:\/\/flightsraw"}},"carrier":{"@href":"#id69","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns370":"http:\/\/flightsraw"}},"@id":"id288","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns370:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns370":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"2:51a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns371":"http:\/\/flightsraw"}},"departureTime":{"$":"1:21a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns371":"http:\/\/flightsraw"}},"number":{"$":"253","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns371":"http:\/\/flightsraw"}},"carrier":{"@href":"#id72","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns371":"http:\/\/flightsraw"}},"@id":"id189","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns371:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns371":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"4:38a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns372":"http:\/\/flightsraw"}},"departureTime":{"$":"2:00a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns372":"http:\/\/flightsraw"}},"number":{"$":"291","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns372":"http:\/\/flightsraw"}},"carrier":{"@href":"#id69","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns372":"http:\/\/flightsraw"}},"@id":"id97","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns372:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns372":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"3:54a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns373":"http:\/\/flightsraw"}},"departureTime":{"$":"2:48a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns373":"http:\/\/flightsraw"}},"number":{"$":"827","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns373":"http:\/\/flightsraw"}},"carrier":{"@href":"#id70","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns373":"http:\/\/flightsraw"}},"@id":"id113","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns373:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns373":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"2:20a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns374":"http:\/\/flightsraw"}},"departureTime":{"$":"1:08a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns374":"http:\/\/flightsraw"}},"number":{"$":"573","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns374":"http:\/\/flightsraw"}},"carrier":{"@href":"#id66","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns374":"http:\/\/flightsraw"}},"@id":"id117","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns374:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns374":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"3:07a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns375":"http:\/\/flightsraw"}},"departureTime":{"$":"1:10a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns375":"http:\/\/flightsraw"}},"number":{"$":"404","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns375":"http:\/\/flightsraw"}},"carrier":{"@href":"#id66","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns375":"http:\/\/flightsraw"}},"@id":"id234","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns375:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns375":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"2:38a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns376":"http:\/\/flightsraw"}},"departureTime":{"$":"1:34a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns376":"http:\/\/flightsraw"}},"number":{"$":"706","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns376":"http:\/\/flightsraw"}},"carrier":{"@href":"#id65","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns376":"http:\/\/flightsraw"}},"@id":"id207","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns376:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns376":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"6:18p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns377":"http:\/\/flightsraw"}},"departureTime":{"$":"1:35p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns377":"http:\/\/flightsraw"}},"number":{"$":"217","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns377":"http:\/\/flightsraw"}},"carrier":{"@href":"#id67","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns377":"http:\/\/flightsraw"}},"@id":"id329","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns377:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns377":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"4:32a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns378":"http:\/\/flightsraw"}},"departureTime":{"$":"2:51a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns378":"http:\/\/flightsraw"}},"number":{"$":"490","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns378":"http:\/\/flightsraw"}},"carrier":{"@href":"#id66","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns378":"http:\/\/flightsraw"}},"@id":"id298","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns378:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns378":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"10:35a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns379":"http:\/\/flightsraw"}},"departureTime":{"$":"6:50a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns379":"http:\/\/flightsraw"}},"number":{"$":"733","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns379":"http:\/\/flightsraw"}},"carrier":{"@href":"#id71","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns379":"http:\/\/flightsraw"}},"@id":"id226","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns379:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns379":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"3:54a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns380":"http:\/\/flightsraw"}},"departureTime":{"$":"2:40a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns380":"http:\/\/flightsraw"}},"number":{"$":"793","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns380":"http:\/\/flightsraw"}},"carrier":{"@href":"#id66","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns380":"http:\/\/flightsraw"}},"@id":"id115","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns380:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns380":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"2:51p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns381":"http:\/\/flightsraw"}},"departureTime":{"$":"12:37p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns381":"http:\/\/flightsraw"}},"number":{"$":"683","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns381":"http:\/\/flightsraw"}},"carrier":{"@href":"#id71","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns381":"http:\/\/flightsraw"}},"@id":"id90","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns381:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns381":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"11:00p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns382":"http:\/\/flightsraw"}},"departureTime":{"$":"9:21p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns382":"http:\/\/flightsraw"}},"number":{"$":"620","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns382":"http:\/\/flightsraw"}},"carrier":{"@href":"#id68","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns382":"http:\/\/flightsraw"}},"@id":"id339","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns382:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns382":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"11:13a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns383":"http:\/\/flightsraw"}},"departureTime":{"$":"8:39a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns383":"http:\/\/flightsraw"}},"number":{"$":"330","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns383":"http:\/\/flightsraw"}},"carrier":{"@href":"#id70","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns383":"http:\/\/flightsraw"}},"@id":"id187","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns383:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns383":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"3:02a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns384":"http:\/\/flightsraw"}},"departureTime":{"$":"4:10a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns384":"http:\/\/flightsraw"}},"number":{"$":"402","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns384":"http:\/\/flightsraw"}},"carrier":{"@href":"#id66","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns384":"http:\/\/flightsraw"}},"@id":"id237","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns384:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns384":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"2:01a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns385":"http:\/\/flightsraw"}},"departureTime":{"$":"3:51a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns385":"http:\/\/flightsraw"}},"number":{"$":"740","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns385":"http:\/\/flightsraw"}},"carrier":{"@href":"#id70","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns385":"http:\/\/flightsraw"}},"@id":"id151","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns385:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns385":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"1:45a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns386":"http:\/\/flightsraw"}},"departureTime":{"$":"10:17p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns386":"http:\/\/flightsraw"}},"number":{"$":"742","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns386":"http:\/\/flightsraw"}},"carrier":{"@href":"#id67","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns386":"http:\/\/flightsraw"}},"@id":"id284","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns386:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns386":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"12:41p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns387":"http:\/\/flightsraw"}},"departureTime":{"$":"10:28a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns387":"http:\/\/flightsraw"}},"number":{"$":"394","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns387":"http:\/\/flightsraw"}},"carrier":{"@href":"#id70","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns387":"http:\/\/flightsraw"}},"@id":"id93","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns387:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns387":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"12:11p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns388":"http:\/\/flightsraw"}},"departureTime":{"$":"10:07a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns388":"http:\/\/flightsraw"}},"number":{"$":"789","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns388":"http:\/\/flightsraw"}},"carrier":{"@href":"#id72","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns388":"http:\/\/flightsraw"}},"@id":"id274","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns388:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns388":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"3:05a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns389":"http:\/\/flightsraw"}},"departureTime":{"$":"1:18a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns389":"http:\/\/flightsraw"}},"number":{"$":"295","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns389":"http:\/\/flightsraw"}},"carrier":{"@href":"#id65","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns389":"http:\/\/flightsraw"}},"@id":"id179","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns389:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns389":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"4:35a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns390":"http:\/\/flightsraw"}},"departureTime":{"$":"1:29a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns390":"http:\/\/flightsraw"}},"number":{"$":"888","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns390":"http:\/\/flightsraw"}},"carrier":{"@href":"#id71","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns390":"http:\/\/flightsraw"}},"@id":"id173","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns390:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns390":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"1:13a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns391":"http:\/\/flightsraw"}},"departureTime":{"$":"1:18a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns391":"http:\/\/flightsraw"}},"number":{"$":"859","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns391":"http:\/\/flightsraw"}},"carrier":{"@href":"#id67","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns391":"http:\/\/flightsraw"}},"@id":"id110","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns391:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns391":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"9:45p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns392":"http:\/\/flightsraw"}},"departureTime":{"$":"6:49p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns392":"http:\/\/flightsraw"}},"number":{"$":"982","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns392":"http:\/\/flightsraw"}},"carrier":{"@href":"#id65","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns392":"http:\/\/flightsraw"}},"@id":"id350","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns392:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns392":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"2:44a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns393":"http:\/\/flightsraw"}},"departureTime":{"$":"1:30a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns393":"http:\/\/flightsraw"}},"number":{"$":"406","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns393":"http:\/\/flightsraw"}},"carrier":{"@href":"#id69","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns393":"http:\/\/flightsraw"}},"@id":"id103","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns393:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns393":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"4:03p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns394":"http:\/\/flightsraw"}},"departureTime":{"$":"12:20p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns394":"http:\/\/flightsraw"}},"number":{"$":"433","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns394":"http:\/\/flightsraw"}},"carrier":{"@href":"#id72","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns394":"http:\/\/flightsraw"}},"@id":"id320","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns394:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns394":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"3:11a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns395":"http:\/\/flightsraw"}},"departureTime":{"$":"3:17a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns395":"http:\/\/flightsraw"}},"number":{"$":"766","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns395":"http:\/\/flightsraw"}},"carrier":{"@href":"#id71","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns395":"http:\/\/flightsraw"}},"@id":"id236","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns395:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns395":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"4:30p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns396":"http:\/\/flightsraw"}},"departureTime":{"$":"12:35p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns396":"http:\/\/flightsraw"}},"number":{"$":"637","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns396":"http:\/\/flightsraw"}},"carrier":{"@href":"#id66","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns396":"http:\/\/flightsraw"}},"@id":"id304","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns396:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns396":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"2:01a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns397":"http:\/\/flightsraw"}},"departureTime":{"$":"4:07a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns397":"http:\/\/flightsraw"}},"number":{"$":"238","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns397":"http:\/\/flightsraw"}},"carrier":{"@href":"#id72","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns397":"http:\/\/flightsraw"}},"@id":"id280","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns397:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns397":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"2:51a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns398":"http:\/\/flightsraw"}},"departureTime":{"$":"2:57a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns398":"http:\/\/flightsraw"}},"number":{"$":"911","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns398":"http:\/\/flightsraw"}},"carrier":{"@href":"#id72","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns398":"http:\/\/flightsraw"}},"@id":"id190","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns398:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns398":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"2:54a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns399":"http:\/\/flightsraw"}},"departureTime":{"$":"3:52a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns399":"http:\/\/flightsraw"}},"number":{"$":"436","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns399":"http:\/\/flightsraw"}},"carrier":{"@href":"#id65","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns399":"http:\/\/flightsraw"}},"@id":"id87","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns399:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns399":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"3:17a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns400":"http:\/\/flightsraw"}},"departureTime":{"$":"12:20a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns400":"http:\/\/flightsraw"}},"number":{"$":"893","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns400":"http:\/\/flightsraw"}},"carrier":{"@href":"#id66","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns400":"http:\/\/flightsraw"}},"@id":"id248","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns400:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns400":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"6:23a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns401":"http:\/\/flightsraw"}},"departureTime":{"$":"3:49a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns401":"http:\/\/flightsraw"}},"number":{"$":"989","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns401":"http:\/\/flightsraw"}},"carrier":{"@href":"#id67","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns401":"http:\/\/flightsraw"}},"@id":"id218","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns401:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns401":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"3:26a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns402":"http:\/\/flightsraw"}},"departureTime":{"$":"2:16a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns402":"http:\/\/flightsraw"}},"number":{"$":"896","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns402":"http:\/\/flightsraw"}},"carrier":{"@href":"#id65","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns402":"http:\/\/flightsraw"}},"@id":"id283","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns402:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns402":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"10:34a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns403":"http:\/\/flightsraw"}},"departureTime":{"$":"7:21a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns403":"http:\/\/flightsraw"}},"number":{"$":"564","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns403":"http:\/\/flightsraw"}},"carrier":{"@href":"#id65","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns403":"http:\/\/flightsraw"}},"@id":"id268","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns403:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns403":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"4:01p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns404":"http:\/\/flightsraw"}},"departureTime":{"$":"2:24p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns404":"http:\/\/flightsraw"}},"number":{"$":"705","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns404":"http:\/\/flightsraw"}},"carrier":{"@href":"#id70","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns404":"http:\/\/flightsraw"}},"@id":"id140","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns404:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns404":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"3:47a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns405":"http:\/\/flightsraw"}},"departureTime":{"$":"1:53a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns405":"http:\/\/flightsraw"}},"number":{"$":"335","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns405":"http:\/\/flightsraw"}},"carrier":{"@href":"#id72","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns405":"http:\/\/flightsraw"}},"@id":"id73","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns405:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns405":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"3:02a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns406":"http:\/\/flightsraw"}},"departureTime":{"$":"3:56a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns406":"http:\/\/flightsraw"}},"number":{"$":"790","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns406":"http:\/\/flightsraw"}},"carrier":{"@href":"#id70","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns406":"http:\/\/flightsraw"}},"@id":"id246","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns406:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns406":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"3:59a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns407":"http:\/\/flightsraw"}},"departureTime":{"$":"3:16a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns407":"http:\/\/flightsraw"}},"number":{"$":"293","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns407":"http:\/\/flightsraw"}},"carrier":{"@href":"#id68","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns407":"http:\/\/flightsraw"}},"@id":"id337","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns407:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns407":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"6:06a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns408":"http:\/\/flightsraw"}},"departureTime":{"$":"2:58a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns408":"http:\/\/flightsraw"}},"number":{"$":"787","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns408":"http:\/\/flightsraw"}},"carrier":{"@href":"#id65","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns408":"http:\/\/flightsraw"}},"@id":"id269","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns408:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns408":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"1:46a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns409":"http:\/\/flightsraw"}},"departureTime":{"$":"2:59a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns409":"http:\/\/flightsraw"}},"number":{"$":"764","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns409":"http:\/\/flightsraw"}},"carrier":{"@href":"#id68","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns409":"http:\/\/flightsraw"}},"@id":"id139","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns409:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns409":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"3:03a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns410":"http:\/\/flightsraw"}},"departureTime":{"$":"4:19a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns410":"http:\/\/flightsraw"}},"number":{"$":"618","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns410":"http:\/\/flightsraw"}},"carrier":{"@href":"#id68","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns410":"http:\/\/flightsraw"}},"@id":"id240","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns410:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns410":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"8:02p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns411":"http:\/\/flightsraw"}},"departureTime":{"$":"5:11p","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns411":"http:\/\/flightsraw"}},"number":{"$":"839","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns411":"http:\/\/flightsraw"}},"carrier":{"@href":"#id70","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns411":"http:\/\/flightsraw"}},"@id":"id193","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns411:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns411":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"1:58a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns412":"http:\/\/flightsraw"}},"departureTime":{"$":"12:28a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns412":"http:\/\/flightsraw"}},"number":{"$":"811","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns412":"http:\/\/flightsraw"}},"carrier":{"@href":"#id70","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns412":"http:\/\/flightsraw"}},"@id":"id341","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns412:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns412":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"11:03a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns413":"http:\/\/flightsraw"}},"departureTime":{"$":"8:07a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns413":"http:\/\/flightsraw"}},"number":{"$":"681","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns413":"http:\/\/flightsraw"}},"carrier":{"@href":"#id72","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns413":"http:\/\/flightsraw"}},"@id":"id82","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns413:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns413":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"11:40a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns414":"http:\/\/flightsraw"}},"departureTime":{"$":"7:50a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns414":"http:\/\/flightsraw"}},"number":{"$":"537","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns414":"http:\/\/flightsraw"}},"carrier":{"@href":"#id71","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns414":"http:\/\/flightsraw"}},"@id":"id114","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns414:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns414":"http:\/\/flightsraw"}},{"arrivalTime":{"$":"1:47a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns415":"http:\/\/flightsraw"}},"departureTime":{"$":"2:43a","@xsi:type":"xsd:string","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns415":"http:\/\/flightsraw"}},"number":{"$":"229","@xsi:type":"xsd:int","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns415":"http:\/\/flightsraw"}},"carrier":{"@href":"#id67","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns415":"http:\/\/flightsraw"}},"@id":"id78","@soapenc:root":"0","@soapenv:encodingStyle":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","@xsi:type":"ns415:FlightBean","@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/","soapenc":"http:\/\/schemas.xmlsoap.org\/soap\/encoding\/","ns415":"http:\/\/flightsraw"}}],"@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/"}},"@xmlns":{"xsi":"http:\/\/www.w3.org\/2001\/XMLSchema-instance","xsd":"http:\/\/www.w3.org\/2001\/XMLSchema","soapenv":"http:\/\/schemas.xmlsoap.org\/soap\/envelope\/"}}}
diff --git a/1.9.10/samples/numbers-fp-4k.jsn b/1.9.10/samples/numbers-fp-4k.jsn new file mode 100644 index 0000000..617542f --- /dev/null +++ b/1.9.10/samples/numbers-fp-4k.jsn
@@ -0,0 +1,6 @@ +[[-4.0517697E24,-4.6834714E9,2.3016275E-5,429379.38,4.1035245E-35,-3.0304818E-8,-6.054423E8,1.2708386E-15,-1.715156E27,-277.43622,2.0346915E-38,-0.01638545,-1.2856552E32,-4.69584413E11,7.477022E-10,1.07893673E12,-3.5855834,103206.47,0.0017756876,-1.61412621E9,-54.93887,-139561.4,-2.378658E22,-3.158278E-35,5.233813E-31,1.76682848E15],[1.0974016E37,5.3739964E-11,-4.9716053E-33,-1.66076738E14,-4.0119002E37,-1.4027267E-32,-2.72471598E18,2.5744203E-19,-4.572614E-38,3.2234583E31,8.654537E19,-3.4919776E-29,-3.25070671E12,-9.000992E-29,1.0441233E36,4.079525E25,1.2051055E-15,-2.29235541E14,-3.2437188E-13,-1.5618475E-4,-4.0124833E-25,2.8310637E-38,-2.7477381E37,1.32944947E9,2.18171494E12,-1.25300354E17,6.0274116E15,-2.107706E23,6.3065464E34,2.51101692E11,5.254233E25,-2.0404816E-19,1.7693594E-33,-1.1974275E35,2.8162636E34,6.4890817E-21,7.184675E-25,7.5984363E34,-5.618655E-11,-3280961.8,1.28438128E8,8.6140408E18,1.1140984E25,1.47108772E10,3.3097485E24,-2052130.9,1.63728826E17,-6256.014,2835.2756,-2.4856512E24,1.2163494E-7,-1.1225695E13,3185.818],[-5.7091426E35,-7.046804E-12,2.8546067E37,-772.3046,-2.1437726E-18,7.247147E36,-1.5350201E29,-8.961063E-10,0.85318434,-7.483097E-33] +,[-1.2860384E8,-8.602547E-36],[-2.944476E-12,2.77460487E13,2.2238986E-12,-4.3412906E19,-5175.8833,-0.0073129623,-2.4091398E-20,-4.1746454E-10,4.45905856E8,1.2805583E28,2.5504562E20,5048020.5,-2.664713E28,-1.3501865E-10,4659.968,-5.82742E-35,-1679.142,-3.875056E-26,-4.033507E24,-4.6903224,1.9332838E38,-2.0680365E29,8.525517E-14,-5.230842E-32,3.673353E-35,-1.7281757E38,-8.2598E-9,-17152.049,-4.852759E-29,-1.0426323E-22,-0.020246392,-3.1350626E-6,1.2408656E-37,1.120012E-28,2.4116303E-15,-0.4785474,346436.97,-5.232122E-33,-1.91926374E9,-3.2487415E19,-8.650112E24,-5.055328E-34,-7.409502E-23,1.2598161E-17,5.4119855E13,-1.1477772E-4,4.6083254E-12,-254158.67,-3562.668,6.329796E-33,1.8004916E-23,9.1474255E-32,2.3754586E-25,-0.3737642,-3.8334996E-8,1.6320389E-21,1.00855703E-16,2.8689735E-36,-1.4815323E20] +,[1.06485072E8,-1.0298127E-36,0.24806988,-1.49687634E10,-3.6207398E32,-1.0312921E-5,-1.2935636E-31,-1.2929703E37,-3.9697367E-19],[1.0102053E15,3.1466665E20,0.08864031,-3.9789494E-35,-2.5044518E-17,4.97892847E17,3.361501E-38,1.9492607E-32,2.0493702E-34,3.00903369E16,-1.6402363E-7,-2.6451675E-18,1.262038E-30,-9.804624E30,-1.2246598E34,-3.315567E25,182204.17,-3.130359E-19,-7.119018E26,-1.48141686E17,4.419125E-31,-2.8471037E-15] +,[8.0939505E9,1.1374584E-19,-1.4202437E-27,1.313552E33,-4.2573942E12,-5.8381478E13],[-2.6502555E30,4.1753343E-29,9.083372E19,-0.068183176,-1.1031515E-26,-2.4913055E-16,-3.6719114E-37,5.8186E37,5.715726,-1.0163735E34,-8.84853E37,-1.1815134E-37,1.0027934E-16] +,[-1.4073724E34,1.30061288E13,0.008461121,-1.3376654E-10,-6.0671164E20,1.1833966E-16,14.809583,3.5770768E-22,-7.530457E-32,-1.5393923E-12,-7.8060027E34,2.1101567E-16,-6.2677943E-17,2.2152926E-20,-1.1757083E-31,2.3695316E19,1.4274136E-12,-1.9480981E26,6.291982E-10,-9.367635E-8,6.9291846E15,4.72749638E11,1.0033393E-12,6.817596E31,-1.2097972E-24,-1.9492175E-8,3.22030314E13,-7.977198E24,-3.4311988,-9.747453,1.6084044E-20,-9.820089E-30,-121.80733,-1.6177538E-27,-8.8467775E-4,5.6503555E-11,2.0995368E26,-5.455361E-9,1.8685779E-32,8.574378E-4,2.1685172E-30],[6.861861E-37,-4.4493197E35] +,[-1.1613617E-18,-4.8534297E20,1.0546074E-20,6.6119614E-25,-2.24921029E17,1.5837627E-19,-186516.12,-3.640935E-33,8.555976E-17,3.2709814E-30,3.63576335E18,1.4442433E-30,2.4232822E-36,-9.666912E31,1.5853016E35,3.73195E21,-125.010605,-2.1777477E-17,1.00537485E-29,-3.1489299E-30,3540.4128,-1.2457142E19,0.002879089,3316.8232,-2.399002E-8,1.2665383E-9,-6.6589328E-21,1.569398E37,-4.0816245E33,7.659948E-29,3.50496255E15,5.2147024E-14,-7.601605E23,3.6567388E7,9.476331E29,6.5074084E7,-3.8742284E-16,-2.8865025E38,-5.8460764E-21,-2.8586424E-36,-1.7062408E32,4.27118324E14,-6.7125395E-28],[3.56796591E16,-618868.25,2.933427E-12,7.236035E-39,1.2127505E-37,9.672922E-34,-4.398644E7,3.5170867E-22,-4.2779222E-30,1.7244597E-28,-2.516157E-4,2.8513992E7,5.198693E-23,1.4477405E19,-1.13826478E10,-2.3829098E-36,18.335575,1.8759609E-13,-1.968288E-22,1.7264434E-37,2.1186231E-17,-1.366064E-37,-2.3724215E-26,-1.83045278E15,-4.5891318E20,1.4144087E33,5517011.0,-1.80326367E18,-3.4664499E-31,8.6163241E12,-3.4160834E-37,1.6376802E-32,-4.1883656E-29,2.1600535E-8,142394.83,-7.924927E24,6.102368E31,5.108181E-15,-3.3982544E21,-0.7968685,1.1872208E35,-5.3212889E17,1.4372333E-9,-2.59713466E11,-1.2630338E34,3.519925E10,7.971905E22,7.0312736E-12,-8.266714E-27],[-1588131.2]]
diff --git a/1.9.10/samples/numbers-fp-64k.jsn b/1.9.10/samples/numbers-fp-64k.jsn new file mode 100644 index 0000000..301f6b1 --- /dev/null +++ b/1.9.10/samples/numbers-fp-64k.jsn
@@ -0,0 +1,68 @@ +[[2.6535229E-31,-6.3308956E19,-3.6612234E15,-2.678559E7,2.6702905,-5.9068637E15,-8.157387E-25] +,[0.0034602399,-4.9989574E-12,5.6027035E-24,2.391569E-20,-4.8545338E-26,-1.9128763E31,-2.2797304E35,-5.6475305E-31,-8.4942343E-16,-3.465149E-16,7.0482251E11,3.126214E-33,1.6426457E-29,-1.07047094E14,2.04265933E9,6459852.5,1.2455255E-19,0.04852945,-4.6918415E-16],[2.993882E-32,-1.2256164E-6,-3.88535779E11,-1.56255725E14,-7.0686278E8,-1.1825112E-8,6.4509857E37,-1.1007136E27,3.5498442E-25,-3.9212004E22,-4.5836344E7,-5.940224E25,69802.234,-5.0968E21,-1.8074694E-8,-3.4485917E31,-0.6611753,2.3213966E24],[1.172189E-29,9.733035E-17,1.0992753E24,8.4844704E12,-8.6683997E-13,1.1094605E11,-1.7965676E7,1.02709966E34,1.0741854E28,1.9185885E-16,-8.3655151E11,-9.856661E-20,-2.85404893E16,-2.379941E-4,-8.3776928E12,1.7867977E-25,0.011597245,-1.41081335E26,-6.6038745E-24,-1.9745221E29,1.539104E24,-5.5591727E28],[1.7871889E25,7.8421593E-26,9.461137E21] +,[-2.12173072E8,-3.795819E31,-1.2554509E28,-2.5654093E-10],[6.5999994,1.7218609E33,-0.012438993,939.1766,7.093138E-23,1.2209317E-25,2.7071306E20,1.77743E-6,2.7941877E-30,1.0859481E-36,-1.0772707E22,1.32352934E9,0.14167772,-6.0089815E-29,-8.502864E25,-5.1308295E-4,-6021.425,-8.89324E-25,-2.500707E-8,0.08228797,-6.8578757E37,-2.9590106E-28,-1.0877065E-20,4.65055536E14,452.99426,-1.69357939E9,1.0729684E10,1.2038169E-24,-144473.9,-1.0064578E-37,-3.062391E-34,-1.100933E-37,-3.0693718E-17,6.763583E-27,4.117854E-39,-1.6736398E-15,8.445957E-9,6.4264248E7,2.2029085E21,-15921.255,-4.3933734E-10,6.940127E32,-3.81793408E9,1.358563E-36,4.1276015E10,-1.4802012E-27,-2.7596408E-32,1.059699E-10,9.104807E-10,8.404422E-26,3.5004688E-9,1.9395138E-21,6.892398E-35,2.03699521E15,8.767824E-20,-2.2651784E23,2.7166499E-17,1.4053419E-4,-1.1724944E25,1.6230291E-24,-1.8291197E29,-4.7328948E10,1.15966246E13,-2.5645604E-21,2.1966392E-20,9.4178323E8,-4.32126144E8,-4.327374E-14,-6.2280279E15,0.004526022,1.9304582E-17,2.3337225E27,6.9692502E16,1.2586697E29],[5997.7617,5.22090368E8,2.19173435E17,1.7981851E37,-9.979369E-12,-0.0017380471,6.2215564E7,-5.697561E37,-1.6502797E37,-3.24494711E14,1.451294E36,-5.835783E-22,0.061836954,1.3775194E-19,-16.837942,-0.23230144,-3.7539396E37,-0.01888702,-2.2541351E-35,1.9484589E-21,-6.7566396E33,0.048821412,-3.495256E27,-1.3285373E-38,4.50898E-28,1.7268163E-20,-955773.6,-6.622828E-29,-8.2036756E-17,2.924259E-13,5.0647647E32,1.1643229E-26,7.2521586E-11,-3.7323227E32,-12991.916,2.339732E29,-2.7075122E-20,-6.8960704E-17,0.51900554,-5.9936054E21,-0.015137768,-3.247555E22,-2.56008961E15,1.47095685E-36,1.4622153E-12,7.7171934E34,-7.544193E-7,5.0779845E-6,3.9633572E-25,2.4219777E-29,0.6069506,2.4379258E34,4.9829147E35,6.2219044E-23,7.4407635E26,-4.8400582E-26,-4.4876697E-10,40811.668,-3.9690345E33,8.862469E-31,-3.20557075E16,-1.1514233E7,-1.9178896E-9,2.11979568E8] +,[-80848.914,-0.0026732397,3.30004746E10,4.9471102E-28,3.8687313E-31,-2.9855964E-5,-3.67212442E9,3.0627095E15,7.8276194E-19,5.3863646E22,-404934.72,1.4820337E-32,1.4192764E-23,1.0121303E-14,-1.7668878E33,-0.06838432,4.233391E22,-4.222806E-39,1.2118468E-30,-35556.418,1.5127279E-15,3.6557565E19,1.5424345E30,6.068394E-39,8.638708E22,3.9049457E24,4.281842E-22,-2.9109668E-30,5.462076E-23,-1.14303206E27,4.688778E-38,-2.8907022E-27,6775.112,-4.3717151E9,5.5270997E-9,-2801.2212,5.6459445E-5,-2.1581222E-27,6.5815562E9,-1.089469E-13,7.1918055E-7,4.5751317E21,-204.8502,-2.8087629E-21,2.6423045E22,-3.340172E-34,5.0326556E-9,-5.22535076E11,-5.4474794E13,6.4334326E21,6.070314E20,23.221071,-6.030393E32,4.538023E-22,-1.9926042E-11,-41.89369],[6.324611E-31,2.6348025E-18,-8.242288E35,2.000639E-16,-3.6666114E26,-5.6946114E26,-4.071132E29],[4.4360223E-14,-2.0585313E36,4.4855497E12,-13.27239,-1.1073428E23,-6.4541437E18,-4.4476496E-25,1.20953678E14,25470.965,-2.7886143E32,3.7357097E-33,-2.2606373E32,-4.23796E35,7720065.5,-2.5043382E-28,4.5656885E-30,-6.961639E-11,-1.9319312E-13,1.26833861E11,1.2163623E-12,-124173.125,3.662106E16,-3.285093E23,5.6386879E11,9.28752E24,5.3346226E25,-4.4209505E20,2.1439174E7,-3.2421666E-22,3.8165513E19,-2.1260923E24,-2.63838945E10,9.541649E-21,-2.5550854E20,0.021623548,5.9854567E26,-5.8091084E11,-7.065009E-32,3.5037792E30,-2.331532E23,5.8431462E8,1.0341694E7,3.896418E-11,4.0183097E-14,2293077.5,-1.5654026E-35,-2.6699253E-14,-7.822621E33,4.315322E-24,-0.002313517,-1.6574543E-21,1.4579729E-20,3591.1572,-4.5170944E-18,-2.78611952E17,-2.1110734E-23,-4.3113246E-6,9.1698276E21,-1.6756981E-15,-6.854833E-6,-2.6159627E-29,412.33392,9.90769E-16,2.8810426E23,-4.9117775E36,5.78823E-40,4.7816546E-9,-1.3817376E7,-3.156944E7,1.5150228E-18,-1.4314575E-32,-4.428179E-28,-2.072301E-34,-5.129252,8.1669195E17,-252.1206,7.001677E-9,-8.144433E-33,-6.253973E-16,-1.8238805E-26,2.4729717E29,3.0851753E25,-3.451688E-35,1.3591939E-11,0.10220055,-1.16058014E11,1.3878365,2.399862E37,-4.3815566E-20,8.3958796E37,-327.94388,5.167833E-38,1.3481001E-36,-4.5197708E-36,0.39352754,-1436.4678],[-3.2871463,-4.2376574E-24,-1.2515325E25,-0.0019005111,-1.2113293E28,9.2862456E-9,-0.0037906703,-1.1611638E37],[-7.978034E-23,2.4743534E36,8.521475E-28,-7.8929362E12,9.952491E-31,1.8642626E-22,-1.719193E-16,0.10001894,-3.523265E-36,249.89531,3.0933438E-35,-1.2585429E7,8.857643E-26,-88230.21,-2.8092234E28,-8.0354126E-13,0.12322309,1.473056E25,-6.8615936E18] +,[-2.5297348E36,-7.368013E-38,-1.076627E-28,-7.7007749E15,-22.372606,-8.977881E22,-7.501992E37,3.7989866E25,2.5683582E28,8.2770024E16,1.87827292E14,-1.33954095E13] +,[2.83583E-36,-3.017899E-34,-9.3147485E-4,-2.9735795E-12,-8.9076545E-31,6.9782866E-36,1.9726709E-22,9.541568E29,-4.834942E-19,-4.6985393E-12,2.4275021E11,-7.481386E-7,6.4340796E-20,-9.9854425E-33,6.7009603E-10,9.471227E-13,-260.90906,1.8235383E-33,-4.95706771E14,-6.952875E-19,9.612285E-8,-1.2719771E-12,-1.12211087E15,55514.207,-4.5526364E27,4.656814E20,1.9872182E-13,0.9946952,2.069911E-5,1.31716538E11,4.0740787E24,-2.487807E-31,4.1312148E7,1.340491E-6,-3.635888E-35,-9.5867587E16,-1.7570944E32],[-2.5722143E27,1.1238163E-38,6.0498795E24,-9.611712E-6,-1.5955684E27,-1.0723542E10,-8.5553495E-7,-4.2760327E-14,-2.630693E21,1.95525083E11,9.127949E29,-7.524899E-23,-2.119795E37,-2.04406235E18,-5.3023616E-19,-3.3658996,8.377197E23,-1.7043822E-5,1.3179344E28,-1.11099537E12,-6.363299E30,-4.7785908E7,3.30950848E8,-3.03227827E9,4.5047694E-32,7.994301E20,3.938957E21,-1.1805678E36,-1.149164E-38,-1.1955668E-17,-1.7497947E-5,1.5460201E-14,0.0011019544,-9.772907E-18,1.6204629E20,3.7992635E19,-0.52898777,-449814.47,1.6927752E-26,-1.890229E-5,3.0518583E31,3.77259452E12,-4.9841966E-17,1.9143402E25,-7.949224E31,7.7348874E-32,-2.44324835E14,-1.2597142E7,3.0461904E28,-1.8065428E36,-5.9193197E-12,29.584963,-9.967072E22,-6.1103116E-22,-2.5339657E-31,-1.24389758E16,5.311816E30,-9.717531E-23,9.976159E-20,-0.4442942,2.046243E-26] +,[-2.96422872E13,-6.3277275E25,5.1580752E-8,1.7779605E-5,-1.4448909,1.041386E19,0.0673465,6428132.0,-0.0062295296,-6.0453197E17,-0.2114366,4.97585952E8,-2.729206E-5,1.82667791E15,-1.3350689E20,1.3113594E20,4.8448774E23,-2.5136028E-36,8.6560627E8,1.32157318E14,1.39104131E12,-1.84373661E12,-1.7154715E-33,2.6342105E-24,5.9719614E34,-1.1233949E31,-1.0465356E-36,1.3186333E-36,-5.2523444E34,-1.5381603E-38,-8.032629E27,1.4126238E-19,-2.4494736E-15,-14.433311,1.0122156E-19,1.5462485E-4,5.852681E-20,-2.2212762E23,-1.01059875E24,-6.394611E20,-0.79532546,-8.351006E-12,2.2660747E-16,4.977851E-10,4.905539E-4,-3.51602465E13,-2.30332976E16,5.59634776E14,-1.0818905E-11,-3.1019576E34,-1273.1372,1.9252214E-22,-9.166295E-20,2.2443522E33,8.7383146E-26,-6.007704E29,-1.6720691E-23,9.061457E-8,-1.2947306E-23,-4.6964997E-38],[7.8893924E31,3.07141837E10,3.5064477E-30,511.66837,2.0288735E-21,1.5008125E-11,4.1229615E19,153.60852,-5.00198464E8,1.0709774E21,4.2353862E-33,-2.55101846E11,-2069187.6,6.164251E-32,-2.7413694E34,4.188528E20,141.74352,-2.6147399E23,7.729892E31,-5.2636273E-18,-0.28653175,5.106643E21,-1.8035745E34,1.9061558E25,4.501794E36,-1.20316945E13,1016.1254,6.061748E-20,-6.4808927E32,5.1562366,5.3972E-38,-0.0032188573,-13.5752735,-3.0721177E22,4.131355E35,-105.52056,8.15333E35,5.363832E29,-0.18775955,4.0500894E22,-1.4168374E21,0.038646944,-7.297702E29,1.1156196E-21,-2.6687906E35,-4.544637E-26,-3.3141204E-4,-4.931643E-19,-5.0394877E12,220407.58,6.1996923E32,1.09094394E-17,-8.928763E-11,0.16848186,1.94481944E15,-7.207436E32,2.3807752E-19,-8.5378472E7,-1.5565517E-15,-934355.0,2.3759372E29,-4.68141849E17,6.417166E-35,-2.2429213E-27,-4.815584E-29,-0.0053960076,105.3496,1.2972911E-24,-2.1951991E23,-4.705652E-22,-6.099291E24,-15635.991,-0.0012562996,6.922176E22,-8.5089015E23,58865.164,2.3982756E-16,9.242356E24,-3.8435752E-9,-6.936914E-14,3.53225146E11,-4.79937E35,3.020672E27,-4.0472785E-24,0.06208434,-0.0010544735,3.2205075E23,2.8516762E21,7.926591E21,-6.8404767E-31,1.1215144E17,-3.3998662E22,7.4122036E34,-4.3587058E22,2.845305E-12,-1.2178893E-24,-4.5326104E16,-1.474497E35,1.6776792E-16,5.79595E-15,7.830873E16,2.212906E-35,2.840859E29,-5.301346E25,3.0949E-36,5.843128E24,2.6651596E-18,4.23338E36,-2.9150254E-25,-8.1340363E12,5.3269786E-36,-1.8946328E-16,-3.8732234E20,3.8953363E11,-1.4908035E-37,1.3413529E7] +,[-4.5626298E-38,4.9297265E9,5.37850817E17,3.974901E30,-7.5143934E37,7.3995796E-9,1.6215814E20,-0.012788779,0.07565902,-7.383337E-23,2.2363313E32],[-9.0022535E-15,2.4458215E32,-8.955363E-29,3.910716E-22,1.1812161E29,-7.7128334E29,-6.5684406E-22,2.6877297E-29,-1.3060789E-11,-1.4532642E19,-1.5384355E36,-9.650132E-19,1.89742E25,-1.26561638E10,1.957695E-37,1.6230686E31,2.8771005E-30] +,[-2.0386938E-10,2.34681E25,-6.2329929E15,-1.4005585E19,1.08749964E14,-461007.44,3.0655994E-16,-3.0385334E25,-1.9790804E31,4.340749E-39, +5.184542E-7,-7.290088E-13,3934.4355,3.079712,-1.3798011E-33,-1.1360229E-26,-6.155818E-6, +-7.5368058E31,1.999573E-7],[9.224108E-15,-3.3340793E-23,1.791771E-21,1.3469135E35,-1.1501752E-14,-3.6089584E-22,2.1340398E-26,2.6019689E38, +1.0074474E-4,-10.901403,2.3974809E-12,1.1665053E-30,1.78668372E11, +-1632184.9,-8.519279E-7,-6.876629E-5,-6.1764878E15,-4.9004257E36, +5.2117971E10,6.8897178E10, +0.0014059772,2.8422242E27,-5.2190044E-36,4.4039364E7,1.5955432E20,-1.0467144E-19,-4.044522E-17,-2.4481046,7.0801434E-6,-6.0419743E9, +-1.66617123E17,9.4009554E27,1.9044671E-31,7.0450094E-23,-1.1768533E28] +,[3.87857E-21,-9.583951E20,-2.70598605E9,-6.307099E-35,2.22536506E12,-59.811153,9.1209144E20,3.4833005E-12,-1.9121487E22,-2.191084E-5,-4.5865073E-28,-6.108937E-30,-3.45633068E13,3.8241077E-19,1.04878048E8,2.9121276E-8,-6.501428E10,-5.8277903E-21] +,[-2.752694E-20,1.674041E38,1.7459461E37,-2.12437861E17] +,[6.991386E-10,3.4141742E-15,-2.3748144E24,-0.007935386,-4.7132715E-17,5.66245E-40,-1.087321E-28,0.0025962195,-1.3299807E25,3.923745E-5,2.1293476E-28,-5.198644E33,-4.2812498E13,8.061859E-33,1.8939721E-8,-4.8484296E-32,8.246557E30,-3.8046344E-28,1.2675797E-23,-1.7817929E-37,1.7236113E-26,-1.5601187E7,1.5747247E-37,-3.748514E-33,1.6529484E-30,-2.7024744E-10,-3.2312002E-25,-235.09137,-2.85875686E17,-1.762145,7.830253E28,4.75398341E11,-3.0335843E-6,-5.6157214E-26,0.0030372695,-8.860499E-31,3.318433E30,-6.7724163E-6,-1.5482294E-27,-4.4418993E-36,6.499332E-34,1.5978082E-32,-2.270039E-4,-0.2433885,1.18475146E14,-0.16603182,3.32074E23,4.82078E-33,1.1191186E23,1.5621392E15,71.506615,6.1661815E10,4.5710682E-17,6.1759707E-37,-7.3347425E23,1.27841115E-8,3.2572577E35,-43.802284,5.324903E-28,-2.830785E22,-4.499699E-26,4.191541E34,3.1751783E-6,-2.66276E-6,-3.0833334E-33,3.3614098E-23,-0.0036774008,-3.8589498E28,-1.2548406,8.259908E7,1.6195077E-28,2.1304361E36,1.4567335E-16,4.3310415E-13,3.3383633E-11,7.885624E-20,-480.6271,1.0037746E35,1.2754476E-9,83.81333,7.898458E-5,-4.03667038E15,-2.2329178E-15,-2.0152636E-13,2.081016E35,1.6286735E-34,1.6121435E24,-6.1771156E-31,-1.7282902E-34],[-3.96941065E15,27.970276,-1.53067066E13,3.6667887E24,2.85265795E15,4.2997931E12,1.4818504E-6,1.0321158E-14,1.5508368E-8,2.927697E-9,-3.39338018E14,-4.4746353E29,-1.5560365E-32,-4.124734E-28,9.0650603E-4,2.30105399E11,-1.3441657E-21,1.9883716E36,15880.264,2.8150516E-36,-11.915885,1.0706588E21,4.223408E8,5.4251542E-12,-1.1481796E-27,5.822903E-33,-3.505783E34,-4.8237903E-14,-7.849323E-38,-4.43749E35,2.2351224E-13,1.8254235E-36,8.9989259E10,1.813454E-36,-1.0558517E-24,-3.6580843E-38,1.4184178E27,1.4560464E34],[85629.22,-1.7003546E-10,-3.5413635E-16,105.94623,-1.4186892E-5,5.2413778E36,9.342507E-9,-1.3427592E-6,-1.2367598E21,-1.55271383E18,-3.2187312E-24,6.251089E35,-1.3887139E-9,-1.03444714E27,1.7714859E-11,-0.005817533,2.4563237E-32,-2.0803736E-28,-13.471874,-1.5048416E-23,-1.7501842E33,-7.2776375,-2.1466478E19,4.853822E36,3.0963873E-12,-3.3486038E37,-1.4131504E25,5.0066066E-18,-1.087173E38,-1.1019988E-18,-7.9779854E37,9.017251E-10,4.0723884E15,-1.341312E-18,-1.0717458E-22,3.46674849E12,-0.02340292,0.22586018,8.6854499E12,2.72159923E16,1.65686212E16,8.758956E-23,2.867559E22,-2.4451188E-9,-1.3564005E24] +,[-6229597.5,2.0014847E31,-3.4308033E-37,-8147.847,-9.0806074E32,-2.1128706E-4,6.6282367E15,1.61200688E8,-2.1548193E-26,2.2858645E31,-6.9279332E22,3.712441E-38],[-3.13842208E18],[-1.9934488E-11,1.3296543E-14,6.088549E-29,2.1249287E-5,-2.3573263E-9,-0.0058179013,1.17241576E21,4.07445E-22],[-1.3451417E-37,-1.5636806E37,-3.764115E-15,-1.0246142E-14,-2.94194173E15,1.9969695E-23,1.2336216E-11,-1.5648814E-38,-1.3196884E-17,4.1131836E-9,-3.1402063E28,-8.293467E-35,-1.79982945E16,-2.0917452E-30,-5.379634E-8,-5.0319304E37,-2.9847737E-12,-1134.7717,1.69248052E13,4.9066194E27,-3.4882248E22,3.7649075E22,4.3517765E-32,2.3000411E32,3.0656001E29,-1.034691E33,5.433126E-7,-7.913855E-16,1.3481003E-8,-9.742205E-31,36.262638,435678.12,1.5763418E-33,-4.031753E-38,4.523754E12] +,[9.943559E23,-1.14064816E-35,-9.176797E-24,-8.234128E-12,0.15862457,-5.4980867E-18,7.7291604E36,-2.6331496E27,4.4836097E-30,-0.041381553,-2.3864592E36,1.0077372E-16,5.853387E37,226.83781,1.8226199E-28,4.0925454E-7,-0.43729714,9.1037206E-11,2.3414647E32,-2.4859513E38,3.1183667E-19,-1.2243246E-11,7.8740177E31,8.458513E-16,1.8281419E-19,1.2040764E7,2.6616312E-34,-67977.56,-1.20570615E30,-6.119411E-38,-1.928541E19,6.815997E-25,-4.2523086E-33,2.876159E31,5.9133672E26,-1.07138136E-29,3.6584114E-38,-4.8518688E-32,1.5660016E33,-5.3123855E-17,-7.438176E-6,-1.0479898E-21,-1432.1406,-1.83065854E15,8.559633E-36,7.294675E-13,6.7877282E15,7.6135919E14,8.0692963E37,5.114364E34,4.2127463E19,1.383909E-7,-4.8990693E-25,6.472123E-37,3.6370087E29,-335.7757,7.5406672E16,1.3973097E-9,-9.911163E28,-5.218519E-19,3.9373206E10,5.8175686E-35,3.3169375E34,0.035486404,-9.863275E24,-3.3888747E19,-2.8939148E19,4.5834077E-35] +,[2.4604633E-21,1.1454275E-37,-4.773637E22,6.88222E-35,2.4849248E-11,5.3971255E13,-0.08682255,-2.1922608E-27,1.48448282E9,-3.808519E-18,-3.891184E31,-2.3028217E-34,5.6621474E32,3.9170726E-27,-1.7524487E22,1.6244168E19,-1.4417567E-34,30673.639,-3.33029107E15,-1.6279645E25,4.7073638E13,-97.48056,1.705634E30,-1.0281326E-10,2.8019733E-7,-8.2943033E-13,14734.208,-9.4815846E8,-7.4620836E14,-6.621855E-15,9.3110124E-8,1.85352217E17,2.3451458E-33,-9.9309604E-17,-4.11369701E11,-5.812215E-11,2.5101806E21,1352671.6,1.7365033E29,2.8036528E-8,5.824094E23,-4.479246E-38,7.213573,-4.2111656E-32,1240764.5,6.305584E28,-7.8413074E-13,-0.0056190337,4.338572E-14,-6.080884E-39,2.7675316E-5,1.5327403E-18,-6.9403528E11,7.8947424E-26,3.1761916E-14,-3151681.0,-2.76852271E13,1.2255282E28,-2344.65,3.2276745E32,1.3160247E22,1.165898E-34,2.5202588E-26,8.5282336E7,2.2256924E33,-6.93265E-8,0.003912731,-1.65872976E11,-3.027568E-12,1.560891E-37,-1.1190163E-30,1.0223823E-24,-2.5976526E-16,3.6897457E20,13499.478,-1.7299861E-18,-3.2848326E37,-1.6212045E-19,1.7557212E-36,-1.0860156E-11,-7.023582E-34,5.6786053E-33,82.14449,-2.5030997E-7,1.400592E-7,1.0625092E21,-8.970597E-17,0.0016552821,-1.0208666E7,1.0773274E29,2.5338252E-6,-3.3852126E11,-1.68228595E9,-7.4949714E-24,-13.60802,1.4036958E7,-1.27623475E13,2.6202063E18,-5.77665E33,-0.1566148,9.465927E-17,6.6991395E-31,2.5110508E27,-1.3195912E26,-509.82,2.650505E-9,1.13659032E18,-4.28806E34,-5.4878118E13,-7.0968315E-22,-173.36906,8.822957E-5,-1.7134555E27,-7.1029226E18,-2.6966985E-33,-1.0770072E30,-7.381477E19,7.909763E-10,-8.2960996E-32,-8.370223E-17,-1.15937536E27,-2.9323547E-32,-5.9325394E-18,4.9792977E28,-5.385977E35,-3064.914,4.4215977E-8,7.5121353E12,-1.1877986E-32,-9.972842E33,-6.1029396E-24,1.4030575E20,7.952922E-20,3.1911554E22,1608748.4,1.5529038E29,-2.1203335E30],[0.013377522,1.6594402E35,9.912939E35,1.9785817E34,2.13610731E17,6.0896337E-9,2.1988515E37,6.2055763E11,-1.4581766E-34,-2.3577012E18,-1.7991664E-36,1.9981725E29,-4.6943924E-9,-1.7148108E33,-9.130543E-39,-6.5057292E11,4784.42,-2.611576E28,3.93782152E17,3.266582E-4,-5.0465737E-10,-6.0319315E-23,-2.8338947E23,-2.2517677E-32,-3.0678122E-22,4.078392E-22,-3.712211E27,9.5129143E-32,6.0775647E16,2.3798107E-30,8.1528656E-10,-2.8964038E-16,-5.9301293E-15,-3.9867887E-29,4.91129064E17,6.320737E-34,-421.9368,2.5257999E-12,-1.17176794E9,1.2343717E-35,1627299.4,-5.810829E-31,-1.185004E38,2.7569042E-33,3.108391E23,2.7838576E25,-1.9218348E-32,3.3662658E-5,2.7247193E-35],[1.3685117E22,-2.2543395E-29,-6.117453E20,-7.79229E-39,1.8904142E-14,-8.3240606E21,15163.21,1.01575E27,1.8002075E-9,-5.4488195E29,0.45126706,-5.16225728E8,-1.4412709E-28,-8.408332E24,-3.6276004E30,1.2204871E23,6.8886653E27,6.2265E31,3.7241733E-33,-2.2511392E32,-1.407166E-23,1.2922098E33,4.2585494E-35,-2.31755248E8,-1.0083557E-38,-4.0378742E29,-3.5291334E-9,-1.4577695E37,9.897636E-39,9.405287E-18,1.3555452E37,-9.078515E-13,-6.2135303E15,4.0782264E-27,-1.4096508E-34,1.2087257E-17,421.17807,-7746.6357,4.445309E-16,-6.2729027E-6,1.8640488E-33,-1.14912232E8,-5.752873E-29,-7.3915064E21,22.460936,5.0996106E9,2.284282,1.7432648E-25,3.2066492E25,20254.875,6.7530603E-22,-3.824307E35,6.3122816E-25,4.1893254E36,7.97705E21,-1.22047866E-29,1.2005957E-36,-8.6610641E10,-5.8215637E-36,4.8796124E-27,1.3179117E36,1.4779165E21,-1301062.1,1.1417486E32,1.3796029E38,6.521187E24,-9.8611437E8,8.250178E-21,4.2303167E-28,1.4423644E-16,2.4052232E-4,-4.4350903E25,961.1548,-2.6661182E-9,4.5496615E-32,1.0892181E33,1.7163632E31,1.3610958E7,6.518452E-9,3.15344788E12,2.2173E-11,-6.5766945E-21,-5.5663702E-5,1.6629153E19,-9.93888E23,-8.599363E-35,2.8860872E-28,1.3699179E-34,8.4352621E15,3.0661657E-24,1.6219009E34,1.157281E37,6.886313E-30,-1.3597877E26,6.9964746E11,-7.2001284E-33,1.4486607E-32,5.7523265E13,-5.6805125E19,4520.4814,-6.977568E35,-1.75602369E15,2.1526697E-17,1.61094E-36,-7.375187E-18,-2.1948729],[-8.791754E-34,6.968372E19,-1.1207005E-24,2.4216982E7,-9.766945E-20,-3.4977608E28,2.1244133E19,-2.9989238E-7,3.10057533E11,-3.2766864E-34,-5.641571E-7,-2.6787975,-1.8415956E27,4.795678E-21,-5.5918408E12,-2.1467392E8,-18879.3,2.6500825E34,7.977973E-10,6.660919E-16,-1.8085991E-25,-6.1228274E20,-3.7943924E-22,1.341398E-8,-8.5483282E10,-8.000307E-35] +,[-5.945489E-11,2.5332061E33,1.2185245E-7,-9.038794E-33,-130.48666,-7.893069E23,29473.13,8.166829E34,-3.9134607E-31,-1.3088044E-14,-5.8650714E10,1.01793837E9,-72652.24,-2.8106998E24,1.6246853E7,-3.39357839E17,-4.67704938E11,-3.2914292E19,4.8891508E-32,2.6304217E-25,0.25187346,-1.7076134E-18,1.754977E38,2.565563E20,-7.8236297E31,8.807448E-4,-8998.401,-1.59900998E12,9.9990304E-29,-2.6473468E36,-2.5573411E-21,-2.55667E-22] +,[-2.65560096E18,-1.4007897E35,12.530237,-3.955555E-36,-5.4991985E9,-1.2324911E-31,0.0026004754,1.5829873E28,1.7246417E19,-8.541806E-9,3.574526E31,-4.9842272E-18,-2.0235442E25,2.02045181E12,-1.6821323E-6,-6.4785885E-11,-5936152.5,-1.720913E7,9.6065487E11],[2.5189547E30,4.408919E25,0.31051606,13.032929,177.4452,-0.01821126,-6.2282225E-21,-7.7406095E-28,3.0242627E-31,-4.0431882E-23,5.8649226E-33,3.675122E26,14912.729,-1.8584317E-24,-4.3161943E-38,6510.859,3.070655E-38,2.7767634E34,3.8474953E-27,-7.2744527E15,1.0053946E37,2.62716481E13,0.013282104],[-1.2254288E20,-4.00565436E11,2.1728722E35,-2.1016934E20,-3.7011133E-36,-8.822166E35,-2463.6926,-56765.113,1.3969837E28,-3.4087975E31,-3.7205904E-38,1.4049089E21,4.38297E-40,-2.1295102E-27,-1.50500217E14],[-2.2349372E29,-6.6248518E15,2.1348871E21,-0.8594765,-5.2489933E-33,-7.7569626E-15,-4.7306723E-28,-1.4602794E-7,-6.2428418E18,-8.1971305E20,-2.029365E-34,-4.4834547E31,1.4006753E-29,1.244169E-33,-1.4092677E-24,-0.0066948957,-2.0225407E-7,-0.14170189,-1.2626884E32,-1.6745427E29,1.14762365E21,4466168.0,-2.7383464E-26,1.2850034E-31,-7.5223203E-31,1.3311776E-37,1.3275721E37,-4.2543905E-30,-0.012650995,-6.6229973E-21,-1.6714041E38,-1.70922376E13,-1.14074306E14,1.6011432,-8.910942E-28,-1.0628991E23,-2.1925081E18,-1.4939666E-37,0.111466296,-5.1021055E-15,-0.0027280378,-1.0441042E-15,4.9724447E-20,-1.9659653E-6,-4.2630705E30,-1.6915913E-11,-1.4960305E-28,-5.5604384E36,-3.870055E25,-6.143615E26,-1.2545532E-33,6.857317E-32,1.4830949E-10,8.35413E30,3406168.2,2.586748E-9,-3.087689E-29,1.3097007E34],[1.5496766E-36] +,[2.277385E-12,-11922.696,-1.0601711E23,6.967414E-19,-5.206316E-22,1.8865904E-23,-3.0848947E-17,-14.666902,2.057501E-13,7.532893,-1.13831456E8,-5.00169834E11,-1.2749845E-15,-26.820055,-3.4026826E12,-8.797125E34,-848.84973,-2746.5835,-303442.44,-7.0334454E22,3.1788996E-24,1.0448093E-33,3.1548128E-26,-3.0011015E-38,-0.7247722,-1.8878101E-17,6.630335E27,-1.5456015E-7,1.0367542E23,2.9280086E36,-2.6455633E-5,3.00810109E12,-9.0245086E33,6.530137E21],[1.38867311E12,-27.486586,-2.434253E-32,2.5778796E20,7.59485E-29,-2.76198201E16,-2.8273008E-13,4.3305346E-23,9.955619E18],[-2.958574E-13,-5.855436E-29,3.1332264E-26,3.2782405E-5,2.23353157E15,3.3291744E-21,-2.33294893E17,-0.001710379,-2.9223552E8,-0.0029085996,1.8074379E31] +,[-4.5601818E24,-8.476378E-37,-1.5906557E-26,4.5619851E10,-5.761538E-19,2.744682E32,-1.10971565E-14,-2.9210783E-9],[5.0052375E-8,-1.6796031E29,6.909423E-30,9.27159E19,1.1730386E-14,0.002774217,-1.6338386E-30,2.4220062E-4,1.6383446E32,1.08755484E14,-1.2060308E-21,6.948288E30,1.6505052E29,8.7491535E-6,-4.480187E34,2.8718891E-27,-6.9487276E-14,-601758.4,-2.92426791E13,2.7383085E-12,1.4675421E-12,1.5540477E33,-9.7484941E17,-1.3063929E-33,-1.5785367E-23,0.21390437,1.69939722E10,4.5304178E-6],[1.0418203E-34,-4.514773E-9,1.03528753E12,6.9052304E-29,-1260908.2,1.59600672E8,3.9271218E14,4.16676172E15,-1.8749305E-10,-6.609547E29],[-4.500122E-4,-1.3003437E26] +,[4.6993582E24,-2.2476652E-35,-2.025543E-38,1.41192624E8,2.2379E12,-6.6317874E-38] +,[-5.4267844E-24,48.191216,-2.3404034E-16,1.0695002E35,-0.24409178,4.834642E-34,2.4793964E-11,-1.5104987E-15,-6.766781E20,3.2134312E-24,2.52508321E13,1.5620833E-5,-2.9720262E-32,8.575686E-26,1.6031063E-6] +,[-3612.9854,-5.444763E-32,-4.4612526E-20,-3.116652E19,-9.344697E-17,0.0052720644,2.338387E-19,2.5050427E-11,-1.998682E19,2.7275892E-13,-1.9041895E24,-1.6710945E-14,230.90535,-3.2392546E38,3.4847934E-11,3.0620878E32,-0.009189749,9.5089046E27,7.239263E-9,-82.75874,5.417001E-21,2.5520123E-8,1.4205682E-13,-3551071.0,5.2756236E-15,-4174.0215,-1.1783311E25,1.0482635E-38,-1.2417504E33,6.4708315E26,-2.1582315E-37,2.4447767E30,2.2057793E-4,1.5143285E-31,-1.98159483E11,-7.471942E-21,-63.107765,6.668308E-14,-1.9725835E36,4.8566816E-4,1.15405865E30,-3.3622467E36,-1.39017204E16,1.9544464E21,2.8000494E-29,4.7190023E31,-7.4939015E17,-5.420105E-5,2.405227E29,180702.77,-1.807901E38,-0.46347526,-1.1928653E38,-1.7304545E22,9.07161E16,-1.8148965E-11,4.7496613E-33,2.7463635E-13,1.542372E24,-5.675163E-38,7.068117E-11,4.9238943E36,-3.983349E32,-13337.522,-3.4916945E-4,1.1932984E31,8.135749E-38],[-2.9809817E-31,3.24457291E17,2.682666E-33,3.5102253E-20,2.6367989E-28,-2.0844399E33,3.528736E-5,-1.0223548E-12,4.36395959E17],[-3.088835E-9,-4.1452816E-25,-5.1354884E37,3.6966E20,-6.658147E21,-4.1318012E-22,-1.43992154E17,2.0267156E-14,-0.019217206,1.8195781E27,-5.35714E-22,3.7145734E-13,-6.06098E22,-1.9937858E-35,-2.750705E-20,-1.3403197E-31,-1.0186433E-31,4.4217047E-18,-2058901.4,4.0615858E-29,-5.590844E29,3.0171224E-19,-1.7438155E22,1.39589798E9,-4.191031E22,2.7864587E-13,1.8216821E19,-1.1428524E17,0.04039231,1.1269817E13,1.145838E19,2.2917673E29,-2.1779514E-21,4.9807283E19,2.8074933E12,4.6995681E10] +,[6.9146962E19,-3.1758063E-8,-1.8491408E-19,-4.4880697E36],[-1.13149512E10,-128055.64,-3.91928033E15,-7.9312525E-37,-8.809E26,-12.84868,2.1193459E-15,6.507739E-22,6.717573E-23],[-47.159573,-4.2953694E23,3.885824E37,-5.25599474E11,3.4922824E-33,240669.95,-5.5850285E23,1.31169579E18],[5.7589196E-35,12876.559,-8.7142436E24,-1.6547342E37],[-5.8402E-31,-8.3912557E12,7.5898206E-6,1.6322806E-34] +,[-33158.465,1.9812552E-27,-4.4407776E-20,5.0424244E-18,1.41699E33,-8.757934E-27,-1081726.5,-2.015518E20,-1.01422044E-26,-3.3002863E-33,13055.995],[1.1319426E20,-1.0948676E22,2.06028027E12,4.1488543E23,-0.005341658,1.18227305E-7,14.305751,-1.6706637E-34,1.56692025E16,-1.6945705E-18,-62.314365,1.9962698E31] +,[-7.368051E-11,-1.2094854E-18,1.0210027E-25,-1995.4661,2.1134639E30,-5.044628E-16,-8.869583E-20] +,[-112.03558,-5.235014E22,-1.2228524E-22,-11133.814,6.6177122E-34,9.791691E37,-1.4827242E25,-3.4249252E-20,4.7146255E35,3.6159345E-5,4.1903357E-7,4.7366243E36,195.98805,-4.5289881E13,2.4037113E-35,2.4560953E16,0.001738607,-5.589831E31,1.7033344E8,1.7232977,-3.3759536E37,-6.339997E-26,1.1119883E-17,9.1740393E-38,-2.51201488E8,5.607045E-39,0.006527377,2.1330482E11,-7.357917E34,-2.1029858E-33,6.9727943E-12,5.6792646E8,1.4564352E-37,-4.3727807E-19,-6.77699E-28,2.296647E38,2.6269462E-12,9.4065273E14,1.3558843E31,-2.3683035E-15,-3.4923606,-3951991.5,256.90814,-3.3386005E23,-3.95611699E9,2.56281504E14,1.87798387E9,-2.75495885E12,-2.237272E20,1.30207002E17,1.07428245E15,-6.6090907E18,-1.3631758E-19,2.9680282E-19,-187.37361,-3.5074108E22,2.8213424E-5,4.292452E-29,-7.131377E-18,15034.558,-4.39418461E12,-2.24211147E18,-1.0460587E-11,-2.80428773E11,1.2054711E22,1.0710614E-12,2.0090904E-20,-5.46057E19,-1.3642586E-35,4.6023165E26,2.43557663E11,-1.2364676E-31,6.8898344E11,1.5083254E-11,-1.6089095E30,-3.843059E-29,-6.4030325E-30,-0.3760086,2.75948E19,3.2108447E26,-4.17577E-30,1.155235E-26,0.060416292,-2.5216004E-26,3.513795E-16,6.519042E-7,-9.254507E-14,441085.44,-0.004158272,-3.1504228E33,2.2683187E-8,1.27185186E-26,-1.2902433E-15,-0.012782133,0.38049155,-3.0701978E-15,-4.3906153E24,1.1270128E-38,1.8822772E-25,-3.9289614E-25,2.05648834E18,-2.8693992E31,-3.1571132E-22,-1.1130514E-7,-1.8716855E-30,1.4887326E-26,4.241542E-13,53695.383,126207.73,-6.6300595E-6],[-1.126504E-27,1.26586E36,2.1201758E-34,1.6026291,-2.430941E38,1.2518707E-37,-1.30829913E14,1.2198096E-29,4.472551E-24,-5.0354387E-26,-7.8567092E14,-0.0025371416,1.0146015E-25,4.2213214E-17,4.7672683E-26,6.0185034E-24,-506132.6,-6.5684215E16,-3.4724798E31,-5.657057E-28,5.647748E-35,5.3402655E-8,7.613152E37,-1.0350687E-12,0.0010120873,-3.70309307E12,-1.6472158E-14,-4.3954373E34,4.00592256E8,-1.2581203E-27,6.0080873E10,1.4912756E35,-4.526522E-19,3.3112363E-18,-6.8008626E-4,5.645379E-16,8.9279052E17,-9.7158696E-20,2.4546924E36,-1.943974E28,-3407.7,-0.019545026,-6.833853,-2.307492E-29,-1.3366143E-35,1.0086338E-11,-3.9686054E-10,8.711066E20,1.1184001E-5,-1.9225208E31,-1.2123996E-37,-1.00854275E-4,3.3385193E28,89.92665,-1.5094693E-8,-1.2247425E-36,-1.0060454E-6,6.858928E-35,3.2533488E-28,-4.2138997E-20,-0.8893121,-3.8721677E-33,1.74107329E11,-1.532285E-16,2.9378392E-33,1.44622561E10] +,[-779.1359,4.5957345E-6,16371.021,-2.3385797E-14,2.704047E-4,-2.6768743E19,1636294.4,7.5111019E11,4.0232038E-32,5.1089298E26,5.76607E-29,-4.393163,3.6522783E22,-2.1372208E38,-5.279335E29,-2.0130148E-34,2.650583,2.15663287E15] +,[2.046967E25,1.0039325E-23,-2.2611841E25,1.5242264E-4,-1.4143259E-9,1.5972371E24,-4.8323383E-4,5.234195E-27,-2.513276E-6,8.543087E-37,2.1127578E19,2.37881679E14,-0.04639983,-3.94664975E12,-1.37400112E8,2.0494555E-15,1.08244195E-14,-2.3964122E-33,1046.1315,-2.5760156E-13,-2.5466814E-23,1.3196846E-8,4.419426E7,2.5098136E-28,-1.825383E-20,-1.1994996E-7,4.9286856E-20,2.0914078E-22,-0.006780296,-9.133744E26,3.7026085E-31,2.17505046E14,-74399.16,-2.07406019E10,1.8340747E-25,470.96228,1.491452E31,9.6333675E36,-7.670459E-26],[1.61482414E10,-2.8478575E25,1.2709846E-26,-6.1345093E22,-3.800501E-37,9.3568824E7,-2.693006E7,3.0798662E-36,-5.6782275E29,-2071453.4,6.9762805E-6,4.672038E-8,2.6068692E-18,4.20126786E12,-1.07101955E-36,1.0209723E23,6.207284E-36,-8.287924E-20,1.1460687E-37,3.6898683E23,-136.22513,-5.19742882E11,3488806.8,1.5953734E19,-1.49981765E-33,4.39981913E17,9.784874E34,2.7060543E25,4.967802E-7,1.947157E12,-5.4016232,-3.9612005E36,7.916292E-25,1.57858513E11,-2.7847707E-15,-2.6330374E-23,4910309.5,-1.5633807E-15,2.1883852E-6,-1.177046E-10,-2.9196513E-13,3.636523E-27,-1.4500978E-9,-6.522685E27,1.0628074E-18,-2.4396341E38,-2.5516168E-14,-3.9965467E10,-6.6444979E8,1.2650369E-5,-3.1459347E34,4.0481756E-18,-3.0360475E-34,-3.41636515E18,-4.3524706E-16,-3.310614E-38,4.6696927E23,1.0129248E-20,-20.945423,-2.961957E31,0.8271526,-4.1675294E-26,3.1402283E-22,1.3237225E38,4.0011433E32,1.7345148E-8,4.880175E-35,-3.2156436E-28,3.7479937E-14,9.995417E26,6.754229E32,-1.0856749E19,3.844049E35,1429744.1,1.7327997E38,-2.04644248E17,-1.5014568E-23,-3.8478078E-4,-1.0011582E-24,-2.0399752E-4,2.13295429E17,7.7851425E-26,1.1652908E-36,7.902411E-25,2.23918653E17,1.0414118E35,-4.670963E-35,8.8482973E-16,-8.801244E34,-6.2454901E12,-104170.57,4.8949002E-21],[-2.2799947E-8,7.639495E-31,-3.66534486E12,8.437986E-5,6.569095E32,1.94218413E12],[29082.746,-5.3562345E-14,3.2055792E-19,3.3885144E24,-2.7307507E-24,1.8294183E-7,2654368.5,-1.9740678E-8,-4.944283E-36,6.881815E-38,5.5142777E-6,1.94791949E9,2.1895704E29,9.1628676E33,-7.475101E33,-4.629694E-26,6.65608E29,-1.0455601E27,2.2842445E-29,-6.2825983E32,3.7540669E-22,2.9792422E17,-2.5226271E19,16431.475,311042.6,-3.2972104E-18,2.836561E-27,2.61553358E14,3.7825254E-20,-9.882928E37],[-1.970304E37,3.280495E-27,-2.8025064E25,-2.0974132E-29,2.52699684E16,-1.1505945E-5,1.519187E23,-9.1113748E15,1.9568832],[-1.9624752E35,3.0642792E33,1.0752591E-28,-5.0235985E-7,3.1543805E-35,-1.2295649E37,5.7295845E33,-1.1539233E22,-9.0622387E8,15.298786,-4.971065,-1.2618188E34,31825.23,8.984011E-14,-1.3667475E-30,-1.317679E21,-1.0995402E32,-8.0578126E-8,-6.4011076E22,1.55622127E17,-6.792501E29,-5.373949E-26,1.6993843E-17,2.3380963E19,3.5186366E25,-161.54507,8.420609E34,-9.641602E-31,4.6381245E-12,1.2518536E-32,7668.5166,4.57002528E8,1.1678749E-20,1.14689526E24,-4.910587E-10,1.6756772E15,-1.2106079E-22,2.3696143E-20,56.631264,-1.6328846E-17,-3.5300533E-26,7.205307E-12,-1.09665414E27,-7.300533E-32,-7.4928196E33,4.3696905E-27,-0.0013854192,-9.873465E-38,0.058501676,-3.1682173E-19,-7.3268664E7,2.0019415E23,1.0920521E24,-3.01774364E13,-1.3145713E-34,4.405406E-5,4.0539798E37,-4.022517E-6,-4.87522912E8,-878.46344,-6.1742166E-30],[-7.4965005E-22,4.581275E-10,5.5573954E-29,6.8123869E13,8.116277E-10,1.98728532E11,-1.644467E-7,2.9436897E-38,1950598.1,3.6343374E-23,-1.3466281E-21,-5.7043828E17,-6.7534076E19,2.9582421E-5,1.5244628E-23] +,[3.9592146E27,-6.5587216E-7,2.1917113E-14,4.4261157E-17,-7.264177E36,-5.739904E-25,5.1055973E-24,-1.1733025E-9,-1.5893152E31],[1.9867963E23,-1.2950139E-37,-6.6832675E-31,3.2167792,3.5190208E-23,-2.806175E23,3.8209556E20,-27186.88,1.7099301E-25,4.4661606E-6,-1.5348093E-7,-1.0886492E-5,5.655572E-28,-244.71165,-1.8909471E19,1.12281036E-7,1.1101646E-11,-4.3777592E20,-0.01849799,8.133171E-19,0.48796266,4464373.0,1.5413162E35,-2.682901E30,-1.9861821E-19,3.2546906E-26,-12.077345,-59279.52,-1.5408482E20,1.6293913,-1.7978099E26,7.1885422E18,-0.74339813,1.8792492E-25,3.3169637E-22,-5.815724E25,1.68538272E8,7.0266443E-35,8.565368E24,7.230063E-30,4.7242993E19,-6.7460835E-22,-4.6872835E-29,-0.1013058,6287194.5,8.7331007E27,2.1940543E19,1.0707918E38,8.664748E22,-6.127593,-4.411171E-19,8.836836E-24,2.1027147E-21,-7.6232244E-35,9.3210624E8,3.5025013E-7,4.6373402E-29,2.5462144E-16,-5.5543312E7,-3.6632652E-13,3.7985408E7,8.538071E-16,3.6094397E-13,-9118150.0,-4.4035589E12,-4.71622E-34,-0.5478556,-0.051223088,-4.8766134E-38,-4.755721E26,-2.7295384E29,-7.2450435E-37,-4.6478435E-17,19.083307,-0.002011672,-6.4378231E15,7.4626866E-29,-6.6496673E24,7.114146,1.10221048E16,-1.1319554E25,3.6191812E29,-5.245042E-4,-3.42991543E12,-3.9315055E36,1.4112847E7,0.001767671,-3.4352837,-2.921994E-22,-394148.47,1.2442059E-28,1.0903586E-28,-1.14717656E-29,-2.4340287E-17,-1.5136631E26,9.304202E27,1.7609354E-7,11337.007,-8.373158E-24,3.1022862E-31,-1.2444933E20,-3.7436606E-17,-1.0777715E37,-2.111371E32,1.9485887E22,6.222807,-1.7070699E-18,7.130554E33,-2.4125381E11,1.1414538E33,-7.7300704E-28,1.1997317E-34,-4.19287532E11,-1.8712265E-21,6.4402985E-7,1.9199932E28,7.761017E21,1.4760437E-34,1.311639E21,-3.473825E-26,1340306.5,7.165198E-25,2.1375271E27,-3.7441183E-20,4.4497543E27,-2.7439192E20,-2.8833095E-33,0.011356765,7.1803647E-28,-2.5945176E23,-1.6136751E22,3.485619E23],[-6.044063E36,-2.6103998E22,1.3173548E-18,-6.674972E-11,3.6872715E30,-8.716288E-33,8.0604186E9,-1.35196679E13,3.954288E32,-1.930289E-29,1.0282257E-8,6.2271836E-35,4.7967978E27] +,[111.52081,-3.4265005E-4,2.08950378E11,-2.6038165E33,-1.2778452E-20,2.0138853E32,5.1685737E13,5.9989783E10,2.7165724E21,-6.1999948E7,-4.2563575E-15,-5.9826374E18,-2.4955483E14,-9.74889E-9,1.998957E-23,1.8474495E34,-4.000669E-24,-1.83592672E16],[-5.9103235E23,1.755274E38,-2.5553578E-12,3.6658224E-4,-5.233411E-24,9.8123824E-36,1.1832269E-15,0.01923362,8.813129E-10,-8.9343013E-13,-8.7737985E-15,5.108798E-18,2.7233456E21,-1.89397654E18,-1.4993371E-18,-1.1762382E-21,-7.55091E-13,1.6910232E25,-6.68898E-36,-4.366135,5.0130123E26,5.658987E-10,1.12944734E-4],[7.670068E-15,-2.80775584E17,-2.9787247E-25,-2.1149537E-8,1.6231991E37,1.1651223E-23,2.0636201E10,-5.1762626E-38,-2.97536597E15,-0.0029359923,2.4034574E21,-1.2315049E29,7.753713E-25,-1.69600369E10,4.523179E31,1.7020673E-18,1338386.4,2.9649162E-21,5.1408284E-30,8.914675E-15,4.534591E-15,1.0657312E-24,-8022.8022,-1.542446E23,9.582449E23,1847851.1,-4.9340898E-26,-38.082893,1123326.2,3.593817E-20,1.328062E-12,-6.9038993E-35],[1.7058306E-37,1.0561656E-18,-3.5017737E-7,-2.309725E32,-3.8855506E-38,-6.4111076E16,-61132.098,7.402418E-32,4.137606E-7,7.0176926E15,-3.8560205E-12,-1.26492795E-36,-229.90636],[-2.0367467E-38,1.7735674E-35] +,[7.8801927E-28,8.99017E-23,-0.12334686,2.267776E-35,6.602E22,-4.1353434E-7,3.8295074E-38,27.062914,-2.6815113E-11,6.647715E30,-6.8557477E22,-0.1737599,3.9544336E-8,4.1595755E-12,-3.9169864E20,3.1313735E-7,-2.22775E19,-2.1013196E30,-5.4897552E7,6.840488E-29,0.5352197,-1.7332099E-18,-8.756769E-33,2.8363015E22,3.6271528E30,-1.32938244E11,2.0292455E-10,1.34025388E13,9.956878E-17,4.8682307E-9,-7.788116E-18,-1.08557995E30,-1.4297638E20,2.306014,-4.2963852E7,1.13428134E9,-1.1373578E29,1.5360171E36,1862.9814,-3.214738E19,1.08695509E15,1.4640759E22] +,[1.28409919E17,3.929078E19,7.398264E37,-5.456806E26,-6.3881414E13,1.995884E-7,2.7377916E-36,2.2008916E29,3.0644462E-15,7.273561E-9,1.01013604E13,-8.7379744E30,926.3532,6.2766252E-37,-6.486869E-25,1.91109896E18,2.3674893E-32,6.6363405E-15,-1.5708478E-32],[2.4038063E-10,-3.50169945E15,-1.8565553E-25,1.3835687E33,-187.00838,-5.0665634E-37,-1.7776346E-8] +,[-7.902012E-19,-2.9315193E28,2.0374592E-23,-8.705462E-38,-3.4425498E-4,2.347934E33,-1.66798356E10,-1.65792252E11,3.1059933E-16,-3.7615085E28,-0.60163826,2.36192557E12,1.8849123E32,-0.026402213,4.7024084E-38,-2.2423211E-38,-1.34600385E13,-2.0817311E23,-3.6401177E-35,9.537745E-18,3.92991736E11,-8.163994E33,5.8147135,-1.510791E30,3.949444E-8,1.38609995E-8,-332381.97,-3.1736623E27,-2.2812714E-29,-2.291572E-9,-4.386445E-25,-8.3170586E37,3.14790117E11,-2753682.5,-4.2155164E26,3.7463407E-31,4.0294633E-26,-1.1594631E-25] +,[-2.787611E38,-1.20194217E15,208.19893,-1.10117254E-16,-2.1501943E24,2.2999115E28,1.03285407E14,4.1158448E-38,-5.9500535E-6,8.709221E-18,-0.41958737,1.4456883E-22,-0.27423915,5.9594743E-23,6.329182E32,-3.8571793E34,3.8146403,-4.4398383E16,1.8653683E-35,-2.0999737E-7,-1.7420561E-15,-4.4825488E8,0.009006739,-1.013476E8,-5.784616E29,5.546931E-33,2.1903438E7,8.8903685E-18,4.2145106E-16,1.06082695E-11,9.3994234E21,-3.2573135E-28,-0.027600484,-1.2911376E-10,2.4733934E-6,1.2162123E30,-3.6730052E-10,-4.779868E-36,7.863201E35,-6.4165717E-21,-2.1013622E29,2.04848678E18,4.4834E-29,4.749279E22,58226.336,1.6627068E-38,5.8317545E12,-1.053897E27,-2.15538E23,-9.140853E-18,-875.62756,-1.830947E-10,-3.415372E34,8.6856913E-32,-5.5848467E-8,-1.2828722E-28,-2.6577513E32,166.79366,1.2213504E-16,2.7111211E14,-2.5846598E-37,-1.5204548E-21,4.3596547E-11,4.4801724E7,-18146.887,-7.418924E28,9.643046E-36,1.2505698E-8,-1.787065E-19,-4.80839765E17,-5.3036786E16,-4.880802E-10,-1.14240748E15,1.1889918E-10,-3.487458E20,-1.72746512E8,-2.6002013E-27,9.447709E24,8.448562E25,3.3825377E-11,1.1789647E23,-7.5225364E15,-1.3568401E23,0.34649983,2797.5444,-8.634043E-10,-1.488431E-23,-4.966701E-24,1.05700284E-14,-398547.53,1.24994286E15,-7.226216E-30,-5.437547E-23,6.955646E-11,4.580792E-15,-2.1163867E27,-8.436962E-9,-8.915255E-23,-3.70964E-8,-1.6971955E-15,-1.09088072E10,-9.016622E-37,-8.4399056E-7,1.303762E31,1.7701865E13,-2.050575E-9,-3.9340855E30,-5.86469E33,-1.9108958E36,-9.45013E-13,1.3413494E-5,-2.3332007E-32,-4.2000536E12,-13.862848,-1.0764852E23,5.2004128E7,9.002588E-34,-2.07457301E13,-7.768945E22,-1.1382736E-10,2.71225426E10,-2.6740375E-18,-1.755016E-33,2.2179205E33,-1633229.8,-6.3014133E-22,-6.6278984E9,-9.227446E-36,3.5444855E-6,2.9015085E-10,-1.003169E-10,-55589.418,-3.0689526E35,-3.0863537E-20,-5.1336855E-38,3.6434092E-32,2.3369965E-24,3.6052084E25,-4.4839972E-35,-1.4167258E-38,3380.7002,-1.2905357,2.82058233E17],[5.338831E-24,2.6178479E36,9.0546997E14,3.7206219E34,1.9083935E-5,6.3134293E-4,-8.3112653E9,-1.9926666E24,3.1517186E27,-2.5517091E20,-1.05800744E8,-9.793455E-14,-2.0169154E37,-3.1260331E-24,-7.613612E-28,6.448219E31,-7.3234214E-29,2.71411919E14,-9.1385004E-8,0.09265018,1.07860514E21,-2.2735031E34,-2.5812135E-15,4770.381,-7.851698E-25,3.49187E-25,-1.2396227E32,-34585.13,17.54151,-3.505097,-1.8355975E-32,-0.037202276,1.5864158E38,3.0053117E-13,5.9356287E-36,-0.008556399,-3.07177E33,-3.8731779E27],[-5.8432459E12,-9.3744706E-29,-3.0442952E31,1.4456566E-20,-2.5532715E25,-1.5532156E-31,4.0604127E-6,3.6498957E35,-3.3537944E19,-6.8137027E-25,-2.1100003E-27,1.4886213E7,-3.0698327E19,2.83065503E13,-4.3249327E30,-6.073115E-23,2.1917574E-35,-205.4083,-9.675174E25,3.5117817E-30,-2.8977774E-36,-5.581732E-14,-1.6782692E-12,1.6625899E-34,-2.0087757E26,-1.5675231E-21,8.767787E-31,47245.637,-1.317919E21,1.5282041E36,2.7906064E-15,2.5141342E35,-1.6795639E34,2.7701904E-34,-7.9624705E31,0.7160752,-1.5922899E-25,1.34162743E11,4.7727696E-8,-3.536734E33,7.8552523,6.858665E27,9.245525E-10,7.298415E-24,9.457784E7,-1.4218246E-27],[-1.3826582E-4,-8365.937,1.5826727E-33,-4.3762118E13,-1.638345E19,2.3506025E-14,7.5632305E35,1.7000062E22,-1.9258136E-26,-3.7648986E-38,-2.1044617E-20,-1.94231665E10,1.4021162E-30,-1.8531586E27,2.2573868E-26,1.8158826E19,-4.8769556E16,-3.519775E-33,-2.776269E30,0.06618641,-1.0570512E31,-2.1206823E-12,-6.407421E-16,-2.4483065E-18,-2.9193552E-36,-1.2697332E-38,-9.11313E-14,-3.60744627E9,5.851594E32,3.343895E19,-1.79549422E16,-1.9918633,1.3503544E-4,-1.9426696E-36,4647990.0,-1.372953E33,-7262599.0,-6.5252539E14,4.9826445E-35,-7.995364E-22,7283753.5,4.2300386E13,-1.4573794E38,3.9310373E-28,-1.8676528E-27,-204610.77] +,[1.1690469E-5] +,[-1.7490238E-20,-335.36093,-0.03876838,5.7398714E-11,2.58614863E16,1.7895315E24,6.746036E-19,8.335507E27,-1.1199012E-8,-70.68674,-100628.875,9.1079204E-23,95.32721,-8.3105464E-5,-1.4512805E-9,1.8253357E-20,9.043557E-12,-1.4538089E34,-1458.933,-1.5232609E13,-3.5019788E21,-6.431496E7,-2.9235591E-34,-3.4052817E30,-5.42358E-15,-1.162009E-19,-1.2892123E25,-1.1598687E-24,-4.9787108E-8,-1.2004785E-23,3.264165E-25,1.08954664E-29,-6.9852667E-25,2.8870893E-35] +,[-5.9509536E-11,3.022469E-31,1.37522086E11,-5.43904525E14,6.7213414E-28,-3.109001E-38,-3.08868E-30,6.997175E-34,-5.7764715E-17,3.0259297E31,8.995435E25,862.57745,5.0345965E-32,-3.75554887E12,3.9959064E-33,7.711432E-29,3.1212494E19,-4.5898716E33,-3.1595166E-27,5.19588E30,3.158304E-28,1.8022409E36,2.9463178E31,-2.0824029E-17,5.21766976E8,4.5923488E-18,-6.8528934E-23,-1.2853099E-8,2.2906182E-14,-7.2089754E-14,-2.5029027E-11,-9.334377E20,1.5007181E34,-4.1258442E27,3.170124E36,1.4901184E8,-2.0482806E-12,-3.1524406E21,-3.684307E-8,2.25045607E18,1.7534187E-16,0.09259096,-1.2650649E7,3.5243125E34,-3.839742E-36,-2.0951473E22,8.4107808E14,2.49820672E9,5.943513E-14,-8.370782,1.7470015E31,2.4800524E-16] +,[-1.8314581E-24,5.3156383E-15,4.06149739E12,-2.0778908E-24],[4.7414213E35,-1.4472924E-24,1.0667976E-27],[1.6747693E-36,-6.3536463E-24,-2.9848924E26,-1.93258496E8,-2.5724427E-17,-4.7488213E15,-2.9393788E36,-24.488659,-1.6337917E-13,0.015942302,-4.50737E-22,0.09000197,-3.7305844E-7,2.705776E-27,5.522876E37,4.9042255E-6,-2.5144967E33,6.326865E-8,-1.6325168E-28,-2.12185456E8,-3.1032023E28,-730.28314,-2.81790566E9,-9.1335451E10,1.944591E32,-1.796695E28,-1.9997478E33,1.5470966E-13,9.697748E-11,2.8183301E-38,9.839224E27,-3.3696503E-36,1.5711026E34,-2.7216077E38,-3.4466444E-32,7.4459716E-10],[4.7447296E8,1.3187252E20,9.5262305E-18,3.48214431E16,-1.48230152E18,3.2828393E9,-89.32659,1.32706145E-5,-2.2086582,4.23790194E15,1.8866916E-38,-1.040885E-9,-19.96205,1.8702944E31,-3.7670456E-10,6.5041374E35,-6.5374434E-29,-2.2779346E-29,-1.930791E-14,-2.0355456E-36,-1.8985005E38,-6.1017356E-38,-9.783483E-11,-2.590552E-10,-2.144385E-14,-5.8224094E-27,-2.1036241E-18,-9.508679E-4,1.046445E-17,-1.06253011E9,6.1921203E9,-5.1182716E-26,-2.8552844E13,-1.0548943E38,-3.1364824E-28,-2.439762E-14,-1.8849034E-22,3.175472E-33,2.85419831E11],[-1.2728546E-25,-2.4089081E-15,-5.345997E25,-2.0281554E-8,3.8364284E-5,-4.7256496E21,-203018.06,-4.859113E-25,1.2689607E-23,1.04371476E10,-1.99889603E16,-1289.2817,-4.082002E21,1.7250264E-18,-4.2471706E35,-1.8774203E-35,-1.80572385E10,6.5519203E28,-2.4870927E-37,-5.33203972E17,-2.0176224E-26,-5.4523193E-34,-2.1113368E8,7.6477055E-20,109985.51,6.157952E-6,3.8773703E-29,1.6886053E-17,-4.7609815E33,-1.730315E-36,1.35175844E-20,5.721813E-18] +,[2.578383E-29,2.1407522E-17,31.79031,7.6587745E-35,1.7669703E-16,-2.2143754E-11,-9.592619E-5,0.25148433,-0.0015977436,-24.724857,-1.0479573E-11,7.600209E26,3.03723119E11,1.60510268E13,-6.43998E37,1.156153E-30,-1260.8202,5.9056794E-31,1.8560622E-13],[2.3129828E21,-1.3179114E-17,0.0018293444,-0.028355591,-5.1170008E20,-1.639061E-35,-4.288461E-12,2.7321386E21,1.2945997E-8,-3.14421658E9,-1.19789886E-29,1.2108384E-19,4.3150282E-38,4178308.2,4.1494581E10,-6.315856E-18,-1.07972675E16,6.0284429E13,-2.5340403E-24,-7.053255E-32,-1.38768728E11,2.5930558E7,3.6359193E34,2.8237853E-36,-3.8022302E-27,-5.9270603E-38,0.0014557667,-3.4602648E18,2.85290394E9,2.15717088E8,-4.783179E21] +,[7.3165595E-21,1.6330827E7,1.949938E22,-3.0818687E36,-9.492587E-15,-8.018424E-19,3.6766472E-25,4.710477E-9,2.4674065E27,8.4178804E-23,-3.0549799E19,0.011932457,-0.064435445,2.8665436E-8,6.5510726E8] +,[4.143027E-8,1.05527866E9,-3.3034116E-17,-0.01745993,-1.6025022E-11,3.98332128E8,-8.147302E-5,-0.0024260967,2.0681027E-15,4.12118E-6,7.8326714E-8,3.033146E-29,0.4014876,-1.7636612E19,-2.1729423E27,4.658796E-9,4.692644E-13,5.6560588E-18,-1.4236583E26,2.1093095E-7,2.8377602E10] +,[-5.3543276E-34,1.2162258E23,-1.725136E38,5.8121733E-21,9698725.0,-1.3808126E-27,-1.9920243E33],[-6.8163403E-28,3.7531467E-29,-1.0797245E-25,-2.04896998E9,-3.2018075E33,6.17484E-5,-6.9869959E15,-1.2112279E-22,-6.8622163E-31,3.27222374E10,0.2774757,9.447319E-20,5.3670025E35,2.5768802E-26,-5.908172E-15,7.111735E31,-1.0841741E-5,-4.5920173E-12,-35.24335,-4.1909565E-10,-1.451999E7,3.113321E32,-2.0105926E-38,7.360878E-22,1.1959701E26,7.8103871E11,-1.01281424E31,2.825187E31,7.791911E-37,-3.8097867E-25,-2.0257489E-22,-6.2790656E-5,-1.0638966E-13,-5.607467E-39,1.4443735E-11],[-1.5659822E12,-1.8548425E20,4.379502E-8,1.6227315E21,0.023761006,-1.4084973E23,-1.0373781E28,-3.92045302E17,-3.6820947E-21,7.721931E-7,4.953904E-5,9.829162E-23,-3.0381864E34,2.2705972E-20,0.45697522,1.37205135E23,-6.7923245E-28,-3.8678106E-14,-2.8258558E-34,-3.4087187E-22,9.985425E-35,-3.208587E23,4.7699587E26,341.0504,1.9148532E-23,1.5104017E-27,2.2115055E-6,-785.40796,2.47666442E10,-1.09997891E15,5.4106214E22,-1.7257473E-19,-1.0920247E28,-1.98869012E16,-3.8831403E31,7.180658E30,1.3781747E26,-9.8714429E13,-2.8494894E-21,3.0224927E-15,7.1029867E19,0.36988097,-52938.695,-3.6699495E-26,-2.1958775E-7,9.4241516E-12,1.3375675E-20,1.641165E-9,-2.1869612E30,-1.592192E35,-1.4863947E32,1.1867613E-34,-1.7990541E31,-9.2414015E-37],[-1.38330671E14,-1.0093699E-25,2.07890816E8,2.495359E-21,2.8600511E-30,1.52352735E13,-3.5963658E-5,-8.4457796E-23,3.2360748E-37,-2.5366527E19,-3.0223868E-10,7.704658E29,-4.891117E-39,1.8510434E-9,-1.9662264E-6,-8.5123343E-35,1.0233703E-29,-4.07778E-4,-4.9774094,-2.1434484E-22],[6.1155787E-15,3.5030426E-35,-2.1463117E36,-3.5930778E-10,2.5891168E31,-2.034399E33,-15.845953,1.2520056E-15,9.271135E-13,-1.0094107E29,-6.2471997E-26,1.6837067E37,-480.735,2.805314E-5,7.38588E16,628.3713,-4.178089E-17,3.659356E-32,1.06922208E9,-3.6458355E32,2.093946E-11,-0.009274969,3.435875E-38,-2.647997E35,4.8889696E-23,-1566708.4,1.8100004E22,-9.7933875E-37,1.6057602E-36,223176.4,7.6059896E7,-1.6038903E-22,8.0857737E-32,4.6276833E22,1.7561114E26,-8.4496947E-16] +,[8.960487E-20,3.8659976E20,3.3677843E19,0.3636747,4.001805E-36,-8.3070655E-30,1.1630094E30,-0.2936796,-1.0943436E-24,2.2370308E32,1.3145464E-21,1.8699703E-12,6.6084256,-1.14621564E-7,5.449864E33],[-9.001434E-5,-0.013550841,0.0024260508,5.977011E-5,0.023893138,-0.79309505,-4.05305385E18,4.2951996E-21,1.8245819E-34,2.092976E22,-1.9596499E37,-1.9850101E-19,-2.95824677E15,-8.9322776E-24,4.7877494E-37,4.6591217E-11,-8.8906435E-32,-6.551076E-26,108380.734,7.2342685E-22,7.864914E-36,-0.74648815,8.7611578E8,2.8797029E-8,-2.16400036E11,-3.991639E-14,8.8960174E32,-3.3295037E-22,3.805071E-34,2.505315E-6,-2.2189872E-15,7.3960384E-25,-1.4324795E28,1.19091597E9,0.30877537,-65596.45,-9.1923716E16,0.002302992,-3.5947764E-6,-2.7453833E25,1.8256555E22,6.296076E32,1.7969349E-29,-1.3224854E-25,-1.865051E-13,-1.6795361E-9,4.58929E-32,-7.5768415E31,8.609212E-13,-1.405573E20,-2.1593589E-20,1.4146859E20,-1.5759025E25,4.11518787E17,-6.6402119E18,-6.538252E-13,6.8095654E-20,4.904244E36,-8.702819E11,-7.804506E27,1.9414134E-30,-7.285966E-6,10.765796,2.6755415E38,-1.080392E-33,-3.3392953E25,3.3808866E36,9.690364E-18,9.63493E-23,3.02373373E13,-186.63098,-3.608344E29,-2.369865E-31,-2.65095208E17,4.233673E36],[1.863118E-38,4.2373912E-32,-5.6873272E9,4.89264807E17,1.4580419E-8,5.801327E25,-3407944.2,-9.989441E-27,-2.3140594E20,-7.439021E37,-4.070032E-8,8.152068E-13,-2.3844628E-13,-1.5062257E-31,-7.664698E-27,-1.0964827E20,1.343938E-12,3.3020196E-27,1.1043192E31,1.2754209E29,1.3173707E-12,6.776007E-15,3.0201242E23,-1.02439533E18,3.9109428E-28,8.868579E31,-2.6422139E-11,-2.794292E37,-7.890599E36,-6.0250507E23,-3.762835E-19,1.54682065E11,-5.7581316E7,3.1687102E-27,1.383549E30,4.5978523E-9,6.571768E-34,3.1372478E-5,-9.483022E29,2896239.0,-1.5946105E-23,-9.604633E23,-3.074529,-7.823916E27,-6.328333E30,-9859902.0,-1.16368385E-26,8536995.0,8.7641715E22,1.3236179E-20,-7.314045E-32,-3.2939533E-17,7.584158E-26,2.2639514E34] +,[2.4222497E31,8.4374126E16,2.7139265E-34,-3.0442354E-12,1.0319381E28,-0.012431737,14300.638,9.864925E31,-8.148761E22,1.6651499E-19,-2897.8486,1.7007772E-21,-2.5553316E-12,-3.8972147E13,-1.3397367E19,-4.28240589E9,-7.330018E-24,-1.3116366E-35,4.0559863E-16,-2.7402616E-30,-9.2888735E-26,-3.033942E32,-3.7567037E28,5.7873286E-29,-2.56340896E8,-2.001569E29,667.44653,2.3909379E-29,-3.8634906E-16,-6.7680235E-26,9.0435826E23,6.6319652E22,-3.3968045E34,-3.48282163E9,-6.46849E31,-6.701696E25,4.722044E-15,-3.899074E-14,3.559046E28,-2.32093161E16,0.92322904],[2.1500663E-14,3.049157E25,-1.77232036E10,0.00621631,9.8988935E-11,-9.894642E19,-1.97949784E11,6.211777E14,2.7481554E28,3.45673034E16,-7.2608294E-8,-7.640893E-5] +,[5.763044E-25,-4.494909E36,7.363763E-29,2.9826397E30,-4.9785089E18,-5.7037541E11,2.6963912E32,3.173759E36,-3.4239266E-37,-229933.92,-1.65245376E8,1.7023391E-19,-1.4045989E23,7.2134404E13,3.421599E-22,-9.9753748E11,-26708.273,1.82239462E15,-7.4102952E7,2.8951376E-15,6.9537265E-25,-1.3446756E28,-7573.729,-1.8991696E-29,-1.1015584E-23,3.071476E34,1.1310751E-36,1.4858923E-24,-6.435571E-11,4.8536323E-14,3.9481112E-17,-8.239384E-8,-1.7388548E23,1.9631239E-14,-7895389.5,5.780547E28,7.1938254E16,0.0014096443,-3.36592E-23,-3.330957E37,5.9715877E27,-5.96862E-12,-27938.877,1.4260314E-28,-7.3189333E-13,1.4535185E35,-6.764541E35,2.0084628E30,4.142594E-25,-6.3855526E11,1.06434352E8,2.064847E-35,4.097626E-33,-2.9355786E-15,-4.885569E-29,-3.34775789E14,3.9914883E-29,5.8714615E13,9.219286E-11,-1.1424285E-10,8.861739E-25,1.01399724E34,-5.582282E33,4.7519065E-36,7.070825E-23,-6.9288425E-37,1.4018126E-21,-1.5138554E26],[-0.014581802,-0.014699543,-0.4107308,-3.1366124E25,2.9320444E-7,-3.89730638E18,5.061011E-35,8.1635905E-30,-1.9888839E33,1.1674182E24,-9.3102266E-36,-4.1034733E35,8.1275039E9,-2.34244896E8,-5.3807376E-21,-2.3239405E30,-1.852454E13,-8.253771E-11,254.91922,1.94037378E14,-1.7782805E-19,1.3514357E-29,7.8769123E17,1.9456303E-38,1.6169681E32,-196.27563,-18449.299,-3.1785905E-25,1.0165525E-7,-6.6392956E-14,-1.9442488E-23,1.72436339E9,1.36848299E16] +,[-9.3395342E17,7.373187E18,1.1399847E-27,-5.316129E-30,7.2988406E-21,2.2520927E34,2.3066718E-32,6.5449464E-30,-6653136.0,-5.077006E24,7.06684E-30,-9.627278E21,5.100456E-19,4.5153296E29,79.27249,-7.572292E-6,-2.206689E34,1.570405E23,1.9953152E7,-5.0584735E37,-2.7735241E-11] +,[3.8347066E16,4.7537537E-21,0.43369678,11.544229,9.141825E-12,3.206481E-7,-5.40461E37,-3.912049E30,2.1420896E-29,-11621.5625,-1.2781598E-26],[1.12640424E16,2.4187301E-11,-3.73978266E9,3.3488855E19,123.37761,1.451703E-22,40880.918,2.8787174,7.8736654E-22,-6614.9106,-67.738495,2.7019217E37,-1.29506644E14,-4.59274304E8,-7.691104E-10,6.803491E30] +,[2.546722E38,6.3388975E27,-3.83930631E17,3.3236818E33,2.2989126E-29,8.8564961E17,-1.6703415E25,5261816.5,-1.6122646E26,-6.534883E-12,-1.4734447E-34,4.461915E32,7.614744E37,-2.5144255E27,3.9098264E20,-25671.889,7.867279E27,4.54826098E14,-2.1246989E24,-6.5303327E-9,-4.1615433E-17,2.27374538E16,4.5768346E-4,11.746855,-3.13760212E17,-1.5043964E-26,-5.7728556E7,6.378261E30,-1.6621725E-34,-2.9804674E25,6.2865331E9,6.566137E-37,-1.3021403E-36,4.8349145E-18,-9.623567E-23,-1852880.6,1.3170271E-6,2.8417924E-10,-1.0297846E-28,7.8908384E-20,1.1305975E-18,-2.298566E-29,0.28349736,-4.1232098E-32],[-53378.02,-2.4348677E-5,2.0141289E22,-2.3816893E19,6.1437776E16,-1.673584E-17,-6.4791756E-8,-2.517094E-29,-2.063491E-33,-2.20992E38,-2.820192E-7,7.1575211E15,1.6017266E-37,-4.1947107E-16,83.15008,1.48910131E18,4.9730394E37,-6.193448E-6,-6.1033527E-38,1.4470078E-11,-109360.18,-2.98181271E13,4.546957E27,28.050613,2.22219595E14,1.76234946E17,6.24209,-3.804794E-13,-2.7770268E34,-1.6883155E21,1.17251257E12,2.85061511E16,7.688295E-26,-8.5139256E20,2.4504939E26,2.5029476E-14,5.9073295E-19,-8.40137E-28,3.663849,1.509104E-29,1.8793774E38,-3.26979486E11,2.2339417E-16,0.0057175397,5.914664E-35,-5.8366517E-18,1.17936447E13,6.9955204E-6,-1.682988E21,-6.0758643E-15,7.311768E23,-9.2867125E14,3.233391E-15,0.4262526,-3.32802392E11,-1.1501448E-11,-1.701389E27] +,[-0.0017165262,-1.2724064E33,-9.009366E-16] +,[1.7839068E-10,7.7823914E-10,-3.07036058E10,-1.5130077E-37,-446.29678,-1.774378E-16,-1.6339367E-16,-1.698852E-31,4.1384502E-14,9.514817E27,-7.864796E-25,-2.9919293E23,0.13843381] +,[2.1279191E-4,190355.83,-4.1957372E-7,1.6358798E-10,-5.546888E24,9.579898E21,9.0732345E-7,-4.8682492E26,1.2438232E-25,-8.743151E-12,1.6934396E34,-1.0441042E-14,1.6620653E19,-8.675206E-27,-758141.7,5.904506E-5,-7.380854E25,3.8057492,-0.00773271,2.5373261E-26,-6.6881906E-10,2.095169E-11,-1.791023E26,7.159086E-32,-9.0563107E33,-6.6240623E16,1.4647568E-12,1.2714292E23,5.4157537E24,7.0665114E-6,9.473122E-35,-1.1077577E-32,8.3889456E16,-1.4109704E25,-4.6205777E-31,272257.78,-1.6126594E-16,-3.998725E-6,-1.0632713E-11,3.4417483E-21,-6.3214898E18,-3.5661094E-12,3.655405E-30,-3.7573435E37,4.25798192E14,-3.514179E30,9.361147E-32,1.1075149E21,0.0029928624,-5.2112356E-13,-6.5362262E15,-1.2038075E-21,3.115808E-21,-2.05605E-36,2.7845992E-30,-4.020312,5.582345E-20,5.8310703E-9,-0.17258346,-52.747665,7.285912E-29,2.61914273E15,9.815328E-23,-1844.2174,9.002968E33,2.1011398E-19,6.693701E-29,-3.1481093E30,0.23139499,-4.3402977E23,-2.6744801E-14,-5.0197025E-16,-689385.5,1.4711415E29,9.5353845E-26,1.0982829E-16,-2.097193E-15,1.0374574E-11,2.8988225E-15,-1.1387278E-29,-2.1959857E-17,3.0753384E-18,-2.1534387E-27,1297446.2,-8.081576E32,7.3064278E11,-2.0182112E27,-1.9000503E-25,3.8570384E34,-1.5915849E-29,3.51232908E17,-5.329934E-6,2.38143219E14,-9.6799263E27,6.160485E-13,2.4711058E35,2.4747681E16,0.09800296,-1.1182718E36,-8.7405578E9,7.566347E-27,54503.645,6.6824335E-21,-3.3890405E-30,2.717748E29,-2.1986161E-5,-245.0435,1.6598992E19,-1.130798E20,1.4756107E-9,-1.5944864E28,8.0335363E30,4.537881E-15,4.99391E-28,-1.9242471E31,1.5696506E21,1.5965287E-36,4.2670817E-6,1.7389909E-36,2.7348243E33,5.4664225E26,3.3139525E-29,-1.6460602E-6,3.43947622E9,-3.470771,54.989876,-0.19886814,-1.85754547E9,1.0683111E27,5.6301133E-24,9.848386E-21,5.2225376E-31,-4.32787E-14,-3.320742E38,-7777458.5,-4.145566E31] +,[-2.5351684E38,5.5903027E-19,1040321.56,3.38312458E10,1.4903255E-12,0.025317257,153.47539,6.8795531E10,7889.5537,-8.9482164E-27,3.12200499E9,1.9048915E-4,2.6747952E8,8.365426E37,3.6656786E-8,4.179911E-19,-1.7171582E31,22418.111,8.0066557E16,-83767.76,109.396736,1.3821912E-31,-2.8017373E-27,58816.56,8.6286327E-26,2.96344124E13,1.6938506E-37,2.62191E-8,3.5752467E-4,3.3806003E31,-1.3314564,-5.653364E-25,-1.7542277E13,-6.0345686E26,-6.1112406E13,49.768883,-7.9691228E9,-3.809219E-17,-2.1541923E-38,-3.9188712E-4,-2.3283323E-17,1.65297894E9,4.83322501E14],[1.8270576E-22,-4.960506E-13,-1446.0315,3.6918467E-19,-3.50016776E15,-2.5466105E-7,1.3753059E27,1.0404823E-8,4723.4307,-2.819457E24,-1.3786469E30,-5.357719E-7,1.58583521E10,1.4863654E28,3.8821987E-13,1.5235958E-6,5.430119,-1.7409842E33,-4.7633066E-21,-2.7903541E26,-2.1037476E29,2.8976874E31,-2.0810089E38,1.1160759E-30,3.1547093E-10,-14455.295,-1.0687387E-26,3.0977924E-28,1.00432466E-13,-1.9730476E-24,9.334673E19,-4.400483E35,-2.0237804E-16,-2.4839214E26,1.2820549E27,-2.9480559E-12,-8.0636827E33,1.0154122E19],[-4.3857993E19,1.877893E-23,-2.7546048E-19,-1.3387484E-37,114.46374,3.4824585E-17,-2.8232162E-32,7.8781281E9,-5.1475985E-30,0.0019016591,1.4153812E7,2.6432982E-37,1.6322665E34,1.7036795E-5,-9.2699866E36,-4.8939908E-15,2.8015324E30,5.558837E19,2.4107695E-22,1.5226718E-36,5.0422913E19] +,[1.8566589E22,1.2250837E37,4.5599097E-14,-4.0511993E-30,6.5709867E11,-2.67016E31,-5.3984523E-14,4.389576E-35,5.0318777E37,-2.30779313E14,-5.773945E-27,-6.68303E-18,-4.458687E-36,-6.861388E-5,-9.377162E31,4.809452E-13,2.58250608E8,405.7435,-8.5590437E27,20.174587,486501.72,5.704466E20],[-9.584733E26,3.3663747E-12,-1.0657247E32,-4.996626E30,1.5157849E25,-5.6416478E-27,-2.8021502E35,1.6830677E-16,4.063297E25,3.884891E-7,-0.20764667,4.2618368E-36,-2.2505126E24,-2.16989951E16,-3.3791352E-23,-2.2622431E-12,-1.9832247E-18,7.9941054E37,4.3089252E10,-3.9480576E16,2738.2466,1.4452786E36,1.321338,-5.733875E-22,-1.23433347E15,2.4229963E38,-1.1628368E-8,4.8816623E31,-2.823122E-6,-1.6411271E31,-6.02098E-22,-6.287941E36,1.8752344E-14,4.3050327E-10,-0.02403785,5.7330963E-37,-2.1668185E22,-2.00985612E14,-4.7075902E21,8.27232E36,-2.6243335E35,3.92364023E17,1.8086118E26,-3.5541944E19,-9.298125E-36,-1.6644138E19,5.4246154E-8,-15749.5,2.19071035E13,7.02522E-12,5.4936867E16,3.0804336E-37,3.0653246E-32,-5.08605E34,-0.0011060967,-2.4211834E-6,-5.309445E-21,1.1074681E-26,-6.079166E-16,8.9123897E10,5.1624315E-22,-8.689611E-9,-8.623229E13,-3.27240473E16,1.3190854E36,-1.4852208E-21,3.027946E21,0.0035015726,-5.748167E-8,-1.9010928E-30,-1.1107124E-17,-6.8929363E18,1.7260037E-38,-0.007688139,4.202356E29,3.5537087E22,9.378857E-24,1.1471318E-24,-4.9013718E-8,-3.6719764E-5,1.01447354E9,-9.823231E-18,8.8776794E16,1.9152184E24,2.4040656E-24,-0.029477606,-5.6788453E26,-7578.009,2918.2883,0.057530016,2.3970672E37,-6.4669535E21,3.5951024E-22,-1019938.8,-0.011560057,8.943859E-6,6.1301847E-33,-1577910.2,-8.1258654E-13,1.0505744E22,6.453602E-21,3.4392283E-30,5.6482457E-14,3.08532364E18,2.0574037E24,2649.5166,5.6074753E-31,-1.65605897E16,-3.6331367E-30,1.0064234E-32,8.064997E24,-3.65624492E11,3.88990658E14,-3.5895756E-27,-2.0697576E34,-7.2641886E-11,-7.456001E-21,-3.9443768E-20,7.68356E-40,-1.3052598E-38,8.222302E-6,-2.0499108E-23,-8.028338E22,-4.527867E-16,-1.0447115E-27,-3.8851717E-12,-4.0457946E-16,1.507552E-34,2.1087501E33,-1.1247249E-4,-2.63530925E15,3.2929465E-18,1.1921536E-27,6.477329E-24,7.7310992E16,1.9015664E-33,-1.0365526E7,3.18606103E17,-6.2920983E16,2.5957222E35,-1.9258832E-31,2.6266172E-19,3.5621542E33,3.0454332E7,1.2476855E-16,-1.8176861E-31,1.36548031E13,4.9214045E25,2.7438851E-17,-1.8473959E33,-3.0454578E-23,-4.8897692E7,7.0721573E37,5.9847318E-27,-4.1846877E25,3.3531302E23,-3.364228E28,-3.74606E-27,8.870112E-19,3.2105653E-19,6.9492075E-24,5.413313E36,-7.762603E28,-2.3253088E-35,-3.31289446E16,-2.16585744E8,1.34195825E10,3.7324236E27,-4.01608869E14,8.3575915E-12,0.0041716653,3.3479494E24,-4.2670086E-19,-2.8259825E-31,1.2722923E-10,-0.0017439951,2.0298965E26,-5.0272176E-21,1.99348746E15,0.18023208,-1.5176701E-24,-2.1410287E-10,5.6091987E8,-1.4499126E-9,1.1885654E-9,2.6898118E-36,-0.18070306,1.4850517E10,-6.852806E20,5.1599894E-22,9.411071,4.89038217E11,1.07041925E-13,-0.020197956,8.366439E-13,-6.4576534E35,3.0023203E-11,-105.14248,2.2960459E14,-2.7814795E-28,2.8688215E-17,-2.3964953E19,-1.6446723E27,-2.1542435E-36,222250.61,2.1277626E31,-3.5781515E-37,13.174928,7.4567587E-19,-2.0350378E-14,5.2352136E24,2.9334891E-5,1.0556122E-7,-140545.3,2.2071881E33,-1.0923296E-35,6.8107282E17,-1.1686143E-36] +,[-3.7570866E-36,4.3920528E-21,-3.0267458E33,-4.8123838E-4,2.12880242E15,2956280.0,-7.4784644E-8,7.6129017E36,-30.573015,2.8056875E-28,6.55768E-28,-1.16929085E-26,-174.06331,80.37314,-1.04798074E14,-1.0279604E8],[2.628307E-16,-1.7618769E-37,-5.0951494E-27,-1.5004825E-38,-1.6793842E-36,4.6419328E9,-1.1114292E-14,-6.980926E-35,-1.10313708E12,5.6927907E-26,1.40455E34,-1.5325342E35,1.3978647E-7,-6.990763E33,1.7162768E31,4.07759687E18,-1.8870195E-22,262014.48,-4.193267E-20,-1.3926199E-21,1.59593477E13,-1.19191731E16,-2.5215198E32,9.60373E23,9.7813126E-11,-1.57487411E9,-1.35527411E9,3.1812082E-9,-6.177941E-16,1.3771007E-36,-6.0719493E15,0.04487049,-1.1324775E33,-5.3247848E7,-6.4157197E-22,2.1571381E-32,-3.3804733E-13,-1.7190284E24,-5.294223E34,1.5343845E25,-7.05058E-9,-3.4925557E-27,-1.2725383E-34,-7.734155E-36,-3.4937855E-28,9.50521E-23,-3555126.5,-4.5004522E-27,8.518416E31,-2.8177185E-35,-5.541759E-34,2.2947006E-17],[6.8358187E34,2.04636401E16,9.12752E30,6.527289E-24,2.9402646E29,2.5824407E36,-4.8833208E30,-5.94667E-15,1.30115923E17,5.6415725E-14,2.4838693E-16,2.2218246E-29,-3.1267355E34,-7.4469495E-32,-2.7373522E-12,-2.622843E34,-1.9547955E20,-8.692458E-33,1.9223859E-5,-4.5640927E-27,-25.795946,4.1003613E29,-9.2776E37,-6.434533E-23,-3.1305103E-38,-9.306484E26,-245004.48,-6.335563E-24,2.0519342E-9,1.2816643E-38,5.482879E33,3.1055513E25,-5.860269E-6,2.974895E21,6.796779E-27,7.070272,6.444903E30,4.9232947E-37],[-21.336824,-4.7621618E-20,-0.66497993,8.3766025E31,-2.3898977E-8,-3.5307857E-9,-1.0266436E-5,1.7609032E38,-7.6773987E-38,3.5121708E33,1.7548092E-35,-1.1697135E-18,2.8212008E-15,-1.986672E-11,317.6892,3.99097434E15,3.63208097E15,4.381874E-11,1.12951248E8,103042.68,2.4132948E23,3.33862067E16,2.4436065E23,-8.328726E32,-4.43866986E14,5.46849E-33,1.1179067E20,1.68093248E9,1.4400609E-4,3.0030544E28,-3.0063615E29,-3.01945897E10,-45050.22,1.398677E-9,-3.7032833E28,9.7888625E25,-1.3143519E-28,1.3282156E-33,-1.06655865E21,-1.4759362E-25,2.58851945E16,-1.7093964E-5,3.72831656E12] +,[1.7212977E22,-1.6110315E-34,4.1975646E19,-5.9847237E18,19.350712] +,[220476.72,-1.18574151E17,2.2182982E-24,-7.739423E-37,-1.9043889E-31,-5.6461822E-8,-2.7649708E-20,13.952787,4.1838666E20,4.38796E37] +,[2.7655644E-4,-5.724242E23,1.96025779E9,-1.5486204E-8,-5.4481943E-11,2.1857963E-5,1.63553918E17,-7.113666E-13,-2.1068328E34,-12630.789,-3.297585E-31,-1.4076463E-7,-9.1754084E-23,-4.44090816E8,1.3148161E-19,-3.0914472E-11,-1.4561927E31,-6.301541E-27,8.399797E30,3.67614331E15,-0.0055200066,-5.7940585E13,-3.43707807E16,2.716806E34,-1.0018717E-8,-2.33219988E17,1.4592641E38,2.6494505E9,1.05013653E14,-8.009347E-33,1.9547011E-29,1.883113E26,31231.357,-1.011895E-5,-9.6077873E12,-1.7764658E-13,4.7828343E32,1.31251164E14,-1.5896487E-16,259.09628,1.0760773E22,-5.309685E-4,12.104666,3.6872232E27,-1.7278494E-33,227827.33,1.17411065E-35,-2.2445887E24,2.4458088E7,-5.3171926E-22,2.1767572E-32,1.85946416E8,2.8596588E7,-1.91242043E11,-7.835202E-18,-2.7471544E-35,0.0010917947,2.1841521E-4,-2.1312299E-29,5.930519E-8,6.6859726E-11,96240.48,4.051071E33,3.168662E-16,4.687558E-8,-4.9372333E20,-1.12451607E17,5.8929087E-5,-1.467048E8,-1.6280365E-30,3.76742784E9],[-1.75584351E16,1.2245168E-33,5123130.0,-4.514292E-33,-1.4935367E22,2764259.5,-1.45118991E17,-6.9147292E13,9.674682E-33,-119250.984,-3.703168E-14,5.6170836E33,116.853165,-5.27508374E11,1.1289592E-15,9.946945E-22,-3.9366324E-30,-1.3504566E33,-1.1016756E38,5.08689719E14,-1.2788694E-32,6.599717E22,-12502.141,2.2842587E21,3.667297E-10,-4.5007733E-32,7309935.0,-1.73013051E17,2.4907978E7,2.02769039E10,-8.224463E-11,3.0989545E35,5.774948E-17,3.74249878E17,-2.061192E-5,9.947499E16,3.0657485E28,2.5322439E32,6.6040974E-15,-0.07022908,1.716999E-9,-1.3621023E21,-1.0400885E-7,-2.9722635E-13,4.9212E29,-1.0066843E-19,1.6089257E-11,2.3340341E20,-6.290064E-29,6.886818E-38,-1327744.8,1.5810359E-38,1.1454622E-28,1.3125685E21,-1.1477186E33,1.7961565E14,8.71463E-36,3.65589472E17,1.1879758E-23,-2.081335E-37,-6.836266E23,5.2622714E-30,-7.0061786E-12,2.9054075E30,-1.7370435E-18,-1.9153267E28,-2.7897597E-18,0.39471734,-2.676496E-23,-4.381145E-9,-2.1551504E-18,-0.52318925,2.546482E-11,-1.0389E29,-10.113984,-4.4505333E-11,-5.4575633E-8,1.2912783E-9,-2.1069744E-37,33.521736,3.1073418E-7,3401.844,-4.8082936E-30,7.357117E-33,3530.7163,-1.0631536E27,1.06069036E15,-1.5604408E-33,2.2575062E-19,-7.26557E36,1.2502042E-34,2.4010126E-34,-1.10593291E18,-4.842133E-36,5.8919647E20,-2986.734,-1.3374483E32,-2.3035782E-27,1.4147205E-18,-1.7623882E7,2.7470034E37,-1.8373128E-16,3.1367524E-35,2.44237078E17,-4.451739E-37,3.404541E-31,1750.7219,1.3187349E-16,-4.686884E-27] +,[-1.2303181E-9,9.170093E-37,0.4784891,-6.1942696E14],[-0.0037292065,1.5047219E21,1.9131262E-14,-2.627254E-27,-1.5929944E-22,-1.4257981E-12,-7.630401E-5,-75804.51],[9.935494E-21,-1.8472805E-36,-5.8191081E10,1.53035242E13,5.576163E-17,0.30631384,4.803341E-28,1.6066789E31,6.2460291E11,1.2759892E29,6.1332144E15,-4.130231E37,-1.2088627E15,4.6335262E-18,1.73138E-38,-2.7958729E-27,4.6879826E24,4.1132406E20,-1.7825944E35,-1.03556544E-19,3.3949943E-9,4.11711579E17,-3.35493888E9,-7744065.0,1.0330292E36,7.724934E-15,0.5944197,-7.936431E-10,3.9887612E29,9.94681E-37,1.04271539E18,-1.6114264E24,-1.0828852E-21,-5.4225265E-28,3.41002289E11,1.375858E-18,1.08457798E14,-372435.97,1.878048E-4,2.839687E19,-3.5429884E-12,-1.4272401E-13,1.1276847E-16,-2.859622E19,1.04727879E15,1.1058462E-28,1.3562694E-28,7.651554E21,-5.4016757E37,-1.0013809E23,1.33454879E10,-1.1905907E21,4.0029266E-10,2.9158632E-21,8.4604236E-24,-2.9850152E-34,-0.012190459] +,[-5.764414E31,-5.2196752E26,6.7858896E7,0.909799,-6077.3174,2.3042354E-21,-5.212471E-5,-5.1442374E-36,-6.9973688E7,-2.727006E34,-1.1359338E-4,-3.9407945E32,1.30400625E11,-9.346719E-24,2.1532475E-26,3.8182804E-22,0.10658172,4.39766374E17,3.70600675E18,3.5758696E11,-6.778952E-15,4681.533,-4.5092954E-24,-2.08312356E16] +,[3.2162023E-22,8.221859E-24,6.462382E-31,9.4229164E21,1.1810377E38,-0.12487992,-1.0157863E-4,1.15495858E15,-6.2867823E31,1.2492463E-23,9.601541E-26,-1.6277776E11,-2.931216E7,3.6215828E-25,-2.7987744E-13,9.694505E-35,1.23615048E10,4.1462154E-13,1.4492912E-25,-32598.293,2.0894494E38,1.2132723E-37,2.2854747E-5,-1.3249754E37,1.8793671,1.1965214E-16,1.2201502E-32,7.583581E19,1.5794895E-9,1.182034E-9,-2.5222528E-12,-9.3422186E36,8.056309E36,-135772.14,-1.523953,-436.8168,-3.447895E-30,8.5902084E-11,-6.1617074E-17,-1.3981657E-14,-4.2009978E19,-6.309546E-29,-731046.6,-4.27337921E18,-9.168636E-26,3.95471999E14,-6.735841E-6,-5.207519E-6],[1.4292304E-8,4.1480423E32,2.0948E-9,-7.849331E23,4.3482833E29,-3.7333004E-27,1.0487214E-9,-7.913312,7.495433E24,1.11571444E-13,6.9270526E31,5.0445893E-12,-5.2592262E20,-3.56502897E11,5019.301,-1.1874029E-27,-1.0265498E35,6.7177503E15,6.86319E-19,1.04973047E17,2.49409959E15] +,[-2.79268102E17]]
diff --git a/1.9.10/samples/numbers-int-4k.jsn b/1.9.10/samples/numbers-int-4k.jsn new file mode 100644 index 0000000..3a1e557 --- /dev/null +++ b/1.9.10/samples/numbers-int-4k.jsn
@@ -0,0 +1,11 @@ +[[ -6815,-15 ,25 ,-2379,-30,20,8 ,-148966676 ,-25,-15 ,-475215790,27 ,-21 ,-18 ,-10 ,-860 ,-2703 ,-747,2886 ,-13,-390],[-242 ,22,-55475680,-11,70 ,8,21 ,-5712,22 ,41741460 ,25,-28 ,175967856,20 ,180766425,425383080,-15,100 ,-22 ,0,-4,-1656 ,-195903072 ,-14 ,103871680 ,1,-30,22,5,30,-7 ,-6566160 ,3,0 ,-5100 ,1,4207210 ,2568240 ,262598850 ,3885852 ,-2968],[30,-14421168 ,16,-30 ,21 ,21,-89984160 ,-36689745 ,656 ,-8 ,29 ,27 ,-45057880 ,-2320 ,31,-24 ,-12,22,22],[0 ,840 ,-12,4548996 ,-4,-15 ,21887400 ,27,2255 ,-15,9 ,28,30 ,-4867 ,-19,4 ,5,-12 ,-3,-2964] +,[-2288,-27,0 ,-450877856,-25 ,-1428,288,68410304 ,-2783,10283700,25,0,3360,3220,2,-14,-3 ,-12,162483684,26,962325,-336726192] +,[2080 ,-18 ,-226446836,24,-9010575],[572,-14 ,0,10,9 ,18,4228 ,474152068 ,-9 ,-249 ,-3504],[29,-8 ,88136384 ,0 ,-31 ,26,-5425,342 ,-6 ,29,22 ,-3 ,29 ,4300 ,9710532,-10,-4,-1326 ,19 ,1420,-11 ,15447796 ,-9,11],[-4,101 ,-26148096,2086410 ,-5100,13 ,-396,-11835750,-1204,-15 ,-2562,25 ,-2418,-65220672 ,0 ,-5200,2],[12 ,25 ,1768,29 ,10,-266238792 ,190918080 ,-66498600 ,74835240,-14,-753 ,-31] +,[-19424880,14 ,673847790 ,2088],[1909 ,-6] +,[-1150 ,864 ,1043,24003072 ,-446 ,-12532509 ,31,-1,26,23 ,29 ,27,-234 ,23,-27,8 ,-5424,59461944,-24 ,-37243800 ,-31 ,429 ,-12950162,-741951 ,330,-1513 ,3744 ,-104324880 ,-1363,13723920 ,1072,0 ,-66401460,-7 ,-28 ,14,-496 ,222896688 ,2392 ,10 ,852 ,10,710600 ,-702268,252678888,31,8],[107921457,0,-69005788 ,-110735688,-2,21 ,620 ,-1],[4,-27,-4,16 ,-1197 ,12575995 ,3248 ,-17 ,-341727540 ,25385304 ,265557816 ,-341890794,44668932,-686426364,-27 ,6 ,-2,850],[59970240,-12 ,-30,26 ,-24 ,640498719,5425,-48,-2418 ,83878272,-948 ,-26,308087920,-22 ,-7320,28,18,-2312,-5084 ,24,18229519 ,-833,30],[17082996 ,7,-12,-493723332 ,184624128,-364 ,10 ,-1950 ,-51792480 ,3,1742,21150360 ,9 ,-730,11 ,153 ,7,-2,-25,342078609 ,123,5 ,48,-19,6500592 ,0,-11] +,[-13,-31 ,-1683 ,-26,-4264 ,1005 ,-18,195189561 ,-13780200 ,-3842 ,19,-109547490 ,-13,22,15] +,[-4247 ,163096443 ,4455,4312824 ,-39474240,221,896] +,[18 ,563669100,-4975,-18,-12 ,8,-14 ,11,12 ,0,24,-337153320,5,237760740,-4520,490,-36,54106920,5 ,1337,-31355456,-26,-5751 ,21 ,-91954704 ,-2952 ,-23,468 ,-97562412,2080,28,5 ,14 ,262828602 ,-1 ,7,-7,6000 ,-28 ,-193977180,-24 ,546,-1615 ,-1,-357052350 ,15,-20,7,-71564800 ,-30,-21,4867 ,-11,14 ,12,-13 ,-8,23],[339311000,-20 ,-459,-20,0] +,[-16,-920,1116 ,11 ,14 ,-6,452 ,-4025 ,20,-347848875 ,-5640,-185852250,6604,-174912615 ,-9 ,11,-38637780 ,-26,19,-3,-2757977,-29,92153700 ,17 ,-341 ,-9 ,1 ,19,17 ,2527,19 ,-10 ,5673,-14 ,30 ,5456,398044154 ,-12 ,27 ,-5,-6356 ,-1 ,0 ,-24,-429469920,9,-30],[449989148 ,-6,37694916 ,26 ,980 ,18 ,-11484696,-14 ,0,7 ,1408 ,3689,22 ,-560 ,-349350300,28238400,702 ,4104 ,1701 ,-13,-2,-17058312 ,-31 ,-25832520 ,31700160 ,-2508,1 ,865 ,-376597728,3484 ,16,83891808,-111926304,0 ,180025335 ,-10,-7 ,-21,2044,73 ,-23,-221454648],[-2875 ,0,-13 ,14 ,-7 ,6448 ,9,-24,48582105 ,-20 ,4885162 ,650,-3770 ,-17632350,-32004840 ,-468,26955450 ,-25,-2223 ,2040 ,246021300 ,3720 ,-71730560,-27,-88855200 ,88889504,-20,16 ,-137357280,-69545280 ,-4,87012325 ,111810816,-415,8 ,14,9,27,-14592798,3,-31,-5060 ,216 ,-9,-6,-3696,-24 ,427221360,-8,-20,16 ,-99887940 ,13 ,11 ,-2596] +,[19 ,8 ,154626318 ,1],[-3072 ,-792 ,27 ,-3438 ,5 ,-13,-5 ,27,-1824 ,9,-75,-108 ,-12,-4028 ,26 ,-2442 ,420,59505320 ,-6],[7 ,97876512 ,-300 ,1955,19],[-3750 ,-3 ,-945,-5,0 ,2028,-5 ,6 ,3 ,5928,357979776 ,-4,-24 ,22,-18,3458,-25363756 ,-28 ,-1816,17 ,9 ,-45321881 ,-30,-26,0,20 ,-15,16520672,-4 ,13 ,-19] +,[93313272,-252644854,3 ,-233450 ,899,6,-26,295789200 ,-840,-13,9,-12 ,-24 ,-5675,-18],[2522 ,339500832 ,0 ,-21 ,14 ,-31,184500,-4 ,0 ,1695330 ,6,-7 ,-27 ,6,-16470210,-4420 ,-15 ,28,2712 ,4,212084622,-26 ,26780400 ,-15,468084708 ,870,-54512648,30923640,59129470,166213800,-69060576,110 ,5,22,47040588,155440992,10],[-759 ,168 ,2938,24 ,1312 ,-18 ,-210243550,171418600,107993520,6,-1918 ,1720 ,3819,20 ,21,-261,-205366356 ,-750675750 ,5 ,19 ,-176472244 ,110 ,194590704 ,-2 ,-23 ,1,278327610,-6 ,0,11,-1,-244155912,15,8,11,-1,-1 ,27 ,-15 ,-22 ,-3696],[-15]]
diff --git a/1.9.10/samples/numbers-int-64k.jsn b/1.9.10/samples/numbers-int-64k.jsn new file mode 100644 index 0000000..7fbe559 --- /dev/null +++ b/1.9.10/samples/numbers-int-64k.jsn
@@ -0,0 +1,154 @@ +[[-5493516,-17565660 ,21,0 ,515145906,23 ,10937052 ,20,-4620 ,1440,-47879778 ,-8 ,13321935],[1,-27,-10,10,-26 ,278053965,-285202170,522,15 ,-8718624],[8 ,22] +,[2,-30,2184 ,-165381615 ,708 ,127883304 ,25,-103616391 ,-3822 ,20,-17,21 ,20,60093036 ,2,-7,-3,28 ,-2 ,-17 ,-234 ,-3472,13,3,-27 ,-21,-14086896,-3360,-592740720 ,-464,46114320,-109179840,26 ,-5 ,-12,146850480 ,-28,-16,22,-20 ,24909960 ,-18,-248,4425] +,[-24,-16,4554,-31,1,65097736 ,-6,4,-21,13 ,-4 ,0 ,-2,42024360,-59395842 ,1620 ,-4320,-8,29822904,-19225596,-29],[-54302595,-480689496,9639280,31 ,-19 ,-38030958 ,-11,-8,-2100,17830400 ,0,-26,6554 ,5,-84105480,3779055,-800792 ,30 ,-22,-28 ,31,74368660 ,-64643320,-4085 ,-20,22 ,5 ,-4 ,-2394,26,-7],[-3648 ,-100 ,31 ,15 ,13] +,[20 ,-28,-53671800 ,-69036933,-142748730 ,-1123836,20,-10] +,[0 ,17,14 ,-1722,-4482 ,24 ,3440 ,-233026686,8979705,-13,11,6615 ,0 ,-17216760 ,12 ,-546099235,24 ,-11,-30,2509 ,-12 ,194635350,-4392 ,4600 ,23 ,20 ,11,25 ,2500 ,-19 ,22 ,570] +,[6084,-1628 ,-9 ,-832 ,2464,-924 ,-2110,13,-6122640 ,-79437728,3,-3910 ,0,28 ,208356300,24 ,-1 ,-30,1281945 ,10,24,84771348,-21717570 ,103233317,221295564,-207229575,-31235848,0,183428940,269512137 ,30 ,-24451560 ,6 ,-4,-1,-816 ,20 ,0 ,-7,-520255008 ,274987448,37809408,-10,-2581,1188 ,-11 ,3435 ,1555080,-9 ,-14,-17,245288250 ,190557000 ,-9 ,9,-840 ,23 ,16] +,[31 ,3 ,-4284,27,20 ,-31,-1 ,-322462868 ,-110720650 ,0,31,-18 ,6,2880 ,-21,-11 ,7427904,-25 ,183814512,16,16,-33760720,118156428,-19,25,-144086850 ,12 ,-230576970 ,27 ,-6 ,477,-4298496,442944544,18 ,29,6420,2728,-3,-161 ,-1 ,0,-22,18 ,15 ,2376,1442376 ,-15,1056,19,28,5278 ,-60587604,-442 ,3726 ,15,-26],[2904,-10 ,-20,14,-17],[27 ,-27 ,10,24,-26 ,-5616,19,-15,-21167916,-1 ,35552800,23,-18,30,208722906 ,-20,-22 ,2205,-1305,-122874700 ,29607207,0 ,38506734,71241456 ,23 ,990,-76136720,-1820 ,0 ,-2070,-3],[-7140000,-207460792],[-469476 ,-72 ,-16,0 ,-5526900 ,30,16315600,3444 ,15,2657088 ,-10 ,-16 ,23 ,-26772705,31,19 ,1140,3312 ,532,-16 ,-3870,-192 ,17 ,-4,-22 ,-3258,-62669288 ,-624,18 ,11 ,-3572 ,109160415,-162],[0,20 ,-23,-14338940,-6 ,1485 ,2820 ,-14,198 ,-27,0,375240600 ,1008,-1152,9 ,-996,-198,1 ,-2860,-2 ,9249808,-129703980,-391,21 ,-10366400,17,680 ,20 ,-17 ,419744364 ,-9,59357600,15,24,-108559969 ,-11 ,-3699 ,0 ,-20 ,2060,24,-1478295,-27 ,-999],[847,9,15 ,135523840 ,-233421441,0,-22 ,117282060 ,-8 ,-48 ,-372,-1056,26 ,31,22,42 ,-17 ,6,-21660480 ,-7 ,113050320,-6,4590,-36883848 ,136,-2565,3553 ,85366848,-25 ,-8,8,-2],[45371755 ,17 ,-828,-144121824 ,-13,-2,-7,776,26811750,74118130,-28,-10,3,1,1380,-3290,-1952370 ,24 ,-12,94710336 ,18,-22 ,-6,-25,0,324699624 ,-26] +,[21,-301316548,-18 ,176284185 ,29 ,2090400,-28 ,15 ,-23 ,26 ,-15617515,31 ,235085200,-14 ,-14 ,-26 ,442007916,-13,7,-67563600,-1380 ,-1216,22,-2,-23,-3 ,-25 ,-4016 ,-14,1568 ,-120 ,-9,-213614520,423411678 ,1 ,-97522128 ,26,-216,-14 ,471416050 ,26 ,-176542740,-50331288,-12762960 ,-272371712 ,-17 ,14,122,-132 ,0 ,-492,-17,-428341420 ,-31 ,60481248,8,-23,4464 ,22 ,16,169607999,200460906,-3 ,-15,11 ,-301622750,46882560,1610 ,390 ,11,-21450335,-11 ,124228764,31 ,400518692,-16 ,-17,6,-7 ,10 ,-28 ,237548850 ,33377136,16,-8450244,-2420,-360 ,-6,-9320784,-244067904 ,1680,1115 ,4100 ,5 ,-27,24,28 ,-788,635 ,14,-156939264,-1190 ,6758,-20,95208960,683216058,21,-26 ,5 ,105055951,-3,-31],[492 ,29 ,21589630 ,23622144 ,6 ,-5 ,-56659912,7161 ,-36724416,53453650,54585100 ,12,-288 ,-560 ,-161335680 ,9],[3 ,378031500,-9,3,2478592 ,26,-5841645,35808752,291812192,8 ,-1020,11 ,-1771,-43215336 ,230590512,-83174850 ,-22 ,-289695297 ,-25622616 ,0,-357 ,-31,13 ,0 ,765,0 ,-31 ,11 ,229068950 ,0,-275265900,-27,251016,-3538 ,503445051 ,5 ,-2128,1411 ,-73133905,28,9305550,-6,156381096,69329196 ,-3424,-1674 ,104380992,16,22,15,399 ,1836720 ,23,23] +,[683575650,0,-1680 ,-21,-3952 ,20 ,-19 ,-2337 ,-112663584 ,9,-660 ,3860,267858844,-2 ,396 ,1] +,[24,0 ,-15 ,907788,377316360 ,-704,-3,-1490 ,-2,-15,-4876,-4,-1360,16,3420,8377530,105796800,-12,18,29 ,540,0 ,204 ,0 ,19,63616890,-1210,689 ,6916,-20,375 ,36113490 ,-4 ,125932336 ,18,-294707160 ,-3 ,12,3,-13 ,18,12 ,15,-64877196 ,-420 ,0,14 ,-4 ,3388 ,-5,35475048,-2616 ,-37500528 ,16,25 ,-3458,-2169 ,-31609176,-14464818 ,762 ,-15 ,-143553780,27],[31,-1701 ,-14 ,0,31,-27069000 ,2752,18,-24,-15,-20 ,9,-700 ,-198 ,-1,42300726,16 ,-1264 ,3510,-325876860 ,-3,-14 ,6 ,25,-3 ,-164],[28,-23287140 ,-3 ,3 ,-3456] +,[28 ,-26 ,-22,54374580,215029760,-24 ,-30,-48048297,1239,2 ,4 ,195 ,0,6 ,-189932544],[402,-29 ,4250,24 ,-26 ,-10854436 ,167269041 ,756 ,-720,-673097850,-26,-19,-5 ,263432520 ,-8,-164350248 ,-13,-2380,160 ,19,6,-12,-27 ,19 ,-2820 ,335281296 ,-2394,-14,-960,36] +,[1480 ,1629,10 ,-41119435 ,-15 ,4142,-15,-3075,29500128,4 ,-31278357,33930750,6,-357723975,21,332867584,-667,-16 ,3,-26 ,291925200 ,-18,28 ,16,-4 ,-101395800,1 ,275218293 ,19,-28,0,-8,169445724,616,-52252560,142371840 ,26,5 ,-555186880 ,-1950,-17 ,11] +,[11,29848320,31,6 ,-13,1674,750 ,5588,-16] +,[4760 ,2214 ,-962 ,-25,-23 ,48461490,793,30817200 ,-3009 ,-8 ,-1710 ,-18 ,27 ,1976,0 ,-7752000 ,31 ,14 ,-20,-7 ,14,4,10 ,-23,4,159148224,11,24 ,-10 ,-537551040 ,7 ,4410,11 ,-34083378 ,29,-64299312 ,2288 ,-25,-28 ,-12 ,8,-3366,-3816 ,19,-197053098 ,-30208064 ,-8,-5324 ,2278,-26 ,31 ,-26 ,28,17 ,-14751288,-16,-24 ,-700],[-1742,189,23 ,-24561075 ,28 ,-45495849 ,2410 ,-10,-9 ,107006580 ,-200353200 ,-208809657,0 ,-3 ,4032,918 ,21147399 ,11 ,931,29 ,8110220 ,3180,3444,3720 ,7 ,10 ,2,6,0 ,-16,1080,-173294592 ,-6,2 ,148752480 ,-6775130 ,-10739718,-30,23 ,-28 ,-18014400 ,-774,-6083028,-362235456,9 ,4 ,225104873,89396937,-700144926 ,-751068864 ,-139500072 ,138 ,-108,-82,20615958 ,-9 ,9567800,2 ,-90 ,15 ,-27 ,-19,-100056960,2431,-21 ,2 ,1421 ,-16,-5,14 ,-24 ,19,18],[0 ,-431028216 ,-256,-12474000,-6,-61380319 ,499792 ,-4960 ,0,-31,3,7 ,-2133,308 ,250921616,-15 ,-7591545 ,0 ,398408400 ,-9 ,-26 ,1579000,-3 ,146901216 ,97546050,-638066,-133298000,-7743750 ,14512302,96 ,1008,24 ,-916560 ,23 ,335329288,15,196,3 ,-7 ,-3724,20 ,544,-6,27 ,186019920,-29 ,105598976 ,-9] +,[11579400,-39621939,-38734462 ,23,153 ,0 ,900 ,6,164459774,9 ,6] +,[17 ,17 ,-18],[-288 ,2142,-19,15],[-300,-37399733 ,4356,3,920 ,-18 ,5765410],[-26,-23 ,-6664 ,-28,-3,-31,-18 ,-225 ,13,1,24 ,-29 ,-29 ,-20,-26,1 ,-24 ,15],[185056188 ,0 ,-3 ,12] +,[1 ,-1027 ,-2373,0 ,20914624 ,0 ,-7,24,60145416 ,-10,-8,-10 ,-5,0,1572,-18 ,1,912520 ,11,-670 ,18,-12,2618 ,23,-15,-2985579 ,-4960 ,31,-17,5 ,23,161903520 ,-26 ,20 ,0 ,-159009768,175160000 ,-277153380,30 ,1548,-11 ,-26,-26,-2790,-17,31] +,[240183450 ,3348,-1,-14,-25 ,10537488 ,-239568840,-29,13,-4,2 ,-7980896 ,-16 ,5741078 ,1687 ,-10609056 ,582310575,10 ,420] +,[1274 ,-8 ,-928,1053 ,-26 ,334698000 ,-62619288,2696100,15447600,-194609952 ,27,-13,3,-1023,265082160 ,-11 ,-69,-28 ,26,-57278188,4060] +,[-26,4000,-29 ,-2044 ,-2,-4 ,-1120,-22,-19,15993392 ,-10 ,-34799506,0 ,416,0 ,-1638360 ,-3],[-23 ,0,0,0 ,-2205216 ,-25,-14312700 ,-14 ,300 ,1482] +,[2538 ,1,1 ,2175,448 ,-3000 ,-5363,186,-9 ,30 ,580,3230,3,-29 ,24 ,155511552] +,[15 ,-27,-11,-90180090,27,-133564464,416774820 ,51377690,25 ,-2688 ,43146272 ,6 ,-21,17 ,-3 ,-22 ,-1793 ,-406095040,21 ,744 ,0,26,-15,-8 ,-4619 ,452,31 ,120 ,18,0,-21,-2060,-16,-21] +,[-23 ,141 ,-207268587 ,1705,-18,171 ,28,-636,-2520,-11 ,10,-8,-4470,-27748474 ,1248,621,17 ,111956952 ,-364 ,14805560 ,-1197 ,-17,-3097920 ,-23,-31] +,[24,-9,139260170,31146600,900 ,-127,-9,0 ,-29,-52391220 ,-671 ,25 ,-24506502,-2280,3000 ,486,20,1498 ,-21,-1520,19],[-1 ,-4497240,4,-25 ,23212008 ,71821823 ,765 ,-20 ,24,810,10,342 ,-233043120 ,-6,-2560 ,8,-2,24 ,2390 ,-8 ,-143,5,0 ,-30 ,-47 ,-14,19 ,512259475 ,2046 ,18 ,1056 ,-5 ,525,18 ,2280,25,-16,710 ,-2898,318896214 ,-23,-13,29,17 ,-28 ,30 ,3102 ,-6,-93884931 ,-1312,-117842202 ,-19,2090 ,-30 ,-10 ,-8075001 ,444929856,-2899 ,-17 ,-20559440,-23784729 ,32332680 ,-3 ,-4350 ,65054580,-20,396,3 ,-2128 ,14053732 ,-29,12 ,-756 ,-8 ,4275,17 ,1133,69328800,-4150,436487874,0,-348985784 ,20,332099750,21,-1,-344,18499264,-78522745 ,-483090300,22 ,-2856,-4],[-245895150 ,25,-1144 ,-149855680 ,23 ,-7,-18,-2727 ,23 ,8 ,-410,2507 ,-10,-26621000,23,-22804848,-306,-3264,-2242 ,23,3390 ,-2735388,-1712],[-4 ,2476656 ,76637600,-144,14 ,27 ,-1615 ,17 ,5150 ,-12,-7 ,-2943,6972 ,-47053125 ,9 ,18 ,3520,-28 ,336 ,-918,4 ,-196881272 ,-1100 ,24 ,-1890000 ,-5913 ,-1470,21,14],[-24 ,-116812696,22 ,4,20 ,13 ,506,15 ,326145816 ,12,-16 ,-26,-2829,-226,590,2652 ,-8,27 ,-162690444,31,-26,-9 ,4 ,-21 ,-112457466 ,15 ,-30,0,350135032 ,3402,1650,-8 ,598,20,233 ,17,-1980,1,-281358000,-6,6,-29,-1350,37555210],[27,11923120 ,4123,2499 ,-13],[-4182,-1606 ,-40257756,27,664 ,-11,-19 ,-18935532 ,215951340,-485,50 ,-131700528 ,-275 ,25 ,276911460,-7 ,8043750 ,-447636392,-3059,-8,-15 ,25091550,0 ,4625 ,-76350330 ,-7793775,16,21,3360,27 ,12 ,-32708185 ,3 ,-4248,7,22 ,-11 ,18 ,-93637440 ,19,34403512,-31 ,14,-395036928,19 ,1425 ,-5487,11,-22 ,259772800 ,5213700,128496450,-803,-3264 ,-1088,54,11,-480 ,-27],[3,10,23 ,25,-26,4 ,5 ,29,-6,-24 ,-14342400 ,31 ,-64156730,-162150660 ,-286569582,21482016 ,14 ,6,-6,-22 ,-5 ,22 ,2759,31 ,-20,16,-6,137,-261762816 ,-25625500 ,3838,12 ,-3220,-358712172,-27689904 ,-7 ,-31,-21,-1395,-28 ,2508,-7 ,128028897 ,-9 ,0 ,13,-15,-9362610 ,5616,-336068852,1428,121983344 ,1,-18 ,-14 ,-1,0,18 ,-1644 ,4071 ,31 ,570,15,4 ,3211 ,4 ,-7,440215424,-16115325,-798411120,25 ,-13 ,-10 ,2205495,-1830,544,725372825 ,44856900 ,-243203380 ,6 ,0 ,-13],[-2610,-27,135,15,-4050,29 ,3632,12 ,-31,-802779120 ,0 ,16 ,-117 ,6 ,11 ,-35099688 ,1729 ,29 ,0,16 ,-18,20,15,-9,-4 ,108754688 ,-6,515074560] +,[1711,7,115977638,-16 ,-98368320,-22 ,13,-3 ,1400,22364160 ,1 ,-8,-23,12,1632 ,-30 ,-5980],[-9,19,-12,0 ,-27,1417,-1782] +,[-4284,42594504 ,-9 ,2 ,28,-14 ,-13,29 ,-1944 ,23 ,-6,-9 ,-23 ,1139022,23,-14 ,629 ,20,-143720085 ,-2136 ,2,21159600 ,28 ,1298,-28,-5138856,-33666120 ,13 ,1656 ,25 ,-13,-17,-560,41,931 ,8,25 ,0 ,-10,-10 ,-540 ,-1,59257800,20 ,-1 ,-78624470,-2412360,4422 ,2,-178849356 ,7 ,15 ,-30,-70116138 ,0 ,-1584 ,-24 ,26 ,304,2 ,-8 ,14,-17,29,-477322560,-1957800,-23 ,4775,-28 ,0 ,876 ,10,-144021960,17,20 ,212339232,16698136,-12,0 ,23 ,-8,17,-75344880 ,-26,-2772 ,0,3,-28,1 ,-285812076,-3,4309 ,14 ,0 ,-4373818 ,-25 ,-400,21121600 ,50506140,-4816 ,-7 ,-2886 ,-2816 ,-12 ,152017488,962,-4807,20 ,696954000 ,-27,-8 ,-6,1403,179759304,28212800 ,5566,-247629177,608,-238,4077,0 ,-2 ,2382900 ,17564508 ,-2730 ,12 ,-10558944 ,-704,-642 ,-5671116 ,-9 ,-461685728,24,-2987040,16,1408,-14,-16,-1510627,56076324,-5510,29 ,-323024016 ,18,-1432,-27 ,915,28,23,48589680 ,335 ,214740526 ,22 ,-6 ,-28 ,60 ,-12,7 ,9,-9,5 ,10 ,182,-15 ,7657,294958755 ,1 ,112677660,-89913240,-2,-1224],[-25 ,-15 ,5220 ,1341 ,-2562 ,-35650602 ,210141000,7 ,296,86113500,131163480 ,-20,7172928 ,20 ,29,-80617332 ,8 ,-5292 ,0 ,0,24,-264,1725],[8,483192675,-2704 ,14 ,-26 ,-385141978 ,1159] +,[-61809318 ,26 ,-1 ,20,-31,-23 ,-1430,9,-2364 ,300,-4080 ,6972,184,-93317301,-394] +,[-1,48814056,-440,-14,4540 ,-7 ,-1,-31 ,-112482180 ,48084704 ,39427046,-7 ,21,-15,26,3 ,21,819,20 ,4424 ,363483936 ,2296,26 ,20,11 ,-3366,115506840,-26 ,29,-27 ,-14,-16 ,27] +,[-20,16661088 ,-12,30591912] +,[-31,-194795790 ,12 ,-99204168,-1665,-28,-11,0 ,-1320,20 ,-376732446,-4066 ,-131922777,-8 ,19,-1719720] +,[-5 ,20 ,-75601253 ,-416038964,24087000,6870],[-3247,-79494870 ,-227768464 ,8297802 ,-13 ,-6,-15,124188750,29659374,11,-7,-2 ,-30 ,0 ,22646580,606662281 ,-13,-4,-21,-25,18245418 ,-9 ,-22 ,-22,4 ,23 ,4,-118270256 ,-25,-32630752,-3888,-89617482,0 ,-4 ,-2500,-8891400,-248,-36 ,58390200 ,7,20 ,10 ,27 ,-6,149634496,28,16786575,12 ,2 ,-16 ,27 ,-17 ,-223677760 ,-22,-228434850,25252787 ,2112,0 ,-18,-6880236,-170549946 ,3 ,30,-4730,-147463232,-26 ,286,16,25,-183,-295,-20 ,-25 ,22 ,36724770,-29 ,-122 ,-92736360 ,-26,-17,3971370 ,-13 ,-18 ,13,20,-2500,2964 ,145931328,29 ,31 ,-16,1943 ,-688842 ,3,12 ,387583119,165678392 ,575 ,10],[50090274,-6 ,-2,466131780,-28 ,162 ,18,100719000 ,24 ,-101334324,-6 ,109600776 ,26,-874,25 ,-3 ,2,1110 ,20,3750 ,-15840836,14,-26552709 ,23 ,27 ,24754368,-16 ,-29 ,54232416,406625200,-5 ,-17346462,-15 ,26,25605168 ,-1303552 ,-15 ,-31,0,1664002,30 ,-216106270,-1376,-2,-3136 ,-1 ,13 ,405748512 ,23 ,7] +,[-2966166,1075032,-4326 ,-3640,5,-2070 ,12206560,3066,-32334336,-7 ,-19 ,22 ,-73863504,-3288660 ,-14,3584,19 ,-28,2688,-525,153811860,-161431296 ,31 ,-108346812,12 ,-156241824,-49663824,-85124256,25 ,0 ,-34692100 ,19599300,13] +,[-3,352,-2 ,106858560 ,-28,15,13 ,21,22,600526360,28 ,-12,-4945149,-14 ,-2125,-21 ,-1650 ,-10,333243900,-146018340 ,1738,-597039696,-31 ,-25,-5,-28126660 ,5080 ,0,-13 ,-2 ,-615 ,476,-22668124,27 ,912,24 ,-25 ,1425 ,14 ,1350,23709378,-21 ,66969100 ,-179585250 ,-2242,443293536,25 ,45749207,602,1944 ,-16855224,15,1771 ,-7 ,-2],[3000 ,120,14 ,-25 ,-3,260000,27 ,-4712,25 ,-6106800,-338696640 ,-3 ,1953 ,-1976 ,144999300 ,27 ,-320254272 ,-25],[11,-47455056,5766 ,310370566 ,-4 ,-29395170,118839840,14 ,-24,-73768338] +,[22 ,174 ,2392 ,450131565,-46205934 ,-14,23,31 ,350555130 ,-28,-6 ,-5,-504 ,424,19 ,-920 ,1323 ,-1000,-840,-30582048 ,-12 ,-25,-50843376,-20677020] +,[-27,7 ,-10173184,1404,-22 ,29,2880,1 ,20 ,5 ,283176000,-9,-14 ,-396538170,-1414],[-870 ,25,24 ,-11,11 ,-2352,-20 ,2520 ,27,19,44968040,197399664,29,30,-1,-30,-3,-7,-8,-2244,-25 ,-687 ,-11 ,-1144 ,-21 ,-14 ,21446400,-2142,-68172960 ,-54684448 ,0 ,24632832 ,882,-1746,24756774 ,-1472046,-11 ,16 ,25 ,-2300 ,46310670,-23,0,0 ,2044 ,-9 ,24352075,-27] +,[25338470,-1452,31 ,14 ,-14 ,-24493014,6,-23,2,-31,2,682 ,1106 ,-30,520 ,-28,-1,-454207860,-532 ,-22,-6541 ,-45384192,3900],[4 ,-10,0 ,687831768 ,7,1152,22,309918570 ,24,-18,26973320,19,-16,16,9,3240 ,261192000,-5 ,-6,-8,29 ,-1,-18 ,102760164,5748048,-132015360,12 ,-27 ,30 ,-735 ,0 ,-572 ,-12,2268,10 ,-63620025 ,-62067600,31 ,11622852,241348564,-56701879 ,-115 ,7 ,-18,-24,12,-12 ,-25 ,64581300],[-75622120,-19 ,44 ,-24,112783712,7,19,-300,5,5 ,-7 ,938,5166,-211981800 ,-10 ,27 ,436,6,-98 ,18,2040,142769536 ,10,-400929408],[-9 ,-16,83225736 ,24,203906100,92101200 ,-1617 ,-15 ,-46952640,-31 ,-2,-309670390 ,-4,-19,-4089,10 ,6390826 ,840,3735] +,[-15,25 ,1716,-42970932,-300534192 ,3,-5684 ,-4482 ,-840 ,9993687,33556320,63784224,0,228,-244446150 ,7 ,112404000 ,3936,87495635 ,28 ,26,-1200,19,26456480,-3,-24794500,20,55302870,-9,-24 ,-14],[20,-1479078] +,[-244976358 ,-24 ,1200 ,143647182 ,93801760,-2327 ,-31,40896898 ,276737250,-21 ,6 ,28,640,238 ,-1,34594800,22 ,12694016 ,69087168 ,516,-11833884,1692 ,-202277372,-14 ,27,-195 ,27 ,-544,16 ,29830944 ,27,0 ,-2106,-41724396,2832 ,165 ,-55291842,27 ,-478705545,7 ,1380,-1152,-29,8 ,14] +,[-27,126772712 ,-4767 ,-11,5 ,-2449,-26,30 ,718485 ,-1680 ,0 ,-1320 ,-6,24,2016,-531,3248 ,55,11,-437141760 ,-22,34,-9,-26,15595356,99038784,-5,0 ,-4,0,14,-31,340,112130620 ,-1612,-23 ,-30,-17499354,-23,102328950,9,392935941 ,1,-29 ,372 ,1482,243497268 ,-30 ,31],[-4082 ,-11,64012410 ,-3,3045 ,-15,230 ,25 ,-11,-8 ,1,648,-213196536,503921250 ,19,-3400 ,-2,-57200640 ,3702006 ,351 ,19,-4 ,316202080 ,-10 ,564] +,[26 ,4560,-17 ,14 ,18,3000 ,16 ,-7099 ,-6 ,10 ,-27 ,636,15331050,-36314902] +,[0 ,17,-212,6225296 ,-11,2616,2448,5,253666336,-261 ,-11535678,16 ,776 ,-11284882 ,5 ,6003,1946088,363,8,145139058 ,5,14 ,-1133,698186940,-15 ,-13517840 ,-249 ,25530816 ,6 ,-677489400,123 ,80502240 ,50,-3,-16,21,-7,-160511940 ,-7 ,0,-8,-2580 ,-2635 ,2460,6,17,18 ,-329,31,-4945 ,31931700 ,13,13,26598465 ,38233278 ,7125532 ,28,-12031155,-3 ,-24,380592775,28,22090950,400 ,-351,-20,22 ,0,1000,-11 ,-85108464 ,5 ,5680440,3841,31 ,-3813 ,-6409,0,7192 ,-4872 ,697249800 ,24 ,2175 ,28,-23 ,67919975,15,12,-3,-23 ,-39512022 ,580,2449,14 ,7 ,0 ,-28,26 ,-201050432 ,-7710105,-2068 ,21,18,2664,-14,21 ,4961938,18 ,-10303020,0,-60081210 ,2366520,13,1320,21 ,-6,-4752 ,-8 ,22,-88,28,-17,-240 ,-780 ,17,-23,31,2929 ,397582812 ,6,-105938532,18,4410 ,0,1,0,10,-68 ,-962],[-10006265 ,83538 ,-28,-6,4700 ,8,237591816,-18 ,7 ,28 ,-5280 ,-3060 ,-1,289333506 ,-1632,18,-20 ,-173058600,486530604 ,1920,-12,81902310,12,174383264 ,-3,-26 ,2682 ,-5 ,-145 ,19606815,996,324847237 ,3,13 ,-7032567,-11,-26,-5 ,18,-23 ,352 ,-3576 ,-182741020 ,1224,28 ,-149884695 ,19,6,20 ,15 ,7,24,21904432 ,573255,-12 ,-1000,-130153760,-19,-25 ,-6 ,-18829824,-14,20 ,-1373675,-15 ,3920,0 ,-10303080,10,25],[-2780 ,8] +,[-12993435 ,713,3360,14325168 ,22,52527552 ,-6024 ,5 ,10 ,30,-16 ,-7 ,-31 ,8 ,-17 ,1932,-16,-27 ,-21 ,22,18,-3 ,-22,24782640,4,-28917119,27 ,1560,-134 ,-1743,-77443908,1770 ,-29238104,-6344 ,13,-26,-226921100,-290844312 ,-3024 ,-1014,-30 ,2,28 ,2175,-31 ,30],[-20,105223500 ,49377244,143736600,1,8 ,14,3150 ,12 ,67945848,-213011526,-1440 ,14] +,[-3591,-5516,396685968 ,31079020 ,28 ,-22 ,-18,17 ,1116,-1 ,19,-21,-5165370,24 ,850,13 ,1827 ,-896 ,10,-3354,-6],[3472 ,-1331,1710 ,30 ,-25,-2712780,3150 ,0 ,11,2941,8 ,-24 ,-10 ,10,-477 ,-396 ,17 ,4179 ,11 ,102765936 ,1278 ,5,30 ,-20,184901424 ,-6757,-11] +,[3 ,43163136 ,-4920 ,-23 ,9,1185 ,-29,12426384 ,24,-210,93918528,-493190,-19,19,-12 ,-606 ,-994,5 ,-13,-25 ,-189 ,-460 ,4,17 ,-187 ,-22 ,-2724,370686960 ,164,2193,25,0,-31,3,1314 ,-99736858 ,3162 ,76107000,-31 ,0,-15 ,-3220,-23681865 ,0 ,13 ,6 ,-3596 ,-32398032,11 ,3420 ,-29,-28 ,3,21,18,21 ,-17 ,30,-57914120 ,905661,54319146 ,182,555,13 ,47419200 ,-1456,1089 ,-43820490 ,91332144 ,-13 ,-3,-2 ,-29 ,2449],[29,-2839 ,13 ,-3378753 ,49048077,53505816,13 ,-22,0,-13,-28282680,-23 ,300,-4843,-27 ,10181640 ,28],[-20] +,[9] +,[-9,-24,25 ,20,31 ,30 ,1],[18 ,-2288,-20,-21,-29,-3332,12],[0 ,-1,-50969604,-8383900 ,-3116694 ,-22446770 ,18,2440 ,-796,-5656 ,2 ,141214320 ,-14,-360,75224968 ,-4 ,-344069000,-29 ,-16474860 ,-16 ,476] +,[-12 ,0,-70509824 ,-2,4 ,260063784 ,-1700 ,1710,-28,14,-16,8,0,119967311 ,22,28273180,-880,702906624,-1056 ,-24,1188 ,0 ,21 ,28 ,4,-28 ,2291,-4 ,-462 ,-940 ,-5932820,19,-20 ,1098,-3,4142 ,-3635450,-34505240,4174800 ,-16,-8 ,4032,362796720,2 ,-28 ,2220 ,8,-2,30,-3173 ,28 ,-475 ,32122160,-8436717 ,38920500 ,-2896,-24 ,-27,-7876080,25 ,-9 ,117250848,7 ,27,13,2,10 ,-1320,26 ,-320 ,280051830 ,-4300 ,-10 ,-10981656,-18 ,-29 ,0,-28 ,1032 ,400233960,11,5,2,5] +,[-8 ,17,-65148800],[-4706600 ,-3 ,0 ,-179794944,7,-2945 ,55431012 ,-28 ,-24 ,1397,9,25 ,-28 ,28,476,-6,-900,4760,30726905 ,11 ,-756,-27,-990,6210,-9167478 ,-1647,-26 ,-96531138,-780],[-77841522,-3781,-12,-29 ,2184,-3289 ,-10,-1012,26,-9 ,-25 ,-18 ,-521783262 ,-1760,-280891611 ,456 ,-29 ,129099648,-5] +,[-183948840 ,8359188,-28 ,-144532752,198,56629881,3111 ,11 ,4446 ,29,605,-91156740 ,10 ,75 ,55 ,-7,29 ,-161628390,448,15711808 ,-58739640,-24 ,-29 ,-85350804 ,174 ,19,-174067404 ,16 ,-28],[16,3942 ,2490,-16200084,19503588,-624 ,62455204 ,-7,-2 ,11477839],[-24,3718 ,3038 ,-72940560,22,-864 ,-7 ,143,3838,26 ,17 ,10 ,-7590 ,-517449920,357106428],[-3906,-29 ,3552 ,-184787320 ,13,30 ,-564355350,32754510,45454080,21,-1162,-30,-486 ,23,-141995000 ,-20 ,-75457410,-2520,-510,-2500] +,[-24,-15,-29,1884,2],[0 ,15,-7,26,-3344],[-18237240 ,0,9,-11,7,-29 ,-16 ,19726416 ,-28 ,1284,3150700 ,-31 ,25 ,2110,0 ,26 ,-24,6,16,-5,138402880 ,316 ,26,-22 ,-30,-204484500,11 ,-14303520,11,30 ,26 ,-9 ,90043272,17,11 ,-2450,871,-694705752,-73301076 ,0,0 ,71706720 ,88229790,-21,-17554880,13919360 ,-2880 ,357980698 ,-120 ,5 ,126365512,-6,-25 ,27,10 ,-28 ,16660720,20,1807240,11 ,-3280 ,4,31,60871440,92743044 ,-24,-1896 ,-19,-26354160 ,100639776,530127000 ,29 ,377260416,1449 ,-6789,10186655,1254,-101534160 ,0 ,-3 ,24,-332550192 ,14,-1330 ,1100 ,1380,27 ,1555747 ,2058 ,211711680 ,-820,-198446355 ,0 ,-1630 ,-14,-17,-19598107,240190076,10478160,-10 ,29 ,1456,-25 ,-59529600 ,20,-6,-173740160] +,[3480680,4370,-1554,30 ,-173851020 ,0 ,-1,-336,11 ,4464,4234 ,-1,23,-3280],[-1,-11 ,-1050 ,23 ,-28 ,-14 ,2944 ,6595200 ,250 ,-11069790,-774,-94 ,-1836,-29 ,-42380811 ,55200870 ,2187,-99540320 ,441775776,-6,5 ,7134,66027318 ,-15391260,81411075,-16,23,32476206 ,-782537743 ,60266240 ,-10,-5 ,11775798 ,23 ,-15 ,-6 ,265750914 ,-198,-23,9 ,1 ,-4500 ,16 ,31 ,13 ,-111085128] +,[15,-17683452,0,-768,15 ,-28 ,-2618 ,551145780,-349133652,23 ,14,-28 ,6,-4 ,1032,-2142,9] +,[-300046068,-4,76082327 ,1472,-4088,12,-26,24,-5 ,-16 ,10,1403 ,8 ,-11 ,-20 ,-2448,-4293,19,13 ,93754284 ,22,-10,-19,2 ,-4,-30 ,15,6390324 ,5,-469,2,-15 ,-377,28,-3,-29 ,-5,-1035 ,398646720 ,320752080 ,-18589500 ,624085632,2 ,252 ,30159394 ,31,1584 ,-28,30 ,-142774344,-16297820 ,20,45591024,373775600 ,-27 ,-67898970,-2736,-576 ,-9 ,20 ,234,-4280,10,4305,5080 ,69223050 ,14 ,63222120,24 ,-1266 ,467409008 ,18 ,27194490,5427 ,28,761669572 ,340810974 ,-38400880 ,4532192 ,11 ,22670460 ,-2352,-7 ,164498880 ,-22 ,-26 ,369203200,-352494090 ,-4465 ,-16,-2 ,-21 ,15,-11221938 ,7 ,233914260 ,579492000,-4 ,-31811028,-4607680,2483 ,136490886 ,5 ,1 ,-15 ,-27 ,9,24 ,-15,30,6561 ,1338,97110108,11 ,-111149901 ,-14,-12992476 ,-12 ,-22 ,3,3456,-5250 ,3,-19,5496,26] +,[-285170325,28 ,-2158,-5974] +,[2,901,1 ,14 ,-31 ,2556,-3120] +,[20 ,-4,-869 ,1728 ,23798125,-2 ,-18 ,-21,-5,340,2 ,-8,13,-8 ,0 ,-437 ,4 ,-18,-211,5126718 ,-106901616,-651 ,407982960,-2716 ,-5 ,-63816662,-25 ,144 ,-12 ,275,-36428028,118037250],[5890 ,106973460 ,-30,4180 ,-21,-18,222472528 ,10 ,10982500 ,-12,-738 ,-26248320],[-785,31,-11 ,18] +,[-457520140],[18,13],[-30,24,-2522],[1225,-185744160 ,-738000 ,2736 ,12,-28,5803625,0 ,20,400246980 ,73571840 ,-20 ,-30,952 ,726831504 ,-76,383505390,-18,240 ,-28,381 ,2822358 ,85395576 ,271558818 ,-27,-23] +,[-19,28 ,-469185838,-19,-13,-18,-400698330,3222 ,-16,-4929 ,18,91372248 ,2 ,11,-187642560,-6 ,341231013 ,6,-52226208 ,-8,-11,9 ,-2070,-19 ,-5,-30,-3243,26 ,16,-2,2415],[-50015700,0,-17 ,155858040] +,[-9,15,-13 ,-11,-20 ,-1026069,49677500 ,-10,-31 ,28 ,282 ,-16,68319600,87606750 ,1 ,1440 ,-1495,5668,-2751 ,15,-18 ,1222 ,8 ,-5 ,90166544,0,-10142028 ,-7 ,440 ,1584,14,-2,-20775555 ,-3006 ,-1482 ,30,-575,1881 ,-7,-14 ,98685600,-119642454 ,-28 ,-475],[-9254520,-6,-3874,-25784148,3 ,9563333 ,-10 ,0 ,-204,1820,6,6,20,68460840,23] +,[855,-28,-30 ,-3050 ,0 ,-13,-241685700,18,3,-1332 ,29,1218,-4,-10,0 ,-7 ,1539,26,1408,-383212980,8,-308 ,-27753460 ,26,-27 ,4,13 ,-6,448],[-25 ,-5512 ,16,-1476 ,57928040 ,17,0 ,-79250600,0,0,2070 ,132,-3] +,[-18875208 ,21 ,5,-20 ,-3791 ,-420521696,-159620890 ,0 ,25 ,-520,390,-13,0,-7,-21,-2740 ,222721065,-7 ,14,20605200,22 ,-528 ,6162,-24 ,-15 ,-75492480 ,4 ,-31,-45394076,2,-1893006 ,4876,0 ,13,8 ,-22 ,-19,-1998 ,-15 ,-340569765 ,-2366,7 ,-20 ,5 ,31 ,-28 ,126499034,-19 ,-60 ,-32478138 ,-225989520],[-9,0,4,-25 ,-156836169,-10 ,-1767 ,9,-285,6 ,414126090 ,-5 ,-31 ,-274760800 ,-3107 ,223992440 ,-472164 ,-2 ,27,21,-10 ,15 ,-3990 ,78704900 ,-26 ,10 ,-20 ,-28 ,-14,-198,-31 ,-98652036 ,1755 ,-540 ,5 ,-2160 ,16 ,-12 ,15,-2291 ,9],[-1832 ,-8,84187740 ,-14 ,-5 ,-120285891 ,-20,-7,2,31 ,-298507587,24 ,-232,-3819 ,1323,10 ,-26499690,24,17787984 ,-8,-18 ,31,1597200 ,-143174560 ,-14 ,-241886880 ,35245440 ,-267,-27] +,[-2466,-207 ,20 ,4,0,-781650],[349123302 ,23509416 ,0,-390 ,-15 ,-4669 ,15,-229139820 ,24 ,2734600 ,-369889632,-27 ,13 ,-2976 ,74053024,-21,1595 ,47597088,109658106 ,-4482],[-160,-167686096 ,22 ,-28,14 ,153050850,-4437477,-29 ,13040080 ,0 ,-24,5 ,-20 ,-5 ,-27 ,7234282 ,-136507500,-226432206,-23,26,23 ,102778200 ,110791850,-100582944 ,-320,24,-1444320,1000 ,-151045500,399231104 ,9,157752882 ,-8415792 ,-64122480 ,-90313540 ,3091086,-279422178,2,-16 ,21 ,-2508,-213551325,2618,418 ,10,-230 ,-1878177,11,-2430,-481,204 ,5109786,23 ,24 ,-3294,-28741614 ,2464,-3640,23,-16 ,-5,-22 ,-1078 ,-4 ,13,-23,28,-9,336,19,7000] +,[-11 ,-25315696 ,-12604800,-15,-1001,17,10,-363142050 ,4525,12 ,-19 ,10 ,-28,9202536,-1566] +,[-43 ,-26,2625,-11438544,-16 ,-9 ,-2 ,100693521 ,1610 ,11,25 ,-256 ,-1482,912 ,164894751 ,-33788502 ,403253400,25 ,-21 ,-4744935 ,-127576944 ,23 ,-4131,-78999904,4613220 ,-27,-13 ,-13151200 ,-1422,-171716020 ,-1568,24 ,58102209 ,11 ,658,-415633170 ,-7,-2356 ,21,-582 ,70774200,-21,31 ,4,-31979352 ,-4548096,-244212150,-1020 ,11 ,9,10,26,-47214488 ,12728430,18 ,-472 ,21,-261326200,7 ,13 ,-21841800,-2 ,-1760,-18,26,-14,-1479 ,17 ,-252,14,-1547 ,-7080 ,-610 ,1440 ,-11 ,-8,1162 ,2,444 ,-9 ,-11664768 ,7,-25],[-21,-4704,-8090760,-1120 ,-918 ,-14 ,-19,-1,-216703800 ,-38544465,241352825,8,23,-20 ,6860,-225700551,13 ,-8 ,-29,-4818 ,-28,0,-196477380,25 ,490,-9 ,-2324 ,-19,-14,15394860,-177302268 ,2898 ,-4712,-7,-9,52019610 ,-23,306619950,4290 ,8 ,-128779488 ,78907616 ,-525872 ,5 ,-5 ,-74542000,-62628027 ,88551372 ,-1380 ,11,4640 ,-2250 ,-19,-9 ,0 ,23,18,-3885,168724920,4351590,-1260 ,-12,420,-29 ,-22 ,-29 ,9,248965024,18,-17,1800 ,243230400],[91450944,11,-37892448 ,-16,-24 ,-6420078] +,[960 ,3636,-2420 ,22 ,-93510384 ,-2859268,-46,-9 ,-1462 ,26 ,3374,4576 ,4080,11,18,27 ,19,-9,31 ,-8,-4290 ,-25,-196948080 ,6,23,151484929,1096056,-14 ,-20 ,-31 ,-10968300,-31,-141860280,3,29510932],[85858080,-8172516 ,-228,-748,6797288,30 ,2782 ,11663100,7047,17 ,13,-5 ,64967040 ,2 ,0,-1148,-21 ,5510 ,-6902,17325340 ,-26 ,-17 ,19 ,612,-16,13 ,-5 ,-28,63914940,-19 ,65924946,-20 ,4752 ,165804585 ,-45499806,11,25,22 ,22,-5615360,-972 ,-20,9,15 ,14 ,220680060 ,225367472 ,10,-22 ,171089808 ,-2 ,320132016,15,73532394],[-1044,-2185,-868,-616,-22,-19 ,28 ,4340 ,10,196,-9,-7,-354207560 ,28 ,-17 ,206957751,-14,-15062975 ,-51126933 ,21 ,2769,27,13,-1720 ,15 ,2004,19,-30,407,-134438400 ,13,-22,4086 ,6,28,-354774168 ,9,-166076504 ,2761,-48274056,-30,29,-51074496,1400,-26,34724875,17 ,-37853475,-75919416,30 ,-4 ,27619460 ,-207029758,177 ,2450 ,-8,-5162 ,-18 ,10885950 ,5 ,15282150,28 ,12,3146 ,0 ,-1156,29,-1 ,93399270,1593 ,-29 ,-490957530 ,7562016 ,-5971968,29,-840 ,0,-3,-24,-8203140,0,28,28 ,-20,-226 ,3654 ,-4200 ,-5 ,29,13597402 ,-72082703,-522 ,16,-10,1534 ,-6534 ,663,-10,-8,28,-184009292 ,-2097,200,31,-24 ,-22,19,24,-1 ,-182626080 ,44505240,-7,-1005,-66734640 ,-9 ,-637 ,-22,-798 ,-8505720 ,550,-143996250,-26,-197450560,8 ,116590914,2 ,-23 ,6,520 ,-18,24 ,288 ,2,-768,-4880 ,18 ,-7,165058740] +,[-18,-3216 ,-27,-714 ,9,-19 ,-3570 ,-16403040,-3360 ,-18,-7,-22 ,-2607,0,43015104 ,6 ,-5177,-28 ,759 ,17,1632 ,7,26,16 ,-15] +,[9 ,-770,16] +,[14 ,-76802600 ,-10],[-306478600,-1710,-2727,4,-5,-22,-21 ,-9,-4,105518966 ,20 ,-373281156,-493,298019834 ,17 ,-12,89861940 ,7 ,-250 ,25],[191874420 ,-200059740],[24 ,4,13 ,2613 ,-30,-19,194345814,16 ,-833952204 ,8 ,-29 ,15,256007760 ,35547675,32,-10 ,43 ,-5656,-690148554 ,65829582 ,-2508 ,18 ,12,464348 ,30607650,13,-1980,342 ,-68174736 ,-8,0,31 ,18 ,5000 ,5 ,-1400,-14 ,-14,-189 ,-29,-57931608,-9 ,28,-26,-9,-705 ,645 ,-126071120,-2,14 ,13 ,23 ,15 ,214511196 ,1111 ,128686833 ,188047710,-30 ,-5,-4400,17,184589130,-13,-22 ,-4 ,-11,10,-5037,615 ,-6,-192917526 ,-29,31,-16,-8 ,-2 ,-15,14 ,5320,26 ,-2680 ,-3600 ,16,-18 ,-767,14 ,-1450,27,22 ,21,65265984 ,250850640,9458667,675,140487864,-2503250 ,1 ,3825612 ,-55,-25 ,-5434,138,-2057,-35635242 ,187077423 ,-5 ,-4 ,-3,-3155790 ,51266457 ,-26 ,-10,-2250 ,-150 ,4232529,-11,3023100 ,6713232,-525311820,1284 ,127895460 ,-10 ,-16,-11,1904 ,-4600,464 ,-137640000,29957585,0,3864,31,-5 ,73524162 ,-436241430 ,498 ,14,14,2472],[690,-6 ,-935,2,-13 ,-15,5 ,3 ,1 ,6820,57075504,4 ,9,-3 ,28 ,-1804,-265268700,-82153568,6571845 ,302999697,-2040,21,4968,7 ,-81925380,6,-22 ,21 ,21,-23,-2112 ,1260 ,12 ,-16 ,-7,-8,27 ,-21,-13 ,12 ,-17,10,3 ,8,-956 ,-3 ,25,-736],[1200,-22,9,18 ,-4 ,141571100 ,-4 ,58397008 ,28,-247 ,-40075020 ,39376480 ,-144 ,150178644 ,-78 ,12 ,25 ,3,-6 ,-11 ,111016224,30,280375290,-3180 ,-19 ,0 ,27555472,-1410,0,-1832 ,-3645 ,-19 ,-6,-190202040,-118995912,-1320,-6858240 ,32038080 ,21,-120582756 ,2373 ,21010400,-3582240 ,-22,-3760 ,-772124610,-18] +,[-18,767 ,2400,29,1659 ,-15 ,10 ,-36246200 ,-88597350 ,30,75091968 ,20 ,481027750 ,-28,2 ,84657536,31,-19,2957420,-7] +,[1,-6318 ,5060,-21,-2,5818020,-1407,-298014145 ,-10 ,-1896,24,-37943948,9 ,-410006080 ,-6250 ,30,20,0 ,19 ,-1992 ,0 ,6 ,2097,4158],[-224 ,25 ,270 ,-14,17 ,-47839446 ,24,108,20 ,11 ,17,2265750] +,[26 ,4025 ,-28,-1508562 ,0,5217885,23,-2044 ,646,-1692 ,-202700960,-4263 ,0 ,-6 ,-29592168,-25 ,26 ,28,-24,0,3,9 ,-11,19,-69 ,2 ,-65002665,-696,-732,14 ,-372,19,98810226 ,-528 ,0 ,-23752197,246,-495],[-27,2312 ,-222884805 ,-247466752,-26,310518 ,4290,8 ,-3 ,-216 ,21 ,-8,-975 ,-330,28,6,-12 ,25,1836,-1976 ,78132276,-575 ,-31779376 ,-12,27 ,-13 ,2169,1048344 ,-6873 ,6075,-10,450,-260,0 ,620 ,-8,13 ,-2323 ,-15,15459048,-605025036,-13 ,18,-258,-1 ,-21,0,2,23 ,3629 ,23,40981200 ,182,1025,-1820 ,-2940 ,-2 ,7,8145306 ,-14 ,8,-23,0,76 ,27 ,496 ,3475,1,-18 ,-20 ,-25838934,7,-67056800 ,-24,10,-5,1743 ,-181152840,76,16971600,73738350,15284740 ,576 ,-1032,152366400,1 ,26 ,-20480750,-1088 ,-12,-28,-1,-3604 ,11728545 ,61127300,-1853544 ,-22 ,1674 ,-15 ,6 ,20 ,-18,-22,7 ,300 ,-15,19,23,-7,-6021,25 ,25 ,1148,-28 ,5,-12 ,-222,4738 ,230 ,728 ,-246118400 ,-2385,-52297372 ,279311760,22 ,21,28,-2175 ,-2277,29,220913640,1190,3,-112490868 ,26,-2,7,-703107900,20 ,-180754332 ,27 ,-496 ,-399614644,21 ,-72087444,7] +,[-1000 ,1456,-936 ,-620 ,17,-17,-19,-2000 ,-107890664,796 ,16,-4,3706 ,482694444,22 ,-3323024,-24587808,-78 ,-15,-13 ,8512152] +,[26,20 ,330 ,-18 ,5,0 ,-3344874 ,20,-3700 ,12 ,-26,-19 ,137969040 ,171721620 ,139926156 ,-391 ,-7,3040 ,33897045,-10,9,-7440 ,262410792 ,58699020,-7 ,8,23 ,49188750 ,-15 ,-4320,-16 ,110819214 ,21 ,1 ,-62384322,9 ,-37542816] +,[4920,-4,241638000 ,-5,19 ,148203520,54835950],[-429 ,18,96881304,159 ,-60,-142733792 ,225,22 ,-6 ,-10,-4860 ,-1458,-25 ,-8,-14,-4966,923220 ,-17 ,-4,-17,1302332 ,-1,10 ,141441904 ,-1 ,-263918088 ,79677108 ,10 ,3672 ,22 ,-287415408 ,-15 ,-30 ,10] +,[-121831736 ,-270272835 ,-14,-16,0 ,-20 ,56684684,22,20],[-5304 ,9 ,-9 ,0 ,31 ,-10 ,1972,516960],[128063705 ,-2376,-30 ,84,19 ,-28,14,-22 ,33859800,24 ,-1482 ,-6982040 ,4972,-4025,8,-29 ,3 ,-5 ,-1104,-16 ,154219032 ,1431,18010380 ,-75647390 ,-19,-15,8019330,17,6,0 ,0 ,204 ,0 ,230608560,-48102208 ,1846 ,1207 ,-3480 ,-726,0 ,-34,-23,-26,-77,-3 ,-5236 ,-12 ,21 ,-27 ,216 ,-3099132,20 ,197917344 ,29,3,2765488 ,-30 ,5175,4600,9537456,-30 ,235486440,8 ,22 ,-20 ,-366429492,-6,-1,16,-1320,27250320 ,7 ,-22,1188 ,-904,-19,1,1936,-4 ,16,-1040,-30 ,-13 ,-26 ,-23 ,18624200,0,122109912 ,676,-13,-29 ,-12 ,4,-7,-312495020,-1 ,-5,-291400188 ,-237 ,20 ,-1 ,801 ,0 ,21,-27,-100055760],[-754 ,-3759,-1872,20149200 ,-19 ,-333898774 ,1964622,389795392 ,3,6,-15] +,[-11,17,-28234800,-17,-7 ,1 ,-696,-9,50115450,2675,-820,50181831 ,30,290580252,-20 ,82086016 ,-1691 ,-1624,-27 ,31 ,16 ,20,0,77085744,2060,40104252 ,68739710,-16,17,10 ,-7 ,-7 ,4680,384,666950986,-3468,232051456 ,3096 ,1 ,-4636 ,0,17507880 ,26 ,-9,-1782,6 ,26 ,426350025,51521570,1,185235876 ,-20,-196,0],[-684,2928,-4,258009720 ,31 ,5 ,-11,14825993,-18,10 ,12,165790656 ,0 ,-4095 ,-3 ,25,594 ,29 ,-6 ,8,6 ,-41387580 ,1624,-13,10 ,45512502,17 ,-24862800 ,30 ,-31,62 ,-495590324,-16 ,896,-27,-17,-25 ,10 ,38988230 ,0 ,8,-3296 ,1134,2 ,-1820] +,[5824 ,-7 ,-30,14 ,4740,3472 ,-14,-98061432 ,-4 ,27 ,29,-3,440228096],[-25,19,-21 ,2299 ,153 ,26 ,29 ,13 ,6599340 ,-163537380,-121627818 ,61821396,-286 ,5,10,31 ,-26,-11,-1378,7380 ,176,-18,-23 ,-26 ,1 ,3564 ,-25 ,-5304 ,-69270080,-8,277200198 ,0,840 ,-53417870,3,-197239962 ,10 ,-4375,3322 ,18,-232895520 ,454,6 ,0,-4444 ,78445314 ,23 ,46085598 ,-3043 ,39814840 ,364 ,-5520 ,-988,-24,178861608,2 ,-2784,-16,42 ,-63349418 ,0 ,281105264 ,177128352 ,-2196 ,-6,0,31 ,-9,457299434 ,-1336 ,4030,-4617984,19] +,[21,0,9,-51830660,1113,-11 ,424,4,26011206 ,19,-645557472,-27],[0 ,-2178,-16 ,-18,-29 ,19 ,83738512],[-16,67544358 ,14,678,-192,20,-24 ,-2,-18 ,-31 ,0,6 ,-2 ,-14724620 ,-155,-12 ,0,-10202465 ,288,-117831762,-26 ,-22,-74400960 ,-5 ,17 ,6975 ,-31,-7080 ,3304 ,-552,-30,-9,-31,3762,19,-25,-13 ,12,49602204 ,-2353,3,14 ,456,3317 ,6500375 ,14,221 ,-67557312 ,0,315,-39121680,-360690975,0,27 ,-367937388 ,1,651,-2 ,738999072,42158550,-1736,-1344,207392400,-429781520 ,0 ,-20,-20882568,-1 ,-95903925 ,-20,-28 ,25 ,0,-28 ,-320,-681,12 ,4158 ,23] +,[658 ,285241400],[8 ,18 ,4 ,-2,-22,-10 ,2 ,17,126704320],[-2580 ,93500496 ,-1757 ,-1243 ,-12 ,2415,2755 ,-2484,-264,-276864750,-10 ,-530881659 ,-18,-24 ,106164,-20 ,-322662120 ,4050 ,201308800 ,-280,2784 ,-2600,-5,-104715648 ,-98829024 ,7560,2266,-22,-1899,-2222,1185 ,-62367840 ,4554,-186 ,-30,-5,3332 ,-15 ,2 ,-5775 ,-280296720,78190800 ,-42366411 ,27,-4994 ,0,6757,-21,-204 ,269712,8092032,-6,-22 ,-5250 ,-2268 ,25974300,10 ,-17 ,43636144 ,11 ,4 ,-3,0 ,29 ,-23 ,5400 ,-134779350 ,-26] +,[14352884 ,-2240 ,29,16 ,-11,-6750,-24 ,2416,888 ,-12,7,8 ,0,21,-563338656 ,-1209,2070,1332 ,-1170 ,-17,-22],[3276 ,30 ,-127666560,-4800 ,-202344716,132157954 ,-4,-7,19],[2 ,21,186965558 ,7,19,4284 ,24 ,-900 ,2511 ,5974,42 ,23,-30 ,-18],[2 ,5,-31,-303251130 ,0,-25,-25 ,-25,-26,17 ,-1,23752872,4121936 ,3306,-2,20] +,[-18,281226296,-5,-3 ,-3864,7,22 ,26,-885,-1116,-7,-5,16,-168862375,-1992,1340 ,-26 ,9850968 ,8 ,8 ,-792 ,-16 ,-19,74410740 ,16,4340,104603520 ,363661740 ,-449766930,259084260] +,[-21 ,744 ,14,-19391424 ,-169683696 ,-4,488 ,408 ,-28,18 ,-26,3 ,-2,16 ,0 ,-159 ,-9 ,26 ,6,0,955 ,1 ,-30,-26 ,5,-9141792 ,-18,3277 ,0,162 ,-27,108 ,4,286101720 ,6,-13700512,-12 ,23 ,180980904 ,24 ,16,-54714330,-67] +,[-28,28 ,150725750 ,-29865472 ,0,-5967,-29,-30 ,-29 ,30 ,-13483596 ,-31 ,2232 ,-297765504 ,0,133803360,89671480,37441440 ,31,26586819 ,0,-31 ,-108426303 ,-14,17,-29 ,30,29 ,-27,128555925 ,0,-300,-4740,9,279863425 ,-23 ,1008 ,27 ,-3 ,-344890128 ,1104 ,-212144988,177,-94197054,16,3268 ,-27,-644,26 ,-26,0 ,-4,-2522 ,-7179732 ,20 ,8,-28,-14,27],[-432 ,-882,-45861200,-72167040 ,23,0 ,14,-20,-576,4212 ,2,2128 ,-23,29,363781594 ,18] +,[-34584870,28 ,5292,3472,2115,1008 ,11 ,-28,-8 ,632382660,9,-17 ,-5,-6 ,6,20424642,-2,1680,-2520,7378 ,-22 ,16 ,-62916966,580 ,3234,16 ,-21],[-755,323,816 ,1554,493,-14 ,-24 ,371897055 ,0 ,-37316496 ,253,-231621460 ,-3668,0 ,21,-249917448 ,13 ,5,27 ,291345080,-12,5 ,7,-11,-2567 ,1] +,[25 ,-13081596,1976,-16505280,26 ,540,3648 ,-36 ,-11 ,-21 ,-21 ,1311 ,-22,-27,28 ,3570,-29,-5564,-11 ,187917912 ,-20599200 ,180669600 ,14,-2378464 ,9 ,-3451 ,107576784 ,-2982,-4263 ,-3840 ,-10 ,-22 ,-21,3360 ,-8,20,1 ,321002000,-2986230,-5460,0 ,-14624712 ,-27,1470 ,8 ,-1296,43547088 ,12],[22 ,0,8 ,682216416 ,6683427,1165236 ,621 ,36251910 ,3,23,-20080,96265400,-441,6 ,56 ,28,-3 ,-5010,-10,9,-44157900 ,18,-19 ,-12,16 ,296978220,1624,-6269090,-2016 ,11,-84898440 ,3466736 ,-11,12 ,9 ,-16 ,26,19 ,-6,4163,183 ,-4150,20 ,-2100 ,0 ,-41321475,315163002 ,-11 ,14 ,274,29 ,-48153960,-3 ,8 ,-2480688 ,560 ,-16148352 ,19 ,25 ,-940 ,-23 ,6247080 ,-14,38234730,29,28 ,-22 ,12 ,-29,-82837872,5 ,0 ,-31 ,-930 ,1160 ,-30,0 ,-16598552 ,21 ,24 ,-3,732 ,150270633,7,16,2460 ,27 ,-10 ,1],[364 ,10646720 ,19,18 ,-7 ,-9 ,1886 ,54012744 ,-25 ,-648] +,[-4848,105137084 ,-17 ,-968 ,18,29 ,37429140,-4 ,21,3205944 ,-3151,-7140 ,19,12 ,-26,1120] +,[30540600,70865760,12376452,9,840 ,16,47 ,0 ,-32,233639599 ,30676840,18,2,8 ,-24,126877608 ,33937512,-1040,-10,13 ,80094600,-5361752 ,31 ,-39981480 ,193889825 ,-159621840,-2 ,-447124608 ,12,482140890 ,1820 ,10,-16 ,26,-1333,-15,18],[-14,-175184856 ,-3340 ,-6 ,-30 ,-4440,-27,12],[-249129270 ,-154,15 ,1819630,3 ,2790 ,696,-174689382 ,-468 ,-22,1206240 ,247589664 ,-300728241,1215 ,-215824056,-12,219168078,28,51214330,2001 ,2231,-858,-20 ,-160,125 ,-18 ,76761384 ,-260895600,36849960,-4 ,23,-2304 ,-19336005 ,-31,6448,0 ,23 ,-6412 ,8,-345,211077432,-10472544 ,-8295363,-1891,29,1666],[192,16 ,0,-2,22 ,11 ,28 ,2,155052660,20,-825,-1 ,2156 ,-3895,-8 ,7,0,1118,-4,1707156 ,10 ,1930,-3,429189192,82452916,10999170,23,15 ,4776992 ,15,-10,-22 ,-16 ,118519000 ,-8,200889920,-12,-30,258081600,-13 ,-11,-193641640 ,317541642,-37506392],[14,-56311728 ,620,19 ,-143,192928176 ,18 ,30 ,-23,-244385700,0 ,27 ,1008,51622164,-29,1674,-256288320,7530,-1243,33802340 ,-6235696 ,1350,-11,-25,26470917 ,102630600 ,9 ,20 ,25,-13,30 ,15,-285 ,18 ,-26 ,3,132369514 ,1534 ,0,25 ,-22 ,912,1 ,-16,-5,-3,-31 ,263797326 ,-1710 ,-31,6 ,9] +,[-12,-161891136 ,-2128,18,1896 ,-6540 ,-546 ,-11 ,8 ,-26 ,1144 ,-9 ,6,31 ,-17,1 ,-30 ,20 ,8,-1,26,7816743,4813460,-8 ,-11,-16,-93755376,-54259260 ,29,-1730,846,-1,13 ,8 ,28 ,20 ,-306 ,-16,46559712,3213 ,81554814 ,-306653225,-27 ,0] +,[21 ,748,-12 ,-2646 ,51161376 ,21,-1 ,31 ,2002 ,-16 ,-118435740,504,22,-199612100 ,26,-1 ,-24,0,-6 ,-19,-8 ,-7 ,15,-5040,78616656,6 ,-9 ,-13 ,-420,-5250 ,-1207844 ,-1776 ,608,25 ,16],[-4,25 ,-107680828 ,-29,27,1,27,229039500 ,244 ,-24 ,-121572594 ,3838,28,-2074,20,-1020,25,-113460480,-4843,441 ,-24 ,6 ,223411176,-16,28,-413236096 ,-1008,1235 ,22712522,-29,-6264 ,-5448 ,-11,125216520 ,16,-11,14,10 ,-14 ,26 ,-1 ,-14,-4851 ,-11392164 ,860861640,85664000 ,750,-10 ,23,14,-43703305,1,-20,46257876 ,70451160 ,3751,-25 ,26,-4,-15,-65788675 ,-23 ,-2366 ,101 ,-4312,-4,78,14662017 ,-123547200,8,38822000,12,-7 ,-6015960 ,21,-4 ,-18,4140 ,5 ,26,14 ,156],[-11 ,10 ,-9792952 ,309246000,15348879 ,22,-77455500 ,-16,-6,-3768,-27,2628 ,5310760,-24,19],[-23417100 ,-4810,1596,-3,-18,-4483608 ,31,22 ,232048896 ,-8,-522 ,-83204800 ,6,0,-28 ,-25 ,0,-17,-26 ,24 ,5832 ,775 ,-29,-22 ,-28245430,-642107340 ,-28,-4 ,-96976 ,-28,5119200 ,-868,0 ,-3712,-31 ,9 ,-1695,-28 ,-22,104251200,11,-4 ,4194,2200],[-31 ,3762160,-2150192 ,3] +,[13,-378599776 ,-3,28010880 ,-21,4914,17,-13,-79473440 ,21,-1230 ,47020160 ,-453189984,3,-148 ,-123831678 ,546],[-371135100 ,8372889,316,-631468344,3108 ,-417384 ,-14,-21 ,306020819,125593416 ,-22,1 ,-27 ,296886601,4114,-3069036 ,15 ,16,138924370 ,28723968,12 ,158455740,152947904,-175142880,-15,-7,-8 ,-124218400,-44,2263,1464 ,-1408 ,133],[-21 ,7,-480590704,-9 ,-10,-11 ,-17 ,23] +,[100,1978,1212 ,-2060 ,-2024 ,-7311360 ,-88742400,-26388675],[-21 ,-3927,-7050 ,-13 ,-22,26,-722,19 ,27 ,11992133 ,-142742880,-200,31 ,-15 ,30 ,-27 ,31,3135 ,1368,21,990,-28,-1 ,15 ,-19 ,-21,2520,-2772,26,24,-1392 ,-14,589 ,24] +,[-5 ,32579412 ,11,8 ,6330 ,-6 ,-29,15 ,-3,-6604,27780000 ,-616,-1560 ,76281832 ,-17 ,-227077189 ,-80869104 ,26 ,30,-25 ,6 ,-4700 ,6 ,-233760800,7,21,7,22,-8,130 ,-6],[-146038551],[-4 ,29 ,19,-16 ,392] +,[-11908910,-3360,4693 ,-358783620 ,189165600],[-1,7778260] +,[14,1276 ,-28,1,13,3637396 ,0],[2080,-24 ,0,-28,-18 ,-17 ,24 ,-25,-4082176 ,-2553],[-131076000 ,-106576722 ,-438412338,89666976,-9 ,3,494,210],[-29,4,-29 ,0,-5 ,279778976,29,-20,15 ,-15 ,-25 ,29 ,-160801452 ,2960,49204688,-25761600,-19,-3240],[-1 ,292097640,-42680000],[584623296 ,-315,-3,-23,-218604312,-8,12,-1 ,-96339342 ,-119214953 ,-8 ,-27 ,438,-2,-27,378609840,25 ,-6 ,-1782704 ,-210,-19402560,-1485,-13,46639700,-5,39413436,27,2320,-13,4,0,418527125,-7,9,432,-22708800 ,-31408566,22 ,-27 ,725 ,0,-771840 ,-76219260 ,-10,0,320,-29 ,-134847396 ,-1737,-990] +,[-68274360 ,11,31 ,26,16 ,-31 ,15] +,[-44 ,9,11 ,-31 ,-1007,2662 ,-6,-915,-47719282,-8 ,-189849640 ,-6] +,[5 ,115,15,13434336,-3630,-17 ,23,-10230920 ,29 ,15 ,-3188160 ,-10 ,-563035,208060500 ,2,7 ,34829406 ,25,-19,4368],[-1,-9,9,-8,11889360,-80403400,768,19 ,-6,-426 ,4,-12 ,1760 ,5 ,174540096 ,-29 ,182229996 ,-4 ,-810 ,144827550 ,-711 ,166752684,-72065136] +,[-56632128 ,-33811456 ,3,300452784,2100,8,107846011 ,-1072,-168715950,19,-6 ,-4,7,-9 ,-200] +,[23 ,-1712 ,1953,15,25,-770 ,10677072,12 ,-872,13856370 ,-23,3348 ,-1416 ,7555275 ,-300,516 ,0 ,-16 ,320279400,-194961816,-62935056,87744564,-23232762,-4800,24,51,10885410,-5 ,1276 ,1201537,-133508370,31257207,-4 ,-1,-25],[-18,-180,-5452,-16,2 ,-31,22121856,-21,796 ,17,23 ,9,11 ,-271697400 ,2 ,-595563936,-30 ,-31 ,11,-30 ,24 ,3 ,1280,0 ,-5,1 ,0 ,24 ,317252754 ,19,20 ,-31 ,66193556 ,26,-138606710,9 ,-20 ,1 ,9,-4620,119660541 ,27,-22,-8 ,-2002,-3328],[5544 ,7,-894360 ,-30,-20890200,-60 ,-1136 ,-30 ,-8,0 ,10,25,29,-462933630,-3 ,258663600,7192 ,2436,2852,-14,-1962,-16,22,-15893350 ,31,-8 ,-4,22 ,5642,-12,23,27 ,14 ,-22 ,-24 ,9 ,-252,-772 ,330792,25,-4,-20 ,1,-15,-26,17,-176508670 ,-442183770,436153830,12 ,-119336008 ,-1040 ,-17,-58023200,-11 ,29,4,-2989884 ,21,13 ,-2320 ,1287,18,-31,-25,10,36 ,-1904,-10,25,432,-309,-5180 ,-3,-22 ,-23 ,153542610,-337345560 ,48 ,2,4290 ,23231160 ,280 ,-26 ,-359915946,-27 ,44693250,-34777665 ,-26] +,[-26,-5,21,-17 ,-1482 ,0 ,-182,2496 ,-306247392,-23 ,27 ,-24,4239 ,-16885330,-1190 ,-170,-3 ,-336,-20,-51975495 ,1628,680,285,0,-186,17 ,29 ,2 ,-19,-7112,-17 ,-23,-2730 ,10 ,223976760],[7,-100 ,24304116 ,-13,405 ,2676833 ,-6,18 ,-57 ,3709696 ,4224,-1272,-19292350,25,3 ,1391,110010672 ,-26,-13933440 ,2608,5232,-11,239263605,289543680 ,3,-13 ,10929490,23,-117672444 ,29,3895 ,-24,432 ,25 ,1 ,665,1824 ,-1,-14,20,-12 ,-4660],[-22 ,121694470 ,-417245400,-462296289 ,-10 ,525,10 ,28,-17],[13,-1696 ,21098088,29 ,2 ,-9,-23,-60718500 ,8],[0 ,288,280,-4,-27 ,363 ,21 ,105918180 ,-353030184 ,-2697 ,1720,-1558 ,4584,21 ,-29151960 ,10546970,0,-22,-1107 ,-19,-16 ,4080,-29 ,2080,30,-4712,-2706 ,1755,-8,2604,23 ,-231267315,23,-3656730,469 ,-15,-22 ,-2,15 ,-16,0 ,68439900 ,-11,-3894 ,4,-1969 ,-28,-387,-59127615,9 ,-10092648 ,-1650 ,-5101428 ,-884,-10 ,-11,-249119640,-25490388 ,165545400 ,-4686 ,0 ,-3287,6,-10 ,-24,18 ,23 ,502 ,6102 ,63704800,-20,-1140,0 ,-5,20 ,3008,-232007516,31,29 ,-16,11,-67118184 ,18 ,-86891332],[-4 ,-12,-7 ,-2068,-29,-25 ,-4 ,14 ,-5832480,-2460 ,-4600,2436,-25 ,8 ,-1470 ,-8,31714144,-6 ,-10 ,-14 ,1411704 ,-86837240 ,-123160128 ,98052864 ,-6,5850 ,232241465 ,8,770,3759552,-8,11 ,-27] +,[-10,27,154 ,5],[4579887 ,-2180 ,12478656,1,408,198,22575240,-24 ,-129542490,4,68517952 ,-20,0 ,20,0,0 ,29,88689835 ,-3674160 ,22,-11 ,24197355 ,-2,25,2500 ,16,-570250800 ,25 ,276450 ,-15590340,-24,11,-24 ,-27,13,21,-23 ,1580,29] +,[1,5,12 ,1,24 ,96938415 ,-28257024,1416,22,2664,-786,-20,-2470,540 ,-341089920 ,-7,-96634944,-380,-136,1036,-306784800,5,-551,-2142 ,11,4,133521388,8 ,-1 ,0,-38862486,22492050,14 ,-174 ,28],[-104,-6 ,-103014072,-28 ,-129708390,-15,-24 ,30,61863480,18 ,-22 ,3,-20,-269748000 ,23,-48 ,4 ,0,-3990 ,18 ,25,-13 ,-5430,40328560 ,-116910196 ,5335248,21 ,-23 ,-28 ,10427400 ,-20,-11 ,-920 ,127181556,3306 ,9 ,28,5 ,6390,10 ,-25 ,-18307120 ,7110 ,21 ,959 ,-9 ,870,330 ,-24,-25,4553 ,-26 ,580 ,-19 ,2057 ,-9930060 ,5 ,648 ,-16 ,-24201384 ,6348372 ,456 ,-27 ,-24 ,252 ,-172016768,11 ,1848 ,16,-148,11,-37695528 ,-8930493,133546392,-27,26637105 ,-194238328 ,76857984 ,21 ,-3268,-10 ,-995 ,63369960 ,-118274640,-237 ,2658736 ,-29,-14 ,774,-22 ,2 ,3360 ,-45749880 ,8 ,-351,-19 ,10066176,78 ,-567666,3] +,[0 ,-15,31581725,-21,-162 ,-6 ,-19,25 ,4752 ,1036 ,-12830706 ,-56050155,12,-20,9930720,3,17,185,10,-26,-24,-2054 ,32 ,868,-21,-144 ,-18 ,4,-7 ,21 ,2178 ,-13,11,-10,63120660,-19 ,27,-67648284,-11,358398710,-1215 ,-18,-17540874 ,0,11122056 ,-31 ,1356,2,-631275390,-1208,-56909820 ,-25 ,-6902 ,0 ,11 ,21,5160,2925 ,86348700 ,16,-13,-2068,160],[-114403520],[-17,-8,-1,1,19,-4 ,17,629 ,6 ,21],[107505 ,30 ,1143 ,-16 ,107521925,17 ,2056865,21 ,-8,-164464020 ,-26,1235 ,124,13 ,7,525 ,164577088,8814750 ,-330,-358918620,0,-10 ,0 ,-13,44604000 ,26 ,6240 ,-580 ,18 ,-8 ,-1,13 ,2 ,8 ,4480 ,-594 ,-2 ,366988496,261365400,-12148840 ,-6,2133,16,-20 ,62797170,9 ,142012416 ,0,0,-99483750,1638 ,407660,-5271 ,-9,-32844070,-1586,380912 ,-6240,0 ,-1,-156,-3570,19,-1052058,5,3402,1 ,-10,-200662000,1134,7 ,-1044 ,-3 ,-2034617,4752,-418803800,-20331540 ,10,20,8,-25 ,6 ,-31147920,-10 ,7,-276 ,-246369546 ,2760500,1278,-129486420 ,-52544376,14,22 ,25,142845612,-5964,-29,2988 ,3 ,-2 ,-13 ,4478292],[-2 ,15 ,2916,9616640 ,1 ,-1 ,7006,14 ,20,-24 ,94645080,14 ,-12,-1746 ,-2 ,729 ,-16 ,28 ,9,-76946100,-23,222,-1,-25,-3952 ,12 ,-23,6634971 ,28 ,-15,2 ,-2002,206892480,13],[234,-9266880 ,16 ,230099760,5 ,-24 ,29,-749,-2016 ,-30,75001550,-22 ,10,-1372,7 ,-30,-5355,80090960,8687744,3015000 ,528636500,1717,-8,27590080,15 ,80354690,13,29 ,-27 ,0 ,-3 ,-20,-4,1360 ,-339,-984,-108 ,-738 ,-25 ,-15 ,-25 ,30 ,-184463818,-29,13,19 ,17,622485,8 ,13 ,1782,-59128380 ,264 ,2354 ,8,-270 ,-24,-22,542651850 ,30,-3893 ,-31,-1582],[61475148 ,-29,-10,73475392,21 ,-5,-19 ,72859176,-19 ,1860,-1938 ,-2266,-7999120 ,2590,-15 ,17 ,-29,-11,26 ,-39142656,-23,-1088 ,211671250,-1476 ,2574,-2,107330598 ,100,-13 ,-5824,-1704,-15 ,104610240 ,-122478312,2610,-69891856,-29 ,-590 ,-31,184370340,-2295 ,-16,-290051892 ,4416,-165,18 ,-25,0,61 ,26,-426 ,24,19 ,-28,-23,-5600,22,-17,27,15 ,-30 ,2728 ,-451237644,1158,3744,-28 ,4 ,-54126300,-2088,-249247320],[3125,109506306 ,-2171 ,252148120 ,3612,-30761289 ,6] +,[-183865344,12564384 ,78006654,-1,-73759500,-4 ,1 ,-3 ,4796,755263440,24,-2782500,0 ,1760 ,11,-18,-100824768 ,-2178 ,5,15,-401903775] +,[25,-67880218 ,15916392,248 ,-21 ,-18 ,47289580 ,2 ,-393,26253220 ,8,-3,3648480 ,-12,3 ,-1645,-1 ,14,-24,-4 ,-6386092,-7,-7,1426,344742660 ,4,-31502308,1 ,233981415 ,-31,1271,3 ,-4843 ,258,30572880 ,-588 ,7,4 ,-1300 ,-16,37690224,-8,-10,-77904560,-46327890,-267658749 ,1755,-28 ,22] +,[-3150,27,-34116768,-28 ,-220700214 ,28,-13,-22001200,-1 ,114385200,-77729287 ,5 ,-112913352,-12 ,-2814 ,13 ,336 ,1508,2525,-3 ,26,-9 ,13 ,102 ,-5,2442 ,-20] +,[-31490389 ,2332,-16,-25,281865194 ,9 ,-525428316 ,16 ,1864 ,31 ,-360,3726,-17 ,-2 ,31,-24,78978412,-45,6904681 ,806,1194,-5,1596,19880994,-10 ,-1404 ,-19 ,-160260000,74105550 ,-5,-19,10,24,84669750 ,2028 ,117 ,17,91,180 ,1032 ,30,31,-103370526 ,9,-17,29,-400],[18458836 ,23,-33608520,27573780 ,26,-1 ,-13,-1,-14 ,10914408 ,5,21 ,-31801050,-10 ,-195458562,15] +,[-22555360 ,-18 ,-19,-14 ,-31 ,-10 ,-30,-8 ,-30,-1 ,2574 ,-2964 ,-52901376 ,714,-29,21,43825680,0 ,2355,180713484,-43846110 ,1476 ,-9820836 ,30,-4020744 ,226 ,-274785467,-1166 ,19 ,26,-7792200,84489780 ,136082232,-1780 ,-7,-3834,0 ,16,25,4 ,-1,-21,-351 ,-237 ,-2415,-15,31 ,121200912,1,8,-1000 ,464 ,-10,36132420,-25 ,20 ,0 ,-16,-3692073 ,-28 ,23,-1661,-265052000 ,22 ,-127416242,80937510 ,14,-8 ,30 ,-17,3 ,-6 ,15 ,44269680 ,-5,0,2180,-596,45075480 ,-25,6426,127243530 ,18 ,-97343840 ,0,81741750 ,-10 ,23 ,9 ,0 ,-19],[-31,-27 ,16 ,10,29119716,18,-6 ,-11 ,-16 ,224 ,-23 ,12,-70525224 ,-11 ,-1339170,447526800 ,2431] +,[-416,7 ,-5 ,-200 ,8],[-62686000 ,5,-277134528 ,80798130] +,[550579680 ,642,18605210,261205680,4 ,1020,-13 ,-5589,-94285620 ,10,-1500 ,4316,27 ,-31,197130080 ,19 ,388911600 ,26 ,371 ,-1692 ,-4,8 ,-32175735 ,-27,-23,-3 ,45093600 ,-53440940 ,23],[-13,3523325,-6757,2 ,-234,31 ,-10 ,406291041,0 ,-247490400,4832724,-29,1830 ,0,-14 ,-25 ,-22 ,-28,-7,-5750,-275,1645434,8 ,78 ,-9,1] +,[52166970,648 ,11043648,10,21 ,6356,-32761440,19,31827128,-67161600,-286226100 ,1550 ,5099040,-26 ,-2737150,6,1955 ,-81798444 ,19,10494236,-3806880 ,29 ,23,71823094 ,-57815775,640 ,1710,4 ,-18,1410,-10347194 ,-9,9 ,-25,8,-6786 ,-2025 ,0 ,-690 ,-4,-23,4094 ,-27 ,1782 ,-28,2,-1812 ,-4,-106072720,-280 ,11 ,-7000999 ,19 ,237097476,1488,1680,-8,-197581760 ,-608994380 ,0,-7192 ,-17,-12021490,-11666336 ,-615 ,34102449,-29 ,24,-3620,6972 ,374,1904,2453724,8 ,25544708 ,1185,-792 ,24 ,-5304 ,0,17 ,17 ,2240,3798,1 ,-65810070 ,6 ,0 ,98785728 ,1275,14,-9261039 ,31 ,-69351072,1716 ,-130,1584,-6,315091260 ,30,132495360 ,-592,6334524 ,437 ,4 ,5 ,-224447795 ,22 ,-5187 ,-297 ,15,118386525,-22,-4420 ,201794779,0 ,-10 ,-424003620,-200,29235816,720,23,-25,-43167924 ,-19,-28 ,-140136750,3546 ,-167652980 ,-9865824 ,5490,9029200,15783840,-45699804 ,-10,2299 ,2441824 ,-97463080,16 ,223411157 ,0 ,2616 ,14 ,7 ,6030,-27 ,8929800,28,282225888 ,-8 ,15 ,50442000 ,-89755560,-41671840 ,-3,1454355 ,65735040 ,-16,3145 ,-27657806,-4046 ,-3304 ,0,-3,638 ,-15 ,-23 ,-93936528 ,28 ,8342624 ,0,-18 ,18449991 ,-2 ,29 ,18,23,43187116,-137887344,-91230075 ,-5 ,-1 ,-22 ,8 ,-3 ,-4360,1212,-28,-4 ,-317239230 ,-7,-8 ,-22,-2,-14 ,864,-2106,30 ,4 ,-25 ,-4,8 ,1776 ,-12 ,-29,1976 ,-30,15 ,-1998 ,0,-7 ,19 ,-324 ,21 ,-16,17,-552 ,-11 ,87441120 ,190079820,28 ,8,2100 ,9105761,30,0,552006 ,20,-24,-9 ,24 ,-9,20,20 ,-5 ,-21489258 ,-77577588 ,24 ,3648 ,0,-17,575,9689940 ,296318898 ,0 ,-9,21 ,95805990 ,-24,194],[2600,-87658256,12 ,26 ,202433688 ,0 ,42008019 ,17,14016990,11 ,-19 ,10,-1998,233624475,7 ,-21,-5,5,0 ,-23,-25 ,768,-26,-28 ,2,11,17 ,206264718 ,24,10,-25 ,12,3,-1890],[784,-18972450,378,24 ,3732300 ,-22,-388855080,8547360,-17,918 ,-188306382 ,0,262719360,26 ,0 ,-30 ,-1 ,-21,7,-7 ,9 ,-1292,-5 ,-12,774 ,235,-505102500,-16 ,68312720 ,2 ,-3111330,-11,184196320,-24,10643496 ,-158814600 ,399420,-10 ,66965096,4218 ,-24 ,3069 ,-1,-34681218 ,2,10,14778575,5 ,88806256,20,-22,-5 ,-369158400,-216702390 ,115453800,-144169130 ,248360112 ,28 ,1248 ,4140 ,-1416,-2366,22,-16 ,26,-18 ,2660 ,3410240,-525780 ,21,-4137,11 ,-1269 ,162583420 ,-5 ,-5,-264,-1651 ,1080,19 ,-527 ,-3 ,-30,14905358 ,-6969312 ,5880 ,-125650764 ,-23,-15,-7320,275 ,-19 ,6664 ,4469820 ,-684 ,-14,-112 ,-26 ,21,-25 ,25 ,16 ,17,9 ,24 ,-1340,156507414,-20,-27 ,13 ,-23,19,7 ,31 ,-16 ,-8],[-27,-26,6 ,-205706592,-14,-8,-5,66539648 ,14,-27 ,-25,-270284220 ,-10,12 ,-18 ,5,2 ,1582920 ,12 ,-2 ,-2233,31 ,-27 ,12,28246995,199408716,1161,-172476690 ,-1358,-28,29828512,7,894255600 ,16 ,700 ,-58525560,-104478561 ,-1,40231296,96779232 ,-12712410 ,26,-1090 ,8 ,23,2896,1066 ,-13,-10,1717 ,12 ,18 ,-4824 ,-34899600,7063200 ,2940 ,16 ,16 ,-29,252 ,-26],[-276,165123000 ,-18 ,-1518 ,-19,-228,-898560 ,-730 ,3,14 ,61063872 ,-14 ,-10154136 ,10 ,95290560 ,24 ,0 ,-2034,18 ,-30,4,19 ,46,-15,-9] +,[247864617 ,-170847600 ,-1053,-5688820,-273,-3264,1030 ,6,-26,242 ,-175262080 ,18 ,0 ,-2736 ,-25 ,-125586756,252,484,-23471289 ,-9019248 ,420 ,-15 ,1390,-5478 ,1030 ,-12 ,-6804 ,-19 ,-21,3364596,-2223,31,-24 ,3054420,12,290197650 ,-28 ,10,14],[482631552,-8 ,0 ,-864,6] +,[0,-2825,79493700,-1,1428 ,28 ,-22,23 ,18130560 ,-5,-26 ,-29881920,-21,16 ,14 ,-25,-3 ,-4818 ,-21,29,13 ,-376202232],[0,5,1582 ,30 ,-513603288,500780610 ,-31 ,-2043 ,59908080 ,23,-26,5112 ,163550070,-4 ,9 ,-416,265067640],[-508232308,20 ,17649920,18],[-33706920 ,-410,-104837820 ,30 ,-11,-82122184 ,238154462 ,-13,21,-15,-2970,-18 ,50004416,16128720 ,-1566 ,-25,-864,966,-3615],[890 ,330 ,161472 ,25898264,-672,25,-61383672,777 ,3 ,-77549160 ,-8 ,-23 ,315424018 ,-26633816,-478,-29,-285,4 ,-1224,-24,-22,-8,10,-783,-19 ,50882544 ,140 ,-63167580 ,-17,-15 ,2,8,4,-19,-24843240 ,227863950,-32059560,24574613,0,3990,-30,14,-22 ,24,24,6 ,16 ,-23 ,-17013360,-23,-2120 ,318,1064 ,3210,-12 ,148974896 ,-5784,-199563085 ,2,-352836441,-596892972 ,1035,5,28,736,131632644,-2387952,-13 ,2241 ,21,22,-23,-23667680 ,15 ,0,2 ,16,2640,1638] +,[3,0 ,26 ,5075 ,-14 ,19 ,-9 ,-220] +,[-19 ,-25,0 ,-11 ,-77435160] +,[1881 ,31,-260,8 ,14145120,18,-25713639 ,-19,448594925,-799 ,-21,-479287776 ,-4488,15 ,-6,-41394046,14,-294 ,20,-5 ,4368,26,27 ,-20 ,6,174531830],[-9118396 ,1375380 ,-396 ,28,-15 ,-1035,-548 ,-6,0,-28,1600 ,18,-4,-88277202 ,-738888 ,-5730 ,6200,13,-3556 ,-20 ,349046550 ,-414,2,-460539673 ,-3079692 ,-1188,25 ,-11 ,-8 ,5699220,-294068016 ,5,-27,-12 ,-15 ,14 ,12,6,1261 ,-15,-19,17 ,23 ,17 ,-188201160,9 ,-27,-4332,-20 ,18,37806470 ,-10 ,-26,-22 ,213 ,15,15 ,67378152 ,965 ,-30 ,-22851752,273948318 ,24 ,-53793180 ,27],[88882332 ,-3281 ,-29,0,0 ,-310317120 ,-20 ,-22 ,-30,-51519678,-498718945 ,28,-47449890 ,0,637080 ,31 ,28,30,-2670,-5,-16],[-11 ,390,2052,955,-6510,20 ,29,236758756,-4785] +,[0,855 ,-8,2,-16 ,-148512480 ,0,-218147265 ,-846 ,360,49703358,-6 ,42482220,-148656024,1,-7395,-57403500 ,121806720,-302,58447350 ,132507960,-13 ,-8 ,0,14,-21 ,-29,-564 ,21,12 ,22222468 ,11 ,4 ,15,14,186244380 ,15,-292719648,13,-16,-4 ,-88672880,21,-1026000 ,-28,-15,13 ,11,-1952 ,-4048,-17 ,-24 ,-30,4237,-16204599,-9,-550,27 ,-737],[10684960 ,26 ,792,-240,-18 ,2697 ,1] +,[6 ,397786312,4784514 ,-651,24,17,47879916 ,6708240,12 ,-29 ,3910,-1 ,-29 ,31 ,-822 ,-26,26,-2832,4248,1584 ,-7 ,8,17411600,-69101400,-19,-1887 ,5301,-4692,4 ,-29,1071,28,-14,-1521,-16,-20 ,-30,-6214 ,19,-24 ,3,18 ,-8,9 ,-31,15 ,-15 ,11 ,-301826616,0,-406817840,-19130085,17,-12 ,44821361,-19,475230720,-5 ,383364300,-5177,-70224000,4475,-1280 ,9 ,4 ,135666140 ,3,0 ,0 ,27 ,408882600,-17 ,-3924,-2,-25 ,8 ,5,-163214304 ,4401,-25,4 ,-690 ,-654,26,-18 ,-1242,24,18,23,249253200 ,-12 ,-12,-1440 ,29,5220,-30,-2744,6,-680 ,-9612720 ,31 ,19 ,6,-704,18258464 ,-17 ,-58287934,-108005760,416,-136 ,104311152 ,-29 ,27199040 ,-19 ,-16 ,-1926 ,-762 ,-1 ,7 ,-247 ,27,14 ,19 ,4,5300491,2,8,-170226360,28 ,110001672 ,-2227,8,-1,29],[-3,354451916 ,-6,-7 ,19 ,30,-213990016 ,-24,-23,-265031493,4,-13 ,-31820162 ,14 ,15 ,-15 ,-9535008 ,-44408736,24735900,108756570,-211,0,-99 ,-26,-24,-13 ,29,20 ,-3454,20 ,1917,514410468 ,2939976,19,23 ,-735 ,15,-19 ,1575,-25 ,-7,165655378,29 ,149618040,-10575552,0,3,7,-19 ,26 ,-28 ,-20,30,326,-29 ,-19,-9 ,161726616 ,-65771160,15,901 ,-580,-78258250,-123865308,-8 ,3948 ,-11,-8,-5236,-2,-978466 ,3 ,7409 ,-8,108,16 ,27,37092160] +,[4 ,6014 ,-186050976 ,-2028,5146 ,-1 ,-1884 ,-3192,-1701 ,-3 ,-6,-252,117453985,-27 ,27 ,3618,2140,2684 ,-6 ,-215197819,23 ,-25,6240,18,29,0 ,-12,-11 ,2717,-25,-28,-247 ,31 ,-55813464,-30],[-4725,702 ,30,-2840 ,166213351 ,-7 ,20 ,-1 ,-4,76,-3555,1096,4,8713200 ,57769740 ,30 ,23,-4 ,-7] +,[-3225 ,163819938,54614868 ,-238713552 ,13 ,24,15],[26,339442116 ,-4 ,76 ,74868480 ,4075,-189026383,10 ,1364 ,2240 ,-28,-450,-23,-27,-754650,50992500,19 ,18,-696240,-198698880 ,31 ,-1890,1,20 ,-136,-26,22 ,-29,13,27 ,-28 ,0 ,-14 ,3,0,6318 ,17,24,-28,0 ,2400 ,-430856400 ,-5066358 ,3],[-25,-7047],[-4032 ,549 ,-17 ,27716992 ,13473120,-2289,837 ,31 ,8 ,-594901944],[-15] +,[124317720 ,-580 ,-25 ,22 ,-15805970,27 ,-11 ,-21 ,-3486 ,13] +,[29 ,-13] +,[3,-18,-52787664 ,1135,-88 ,4991,-28,-3552 ,14487795,34021080 ,-2100,-44106216 ,-6 ,-216,1260,2070 ,-1854 ,-22 ,-1341 ,-1587,18617000,26356500,10485447 ,-24,-4394,27 ,3510 ,-30 ,-31952851 ,-18 ,-2,31,150 ,22 ,-74 ,3,-3300 ,-1552,3900,-376,67120704 ,2301312,1,-23 ,11 ,-29,-1,91577213 ,5520,0],[-2004300 ,0,-12 ,326332638 ,-13831818,-20 ,127072652,-3,13 ,1,2760 ,-15 ,-1712],[-26,-171753 ,-84823600,22,-486402147,25 ,472013580,10 ,-3,22 ,-4252932 ,-717336837 ,28,-18,17,-27,2300,-447120 ,4131,3956 ,8,4554,-391,-22 ,70797909 ,14,76 ,1,-149289400,7130,-5,-2626 ,-3451,-21,432646099 ,1958 ,24,1,31,-3080,255461696 ,18],[212402960] +,[9,4,-28,117984240,3840 ,9 ,-31,15 ,29 ,19254312 ,-24,-211963500 ,-23,-14 ,9,-25],[1650,53155872 ,-139994008 ,23,1 ,0,-364,-20,-139320610 ,12,-11372608 ,-417810,10 ,-21,210,1464,15 ,-18,15 ,4 ,-7766550,-22,11 ,193392 ,-6,-8 ,28,-27695160,-12127130,-49655340,-31,9,-158584218,310676544,6,27 ,2632,3,26,-9,-16,-17 ,0 ,1 ,-252 ,-2958,6,0,-25],[4060,-3375,-3420 ,-96327525,-339165000],[-7,-3 ,-4 ,-31],[-27 ,-15 ,3360,6846420,-15 ,0,-12 ,6,125034325 ,16184718,247873920,-26 ,232,-28 ,1440,21,131702571,24,-21,-17,-289912392 ,0 ,0,28 ,-1540,57003606,-4150 ,1 ,-31 ,20,3780,-26 ,-7122204,-3675,324 ,-40084786 ,14790238,124614704 ,-16],[452182830 ,14,-3 ,5,11 ,23,-2325 ,-2 ,-25,0,16,24 ,20,-4847040,165754314 ,18,-8,12,163,20 ,346752945,3000,-420877976,-23 ,-12,6,-26,-56,64488080] +,[3105,12,29 ,14] +,[1308 ,-3 ,4050,-379124550,-2522 ,-23,21 ,-1705,-873 ,-14649999,-23 ,-144682720,-15,-1880 ,-20 ,127601280 ,-21 ,0,-1564,42905984,23 ,-3276,0,-7,-3474 ,-3660,-9 ,-4 ,-30,1800 ,2 ,1,376920320 ,3129041 ,-18 ,-5 ,-4290 ,-9 ,31 ,529439814],[26 ,108 ,-10,-22,196,-585,3,-18,149848818,-14250240],[25 ,-692 ,-3906,310294040,-48471654,-1 ,-6,17,4180,-1964100 ,26,-3,-11,20,-93937473 ,-25 ,2,17,-25 ,23 ,770 ,-23,-545 ,2,9 ,-3289 ,682,0,1 ,30,30 ,-73012992,3420 ,26144076 ,-19,172 ,131136789 ,7 ,-1260,-825,-8,0 ,16 ,91103232,-6552 ,340468920 ,-18 ,-48828224,6],[-1748 ,-855324,72494298 ,-23,40292720,15,-21,26 ,-3 ,2548 ,26 ,-410032392,420 ,-29 ,28 ,39394296,19,1414,6,9 ,-19,-22 ,9738162,-29 ,8 ,18,31 ,30 ,341181708 ,-576,-2 ,-20,-2982 ,4220,3192] +,[-26,-26,4,-10,151967340 ,-21,1136 ,-66 ,-58540725,1533 ,-3500,1620,-1,-19,28 ,187124080,-5,20,-1595,0,-67055100,0,-3,10 ,-9553986,24 ,-5365 ,-55411776,49227948 ,23,24,-1872,-3225 ,20 ,-2176,18,285631890 ,4,-19,-25,-68592656 ,-5145,-3952 ,-9133306] +,[1648792,-78699390 ,-6,133358454,0,127693746 ,0 ,-25,0 ,3075016,0,-9353421 ,5,-29,-527 ,13 ,-2230 ,0 ,167554576,3514,-30 ,-240 ,3400,2757144,270 ,-316680624,90067200 ,9596710,-27,3542,-110760842,26 ,21,-475673022 ,21 ,-9 ,12,24494960,-64224696,-24 ,2520 ,357371190 ,30,-29,2,212 ,19,-1190 ,21,-10 ,-2 ,-21 ,0,-24 ,-3024,82,1,0,-112,0,-11 ,-31,66832470,29,434 ,180692370,27,-20 ,24185850 ,171745368,99865560 ,-115525840,0 ,1 ,1 ,2600,765,-91387464,-6,-132197454 ,27,-74,-110544098,26 ,-29,77874804,413550005,59963760,3540,-2530,2016 ,28 ,-10,30 ,20,1 ,3,41713444,-1323 ,69840120,-2,-2] +,[-28,-295589376,72707292 ,480719808,-26 ,5324 ,-4110 ,-26,552,-11 ,-350,10 ,-15,5,-29 ,12837930 ,-92 ,10,-24,-24,-13,-167246664 ,0,-18,-168,-26 ,-16 ,3450,16,-20,6,-5508 ,-2352 ,-18,-1467 ,-1140,14 ,87365750 ,-376479714 ,29651328,24,-405905214 ,122925600 ,31,-4599,-3,-1,0] +,[-882,24164973 ,-3267855 ,-1725003,134832900,7,-310859076 ,8249904,2662 ,-215,13 ,1152,1475,-30 ,29,689 ,0 ,-10 ,3795 ,-3,2 ,423658390,0,-22 ,-11 ,19,-24,17 ,3 ,369312762,-69569280 ,-840 ,2,-476,-72469323,-12 ,-30 ,990,29,-4,29 ,2124 ,20,495,97402905 ,395335603,-238844448,-4543236 ,-12 ,2070 ,15] +,[14 ,-14613750,12 ,-798,-11 ,-17,29 ,3777900,13 ,17 ,2716,-1056 ,4628 ,560,320466510 ,117868863,117,8879452,984 ,-16,6384 ,28 ,-7,16941600,142599852 ,-1480,-259653240 ,22 ,-5,-1020,252603360 ,29,-30 ,-22 ,0,-144503190 ,12,-9 ,-21 ,-1375 ,1645497] +,[108529824 ,7 ,-1025,656,54092640 ,12 ,-4,-1656 ,-16 ,-14 ,-27 ,-15,-31,-8,26 ,-642 ,4061,-2628780 ,-2700,-31079664,-512047055 ,-81148844 ,810 ,-3770,8 ,7285 ,-14,14 ,-18803343,2 ,16,9,-23 ,-6,68748328,-2 ,-28,-54555174,-14,-17,-12,-74 ,-2 ,20 ,340565760 ,201],[10 ,-22 ,-28 ,10,8 ,178270752,-1150,22 ,-11 ,-1398,-17 ,-2460 ,1824 ,946 ,-860 ,-7590 ,-7 ,89781000 ,-35513280 ,3 ,122710896,-4 ,-4738480,29,520,-1,-175348688 ,120341760 ,-658 ,-548523008,-67381144 ,21925683 ,47773236 ,17,-20 ,10 ,-14,-4480 ,-426,18,21 ,562102272 ,4515,93873432,-17,27 ,-3696,-552 ,-3,-3,11 ,37931400,-190565725,-19,-40226760 ,-5486],[13 ,-1700,6060],[23,740 ,40700166,11,5,29,25675104 ,5,40,15 ,-4,-28,2494,45760780 ,-3 ,10 ,-10,1,27 ,2432 ,-5 ,-81546630,20133540 ,80406560 ,-197247330,-5,-23 ,-19,1,-2 ,-43977400,-4508,28,20,8,-20,-192435880 ,-400440600 ,2912 ,-1,-491425440,-28 ,4129947 ,-12,-21 ,-16,550,19,6006 ,252 ,20,6,85660084,-491183592,2 ,-2,23769864 ,-4108 ,-636398400 ,26,166937568 ,23,115806600,-13,2704 ,-31 ,3,16 ,5 ,22 ,-104017914,242994720 ,-1716,-2436,-980,2604 ,21 ,-8 ,17,16,18 ,0,21,20879480,19410795 ,5,327006360,4925,-18 ,-5456,-18,-24,-20 ,-260234854,3,0 ,360,262992450 ,218608560,-15 ,1,-238,-1085 ,3 ,17,-2064 ,-236634801,2926 ,-298517184 ,20 ,-170],[1113 ,-27057888 ,30,4579 ,-157899384 ,-143 ,714 ,10,-9,-25 ,-5 ,-2772 ,12 ,4,-18576844 ,31,1256 ,-952,28,-256 ,-1 ,47411580 ,208 ,-13 ,2420,14 ,2352 ,2 ,1032 ,-6018528 ,-1026 ,6 ,-16 ,-3 ,-10 ,-544 ,-5] +,[-18 ,20,13 ,-22,89742450,0,30,-150,-184609320 ,-7] +,[29150100 ,-23,-12,-390,7071840,16 ,-451,-7,-21,60403152,4,-210 ,25,18,22 ,7350 ,-1,-462 ,3200 ,-69149484 ,-26 ,2460 ,6,-21] +,[-8 ,3185,27724476,-317469746 ,26,-27 ,7 ,4,-119802298,24 ,4960 ,6,12,-21 ,4300 ,26,-21,305324080,-402020772,2775 ,-97617277 ,9 ,-18 ,5,163144692 ,2261 ,-1068,-14] +,[-10,-23157660 ,3816 ,-25 ,240,16 ,-98315856,0 ,25,-20,-26779599,-3300,10,-375500903,31,-21,13,1872,16464000 ,28 ,-1,-6479] +,[-2520 ,2904,-419896120 ,-109098696,-1305 ,30 ,-7 ,0,-30 ,-21 ,-3 ,-26,512502767,5130 ,-181762372 ,-2780 ,19,2754,6125 ,-2856,4425,-410911788 ,3 ,31 ,12 ,29 ,4920 ,-1 ,390 ,2 ,24 ,-3382,-406 ,44786736 ,-4,24 ,-5944752 ,538383240,29,9 ,-13 ,-1454733,17 ,-71000976 ,-11 ,-3572 ,104,-12,31,-1691] +,[-20,21,0 ,-26175540,-34011120 ,29,15,15 ,182,-29 ,31 ,-7,5,-3465 ,13 ,-27 ,-29836992 ,21,5070,-150933276,-27 ,24 ,44983350 ,-2350,2673,12 ,-31 ,2250,-26 ,-14145000,18,21531312,26,-1920,2500 ,594 ,-1,-249 ,-164792628 ,-2 ,-8,-34453152 ,3 ,-7] +,[-3 ,150,-336311040 ,-24 ,-2205 ,4320,21 ,-14,31 ,25,-57851136,-17 ,22 ,-3],[-262251990 ,0,61747920 ,453302244,-11464704 ,-75850740,23 ,-5,-234145670,-3 ,30 ,20287017 ,-22,95308902 ,6458760,18,-84530592,18,-13,6,-13 ,78954057,56107000 ,-6900,428,18 ,-86625000 ,7466536,2552 ,-8290926,-25 ,18382600,0 ,529287696,25,2060 ,88141584,13,-1102 ,-448153160,2322,0 ,21 ,-141618375,-1870,-80788266,784,-86107032 ,-22 ,-21 ,6692,-191252880 ,-85158627 ,0,5,-4389,1860,-22 ,-20,3] +,[-592120320,30 ,1755,-36301475,0,29,14 ,17 ,17,-3,21,-184075398 ,73385447,1800687,-3,-8 ,121628913 ,7 ,1750 ,-24,3960,2964,42995232 ,29 ,-11,300597765 ,31012256 ,-16,2892 ,42054600],[26 ,-3,0 ,-22,160,0,3258840,-21,185895336,-3502 ,7 ,3661290,108 ,108804555,18,-45506340,-24 ,-13 ,0,-142857702 ,-21 ,-165349616,22 ,11,8 ,22 ,-30,-6 ,-5 ,920,-1612,52286475,30] +,[-8847696,-780 ,-1 ,0,20 ,177799509 ,3744 ,10427157 ,-4680 ,-76 ,-2180,18,-3912040,-15,5,8239374,-5736,2,-13 ,-10,2001046 ,74422845 ,-18 ,-3630 ,-47685000 ,2659392 ,9,23655300 ,-3,-4488 ,-12,-11,23 ,7 ,12 ,0 ,16,-2 ,-3211,-29 ,11,0 ,-250354260 ,-238 ,0,1468929 ,527,96271860 ,39963022 ,3979,4,-5,-504 ,25 ,-16,250180144 ,35091043 ,-3136 ,14,13 ,-13,-10 ,400 ,-25,-1197 ,-171 ,-23,-1570,13,18 ,-21,8,2 ,-103646970 ,27 ,87702784,264212940,13886378,25,-6348000 ,20 ,-2272 ,1586 ,-21 ,10,15 ,-47871792,1200,-456 ,320024208] +,[20 ,-166190700 ,21 ,22 ,4524,-3 ,-31],[-16,-41307420 ,-2,475202700 ,-32406000,-1792,2587296 ,207,386347000,-6 ,-13,19 ,190896096 ,0,-8,-745,-22 ,23,1212],[17,-222362560,-154951069 ,-14221792,512,-2175 ,-1001,-576,-2142 ,-3 ,-89438310 ,102616480 ,157615470,-135337986,30,644 ,6 ,-490 ,4,28,-8,10 ,255841536 ,-27,-4636440 ,-9 ,17,-80631590,238569786,-23,-9,-890,4340,-17 ,29,0 ,278,12 ,-19 ,-65165405,-782 ,-238 ,23 ,-3528,-5],[675,-1768,936,31,-381251226 ,-16 ,3654,-9 ,23 ,287601600,-2060 ,394880,-138511500,-11947936,4509,-4,3007 ,-4,70425290,27 ,-180433620,8366358 ,-31 ,-26,0 ,-990,27,2982,49597800] +,[-92456250,2436840,-31,0,2727,22971240 ,-20,0,-164,23,-5,-8199200 ,7,6,23 ,700,16,28,29,10,492,13,3760 ,-19,-1272 ,-13 ,12484104 ,861 ,1512,31],[397646982 ,25 ,9],[-4675 ,814 ,-26,3712,3 ,-15 ,-24 ,-21 ,28 ,7006,309446592 ,-5797 ,27 ,24,28 ,-5304 ,0,26 ,-25 ,21,-454475,22],[-102 ,1264 ,-18,1751250,-5 ,-25 ,7,23 ,924,-209630750,5 ,-366171330,-536085480,26,0 ,-41575040,22,-31,480 ,-2 ,-25,24 ,-17 ,21],[-12644544,-24 ,-115822005,-1,190042560,12841620 ,-10 ,6,3 ,-1502585,-18 ,-446003910,-162 ,-24865000,24,54932150,4620 ,-27,-23,-31,14,-4 ,859902568 ,23374728 ,-28415772 ,-110584800,7 ,-130756194 ,16 ,-123969780 ,30,11,84423534 ,9,27 ,-172224936 ,17 ,19 ,-2385 ,219956880,-1188],[93485448 ,13875840,-14885955,10,17 ,-12] +,[-4554 ,824 ,795 ,-2912 ,-20,23,26,-19 ,-7,15 ,53701380,5040,-9186690] +,[-3648,4712,-76 ,46871748 ,-1673 ,1,31796184 ,13 ,3872 ,13,955 ,-8541592,22,-33611602,60138180,13,-29 ,-2178 ,-459545520 ,2962120,-95500248 ,-5,-3,-31,2419380 ,2784,254594300,-8 ,30929760,-1337 ,17,9 ,0 ,0 ,961632],[-466569840,-26 ,209556900,6726645 ,-26 ,108112290 ,1666 ,-4625,-26,-1275372,8,-1125 ,26,4650,-46597815 ,-23 ,-2,140803677 ,26,-1233 ,-10,-824 ,-108590820 ,-6630,-594306076,21] +,[1 ,546,66110198,25 ,-608784363 ,12 ,21 ,-28 ,-7,25,15 ,0,-3,1344,-30 ,1496 ,5 ,-25,1 ,-3280,-5857024 ,28,-18,-30,84110832,1988,-3016 ,30,20 ,30,23437184,1330 ,35,-4 ,-12 ,-3968,234853830,505614060,640711384 ,21 ,-2184,-2,2231 ,-9,-5,-25,-920 ,1,3196,17,-22 ,-11,924 ,20,-2 ,-9 ,18 ,79583400],[-17,16388816 ,2 ,-135 ,60 ,708 ,-28 ,-14,-20,10,10080720 ,22,-21,35932650,18 ,5905380,-13 ,-10 ,32995080,31 ,-13,-25] +,[-364,35,12,255,-22559328 ,31,30 ,11503096,100566000,-1070,2340,7,-45786972,103558620,-340,16 ,302377519 ,21 ,28 ,-486,4,0,6 ,-2] +,[-17507952 ,4,-13],[18,-7,-4935,19 ,-12,-31 ,586269320 ,94248756 ,-14,-2,-9 ,1056 ,-17,-2240 ,-536,54269556 ,-373637544 ,19 ,-22 ,-185907696,77205960 ,-252,306,9,19,5,17,1188 ,-558 ,3381,23 ,118742400,6840 ,-2 ,-3420 ,458163720],[5684 ,26 ,-12 ,16,-11,-4698,164163285,40922910 ,447213690,7 ,2859885 ,98382200 ,67216810,17 ,-15,3696,5334,-12 ,-20 ,15,-5040,30,16020018,-4 ,-10321419 ,10,0 ,-16 ,6,21,-34251300 ,-13,20 ,19,99,510 ,242672724,-13] +,[-544293984,-30 ,-390 ,3726 ,-200 ,-18,3234,24,8,19,17040240,0,3,-139063320 ,-117010410,336,20 ,-1004,22609314 ,6 ,-1584,13,-35266560 ,-112822227,581416408 ,-17,-9 ,3,-5549,93279312 ,36349040 ,19,28311360,27],[11 ,-21 ,1340 ,108 ,546,3 ,113782548,-28 ,2 ,-25 ,90818400 ,12809988,462,178335625,-17 ,-812880636,88 ,-7] +,[-17 ,378 ,180155136,17 ,-21 ,-13 ,-13,23 ,31,-30,-10 ,-261623362 ,-1652 ,-12,-15277200 ,46070712,-20,-349139520,-9022862 ,17,532,3,119279250] +,[7 ,3247 ,-17,11 ,-21,810,-16 ,-2079 ,-22 ,-6 ,-25 ,6] +,[21 ,-16,-280,-352,319,21 ,-29] +,[0,6,-29378921 ,-1 ,-33256665 ,-7,197411994 ,-18 ,-24,-300 ,-28 ,27,1998,208728000,3 ,1392 ,-195,-31540992 ,25,84068600 ,-19856964 ,12 ,-27,-31 ,0 ,5308576 ,-4 ,-83394360,28 ,-306533190 ,-11 ,-132402256 ,14,3024,-12,16 ,-280768950,29210368 ,0,58397100 ,31 ,-31 ,-12 ,3 ,4620 ,-28,8,997440,27 ,4 ,2625 ,27,-67382718 ,9,639,103714200 ,-7,945 ,-1404],[-16,382 ,-26 ,1 ,10 ,-6,-17,-7 ,-20,-30,15,-2716,-27,5 ,19572570,-11,5,-2 ,9 ,59773440 ,-36112635 ,-10,144879644 ,16 ,36187200,58673855,2000,-116289420] +,[23]]
diff --git a/1.9.10/samples/test1.jsn b/1.9.10/samples/test1.jsn new file mode 100644 index 0000000..94ad459 --- /dev/null +++ b/1.9.10/samples/test1.jsn
@@ -0,0 +1,9 @@ +{ "test key" : true, +"nullField":null, +"foo":1, +"foo2": { "a" : 3 }, + "a\u00E3b" : -323, + "2" : [ 1, 2, 3], + "\"foo\"" : "foo\nbar" +} +
diff --git a/1.9.10/samples/test2.jsn b/1.9.10/samples/test2.jsn new file mode 100644 index 0000000..2629250 --- /dev/null +++ b/1.9.10/samples/test2.jsn
@@ -0,0 +1 @@ +{"\"abKey\"":3, "foo":false}
diff --git a/1.9.10/sandbox/tests/TestOverloaded.java b/1.9.10/sandbox/tests/TestOverloaded.java new file mode 100644 index 0000000..76aaec3 --- /dev/null +++ b/1.9.10/sandbox/tests/TestOverloaded.java
@@ -0,0 +1,38 @@ +package org.codehaus.jackson.map.deser; + +import org.codehaus.jackson.map.*; + +/** + * Unit tests related to handling of overloaded methods; + * and specifically addressing problem [JACKSON-189]. + * + * @since 1.5 + */ +public class TestOverloaded + extends BaseMapTest +{ + static class OverloadBean + { + String a; + + public OverloadBean() { } + + public void setA(int value) { a = String.valueOf(value); } + public void setA(String value) { a = value; } + } + + /** + * Unit test related to [JACKSON-189] + */ + public void testSimpleOverload() throws Exception + { + OverloadBean bean; + try { + bean = new ObjectMapper().readValue("{ \"a\" : 13 }", OverloadBean.class); + } catch (JsonMappingException e) { + fail("Did not expect an exception, got: "+e.getMessage()); + return; + } + assertEquals("13", bean.a); + } +}
diff --git a/1.9.10/src/VERSION.txt b/1.9.10/src/VERSION.txt new file mode 100644 index 0000000..d78bda9 --- /dev/null +++ b/1.9.10/src/VERSION.txt
@@ -0,0 +1 @@ +@VERSION@
diff --git a/1.9.10/src/java/org/codehaus/jackson/Base64Variant.java b/1.9.10/src/java/org/codehaus/jackson/Base64Variant.java new file mode 100644 index 0000000..308c4ab --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/Base64Variant.java
@@ -0,0 +1,413 @@ +/* Jackson JSON-processor. + * + * Copyright (c) 2007- Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in file LICENSE, included with + * the source code and binary code bundles. + * You may not use this file except in compliance with the License. + * + * 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.codehaus.jackson; + +import java.util.Arrays; + +/** + * Abstract base class used to define specific details of which + * variant of Base64 encoding/decoding is to be used. Although there is + * somewhat standard basic version (so-called "MIME Base64"), other variants + * exists, see <a href="http://en.wikipedia.org/wiki/Base64">Base64 Wikipedia entry</a> for details. + * + * @author Tatu Saloranta + * + * @since 0.9.3 + */ +public final class Base64Variant +{ + /** + * Placeholder used by "no padding" variant, to be used when a character + * value is needed. + */ + final static char PADDING_CHAR_NONE = '\0'; + + /** + * Marker used to denote ascii characters that do not correspond + * to a 6-bit value (in this variant), and is not used as a padding + * character. + */ + public final static int BASE64_VALUE_INVALID = -1; + + /** + * Marker used to denote ascii character (in decoding table) that + * is the padding character using this variant (if any). + */ + public final static int BASE64_VALUE_PADDING = -2; + + /* + /********************************************************** + /* Encoding/decoding tables + /********************************************************** + */ + + /** + * Decoding table used for base 64 decoding. + */ + private final int[] _asciiToBase64 = new int[128]; + + /** + * Encoding table used for base 64 decoding when output is done + * as characters. + */ + private final char[] _base64ToAsciiC = new char[64]; + + /** + * Alternative encoding table used for base 64 decoding when output is done + * as ascii bytes. + */ + private final byte[] _base64ToAsciiB = new byte[64]; + + /* + /********************************************************** + /* Other configuration + /********************************************************** + */ + + /** + * Symbolic name of variant; used for diagnostics/debugging. + */ + final String _name; + + /** + * Whether this variant uses padding or not. + */ + final boolean _usesPadding; + + /** + * Characted used for padding, if any ({@link #PADDING_CHAR_NONE} if not). + */ + final char _paddingChar; + + /** + * Maximum number of encoded base64 characters to output during encoding + * before adding a linefeed, if line length is to be limited + * ({@link java.lang.Integer#MAX_VALUE} if not limited). + *<p> + * Note: for some output modes (when writing attributes) linefeeds may + * need to be avoided, and this value ignored. + */ + final int _maxLineLength; + + /* + /********************************************************** + /* Life-cycle + /********************************************************** + */ + + public Base64Variant(String name, String base64Alphabet, boolean usesPadding, char paddingChar, int maxLineLength) + { + _name = name; + _usesPadding = usesPadding; + _paddingChar = paddingChar; + _maxLineLength = maxLineLength; + + // Ok and then we need to create codec tables. + + // First the main encoding table: + int alphaLen = base64Alphabet.length(); + if (alphaLen != 64) { + throw new IllegalArgumentException("Base64Alphabet length must be exactly 64 (was "+alphaLen+")"); + } + + // And then secondary encoding table and decoding table: + base64Alphabet.getChars(0, alphaLen, _base64ToAsciiC, 0); + Arrays.fill(_asciiToBase64, BASE64_VALUE_INVALID); + for (int i = 0; i < alphaLen; ++i) { + char alpha = _base64ToAsciiC[i]; + _base64ToAsciiB[i] = (byte) alpha; + _asciiToBase64[alpha] = i; + } + + // Plus if we use padding, add that in too + if (usesPadding) { + _asciiToBase64[(int) paddingChar] = BASE64_VALUE_PADDING; + } + } + + /** + * "Copy constructor" that can be used when the base alphabet is identical + * to one used by another variant except for the maximum line length + * (and obviously, name). + */ + public Base64Variant(Base64Variant base, String name, int maxLineLength) + { + this(base, name, base._usesPadding, base._paddingChar, maxLineLength); + } + + /** + * "Copy constructor" that can be used when the base alphabet is identical + * to one used by another variant, but other details (padding, maximum + * line length) differ + */ + public Base64Variant(Base64Variant base, String name, boolean usesPadding, char paddingChar, int maxLineLength) + { + _name = name; + byte[] srcB = base._base64ToAsciiB; + System.arraycopy(srcB, 0, this._base64ToAsciiB, 0, srcB.length); + char[] srcC = base._base64ToAsciiC; + System.arraycopy(srcC, 0, this._base64ToAsciiC, 0, srcC.length); + int[] srcV = base._asciiToBase64; + System.arraycopy(srcV, 0, this._asciiToBase64, 0, srcV.length); + + _usesPadding = usesPadding; + _paddingChar = paddingChar; + _maxLineLength = maxLineLength; + } + + /* + /********************************************************** + /* Public accessors + /********************************************************** + */ + + public String getName() { return _name; } + + public boolean usesPadding() { return _usesPadding; } + public boolean usesPaddingChar(char c) { return c == _paddingChar; } + public boolean usesPaddingChar(int ch) { return ch == (int) _paddingChar; } + public char getPaddingChar() { return _paddingChar; } + public byte getPaddingByte() { return (byte)_paddingChar; } + + public int getMaxLineLength() { return _maxLineLength; } + + /* + /********************************************************** + /* Decoding support + /********************************************************** + */ + + /** + * @return 6-bit decoded value, if valid character; + */ + public int decodeBase64Char(char c) + { + int ch = (int) c; + return (ch <= 127) ? _asciiToBase64[ch] : BASE64_VALUE_INVALID; + } + + public int decodeBase64Char(int ch) + { + return (ch <= 127) ? _asciiToBase64[ch] : BASE64_VALUE_INVALID; + } + + public int decodeBase64Byte(byte b) + { + int ch = (int) b; + return (ch <= 127) ? _asciiToBase64[ch] : BASE64_VALUE_INVALID; + } + + /* + /********************************************************** + /* Encoding support + /********************************************************** + */ + + public char encodeBase64BitsAsChar(int value) + { + /* Let's assume caller has done necessary checks; this + * method must be fast and inlinable + */ + return _base64ToAsciiC[value]; + } + + /** + * Method that encodes given right-aligned (LSB) 24-bit value + * into 4 base64 characters, stored in given result buffer. + */ + public int encodeBase64Chunk(int b24, char[] buffer, int ptr) + { + buffer[ptr++] = _base64ToAsciiC[(b24 >> 18) & 0x3F]; + buffer[ptr++] = _base64ToAsciiC[(b24 >> 12) & 0x3F]; + buffer[ptr++] = _base64ToAsciiC[(b24 >> 6) & 0x3F]; + buffer[ptr++] = _base64ToAsciiC[b24 & 0x3F]; + return ptr; + } + + public void encodeBase64Chunk(StringBuilder sb, int b24) + { + sb.append(_base64ToAsciiC[(b24 >> 18) & 0x3F]); + sb.append(_base64ToAsciiC[(b24 >> 12) & 0x3F]); + sb.append(_base64ToAsciiC[(b24 >> 6) & 0x3F]); + sb.append(_base64ToAsciiC[b24 & 0x3F]); + } + + /** + * Method that outputs partial chunk (which only encodes one + * or two bytes of data). Data given is still aligned same as if + * it as full data; that is, missing data is at the "right end" + * (LSB) of int. + * + * @param outputBytes Number of encoded bytes included (either 1 or 2) + */ + public int encodeBase64Partial(int bits, int outputBytes, char[] buffer, int outPtr) + { + buffer[outPtr++] = _base64ToAsciiC[(bits >> 18) & 0x3F]; + buffer[outPtr++] = _base64ToAsciiC[(bits >> 12) & 0x3F]; + if (_usesPadding) { + buffer[outPtr++] = (outputBytes == 2) ? + _base64ToAsciiC[(bits >> 6) & 0x3F] : _paddingChar; + buffer[outPtr++] = _paddingChar; + } else { + if (outputBytes == 2) { + buffer[outPtr++] = _base64ToAsciiC[(bits >> 6) & 0x3F]; + } + } + return outPtr; + } + + public void encodeBase64Partial(StringBuilder sb, int bits, int outputBytes) + { + sb.append(_base64ToAsciiC[(bits >> 18) & 0x3F]); + sb.append(_base64ToAsciiC[(bits >> 12) & 0x3F]); + if (_usesPadding) { + sb.append((outputBytes == 2) ? + _base64ToAsciiC[(bits >> 6) & 0x3F] : _paddingChar); + sb.append(_paddingChar); + } else { + if (outputBytes == 2) { + sb.append(_base64ToAsciiC[(bits >> 6) & 0x3F]); + } + } + } + + public byte encodeBase64BitsAsByte(int value) + { + // As with above, assuming it is 6-bit value + return _base64ToAsciiB[value]; + } + + /** + * Method that encodes given right-aligned (LSB) 24-bit value + * into 4 base64 bytes (ascii), stored in given result buffer. + */ + public int encodeBase64Chunk(int b24, byte[] buffer, int ptr) + { + buffer[ptr++] = _base64ToAsciiB[(b24 >> 18) & 0x3F]; + buffer[ptr++] = _base64ToAsciiB[(b24 >> 12) & 0x3F]; + buffer[ptr++] = _base64ToAsciiB[(b24 >> 6) & 0x3F]; + buffer[ptr++] = _base64ToAsciiB[b24 & 0x3F]; + return ptr; + } + + /** + * Method that outputs partial chunk (which only encodes one + * or two bytes of data). Data given is still aligned same as if + * it as full data; that is, missing data is at the "right end" + * (LSB) of int. + * + * @param outputBytes Number of encoded bytes included (either 1 or 2) + */ + public int encodeBase64Partial(int bits, int outputBytes, byte[] buffer, int outPtr) + { + buffer[outPtr++] = _base64ToAsciiB[(bits >> 18) & 0x3F]; + buffer[outPtr++] = _base64ToAsciiB[(bits >> 12) & 0x3F]; + if (_usesPadding) { + byte pb = (byte) _paddingChar; + buffer[outPtr++] = (outputBytes == 2) ? + _base64ToAsciiB[(bits >> 6) & 0x3F] : pb; + buffer[outPtr++] = pb; + } else { + if (outputBytes == 2) { + buffer[outPtr++] = _base64ToAsciiB[(bits >> 6) & 0x3F]; + } + } + return outPtr; + } + + /** + * Convenience method for converting given byte array as base64 encoded + * String using this variant's settings. + * Resulting value is "raw", that is, not enclosed in double-quotes. + * + * @param input Byte array to encode + * + * @since 1.6 + */ + public String encode(byte[] input) + { + return encode(input, false); + } + + /** + * Convenience method for converting given byte array as base64 encoded + * String using this variant's settings, optionally enclosed in + * double-quotes. + * + * @param input Byte array to encode + * @param addQuotes Whether to surround resulting value in double quotes + * or not + * + * @since 1.6 + */ + public String encode(byte[] input, boolean addQuotes) + { + int inputEnd = input.length; + StringBuilder sb; + { + // let's approximate... 33% overhead, ~= 3/8 (0.375) + int outputLen = inputEnd + (inputEnd >> 2) + (inputEnd >> 3); + sb = new StringBuilder(outputLen); + } + if (addQuotes) { + sb.append('"'); + } + + int chunksBeforeLF = getMaxLineLength() >> 2; + + // Ok, first we loop through all full triplets of data: + int inputPtr = 0; + int safeInputEnd = inputEnd-3; // to get only full triplets + + while (inputPtr <= safeInputEnd) { + // First, mash 3 bytes into lsb of 32-bit int + int b24 = ((int) input[inputPtr++]) << 8; + b24 |= ((int) input[inputPtr++]) & 0xFF; + b24 = (b24 << 8) | (((int) input[inputPtr++]) & 0xFF); + encodeBase64Chunk(sb, b24); + if (--chunksBeforeLF <= 0) { + // note: must quote in JSON value, so not really useful... + sb.append('\\'); + sb.append('n'); + chunksBeforeLF = getMaxLineLength() >> 2; + } + } + + // And then we may have 1 or 2 leftover bytes to encode + int inputLeft = inputEnd - inputPtr; // 0, 1 or 2 + if (inputLeft > 0) { // yes, but do we have room for output? + int b24 = ((int) input[inputPtr++]) << 16; + if (inputLeft == 2) { + b24 |= (((int) input[inputPtr++]) & 0xFF) << 8; + } + encodeBase64Partial(sb, b24, inputLeft); + } + + if (addQuotes) { + sb.append('"'); + } + return sb.toString(); + } + + /* + /********************************************************** + /* other methods + /********************************************************** + */ + + @Override + public String toString() { return _name; } +} +
diff --git a/1.9.10/src/java/org/codehaus/jackson/Base64Variants.java b/1.9.10/src/java/org/codehaus/jackson/Base64Variants.java new file mode 100644 index 0000000..3c67ba4 --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/Base64Variants.java
@@ -0,0 +1,90 @@ +/* Jackson JSON-processor. + * + * Copyright (c) 2007- Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in file LICENSE, included with + * the source code and binary code bundles. + * You may not use this file except in compliance with the License. + * + * 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.codehaus.jackson; + +/** + * Container for commonly used Base64 variants. + * + * @author Tatu Saloranta + */ +public final class Base64Variants +{ + final static String STD_BASE64_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + + /** + * This variant is what most people would think of "the standard" + * Base64 encoding. + *<p> + * See <a href="">wikipedia Base64 entry</a> for details. + *<p> + * Note that although this can be thought of as the standard variant, + * it is <b>not</b> the default for Jackson: no-linefeeds alternative + * is because of JSON requirement of escaping all linefeeds. + */ + public final static Base64Variant MIME; + static { + MIME = new Base64Variant("MIME", STD_BASE64_ALPHABET, true, '=', 76); + } + + /** + * Slightly non-standard modification of {@link #MIME} which does not + * use linefeeds (max line length set to infinite). Useful when linefeeds + * wouldn't work well (possibly in attributes), or for minor space savings + * (save 1 linefeed per 76 data chars, ie. ~1.4% savings). + */ + public final static Base64Variant MIME_NO_LINEFEEDS; + static { + MIME_NO_LINEFEEDS = new Base64Variant(MIME, "MIME-NO-LINEFEEDS", Integer.MAX_VALUE); + } + + /** + * This variant is the one that predates {@link #MIME}: it is otherwise + * identical, except that it mandates shorter line length. + */ + public final static Base64Variant PEM = new Base64Variant(MIME, "PEM", true, '=', 64); + + /** + * This non-standard variant is usually used when encoded data needs to be + * passed via URLs (such as part of GET request). It differs from the + * base {@link #MIME} variant in multiple ways. + * First, no padding is used: this also means that it generally can not + * be written in multiple separate but adjacent chunks (which would not + * be the usual use case in any case). Also, no linefeeds are used (max + * line length set to infinite). And finally, two characters (plus and + * slash) that would need quoting in URLs are replaced with more + * optimal alternatives (hyphen and underscore, respectively). + */ + public final static Base64Variant MODIFIED_FOR_URL; + static { + StringBuffer sb = new StringBuffer(STD_BASE64_ALPHABET); + // Replace plus with hyphen, slash with underscore (and no padding) + sb.setCharAt(sb.indexOf("+"), '-'); + sb.setCharAt(sb.indexOf("/"), '_'); + /* And finally, let's not split lines either, wouldn't work too + * well with URLs + */ + MODIFIED_FOR_URL = new Base64Variant("MODIFIED-FOR-URL", sb.toString(), false, Base64Variant.PADDING_CHAR_NONE, Integer.MAX_VALUE); + } + + /** + * Method used to get the default variant ("MIME_NO_LINEFEEDS") for cases + * where caller does not explicitly specify the variant. + * We will prefer no-linefeed version because linefeeds in JSON values + * must be escaped, making linefeed-containing variants sub-optimal. + */ + public static Base64Variant getDefaultVariant() { + return MIME_NO_LINEFEEDS; + } +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/FormatSchema.java b/1.9.10/src/java/org/codehaus/jackson/FormatSchema.java new file mode 100644 index 0000000..b59ae41 --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/FormatSchema.java
@@ -0,0 +1,29 @@ +package org.codehaus.jackson; + +/** + * Simple tag interface used to mark schema objects that are used by some + * {@link JsonParser} and {@link JsonGenerator} implementations to further + * specify structure of expected format. + * Basic JSON-based parsers and generators do not use schemas, but some data + * formats (like many binary data formats like Thrift, protobuf) mandate + * use of schemas. + *<p> + * Since there is little commonality between schemas for different data formats, + * this interface does not define much meaningful functionality for accessing + * schema details; rather, specific parser and generator implementations need + * to cast to schema implementations they use. This marker interface is mostly + * used for tagging "some kind of schema" -- instead of passing opaque + * {@link java.lang.Object} -- for documentation purposes. + * + * @since 1.8 + */ +public interface FormatSchema +{ + /** + * Method that can be used to get an identifier that can be used for diagnostics + * purposes, to indicate what kind of data format this schema is used for: typically + * it is a short name of format itself, but it can also contain additional information + * in cases where data format supports multiple types of schemas. + */ + public String getSchemaType(); +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/JsonEncoding.java b/1.9.10/src/java/org/codehaus/jackson/JsonEncoding.java new file mode 100644 index 0000000..5780d86 --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/JsonEncoding.java
@@ -0,0 +1,47 @@ +package org.codehaus.jackson; + +/** + * Enumeration that defines legal encodings that can be used + * for JSON content, based on list of allowed encodings from + * <a href="http://www.ietf.org/rfc/rfc4627.txt">JSON specification</a>. + *<p> + * Note: if application want to explicitly disregard Encoding + * limitations (to read in JSON encoded using an encoding not + * listed as allowed), they can use {@link java.io.Reader} / + * {@link java.io.Writer} instances as input + */ +public enum JsonEncoding { + UTF8("UTF-8", false), // N/A for big-endian, really + UTF16_BE("UTF-16BE", true), + UTF16_LE("UTF-16LE", false), + UTF32_BE("UTF-32BE", true), + UTF32_LE("UTF-32LE", false) + ; + + protected final String _javaName; + + protected final boolean _bigEndian; + + JsonEncoding(String javaName, boolean bigEndian) + { + _javaName = javaName; + _bigEndian = bigEndian; + } + + /** + * Method for accessing encoding name that JDK will support. + * + * @return Matching encoding name that JDK will support. + */ + public String getJavaName() { return _javaName; } + + /** + * Whether encoding is big-endian (if encoding supports such + * notion). If no such distinction is made (as is the case for + * {@link #UTF8}), return value is undefined. + * + * @return True for big-endian encodings; false for little-endian + * (or if not applicable) + */ + public boolean isBigEndian() { return _bigEndian; } +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/JsonFactory.java b/1.9.10/src/java/org/codehaus/jackson/JsonFactory.java new file mode 100644 index 0000000..bf47e7e --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/JsonFactory.java
@@ -0,0 +1,937 @@ +/* Jackson JSON-processor. + * + * Copyright (c) 2007- Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in file LICENSE, included with + * the source code and binary code bundles. + * You may not use this file except in compliance with the License. + * + * 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.codehaus.jackson; + +import java.io.*; +import java.lang.ref.SoftReference; +import java.net.URL; + +import org.codehaus.jackson.format.InputAccessor; +import org.codehaus.jackson.format.MatchStrength; +import org.codehaus.jackson.io.*; +import org.codehaus.jackson.impl.ByteSourceBootstrapper; +import org.codehaus.jackson.impl.ReaderBasedParser; +import org.codehaus.jackson.impl.Utf8Generator; +import org.codehaus.jackson.impl.WriterBasedGenerator; +import org.codehaus.jackson.sym.BytesToNameCanonicalizer; +import org.codehaus.jackson.sym.CharsToNameCanonicalizer; +import org.codehaus.jackson.util.BufferRecycler; +import org.codehaus.jackson.util.VersionUtil; + +/** + * The main factory class of Jackson package, used to configure and + * construct reader (aka parser, {@link JsonParser}) + * and writer (aka generator, {@link JsonGenerator}) + * instances. + *<p> + * Factory instances are thread-safe and reusable after configuration + * (if any). Typically applications and services use only a single + * globally shared factory instance, unless they need differently + * configured factories. Factory reuse is important if efficiency matters; + * most recycling of expensive construct is done on per-factory basis. + *<p> + * Creation of a factory instance is a light-weight operation, + * and since there is no need for pluggable alternative implementations + * (as there is no "standard" JSON processor API to implement), + * the default constructor is used for constructing factory + * instances. + * + * @author Tatu Saloranta + */ +public class JsonFactory implements Versioned +{ + /** + * Name used to identify JSON format + * (and returned by {@link #getFormatName()} + */ + public final static String FORMAT_NAME_JSON = "JSON"; + + /** + * Bitfield (set of flags) of all parser features that are enabled + * by default. + */ + final static int DEFAULT_PARSER_FEATURE_FLAGS = JsonParser.Feature.collectDefaults(); + + /** + * Bitfield (set of flags) of all generator features that are enabled + * by default. + */ + final static int DEFAULT_GENERATOR_FEATURE_FLAGS = JsonGenerator.Feature.collectDefaults(); + + /* + /********************************************************** + /* Buffer, symbol table management + /********************************************************** + */ + + /** + * This <code>ThreadLocal</code> contains a {@link java.lang.ref.SoftRerefence} + * to a {@link BufferRecycler} used to provide a low-cost + * buffer recycling between reader and writer instances. + */ + final protected static ThreadLocal<SoftReference<BufferRecycler>> _recyclerRef + = new ThreadLocal<SoftReference<BufferRecycler>>(); + + /** + * Each factory comes equipped with a shared root symbol table. + * It should not be linked back to the original blueprint, to + * avoid contents from leaking between factories. + */ + protected CharsToNameCanonicalizer _rootCharSymbols = CharsToNameCanonicalizer.createRoot(); + + /** + * Alternative to the basic symbol table, some stream-based + * parsers use different name canonicalization method. + *<p> + * TODO: should clean up this; looks messy having 2 alternatives + * with not very clear differences. + */ + protected BytesToNameCanonicalizer _rootByteSymbols = BytesToNameCanonicalizer.createRoot(); + + /* + /********************************************************** + /* Configuration + /********************************************************** + */ + + /** + * Object that implements conversion functionality between + * Java objects and JSON content. For base JsonFactory implementation + * usually not set by default, but can be explicitly set. + * Sub-classes (like @link org.codehaus.jackson.map.MappingJsonFactory} + * usually provide an implementation. + */ + protected ObjectCodec _objectCodec; + + /** + * Currently enabled parser features. + */ + protected int _parserFeatures = DEFAULT_PARSER_FEATURE_FLAGS; + + /** + * Currently enabled generator features. + */ + protected int _generatorFeatures = DEFAULT_GENERATOR_FEATURE_FLAGS; + + /** + * Definition of custom character escapes to use for generators created + * by this factory, if any. If null, standard data format specific + * escapes are used. + * + * @since 1.8 + */ + protected CharacterEscapes _characterEscapes; + + /** + * Optional helper object that may decorate input sources, to do + * additional processing on input during parsing. + * + * @since 1.8 + */ + protected InputDecorator _inputDecorator; + + /** + * Optional helper object that may decorate output object, to do + * additional processing on output during content generation. + * + * @since 1.8 + */ + protected OutputDecorator _outputDecorator; + + /* + /********************************************************** + /* Construction + /********************************************************** + */ + + /** + * Default constructor used to create factory instances. + * Creation of a factory instance is a light-weight operation, + * but it is still a good idea to reuse limited number of + * factory instances (and quite often just a single instance): + * factories are used as context for storing some reused + * processing objects (such as symbol tables parsers use) + * and this reuse only works within context of a single + * factory instance. + */ + public JsonFactory() { this(null); } + + public JsonFactory(ObjectCodec oc) { _objectCodec = oc; } + + /* + /********************************************************** + /* Format detection functionality (since 1.8) + /********************************************************** + */ + + /** + * Method that returns short textual id identifying format + * this factory supports. + *<p> + * Note: sub-classes should override this method; default + * implementation will return null for all sub-classes + * + * @since 1.8 + */ + public String getFormatName() + { + /* Somewhat nasty check: since we can't make this abstract + * (due to backwards compatibility concerns), need to prevent + * format name "leakage" + */ + if (getClass() == JsonFactory.class) { + return FORMAT_NAME_JSON; + } + return null; + } + + public MatchStrength hasFormat(InputAccessor acc) throws IOException + { + // since we can't keep this abstract, only implement for "vanilla" instance + if (getClass() == JsonFactory.class) { + return hasJSONFormat(acc); + } + return null; + } + + protected MatchStrength hasJSONFormat(InputAccessor acc) throws IOException + { + return ByteSourceBootstrapper.hasJSONFormat(acc); + } + + /* + /********************************************************** + /* Versioned + /********************************************************** + */ + + @Override + public Version version() { + // VERSION is included under impl, so can't pass this class: + return VersionUtil.versionFor(Utf8Generator.class); + } + + /* + /********************************************************** + /* Configuration, parser settings + /********************************************************** + */ + + /** + * Method for enabling or disabling specified parser feature + * (check {@link JsonParser.Feature} for list of features) + * + * @since 1.2 + */ + public final JsonFactory configure(JsonParser.Feature f, boolean state) + { + if (state) { + enable(f); + } else { + disable(f); + } + return this; + } + + /** + * Method for enabling specified parser feature + * (check {@link JsonParser.Feature} for list of features) + * + * @since 1.2 + */ + public JsonFactory enable(JsonParser.Feature f) { + _parserFeatures |= f.getMask(); + return this; + } + + /** + * Method for disabling specified parser features + * (check {@link JsonParser.Feature} for list of features) + * + * @since 1.2 + */ + public JsonFactory disable(JsonParser.Feature f) { + _parserFeatures &= ~f.getMask(); + return this; + } + + /** + * Checked whether specified parser feature is enabled. + * + * @since 1.2 + */ + public final boolean isEnabled(JsonParser.Feature f) { + return (_parserFeatures & f.getMask()) != 0; + } + + // // // Older deprecated (as of 1.2) methods + + /** + * @deprecated Use {@link #enable(JsonParser.Feature)} instead + */ + @SuppressWarnings("dep-ann") + public final void enableParserFeature(JsonParser.Feature f) { + enable(f); + } + + /** + * @deprecated Use {@link #disable(JsonParser.Feature)} instead + */ + @SuppressWarnings("dep-ann") + public final void disableParserFeature(JsonParser.Feature f) { + disable(f); + } + + /** + * @deprecated Use {@link #configure(JsonParser.Feature, boolean)} instead + */ + @SuppressWarnings("dep-ann") + public final void setParserFeature(JsonParser.Feature f, boolean state) { + configure(f, state); + } + + /** + * @deprecated Use {@link #isEnabled(JsonParser.Feature)} instead + */ + @SuppressWarnings("dep-ann") + public final boolean isParserFeatureEnabled(JsonParser.Feature f) { + return (_parserFeatures & f.getMask()) != 0; + } + + /** + * Method for getting currently configured input decorator (if any; + * there is no default decorator). + * + * @since 1.8 + */ + public InputDecorator getInputDecorator() { + return _inputDecorator; + } + + /** + * Method for overriding currently configured input decorator + * + * @since 1.8 + */ + public JsonFactory setInputDecorator(InputDecorator d) { + _inputDecorator = d; + return this; + } + + /* + /********************************************************** + /* Configuration, generator settings + /********************************************************** + */ + + /** + * Method for enabling or disabling specified generator feature + * (check {@link JsonGenerator.Feature} for list of features) + * + * @since 1.2 + */ + public final JsonFactory configure(JsonGenerator.Feature f, boolean state) { + if (state) { + enable(f); + } else { + disable(f); + } + return this; + } + + + /** + * Method for enabling specified generator features + * (check {@link JsonGenerator.Feature} for list of features) + * + * @since 1.2 + */ + public JsonFactory enable(JsonGenerator.Feature f) { + _generatorFeatures |= f.getMask(); + return this; + } + + /** + * Method for disabling specified generator feature + * (check {@link JsonGenerator.Feature} for list of features) + * + * @since 1.2 + */ + public JsonFactory disable(JsonGenerator.Feature f) { + _generatorFeatures &= ~f.getMask(); + return this; + } + + /** + * Check whether specified generator feature is enabled. + * + * @since 1.2 + */ + public final boolean isEnabled(JsonGenerator.Feature f) { + return (_generatorFeatures & f.getMask()) != 0; + } + + // // // Older deprecated (as of 1.2) methods + + /** + * @deprecated Use {@link #enable(JsonGenerator.Feature)} instead + */ + @Deprecated + public final void enableGeneratorFeature(JsonGenerator.Feature f) { + enable(f); + } + + /** + * @deprecated Use {@link #disable(JsonGenerator.Feature)} instead + */ + @Deprecated + public final void disableGeneratorFeature(JsonGenerator.Feature f) { + disable(f); + } + + /** + * @deprecated Use {@link #configure(JsonGenerator.Feature, boolean)} instead + */ + @Deprecated + public final void setGeneratorFeature(JsonGenerator.Feature f, boolean state) { + configure(f, state); + } + + /** + * @deprecated Use {@link #isEnabled(JsonGenerator.Feature)} instead + */ + @Deprecated + public final boolean isGeneratorFeatureEnabled(JsonGenerator.Feature f) { + return isEnabled(f); + } + + /** + * Method for accessing custom escapes factory uses for {@link JsonGenerator}s + * it creates. + * + * @since 1.8 + */ + public CharacterEscapes getCharacterEscapes() { + return _characterEscapes; + } + + /** + * Method for defining custom escapes factory uses for {@link JsonGenerator}s + * it creates. + * + * @since 1.8 + */ + public JsonFactory setCharacterEscapes(CharacterEscapes esc) { + _characterEscapes = esc; + return this; + } + + /** + * Method for getting currently configured output decorator (if any; + * there is no default decorator). + * + * @since 1.8 + */ + public OutputDecorator getOutputDecorator() { + return _outputDecorator; + } + + /** + * Method for overriding currently configured output decorator + * + * @since 1.8 + */ + public JsonFactory setOutputDecorator(OutputDecorator d) { + _outputDecorator = d; + return this; + } + + /* + /********************************************************** + /* Configuration, other + /********************************************************** + */ + + /** + * Method for associating a {@link ObjectCodec} (typically + * a {@link org.codehaus.jackson.map.ObjectMapper}) with + * this factory (and more importantly, parsers and generators + * it constructs). This is needed to use data-binding methods + * of {@link JsonParser} and {@link JsonGenerator} instances. + */ + public JsonFactory setCodec(ObjectCodec oc) { + _objectCodec = oc; + return this; + } + + public ObjectCodec getCodec() { return _objectCodec; } + + /* + /********************************************************** + /* Reader factories + /********************************************************** + */ + + /** + * Method for constructing JSON parser instance to parse + * contents of specified file. Encoding is auto-detected + * from contents according to JSON specification recommended + * mechanism. + *<p> + * Underlying input stream (needed for reading contents) + * will be <b>owned</b> (and managed, i.e. closed as need be) by + * the parser, since caller has no access to it. + * + * @param f File that contains JSON content to parse + */ + public JsonParser createJsonParser(File f) + throws IOException, JsonParseException + { + // true, since we create InputStream from File + IOContext ctxt = _createContext(f, true); + InputStream in = new FileInputStream(f); + // [JACKSON-512]: allow wrapping with InputDecorator + if (_inputDecorator != null) { + in = _inputDecorator.decorate(ctxt, in); + } + return _createJsonParser(in, ctxt); + } + + /** + * Method for constructing JSON parser instance to parse + * contents of resource reference by given URL. + * Encoding is auto-detected + * from contents according to JSON specification recommended + * mechanism. + *<p> + * Underlying input stream (needed for reading contents) + * will be <b>owned</b> (and managed, i.e. closed as need be) by + * the parser, since caller has no access to it. + * + * @param url URL pointing to resource that contains JSON content to parse + */ + public JsonParser createJsonParser(URL url) + throws IOException, JsonParseException + { + // true, since we create InputStream from URL + IOContext ctxt = _createContext(url, true); + InputStream in = _optimizedStreamFromURL(url); + // [JACKSON-512]: allow wrapping with InputDecorator + if (_inputDecorator != null) { + in = _inputDecorator.decorate(ctxt, in); + } + return _createJsonParser(in, ctxt); + } + + /** + * Method for constructing JSON parser instance to parse + * the contents accessed via specified input stream. + *<p> + * The input stream will <b>not be owned</b> by + * the parser, it will still be managed (i.e. closed if + * end-of-stream is reacher, or parser close method called) + * if (and only if) {@link org.codehaus.jackson.JsonParser.Feature#AUTO_CLOSE_SOURCE} + * is enabled. + *<p> + * Note: no encoding argument is taken since it can always be + * auto-detected as suggested by Json RFC. + * + * @param in InputStream to use for reading JSON content to parse + */ + public JsonParser createJsonParser(InputStream in) + throws IOException, JsonParseException + { + IOContext ctxt = _createContext(in, false); + // [JACKSON-512]: allow wrapping with InputDecorator + if (_inputDecorator != null) { + in = _inputDecorator.decorate(ctxt, in); + } + return _createJsonParser(in, ctxt); + } + + /** + * Method for constructing parser for parsing + * the contents accessed via specified Reader. + <p> + * The read stream will <b>not be owned</b> by + * the parser, it will still be managed (i.e. closed if + * end-of-stream is reacher, or parser close method called) + * if (and only if) {@link org.codehaus.jackson.JsonParser.Feature#AUTO_CLOSE_SOURCE} + * is enabled. + *<p> + * + * @param r Reader to use for reading JSON content to parse + */ + public JsonParser createJsonParser(Reader r) + throws IOException, JsonParseException + { + // false -> we do NOT own Reader (did not create it) + IOContext ctxt = _createContext(r, false); + // [JACKSON-512]: allow wrapping with InputDecorator + if (_inputDecorator != null) { + r = _inputDecorator.decorate(ctxt, r); + } + return _createJsonParser(r, ctxt); + } + + /** + * Method for constructing parser for parsing + * the contents of given byte array. + */ + public JsonParser createJsonParser(byte[] data) + throws IOException, JsonParseException + { + IOContext ctxt = _createContext(data, true); + // [JACKSON-512]: allow wrapping with InputDecorator + if (_inputDecorator != null) { + InputStream in = _inputDecorator.decorate(ctxt, data, 0, data.length); + if (in != null) { + return _createJsonParser(in, ctxt); + } + } + return _createJsonParser(data, 0, data.length, ctxt); + } + + /** + * Method for constructing parser for parsing + * the contents of given byte array. + * + * @param data Buffer that contains data to parse + * @param offset Offset of the first data byte within buffer + * @param len Length of contents to parse within buffer + */ + public JsonParser createJsonParser(byte[] data, int offset, int len) + throws IOException, JsonParseException + { + IOContext ctxt = _createContext(data, true); + // [JACKSON-512]: allow wrapping with InputDecorator + if (_inputDecorator != null) { + InputStream in = _inputDecorator.decorate(ctxt, data, offset, len); + if (in != null) { + return _createJsonParser(in, ctxt); + } + } + return _createJsonParser(data, offset, len, ctxt); + } + + /** + * Method for constructing parser for parsing + * contens of given String. + */ + public JsonParser createJsonParser(String content) + throws IOException, JsonParseException + { + Reader r = new StringReader(content); + // true -> we own the Reader (and must close); not a big deal + IOContext ctxt = _createContext(r, true); + // [JACKSON-512]: allow wrapping with InputDecorator + if (_inputDecorator != null) { + r = _inputDecorator.decorate(ctxt, r); + } + return _createJsonParser(r, ctxt); + } + + /* + /********************************************************** + /* Generator factories + /********************************************************** + */ + + /** + * Method for constructing JSON generator for writing JSON content + * using specified output stream. + * Encoding to use must be specified, and needs to be one of available + * types (as per JSON specification). + *<p> + * Underlying stream <b>is NOT owned</b> by the generator constructed, + * so that generator will NOT close the output stream when + * {@link JsonGenerator#close} is called (unless auto-closing + * feature, + * {@link org.codehaus.jackson.JsonGenerator.Feature#AUTO_CLOSE_TARGET} + * is enabled). + * Using application needs to close it explicitly if this is the case. + *<p> + * Note: there are formats that use fixed encoding (like most binary data formats) + * and that ignore passed in encoding. + * + * @param out OutputStream to use for writing JSON content + * @param enc Character encoding to use + */ + public JsonGenerator createJsonGenerator(OutputStream out, JsonEncoding enc) + throws IOException + { + // false -> we won't manage the stream unless explicitly directed to + IOContext ctxt = _createContext(out, false); + ctxt.setEncoding(enc); + if (enc == JsonEncoding.UTF8) { + // [JACKSON-512]: allow wrapping with _outputDecorator + if (_outputDecorator != null) { + out = _outputDecorator.decorate(ctxt, out); + } + return _createUTF8JsonGenerator(out, ctxt); + } + Writer w = _createWriter(out, enc, ctxt); + // [JACKSON-512]: allow wrapping with _outputDecorator + if (_outputDecorator != null) { + w = _outputDecorator.decorate(ctxt, w); + } + return _createJsonGenerator(w, ctxt); + } + + /** + * Method for constructing JSON generator for writing JSON content + * using specified Writer. + *<p> + * Underlying stream <b>is NOT owned</b> by the generator constructed, + * so that generator will NOT close the Reader when + * {@link JsonGenerator#close} is called (unless auto-closing + * feature, + * {@link org.codehaus.jackson.JsonGenerator.Feature#AUTO_CLOSE_TARGET} is enabled). + * Using application needs to close it explicitly. + * + * @param out Writer to use for writing JSON content + */ + public JsonGenerator createJsonGenerator(Writer out) + throws IOException + { + IOContext ctxt = _createContext(out, false); + // [JACKSON-512]: allow wrapping with _outputDecorator + if (_outputDecorator != null) { + out = _outputDecorator.decorate(ctxt, out); + } + return _createJsonGenerator(out, ctxt); + } + + /** + * Convenience method for constructing generator that uses default + * encoding of the format (UTF-8 for JSON and most other data formats). + *<p> + * Note: there are formats that use fixed encoding (like most binary data formats). + * + * @since 1.8 + */ + public JsonGenerator createJsonGenerator(OutputStream out) throws IOException { + return createJsonGenerator(out, JsonEncoding.UTF8); + } + + /** + * Method for constructing JSON generator for writing JSON content + * to specified file, overwriting contents it might have (or creating + * it if such file does not yet exist). + * Encoding to use must be specified, and needs to be one of available + * types (as per JSON specification). + *<p> + * Underlying stream <b>is owned</b> by the generator constructed, + * i.e. generator will handle closing of file when + * {@link JsonGenerator#close} is called. + * + * @param f File to write contents to + * @param enc Character encoding to use + */ + public JsonGenerator createJsonGenerator(File f, JsonEncoding enc) + throws IOException + { + OutputStream out = new FileOutputStream(f); + // true -> yes, we have to manage the stream since we created it + IOContext ctxt = _createContext(out, true); + ctxt.setEncoding(enc); + if (enc == JsonEncoding.UTF8) { + // [JACKSON-512]: allow wrapping with _outputDecorator + if (_outputDecorator != null) { + out = _outputDecorator.decorate(ctxt, out); + } + return _createUTF8JsonGenerator(out, ctxt); + } + Writer w = _createWriter(out, enc, ctxt); + // [JACKSON-512]: allow wrapping with _outputDecorator + if (_outputDecorator != null) { + w = _outputDecorator.decorate(ctxt, w); + } + return _createJsonGenerator(w, ctxt); + } + + /* + /********************************************************** + /* Factory methods used by factory for creating parser instances, + /* overridable by sub-classes + /********************************************************** + */ + + /** + * Overridable factory method that actually instantiates desired parser + * given {@link InputStream} and context object. + *<p> + * This method is specifically designed to remain + * compatible between minor versions so that sub-classes can count + * on it being called as expected. That is, it is part of official + * interface from sub-class perspective, although not a public + * method available to users of factory implementations. + */ + protected JsonParser _createJsonParser(InputStream in, IOContext ctxt) + throws IOException, JsonParseException + { + return new ByteSourceBootstrapper(ctxt, in).constructParser(_parserFeatures, + _objectCodec, _rootByteSymbols, _rootCharSymbols); + } + + /** + * Overridable factory method that actually instantiates parser + * using given {@link Reader} object for reading content. + *<p> + * This method is specifically designed to remain + * compatible between minor versions so that sub-classes can count + * on it being called as expected. That is, it is part of official + * interface from sub-class perspective, although not a public + * method available to users of factory implementations. + */ + protected JsonParser _createJsonParser(Reader r, IOContext ctxt) + throws IOException, JsonParseException + { + return new ReaderBasedParser(ctxt, _parserFeatures, r, _objectCodec, + _rootCharSymbols.makeChild(isEnabled(JsonParser.Feature.CANONICALIZE_FIELD_NAMES), + isEnabled(JsonParser.Feature.INTERN_FIELD_NAMES))); + } + + /** + * Overridable factory method that actually instantiates parser + * using given {@link Reader} object for reading content + * passed as raw byte array. + *<p> + * This method is specifically designed to remain + * compatible between minor versions so that sub-classes can count + * on it being called as expected. That is, it is part of official + * interface from sub-class perspective, although not a public + * method available to users of factory implementations. + */ + protected JsonParser _createJsonParser(byte[] data, int offset, int len, IOContext ctxt) + throws IOException, JsonParseException + { + return new ByteSourceBootstrapper(ctxt, data, offset, len).constructParser(_parserFeatures, + _objectCodec, _rootByteSymbols, _rootCharSymbols); + } + + /* + /********************************************************** + /* Factory methods used by factory for creating generator instances, + /* overridable by sub-classes + /********************************************************** + */ + + /** + * Overridable factory method that actually instantiates generator for + * given {@link Writer} and context object. + *<p> + * This method is specifically designed to remain + * compatible between minor versions so that sub-classes can count + * on it being called as expected. That is, it is part of official + * interface from sub-class perspective, although not a public + * method available to users of factory implementations. + */ + protected JsonGenerator _createJsonGenerator(Writer out, IOContext ctxt) + throws IOException + { + WriterBasedGenerator gen = new WriterBasedGenerator(ctxt, _generatorFeatures, _objectCodec, out); + if (_characterEscapes != null) { + gen.setCharacterEscapes(_characterEscapes); + } + return gen; + } + + /** + * Overridable factory method that actually instantiates generator for + * given {@link OutputStream} and context object, using UTF-8 encoding. + *<p> + * This method is specifically designed to remain + * compatible between minor versions so that sub-classes can count + * on it being called as expected. That is, it is part of official + * interface from sub-class perspective, although not a public + * method available to users of factory implementations. + */ + protected JsonGenerator _createUTF8JsonGenerator(OutputStream out, IOContext ctxt) + throws IOException + { + Utf8Generator gen = new Utf8Generator(ctxt, _generatorFeatures, _objectCodec, out); + if (_characterEscapes != null) { + gen.setCharacterEscapes(_characterEscapes); + } + return gen; + } + + protected Writer _createWriter(OutputStream out, JsonEncoding enc, IOContext ctxt) throws IOException + { + // note: this should not get called any more (caller checks, dispatches) + if (enc == JsonEncoding.UTF8) { // We have optimized writer for UTF-8 + return new UTF8Writer(ctxt, out); + } + // not optimal, but should do unless we really care about UTF-16/32 encoding speed + return new OutputStreamWriter(out, enc.getJavaName()); + } + + /* + /********************************************************** + /* Internal factory methods, other + /********************************************************** + */ + + /** + * Overridable factory method that actually instantiates desired + * context object. + */ + protected IOContext _createContext(Object srcRef, boolean resourceManaged) + { + return new IOContext(_getBufferRecycler(), srcRef, resourceManaged); + } + + /** + * Method used by factory to create buffer recycler instances + * for parsers and generators. + *<p> + * Note: only public to give access for <code>ObjectMapper</code> + */ + public BufferRecycler _getBufferRecycler() + { + SoftReference<BufferRecycler> ref = _recyclerRef.get(); + BufferRecycler br = (ref == null) ? null : ref.get(); + + if (br == null) { + br = new BufferRecycler(); + _recyclerRef.set(new SoftReference<BufferRecycler>(br)); + } + return br; + } + + /** + * Helper methods used for constructing an optimal stream for + * parsers to use, when input is to be read from an URL. + * This helps when reading file content via URL. + */ + protected InputStream _optimizedStreamFromURL(URL url) + throws IOException + { + if ("file".equals(url.getProtocol())) { + /* Can not do this if the path refers + * to a network drive on windows. This fixes the problem; + * might not be needed on all platforms (NFS?), but should not + * matter a lot: performance penalty of extra wrapping is more + * relevant when accessing local file system. + */ + String host = url.getHost(); + if (host == null || host.length() == 0) { + return new FileInputStream(url.getPath()); + } + } + return url.openStream(); + } +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/JsonGenerationException.java b/1.9.10/src/java/org/codehaus/jackson/JsonGenerationException.java new file mode 100644 index 0000000..84e6d3f --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/JsonGenerationException.java
@@ -0,0 +1,28 @@ +package org.codehaus.jackson; + +/** + * Exception type for exceptions during JSON writing, such as trying + * to output content in wrong context (non-matching end-array or end-object, + * for example). + */ +public class JsonGenerationException + extends JsonProcessingException +{ + @SuppressWarnings("hiding") + final static long serialVersionUID = 123; // Stupid eclipse... + + public JsonGenerationException(Throwable rootCause) + { + super(rootCause); + } + + public JsonGenerationException(String msg) + { + super(msg, (JsonLocation)null); + } + + public JsonGenerationException(String msg, Throwable rootCause) + { + super(msg, (JsonLocation)null, rootCause); + } +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/JsonGenerator.java b/1.9.10/src/java/org/codehaus/jackson/JsonGenerator.java new file mode 100644 index 0000000..1d89d9e --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/JsonGenerator.java
@@ -0,0 +1,1197 @@ +/* Jackson JSON-processor. + * + * Copyright (c) 2007- Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in file LICENSE, included with + * the source code and binary code bundles. + * You may not use this file except in compliance with the License. + * + * 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.codehaus.jackson; + +import java.io.*; +import java.math.BigDecimal; +import java.math.BigInteger; + +import org.codehaus.jackson.io.CharacterEscapes; +import org.codehaus.jackson.io.SerializedString; + +/** + * Base class that defines public API for writing JSON content. + * Instances are created using factory methods of + * a {@link JsonFactory} instance. + * + * @author Tatu Saloranta + */ +public abstract class JsonGenerator + implements Closeable, Versioned +{ + /** + * Enumeration that defines all togglable features for generators. + */ + public enum Feature { + /** + * Feature that determines whether generator will automatically + * close underlying output target that is NOT owned by the + * generator. + * If disabled, calling application has to separately + * close the underlying {@link OutputStream} and {@link Writer} + * instances used to create the generator. If enabled, generator + * will handle closing, as long as generator itself gets closed: + * this happens when end-of-input is encountered, or generator + * is closed by a call to {@link JsonGenerator#close}. + *<p> + * Feature is enabled by default. + */ + AUTO_CLOSE_TARGET(true), + + /** + * Feature that determines what happens when the generator is + * closed while there are still unmatched + * {@link JsonToken#START_ARRAY} or {@link JsonToken#START_OBJECT} + * entries in output content. If enabled, such Array(s) and/or + * Object(s) are automatically closed; if disabled, nothing + * specific is done. + *<p> + * Feature is enabled by default. + */ + AUTO_CLOSE_JSON_CONTENT(true), + + /** + * Feature that determines whether JSON Object field names are + * quoted using double-quotes, as specified by JSON specification + * or not. Ability to disable quoting was added to support use + * cases where they are not usually expected, which most commonly + * occurs when used straight from Javascript. + */ + QUOTE_FIELD_NAMES(true), + + /** + * Feature that determines whether "exceptional" (not real number) + * float/double values are output as quoted strings. + * The values checked are Double.Nan, + * Double.POSITIVE_INFINITY and Double.NEGATIVE_INIFINTY (and + * associated Float values). + * If feature is disabled, these numbers are still output using + * associated literal values, resulting in non-conformant + * output. + *<p> + * Feature is enabled by default. + */ + QUOTE_NON_NUMERIC_NUMBERS(true), + + /** + * Feature that forces all Java numbers to be written as JSON strings. + * Default state is 'false', meaning that Java numbers are to + * be serialized using basic numeric serialization (as JSON + * numbers, integral or floating point). If enabled, all such + * numeric values are instead written out as JSON Strings. + *<p> + * One use case is to avoid problems with Javascript limitations: + * since Javascript standard specifies that all number handling + * should be done using 64-bit IEEE 754 floating point values, + * result being that some 64-bit integer values can not be + * accurately represent (as mantissa is only 51 bit wide). + *<p> + * Feature is disabled by default. + * + * @since 1.3 + */ + WRITE_NUMBERS_AS_STRINGS(false), + + /** + * Feature that specifies that calls to {@link #flush} will cause + * matching <code>flush()</code> to underlying {@link OutputStream} + * or {@link Writer}; if disabled this will not be done. + * Main reason to disable this feature is to prevent flushing at + * generator level, if it is not possible to prevent method being + * called by other code (like <code>ObjectMapper</code> or third + * party libraries). + *<p> + * Feature is enabled by default. + * + * @since 1.7 + */ + FLUSH_PASSED_TO_STREAM(true), + + /** + * Feature that specifies that all characters beyond 7-bit ASCII + * range (i.e. code points of 128 and above) need to be output + * using format-specific escapes (for JSON, backslash escapes), + * if format uses escaping mechanisms (which is generally true + * for textual formats but not for binary formats). + * + * @since 1.8 + */ + ESCAPE_NON_ASCII(false) + + ; + + final boolean _defaultState; + + final int _mask; + + /** + * Method that calculates bit set (flags) of all features that + * are enabled by default. + */ + public static int collectDefaults() + { + int flags = 0; + for (Feature f : values()) { + if (f.enabledByDefault()) { + flags |= f.getMask(); + } + } + return flags; + } + + private Feature(boolean defaultState) { + _defaultState = defaultState; + _mask = (1 << ordinal()); + } + + public boolean enabledByDefault() { return _defaultState; } + + public int getMask() { return _mask; } + } + + /* + /********************************************************** + /* Configuration + /********************************************************** + */ + + /** + * Object that handles pretty-printing (usually additional + * white space to make results more human-readable) during + * output. If null, no pretty-printing is done. + */ + protected PrettyPrinter _cfgPrettyPrinter; + + /* + /********************************************************** + /* Construction, configuration, initialization + /********************************************************** + */ + + protected JsonGenerator() { } + + /** + * Method to call to make this generator use specified schema. + * Method must be called before generating any content, right after instance + * has been created. + * Note that not all generators support schemas; and those that do usually only + * accept specific types of schemas: ones defined for data format this generator + * produces. + *<p> + * If generator does not support specified schema, {@link UnsupportedOperationException} + * is thrown. + * + * @param schema Schema to use + * + * @throws UnsupportedOperationException if generator does not support schema + * + * @since 1.8 + */ + public void setSchema(FormatSchema schema) + { + throw new UnsupportedOperationException("Generator of type "+getClass().getName()+" does not support schema of type '" + +schema.getSchemaType()+"'"); + } + + /** + * Method that can be used to verify that given schema can be used with + * this generator (using {@link #setSchema}). + * + * @param schema Schema to check + * + * @return True if this generator can use given schema; false if not + * + * @since 1.8 + */ + public boolean canUseSchema(FormatSchema schema) { + return false; + } + + /** + * @since 1.6 + */ + @Override + public Version version() { + return Version.unknownVersion(); + } + + /** + * Method that can be used to get access to object that is used + * as target for generated output; this is usually either + * {@link OutputStream} or {@link Writer}, depending on what + * generator was constructed with. + * Note that returned value may be null in some cases; including + * case where implementation does not want to exposed raw + * source to caller. + * In cases where output has been decorated, object returned here + * is the decorated version; this allows some level of interaction + * between users of generator and decorator object. + *<p> + * In general use of this accessor should be considered as + * "last effort", i.e. only used if no other mechanism is applicable. + * + * @since 1.8 + */ + public Object getOutputTarget() { + return null; + } + + /* + /********************************************************** + /* Public API, configuration + /********************************************************** + */ + + /** + * Method for enabling specified parser features: + * check {@link Feature} for list of available features. + * + * @return Generator itself (this), to allow chaining + * + * @since 1.2 + */ + public abstract JsonGenerator enable(Feature f); + + /** + * Method for disabling specified features + * (check {@link Feature} for list of features) + * + * @return Generator itself (this), to allow chaining + * + * @since 1.2 + */ + public abstract JsonGenerator disable(Feature f); + + /** + * Method for enabling or disabling specified feature: + * check {@link Feature} for list of available features. + * + * @return Generator itself (this), to allow chaining + * + * @since 1.2 + */ + public JsonGenerator configure(Feature f, boolean state) + { + if (state) { + enable(f); + } else { + disable(f); + } + return this; + } + + /** + * Method for checking whether given feature is enabled. + * Check {@link Feature} for list of available features. + * + * @since 1.2 + */ + public abstract boolean isEnabled(Feature f); + + /** + * Method that can be called to set or reset the object to + * use for writing Java objects as JsonContent + * (using method {@link #writeObject}). + * + * @return Generator itself (this), to allow chaining + */ + public abstract JsonGenerator setCodec(ObjectCodec oc); + + /** + * Method for accessing the object used for writing Java + * object as Json content + * (using method {@link #writeObject}). + */ + public abstract ObjectCodec getCodec(); + + // // // Older deprecated versions + + /** @deprecated Use {@link #enable} instead + */ + @Deprecated + public void enableFeature(Feature f) { enable(f); } + + /** @deprecated Use {@link #disable} instead + */ + @Deprecated + public void disableFeature(Feature f) { disable(f); } + + /** @deprecated Use {@link #configure} instead + */ + @Deprecated + public void setFeature(Feature f, boolean state) { configure(f, state); } + + /** @deprecated Use {@link #isEnabled} instead + */ + @Deprecated + public boolean isFeatureEnabled(Feature f) { return isEnabled(f); } + + /* + /********************************************************** + /* Configuring generator + /********************************************************** + */ + + /** + * Method for setting a custom pretty printer, which is usually + * used to add indentation for improved human readability. + * By default, generator does not do pretty printing. + *<p> + * To use the default pretty printer that comes with core + * Jackson distribution, call {@link #useDefaultPrettyPrinter} + * instead. + * + * @return Generator itself (this), to allow chaining + */ + public JsonGenerator setPrettyPrinter(PrettyPrinter pp) { + _cfgPrettyPrinter = pp; + return this; + } + + /** + * Convenience method for enabling pretty-printing using + * the default pretty printer + * ({@link org.codehaus.jackson.util.DefaultPrettyPrinter}). + * + * @return Generator itself (this), to allow chaining + */ + public abstract JsonGenerator useDefaultPrettyPrinter(); + + /** + * Method that can be called to request that generator escapes + * all character codes above specified code point (if positive value); + * or, to not escape any characters except for ones that must be + * escaped for the data format (if -1). + * To force escaping of all non-ASCII characters, for example, + * this method would be called with value of 127. + *<p> + * Note that generators are NOT required to support setting of value + * higher than 127, because there are other ways to affect quoting + * (or lack thereof) of character codes between 0 and 127. + * Not all generators support concept of escaping, either; if so, + * calling this method will have no effect. + *<p> + * Default implementation does nothing; sub-classes need to redefine + * it according to rules of supported data format. + * + * @param charCode Either -1 to indicate that no additional escaping + * is to be done; or highest code point not to escape (meaning higher + * ones will be), if positive value. + * + * @since 1.8 + */ + public JsonGenerator setHighestNonEscapedChar(int charCode) { + return this; + } + + /** + * Accessor method for testing what is the highest unescaped character + * configured for this generator. This may be either positive value + * (when escaping configuration has been set and is in effect), or + * 0 to indicate that no additional escaping is in effect. + * Some generators may not support additional escaping: for example, + * generators for binary formats that do not use escaping should + * simply return 0. + * + * @return Currently active limitation for highest non-escaped character, + * if defined; or -1 to indicate no additional escaping is performed. + */ + public int getHighestEscapedChar() { + return 0; + } + /** + * Method for accessing custom escapes factory uses for {@link JsonGenerator}s + * it creates. + * + * @since 1.8 + */ + public CharacterEscapes getCharacterEscapes() { + return null; + } + + /** + * Method for defining custom escapes factory uses for {@link JsonGenerator}s + * it creates. + * + * @since 1.8 + */ + public JsonGenerator setCharacterEscapes(CharacterEscapes esc) { + return this; + } + + /* + /********************************************************** + /* Public API, write methods, structural + /********************************************************** + */ + + /** + * Method for writing starting marker of a JSON Array value + * (character '['; plus possible white space decoration + * if pretty-printing is enabled). + *<p> + * Array values can be written in any context where values + * are allowed: meaning everywhere except for when + * a field name is expected. + */ + public abstract void writeStartArray() + throws IOException, JsonGenerationException; + + /** + * Method for writing closing marker of a JSON Array value + * (character ']'; plus possible white space decoration + * if pretty-printing is enabled). + *<p> + * Marker can be written if the innermost structured type + * is Array. + */ + public abstract void writeEndArray() + throws IOException, JsonGenerationException; + + /** + * Method for writing starting marker of a JSON Object value + * (character '{'; plus possible white space decoration + * if pretty-printing is enabled). + *<p> + * Object values can be written in any context where values + * are allowed: meaning everywhere except for when + * a field name is expected. + */ + public abstract void writeStartObject() + throws IOException, JsonGenerationException; + + /** + * Method for writing closing marker of a JSON Object value + * (character '}'; plus possible white space decoration + * if pretty-printing is enabled). + *<p> + * Marker can be written if the innermost structured type + * is Object, and the last written event was either a + * complete value, or START-OBJECT marker (see JSON specification + * for more details). + */ + public abstract void writeEndObject() + throws IOException, JsonGenerationException; + + /** + * Method for writing a field name (JSON String surrounded by + * double quotes: syntactically identical to a JSON String value), + * possibly decorated by white space if pretty-printing is enabled. + *<p> + * Field names can only be written in Object context (check out + * JSON specification for details), when field name is expected + * (field names alternate with values). + */ + public abstract void writeFieldName(String name) + throws IOException, JsonGenerationException; + + /** + * Method similar to {@link #writeFieldName(String)}, main difference + * being that it may perform better as some of processing (such as + * quoting of certain characters, or encoding into external encoding + * if supported by generator) can be done just once and reused for + * later calls. + *<p> + * Default implementation simple uses unprocessed name container in + * serialized String; implementations are strongly encouraged to make + * use of more efficient methods argument object has. + * + * @since 1.6 + */ + public void writeFieldName(SerializedString name) + throws IOException, JsonGenerationException + { + writeFieldName(name.getValue()); + } + + /** + * Method similar to {@link #writeFieldName(String)}, main difference + * being that it may perform better as some of processing (such as + * quoting of certain characters, or encoding into external encoding + * if supported by generator) can be done just once and reused for + * later calls. + *<p> + * Default implementation simple uses unprocessed name container in + * serialized String; implementations are strongly encouraged to make + * use of more efficient methods argument object has. + * + * @since 1.7 + */ + public void writeFieldName(SerializableString name) + throws IOException, JsonGenerationException + { + writeFieldName(name.getValue()); + } + + /* + /********************************************************** + /* Public API, write methods, text/String values + /********************************************************** + */ + + /** + * Method for outputting a String value. Depending on context + * this means either array element, (object) field value or + * a stand alone String; but in all cases, String will be + * surrounded in double quotes, and contents will be properly + * escaped as required by JSON specification. + */ + public abstract void writeString(String text) + throws IOException, JsonGenerationException; + + /** + * Method for outputting a String value. Depending on context + * this means either array element, (object) field value or + * a stand alone String; but in all cases, String will be + * surrounded in double quotes, and contents will be properly + * escaped as required by JSON specification. + */ + public abstract void writeString(char[] text, int offset, int len) + throws IOException, JsonGenerationException; + + /** + * Method similar to {@link #writeString(String)}, but that takes + * {@link SerializableString} which can make this potentially + * more efficient to call as generator may be able to reuse + * quoted and/or encoded representation. + *<p> + * Default implementation just calls {@link #writeString(String)}; + * sub-classes should override it with more efficient implementation + * if possible. + * + * @since 1.7 + */ + public void writeString(SerializableString text) + throws IOException, JsonGenerationException + { + writeString(text.getValue()); + } + + /** + * Method similar to {@link #writeString(String)} but that takes as + * its input a UTF-8 encoded String that is to be output as-is, without additional + * escaping (type of which depends on data format; backslashes for JSON). + * However, quoting that data format requires (like double-quotes for JSON) will be added + * around the value if and as necessary. + *<p> + * Note that some backends may choose not to support this method: for + * example, if underlying destination is a {@link java.io.Writer} + * using this method would require UTF-8 decoding. + * If so, implementation may instead choose to throw a + * {@link UnsupportedOperationException} due to ineffectiveness + * of having to decode input. + * + * @since 1.7 + */ + public abstract void writeRawUTF8String(byte[] text, int offset, int length) + throws IOException, JsonGenerationException; + + /** + * Method similar to {@link #writeString(String)} but that takes as its input + * a UTF-8 encoded String which has <b>not</b> been escaped using whatever + * escaping scheme data format requires (for JSON that is backslash-escaping + * for control characters and double-quotes; for other formats something else). + * This means that textual JSON backends need to check if value needs + * JSON escaping, but otherwise can just be copied as is to output. + * Also, quoting that data format requires (like double-quotes for JSON) will be added + * around the value if and as necessary. + *<p> + * Note that some backends may choose not to support this method: for + * example, if underlying destination is a {@link java.io.Writer} + * using this method would require UTF-8 decoding. + * In this case + * generator implementation may instead choose to throw a + * {@link UnsupportedOperationException} due to ineffectiveness + * of having to decode input. + * + * @since 1.7 + */ + public abstract void writeUTF8String(byte[] text, int offset, int length) + throws IOException, JsonGenerationException; + + /* + /********************************************************** + /* Public API, write methods, binary/raw content + /********************************************************** + */ + + /** + * Method that will force generator to copy + * input text verbatim with <b>no</b> modifications (including + * that no escaping is done and no separators are added even + * if context [array, object] would otherwise require such). + * If such separators are desired, use + * {@link #writeRawValue(String)} instead. + *<p> + * Note that not all generator implementations necessarily support + * such by-pass methods: those that do not will throw + * {@link UnsupportedOperationException}. + */ + public abstract void writeRaw(String text) + throws IOException, JsonGenerationException; + + /** + * Method that will force generator to copy + * input text verbatim with <b>no</b> modifications (including + * that no escaping is done and no separators are added even + * if context [array, object] would otherwise require such). + * If such separators are desired, use + * {@link #writeRawValue(String)} instead. + *<p> + * Note that not all generator implementations necessarily support + * such by-pass methods: those that do not will throw + * {@link UnsupportedOperationException}. + */ + public abstract void writeRaw(String text, int offset, int len) + throws IOException, JsonGenerationException; + + /** + * Method that will force generator to copy + * input text verbatim with <b>no</b> modifications (including + * that no escaping is done and no separators are added even + * if context [array, object] would otherwise require such). + * If such separators are desired, use + * {@link #writeRawValue(String)} instead. + *<p> + * Note that not all generator implementations necessarily support + * such by-pass methods: those that do not will throw + * {@link UnsupportedOperationException}. + */ + public abstract void writeRaw(char[] text, int offset, int len) + throws IOException, JsonGenerationException; + + /** + * Method that will force generator to copy + * input text verbatim with <b>no</b> modifications (including + * that no escaping is done and no separators are added even + * if context [array, object] would otherwise require such). + * If such separators are desired, use + * {@link #writeRawValue(String)} instead. + *<p> + * Note that not all generator implementations necessarily support + * such by-pass methods: those that do not will throw + * {@link UnsupportedOperationException}. + */ + public abstract void writeRaw(char c) + throws IOException, JsonGenerationException; + + /** + * Method that will force generator to copy + * input text verbatim without any modifications, but assuming + * it must constitute a single legal JSON value (number, string, + * boolean, null, Array or List). Assuming this, proper separators + * are added if and as needed (comma or colon), and generator + * state updated to reflect this. + */ + public abstract void writeRawValue(String text) + throws IOException, JsonGenerationException; + + public abstract void writeRawValue(String text, int offset, int len) + throws IOException, JsonGenerationException; + + public abstract void writeRawValue(char[] text, int offset, int len) + throws IOException, JsonGenerationException; + + /** + * Method that will output given chunk of binary data as base64 + * encoded, as a complete String value (surrounded by double quotes). + * This method defaults + *<p> + * Note: because Json Strings can not contain unescaped linefeeds, + * if linefeeds are included (as per last argument), they must be + * escaped. This adds overhead for decoding without improving + * readability. + * Alternatively if linefeeds are not included, + * resulting String value may violate the requirement of base64 + * RFC which mandates line-length of 76 characters and use of + * linefeeds. However, all {@link JsonParser} implementations + * are required to accept such "long line base64"; as do + * typical production-level base64 decoders. + * + * @param b64variant Base64 variant to use: defines details such as + * whether padding is used (and if so, using which character); + * what is the maximum line length before adding linefeed, + * and also the underlying alphabet to use. + */ + public abstract void writeBinary(Base64Variant b64variant, + byte[] data, int offset, int len) + throws IOException, JsonGenerationException; + + /** + * Similar to {@link #writeBinary(Base64Variant,byte[],int,int)}, + * but default to using the Jackson default Base64 variant + * (which is {@link Base64Variants#MIME_NO_LINEFEEDS}). + */ + public void writeBinary(byte[] data, int offset, int len) + throws IOException, JsonGenerationException + { + writeBinary(Base64Variants.getDefaultVariant(), data, offset, len); + } + + /** + * Similar to {@link #writeBinary(Base64Variant,byte[],int,int)}, + * but assumes default to using the Jackson default Base64 variant + * (which is {@link Base64Variants#MIME_NO_LINEFEEDS}). Also + * assumes that whole byte array is to be output. + */ + public void writeBinary(byte[] data) + throws IOException, JsonGenerationException + { + writeBinary(Base64Variants.getDefaultVariant(), data, 0, data.length); + } + + /* + /********************************************************** + /* Public API, write methods, other value types + /********************************************************** + */ + + /** + * Method for outputting given value as Json number. + * Can be called in any context where a value is expected + * (Array value, Object field value, root-level value). + * Additional white space may be added around the value + * if pretty-printing is enabled. + */ + public abstract void writeNumber(int v) + throws IOException, JsonGenerationException; + + /** + * Method for outputting given value as Json number. + * Can be called in any context where a value is expected + * (Array value, Object field value, root-level value). + * Additional white space may be added around the value + * if pretty-printing is enabled. + */ + public abstract void writeNumber(long v) + throws IOException, JsonGenerationException; + + /** + * Method for outputting given value as Json number. + * Can be called in any context where a value is expected + * (Array value, Object field value, root-level value). + * Additional white space may be added around the value + * if pretty-printing is enabled. + */ + public abstract void writeNumber(BigInteger v) + throws IOException, JsonGenerationException; + + /** + * Method for outputting indicate Json numeric value. + * Can be called in any context where a value is expected + * (Array value, Object field value, root-level value). + * Additional white space may be added around the value + * if pretty-printing is enabled. + */ + public abstract void writeNumber(double d) + throws IOException, JsonGenerationException; + + /** + * Method for outputting indicate Json numeric value. + * Can be called in any context where a value is expected + * (Array value, Object field value, root-level value). + * Additional white space may be added around the value + * if pretty-printing is enabled. + */ + public abstract void writeNumber(float f) + throws IOException, JsonGenerationException; + + /** + * Method for outputting indicate Json numeric value. + * Can be called in any context where a value is expected + * (Array value, Object field value, root-level value). + * Additional white space may be added around the value + * if pretty-printing is enabled. + */ + public abstract void writeNumber(BigDecimal dec) + throws IOException, JsonGenerationException; + + /** + * Write method that can be used for custom numeric types that can + * not be (easily?) converted to "standard" Java number types. + * Because numbers are not surrounded by double quotes, regular + * {@link #writeString} method can not be used; nor + * {@link #writeRaw} because that does not properly handle + * value separators needed in Array or Object contexts. + *<p> + * Note: because of lack of type safety, some generator + * implementations may not be able to implement this + * method. For example, if a binary json format is used, + * it may require type information for encoding; similarly + * for generator-wrappers around Java objects or Json nodes. + * If implementation does not implement this method, + * it needs to throw {@link UnsupportedOperationException}. + */ + public abstract void writeNumber(String encodedValue) + throws IOException, JsonGenerationException, + UnsupportedOperationException; + + /** + * Method for outputting literal Json boolean value (one of + * Strings 'true' and 'false'). + * Can be called in any context where a value is expected + * (Array value, Object field value, root-level value). + * Additional white space may be added around the value + * if pretty-printing is enabled. + */ + public abstract void writeBoolean(boolean state) + throws IOException, JsonGenerationException; + + /** + * Method for outputting literal Json null value. + * Can be called in any context where a value is expected + * (Array value, Object field value, root-level value). + * Additional white space may be added around the value + * if pretty-printing is enabled. + */ + public abstract void writeNull() + throws IOException, JsonGenerationException; + + /* + /********************************************************** + /* Public API, write methods, serializing Java objects + /********************************************************** + */ + + /** + * Method for writing given Java object (POJO) as Json. + * Exactly how the object gets written depends on object + * in question (ad on codec, its configuration); for most + * beans it will result in Json object, but for others Json + * array, or String or numeric value (and for nulls, Json + * null literal. + * <b>NOTE</b>: generator must have its <b>object codec</b> + * set to non-null value; for generators created by a mapping + * factory this is the case, for others not. + */ + public abstract void writeObject(Object pojo) + throws IOException, JsonProcessingException; + + /** + * Method for writing given JSON tree (expressed as a tree + * where given JsonNode is the root) using this generator. + * This will generally just call + * {@link #writeObject} with given node, but is added + * for convenience and to make code more explicit in cases + * where it deals specifically with trees. + */ + public abstract void writeTree(JsonNode rootNode) + throws IOException, JsonProcessingException; + + /* + /********************************************************** + /* Public API, convenience field write methods + /********************************************************** + */ + + /** + * Convenience method for outputting a field entry ("member") + * that has a String value. Equivalent to: + *<pre> + * writeFieldName(fieldName); + * writeString(value); + *</pre> + *<p> + * Note: many performance-sensitive implementations override this method + */ + public void writeStringField(String fieldName, String value) + throws IOException, JsonGenerationException + { + writeFieldName(fieldName); + writeString(value); + } + + /** + * Convenience method for outputting a field entry ("member") + * that has a boolean value. Equivalent to: + *<pre> + * writeFieldName(fieldName); + * writeBoolean(value); + *</pre> + */ + public final void writeBooleanField(String fieldName, boolean value) + throws IOException, JsonGenerationException + { + writeFieldName(fieldName); + writeBoolean(value); + } + + /** + * Convenience method for outputting a field entry ("member") + * that has JSON literal value null. Equivalent to: + *<pre> + * writeFieldName(fieldName); + * writeNull(); + *</pre> + */ + public final void writeNullField(String fieldName) + throws IOException, JsonGenerationException + { + writeFieldName(fieldName); + writeNull(); + } + /** + * Convenience method for outputting a field entry ("member") + * that has the specified numeric value. Equivalent to: + *<pre> + * writeFieldName(fieldName); + * writeNumber(value); + *</pre> + */ + public final void writeNumberField(String fieldName, int value) + throws IOException, JsonGenerationException + { + writeFieldName(fieldName); + writeNumber(value); + } + + /** + * Convenience method for outputting a field entry ("member") + * that has the specified numeric value. Equivalent to: + *<pre> + * writeFieldName(fieldName); + * writeNumber(value); + *</pre> + */ + public final void writeNumberField(String fieldName, long value) + throws IOException, JsonGenerationException + { + writeFieldName(fieldName); + writeNumber(value); + } + + /** + * Convenience method for outputting a field entry ("member") + * that has the specified numeric value. Equivalent to: + *<pre> + * writeFieldName(fieldName); + * writeNumber(value); + *</pre> + */ + public final void writeNumberField(String fieldName, double value) + throws IOException, JsonGenerationException + { + writeFieldName(fieldName); + writeNumber(value); + } + + /** + * Convenience method for outputting a field entry ("member") + * that has the specified numeric value. Equivalent to: + *<pre> + * writeFieldName(fieldName); + * writeNumber(value); + *</pre> + */ + public final void writeNumberField(String fieldName, float value) + throws IOException, JsonGenerationException + { + writeFieldName(fieldName); + writeNumber(value); + } + + /** + * Convenience method for outputting a field entry ("member") + * that has the specified numeric value. + * Equivalent to: + *<pre> + * writeFieldName(fieldName); + * writeNumber(value); + *</pre> + */ + public final void writeNumberField(String fieldName, BigDecimal value) + throws IOException, JsonGenerationException + { + writeFieldName(fieldName); + writeNumber(value); + } + + /** + * Convenience method for outputting a field entry ("member") + * that contains specified data in base64-encoded form. + * Equivalent to: + *<pre> + * writeFieldName(fieldName); + * writeBinary(value); + *</pre> + */ + public final void writeBinaryField(String fieldName, byte[] data) + throws IOException, JsonGenerationException + { + writeFieldName(fieldName); + writeBinary(data); + } + + /** + * Convenience method for outputting a field entry ("member") + * (that will contain a JSON Array value), and the START_ARRAY marker. + * Equivalent to: + *<pre> + * writeFieldName(fieldName); + * writeStartArray(); + *</pre> + *<p> + * Note: caller still has to take care to close the array + * (by calling {#link #writeEndArray}) after writing all values + * of the value Array. + */ + public final void writeArrayFieldStart(String fieldName) + throws IOException, JsonGenerationException + { + writeFieldName(fieldName); + writeStartArray(); + } + + /** + * Convenience method for outputting a field entry ("member") + * (that will contain a JSON Object value), and the START_OBJECT marker. + * Equivalent to: + *<pre> + * writeFieldName(fieldName); + * writeStartObject(); + *</pre> + *<p> + * Note: caller still has to take care to close the Object + * (by calling {#link #writeEndObject}) after writing all + * entries of the value Object. + */ + public final void writeObjectFieldStart(String fieldName) + throws IOException, JsonGenerationException + { + writeFieldName(fieldName); + writeStartObject(); + } + + /** + * Convenience method for outputting a field entry ("member") + * that has contents of specific Java object as its value. + * Equivalent to: + *<pre> + * writeFieldName(fieldName); + * writeObject(pojo); + *</pre> + */ + public final void writeObjectField(String fieldName, Object pojo) + throws IOException, JsonProcessingException + { + writeFieldName(fieldName); + writeObject(pojo); + } + + /* + /********************************************************** + /* Public API, copy-through methods + /********************************************************** + */ + + /** + * Method for copying contents of the current event that + * the given parser instance points to. + * Note that the method <b>will not</b> copy any other events, + * such as events contained within Json Array or Object structures. + *<p> + * Calling this method will not advance the given + * parser, although it may cause parser to internally process + * more data (if it lazy loads contents of value events, for example) + */ + public abstract void copyCurrentEvent(JsonParser jp) + throws IOException, JsonProcessingException; + + /** + * Method for copying contents of the current event + * <b>and following events that it encloses</b> + * the given parser instance points to. + *<p> + * So what constitutes enclosing? Here is the list of + * events that have associated enclosed events that will + * get copied: + *<ul> + * <li>{@link JsonToken#START_OBJECT}: + * all events up to and including matching (closing) + * {@link JsonToken#END_OBJECT} will be copied + * </li> + * <li>{@link JsonToken#START_ARRAY} + * all events up to and including matching (closing) + * {@link JsonToken#END_ARRAY} will be copied + * </li> + * <li>{@link JsonToken#FIELD_NAME} the logical value (which + * can consist of a single scalar value; or a sequence of related + * events for structured types (Json Arrays, Objects)) will + * be copied along with the name itself. So essentially the + * whole <b>field entry</b> (name and value) will be copied. + * </li> + *</ul> + *<p> + * After calling this method, parser will point to the + * <b>last event</b> that was copied. This will either be + * the event parser already pointed to (if there were no + * enclosed events), or the last enclosed event copied. + */ + public abstract void copyCurrentStructure(JsonParser jp) + throws IOException, JsonProcessingException; + + /* + /********************************************************** + /* Public API, context access + /********************************************************** + */ + + /** + * @return Context object that can give information about logical + * position within generated json content. + */ + public abstract JsonStreamContext getOutputContext(); + + /* + /********************************************************** + /* Public API, buffer handling + /********************************************************** + */ + + /** + * Method called to flush any buffered content to the underlying + * target (output stream, writer), and to flush the target itself + * as well. + */ + public abstract void flush() throws IOException; + + /** + * Method that can be called to determine whether this generator + * is closed or not. If it is closed, no more output can be done. + */ + public abstract boolean isClosed(); + + /* + /********************************************************** + /* Closeable implementation + /********************************************************** + */ + + /** + * Method called to close this generator, so that no more content + * can be written. + *<p> + * Whether the underlying target (stream, writer) gets closed depends + * on whether this generator either manages the target (i.e. is the + * only one with access to the target -- case if caller passes a + * reference to the resource such as File, but not stream); or + * has feature {@link Feature#AUTO_CLOSE_TARGET} enabled. + * If either of above is true, the target is also closed. Otherwise + * (not managing, feature not enabled), target is not closed. + */ + @Override + public abstract void close() + throws IOException; +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/JsonLocation.java b/1.9.10/src/java/org/codehaus/jackson/JsonLocation.java new file mode 100644 index 0000000..a861b5c --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/JsonLocation.java
@@ -0,0 +1,141 @@ +package org.codehaus.jackson; + +import org.codehaus.jackson.annotate.JsonCreator; +import org.codehaus.jackson.annotate.JsonProperty; + +/** + * Object that encapsulates Location information used for reporting + * parsing (or potentially generation) errors, as well as current location + * within input streams. + */ +public class JsonLocation + implements java.io.Serializable // as per [JACKSON-168] +{ + private static final long serialVersionUID = 1L; + + /** + * Shared immutable "N/A location" that can be returned to indicate + * that no location information is available + * + * @since 1.3 + */ + public final static JsonLocation NA = new JsonLocation("N/A", -1L, -1L, -1, -1); + + final long _totalBytes; + final long _totalChars; + + final int _lineNr; + final int _columnNr; + + /** + * Displayable description for input source: file path, url + */ + final Object _sourceRef; + + public JsonLocation(Object srcRef, long totalChars, int lineNr, int colNr) + { + /* Unfortunately, none of legal encodings are straight single-byte + * encodings. Could determine offset for UTF-16/UTF-32, but the + * most important one is UTF-8... + * so for now, we'll just not report any real byte count + */ + this(srcRef, -1L, totalChars, lineNr, colNr); + } + + @JsonCreator + public JsonLocation(@JsonProperty("sourceRef") Object sourceRef, + @JsonProperty("byteOffset") long totalBytes, + @JsonProperty("charOffset") long totalChars, + @JsonProperty("lineNr") int lineNr, + @JsonProperty("columnNr") int columnNr) + { + _sourceRef = sourceRef; + _totalBytes = totalBytes; + _totalChars = totalChars; + _lineNr = lineNr; + _columnNr = columnNr; + } + + /** + * Reference to the original resource being read, if one available. + * For example, when a parser has been constructed by passing + * a {@link java.io.File} instance, this method would return + * that File. Will return null if no such reference is available, + * for example when {@link java.io.InputStream} was used to + * construct the parser instance. + */ + public Object getSourceRef() { return _sourceRef; } + + /** + * @return Line number of the location (1-based) + */ + public int getLineNr() { return _lineNr; } + + /** + * @return Column number of the location (1-based) + */ + public int getColumnNr() { return _columnNr; } + + /** + * @return Character offset within underlying stream, reader or writer, + * if available; -1 if not. + */ + public long getCharOffset() { return _totalChars; } + + /** + * @return Byte offset within underlying stream, reader or writer, + * if available; -1 if not. + */ + public long getByteOffset() + { + return _totalBytes; + } + + @Override + public String toString() + { + StringBuilder sb = new StringBuilder(80); + sb.append("[Source: "); + if (_sourceRef == null) { + sb.append("UNKNOWN"); + } else { + sb.append(_sourceRef.toString()); + } + sb.append("; line: "); + sb.append(_lineNr); + sb.append(", column: "); + sb.append(_columnNr); + sb.append(']'); + return sb.toString(); + } + + @Override + public int hashCode() + { + int hash = (_sourceRef == null) ? 1 : _sourceRef.hashCode(); + hash ^= _lineNr; + hash += _columnNr; + hash ^= (int) _totalChars; + hash += (int) _totalBytes; + return hash; + } + + @Override + public boolean equals(Object other) + { + if (other == this) return true; + if (other == null) return false; + if (!(other instanceof JsonLocation)) return false; + JsonLocation otherLoc = (JsonLocation) other; + + if (_sourceRef == null) { + if (otherLoc._sourceRef != null) return false; + } else if (!_sourceRef.equals(otherLoc._sourceRef)) return false; + + return (_lineNr == otherLoc._lineNr) + && (_columnNr == otherLoc._columnNr) + && (_totalChars == otherLoc._totalChars) + && (getByteOffset() == otherLoc.getByteOffset()) + ; + } +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/JsonNode.java b/1.9.10/src/java/org/codehaus/jackson/JsonNode.java new file mode 100644 index 0000000..db51828 --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/JsonNode.java
@@ -0,0 +1,879 @@ +package org.codehaus.jackson; + +import java.io.IOException; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.*; + +/** + * Base class for all JSON nodes, which form the basis of JSON + * Tree Model that Jackson implements. + * One way to think of these nodes is to consider them + * similar to DOM nodes in XML DOM trees. + *<p> + * As a general design rule, most accessors ("getters") are included + * in this base class, to allow for traversing structure without + * type casts. Most mutators, however, need to be accessed through + * specific sub-classes (such as <code>org.codehaus.jackson.node.ObjectNode</code> + * and <code>org.codehaus.jackson.node.ArrayNode</code>). + * This seems sensible because proper type + * information is generally available when building or modifying + * trees, but less often when reading a tree (newly built from + * parsed JSON content). + *<p> + * Actual concrete sub-classes can be found from package + * {@link org.codehaus.jackson.node}, which is in 'mapper' jar + * (whereas this class is in 'core' jar, since it is declared as + * nominal type for operations in {@link ObjectCodec}) + */ +public abstract class JsonNode + implements Iterable<JsonNode> +{ + protected final static List<JsonNode> NO_NODES = Collections.emptyList(); + protected final static List<String> NO_STRINGS = Collections.emptyList(); + + protected JsonNode() { } + + /* + /********************************************************** + /* Public API, type introspection + /********************************************************** + */ + + // // First high-level division between values, containers and "missing" + + /** + * Method that returns true for all value nodes: ones that + * are not containers, and that do not represent "missing" nodes + * in the path. Such value nodes represent String, Number, Boolean + * and null values from JSON. + *<p> + * Note: one and only one of methods {@link #isValueNode}, + * {@link #isContainerNode} and {@link #isMissingNode} ever + * returns true for any given node. + */ + public boolean isValueNode() { return false; } + + /** + * Method that returns true for container nodes: Arrays and Objects. + *<p> + * Note: one and only one of methods {@link #isValueNode}, + * {@link #isContainerNode} and {@link #isMissingNode} ever + * returns true for any given node. + */ + public boolean isContainerNode() { return false; } + + /** + * Method that returns true for "virtual" nodes which represent + * missing entries constructed by path accessor methods when + * there is no actual node matching given criteria. + *<p> + * Note: one and only one of methods {@link #isValueNode}, + * {@link #isContainerNode} and {@link #isMissingNode} ever + * returns true for any given node. + */ + public boolean isMissingNode() { return false; } + + // // Then more specific type introspection + // // (along with defaults to be overridden) + + /** + * @return True if this node represents Json Array + */ + public boolean isArray() { return false; } + + /** + * @return True if this node represents Json Object + */ + public boolean isObject() { return false; } + + /** + * Method that can be used to check if the node is a wrapper + * for a POJO ("Plain Old Java Object" aka "bean". + * Returns true only for + * instances of {@link org.codehaus.jackson.node.POJONode}. + * + * @return True if this node wraps a POJO + */ + public boolean isPojo() { return false; } + + /** + * @return True if this node represents a numeric Json + * value + */ + public boolean isNumber() { return false; } + + /** + * @return True if this node represents an integral (integer) + * numeric Json value + */ + public boolean isIntegralNumber() { return false; } + + /** + * @return True if this node represents a non-integral + * numeric Json value + */ + public boolean isFloatingPointNumber() { return false; } + + /** + * @return True if this node represents an integral + * numeric Json value that withs in Java int value space + */ + public boolean isInt() { return false; } + + /** + * @return True if this node represents an integral + * numeric Json value that fits in Java long value space + * (but not int value space, i.e. {@link #isInt} returns false) + */ + public boolean isLong() { return false; } + + public boolean isDouble() { return false; } + public boolean isBigDecimal() { return false; } + public boolean isBigInteger() { return false; } + + public boolean isTextual() { return false; } + + /** + * Method that can be used to check if this node was created from + * Json boolean value (literals "true" and "false"). + */ + public boolean isBoolean() { return false; } + + /** + * Method that can be used to check if this node was created from + * Json liternal null value. + */ + public boolean isNull() { return false; } + + /** + * Method that can be used to check if this node represents + * binary data (Base64 encoded). Although this will be externally + * written as Json String value, {@link #isTextual} will + * return false if this method returns true. + * + * @return True if this node represents base64 encoded binary data + */ + public boolean isBinary() { return false; } + + /** + * Method that can be used for efficient type detection + * when using stream abstraction for traversing nodes. + * Will return the first {@link JsonToken} that equivalent + * stream event would produce (for most nodes there is just + * one token but for structured/container types multiple) + * + * @since 1.3 + */ + public abstract JsonToken asToken(); + + /** + * If this node is a numeric type (as per {@link #isNumber}), + * returns native type that node uses to store the numeric + * value. + */ + public abstract JsonParser.NumberType getNumberType(); + + /* + /********************************************************** + /* Public API, straight value access + /********************************************************** + */ + + /** + * Method to use for accessing String values. + * Does <b>NOT</b> do any conversions for non-String value nodes; + * for non-String values (ones for which {@link #isTextual} returns + * false) null will be returned. + * For String values, null is never returned (but empty Strings may be) + * + * @return Textual value this node contains, iff it is a textual + * json node (comes from Json String value entry) + */ + public String getTextValue() { return null; } + + /** + * Method to use for accessing binary content of binary nodes (nodes + * for which {@link #isBinary} returns true); or for Text Nodes + * (ones for which {@link #getTextValue} returns non-null value), + * to read decoded base64 data. + * For other types of nodes, returns null. + * + * @return Binary data this node contains, iff it is a binary + * node; null otherwise + */ + public byte[] getBinaryValue() throws IOException + { + return null; + } + + /** + * Method to use for accessing JSON boolean values (value + * literals 'true' and 'false'). + * For other types, always returns false. + * + * @return Textual value this node contains, iff it is a textual + * json node (comes from Json String value entry) + */ + public boolean getBooleanValue() { return false; } + + /** + * Returns numeric value for this node, <b>if and only if</b> + * this node is numeric ({@link #isNumber} returns true); otherwise + * returns null + * + * @return Number value this node contains, if any (null for non-number + * nodes). + */ + public Number getNumberValue() { return null; } + + /** + * Returns integer value for this node, <b>if and only if</b> + * this node is numeric ({@link #isNumber} returns true). For other + * types returns 0. + * For floating-point numbers, value is truncated using default + * Java coercion, similar to how cast from double to int operates. + * + * @return Integer value this node contains, if any; 0 for non-number + * nodes. + */ + public int getIntValue() { return 0; } + + public long getLongValue() { return 0L; } + public double getDoubleValue() { return 0.0; } + public BigDecimal getDecimalValue() { return BigDecimal.ZERO; } + public BigInteger getBigIntegerValue() { return BigInteger.ZERO; } + + /** + * Method for accessing value of the specified element of + * an array node. For other nodes, null is always returned. + *<p> + * For array nodes, index specifies + * exact location within array and allows for efficient iteration + * over child elements (underlying storage is guaranteed to + * be efficiently indexable, i.e. has random-access to elements). + * If index is less than 0, or equal-or-greater than + * <code>node.size()</code>, null is returned; no exception is + * thrown for any index. + * + * @return Node that represent value of the specified element, + * if this node is an array and has specified element. + * Null otherwise. + */ + public JsonNode get(int index) { return null; } + + /** + * Method for accessing value of the specified field of + * an object node. If this node is not an object (or it + * does not have a value for specified field name), or + * if there is no field with such name, null is returned. + * + * @return Node that represent value of the specified field, + * if this node is an object and has value for the specified + * field. Null otherwise. + */ + public JsonNode get(String fieldName) { return null; } + + /* + /********************************************************** + /* Public API, value access with conversion(s)/coercion(s) + /********************************************************** + */ + + /** + * Method that will return valid String representation of + * the container value, if the node is a value node + * (method {@link #isValueNode} returns true), otherwise + * empty String. + * + * @since 1.9 (replaces <code>getValueAsText</code>) + */ + public abstract String asText(); + + /** + * Method that will try to convert value of this node to a Java <b>int</b>. + * Numbers are coerced using default Java rules; booleans convert to 0 (false) + * and 1 (true), and Strings are parsed using default Java language integer + * parsing rules. + *<p> + * If representation can not be converted to an int (including structured types + * like Objects and Arrays), + * default value of <b>0</b> will be returned; no exceptions are thrown. + * + * @since 1.9 (replaces <code>getValueAsInt</code>) + */ + public int asInt() { + return asInt(0); + } + + /** + * Method that will try to convert value of this node to a Java <b>int</b>. + * Numbers are coerced using default Java rules; booleans convert to 0 (false) + * and 1 (true), and Strings are parsed using default Java language integer + * parsing rules. + *<p> + * If representation can not be converted to an int (including structured types + * like Objects and Arrays), + * specified <b>defaultValue</b> will be returned; no exceptions are thrown. + * + * @since 1.9 (replaces <code>getValueAsInt</code>) + */ + public int asInt(int defaultValue) { + return defaultValue; + } + + /** + * Method that will try to convert value of this node to a Java <b>long</b>. + * Numbers are coerced using default Java rules; booleans convert to 0 (false) + * and 1 (true), and Strings are parsed using default Java language integer + * parsing rules. + *<p> + * If representation can not be converted to an long (including structured types + * like Objects and Arrays), + * default value of <b>0</b> will be returned; no exceptions are thrown. + * + * @since 1.9 (replaces <code>getValueAsLong</code>) + */ + public long asLong() { + return asLong(0L); + } + + /** + * Method that will try to convert value of this node to a Java <b>long</b>. + * Numbers are coerced using default Java rules; booleans convert to 0 (false) + * and 1 (true), and Strings are parsed using default Java language integer + * parsing rules. + *<p> + * If representation can not be converted to an long (including structured types + * like Objects and Arrays), + * specified <b>defaultValue</b> will be returned; no exceptions are thrown. + * + * @since 1.9 (replaces <code>getValueAsLong</code>) + */ + public long asLong(long defaultValue) { + return defaultValue; + } + + /** + * Method that will try to convert value of this node to a Java <b>double</b>. + * Numbers are coerced using default Java rules; booleans convert to 0.0 (false) + * and 1.0 (true), and Strings are parsed using default Java language integer + * parsing rules. + *<p> + * If representation can not be converted to an int (including structured types + * like Objects and Arrays), + * default value of <b>0.0</b> will be returned; no exceptions are thrown. + * + * @since 1.9 (replaces <code>getValueAsDouble</code>) + */ + public double asDouble() { + return asDouble(0.0); + } + + /** + * Method that will try to convert value of this node to a Java <b>double</b>. + * Numbers are coerced using default Java rules; booleans convert to 0.0 (false) + * and 1.0 (true), and Strings are parsed using default Java language integer + * parsing rules. + *<p> + * If representation can not be converted to an int (including structured types + * like Objects and Arrays), + * specified <b>defaultValue</b> will be returned; no exceptions are thrown. + * + * @since 1.9 (replaces <code>getValueAsLong</code>) + */ + public double asDouble(double defaultValue) { + return defaultValue; + } + + /** + * Method that will try to convert value of this node to a Java <b>boolean</b>. + * JSON booleans map naturally; integer numbers other than 0 map to true, and + * 0 maps to false + * and Strings 'true' and 'false' map to corresponding values. + *<p> + * If representation can not be converted to a boolean value (including structured types + * like Objects and Arrays), + * default value of <b>false</b> will be returned; no exceptions are thrown. + * + * @since 1.9 (replaces <code>getValueAsBoolean</code>) + */ + public boolean asBoolean() { + return asBoolean(false); + } + + /** + * Method that will try to convert value of this node to a Java <b>boolean</b>. + * JSON booleans map naturally; integer numbers other than 0 map to true, and + * 0 maps to false + * and Strings 'true' and 'false' map to corresponding values. + *<p> + * If representation can not be converted to a boolean value (including structured types + * like Objects and Arrays), + * specified <b>defaultValue</b> will be returned; no exceptions are thrown. + * + * @since 1.9 (replaces <code>getValueAsBoolean</code>) + */ + public boolean asBoolean(boolean defaultValue) { + return defaultValue; + } + + /* + /********************************************************** + /* Public API, value access with conversion(s)/coercion(s) + /********************************************************** + */ + + /** + * Method that will return valid String representation of + * the container value, if the node is a value node + * (method {@link #isValueNode} returns true), otherwise null. + *<p> + * Note: to serialize nodes of any type, you should call + * {@link #toString} instead. + * + * @deprecated Since 1.9, use {@link #asText} instead + */ + @Deprecated + public String getValueAsText() { return asText(); } + + /** + * Method that will try to convert value of this node to a Java <b>int</b>. + * Numbers are coerced using default Java rules; booleans convert to 0 (false) + * and 1 (true), and Strings are parsed using default Java language integer + * parsing rules. + *<p> + * If representation can not be converted to an int (including structured types + * like Objects and Arrays), + * default value of <b>0</b> will be returned; no exceptions are thrown. + * + * @since 1.6 + * + * @deprecated Since 1.9, use {@link #asInt} instead + */ + @Deprecated + public int getValueAsInt() { return asInt(0); } + + /** + * Method that will try to convert value of this node to a Java <b>int</b>. + * Numbers are coerced using default Java rules; booleans convert to 0 (false) + * and 1 (true), and Strings are parsed using default Java language integer + * parsing rules. + *<p> + * If representation can not be converted to an int (including structured types + * like Objects and Arrays), + * specified <b>defaultValue</b> will be returned; no exceptions are thrown. + * + * @since 1.6 + * + * @deprecated Since 1.9, use {@link #asInt} instead + */ + @Deprecated + public int getValueAsInt(int defaultValue) { return asInt(defaultValue); } + + /** + * Method that will try to convert value of this node to a Java <b>long</b>. + * Numbers are coerced using default Java rules; booleans convert to 0 (false) + * and 1 (true), and Strings are parsed using default Java language integer + * parsing rules. + *<p> + * If representation can not be converted to an long (including structured types + * like Objects and Arrays), + * default value of <b>0</b> will be returned; no exceptions are thrown. + * + * @since 1.6 + * + * @deprecated Since 1.9, use {@link #asLong} instead + */ + @Deprecated + public long getValueAsLong() { return asLong(0L); } + + /** + * Method that will try to convert value of this node to a Java <b>long</b>. + * Numbers are coerced using default Java rules; booleans convert to 0 (false) + * and 1 (true), and Strings are parsed using default Java language integer + * parsing rules. + *<p> + * If representation can not be converted to an long (including structured types + * like Objects and Arrays), + * specified <b>defaultValue</b> will be returned; no exceptions are thrown. + * + * @since 1.6 + * + * @deprecated Since 1.9, use {@link #asLong} instead + */ + @Deprecated + public long getValueAsLong(long defaultValue) { return asLong(defaultValue); } + + /** + * Method that will try to convert value of this node to a Java <b>double</b>. + * Numbers are coerced using default Java rules; booleans convert to 0.0 (false) + * and 1.0 (true), and Strings are parsed using default Java language integer + * parsing rules. + *<p> + * If representation can not be converted to an int (including structured types + * like Objects and Arrays), + * default value of <b>0.0</b> will be returned; no exceptions are thrown. + * + * @since 1.6 + * + * @deprecated Since 1.9, use {@link #asDouble} instead + */ + @Deprecated + public double getValueAsDouble() { return asDouble(0.0); } + + /** + * Method that will try to convert value of this node to a Java <b>double</b>. + * Numbers are coerced using default Java rules; booleans convert to 0.0 (false) + * and 1.0 (true), and Strings are parsed using default Java language integer + * parsing rules. + *<p> + * If representation can not be converted to an int (including structured types + * like Objects and Arrays), + * specified <b>defaultValue</b> will be returned; no exceptions are thrown. + * + * @since 1.6 + * + * @deprecated Since 1.9, use {@link #asDouble} instead + */ + @Deprecated + public double getValueAsDouble(double defaultValue) { return asDouble(defaultValue); } + + /** + * Method that will try to convert value of this node to a Java <b>boolean</b>. + * JSON booleans map naturally; integer numbers other than 0 map to true, and + * 0 maps to false + * and Strings 'true' and 'false' map to corresponding values. + *<p> + * If representation can not be converted to a boolean value (including structured types + * like Objects and Arrays), + * default value of <b>false</b> will be returned; no exceptions are thrown. + * + * @since 1.7 + * + * @deprecated Since 1.9, use {@link #asBoolean} instead + */ + @Deprecated + public boolean getValueAsBoolean() { return asBoolean(false); } + + /** + * Method that will try to convert value of this node to a Java <b>boolean</b>. + * JSON booleans map naturally; integer numbers other than 0 map to true, and + * 0 maps to false + * and Strings 'true' and 'false' map to corresponding values. + *<p> + * If representation can not be converted to a boolean value (including structured types + * like Objects and Arrays), + * specified <b>defaultValue</b> will be returned; no exceptions are thrown. + * + * @since 1.7 + * + * @deprecated Since 1.9, use {@link #asBoolean} instead + */ + @Deprecated + public boolean getValueAsBoolean(boolean defaultValue) { return asBoolean(defaultValue); } + + /* + /********************************************************** + /* Public API, value find / existence check methods + /********************************************************** + */ + + /** + * Method that allows checking whether this node is JSON Object node + * and contains value for specified property. If this is the case + * (including properties with explicit null values), returns true; + * otherwise returns false. + *<p> + * This method is equivalent to: + *<pre> + * node.get(fieldName) != null + *</pre> + * (since return value of get() is node, not value node contains) + * + * @param fieldName Name of element to check + * + * @return True if this node is a JSON Object node, and has a property + * entry with specified name (with any value, including null value) + * + * @since 1.6 + */ + public boolean has(String fieldName) { + return get(fieldName) != null; + } + + /** + * Method that allows checking whether this node is JSON Array node + * and contains a value for specified index + * If this is the case + * (including case of specified indexing having null as value), returns true; + * otherwise returns false. + *<p> + * Note: array element indexes are 0-based. + *<p> + * This method is equivalent to: + *<pre> + * node.get(index) != null + *</pre> + * + * @param index Index to check + * + * @return True if this node is a JSON Object node, and has a property + * entry with specified name (with any value, including null value) + * + * @since 1.6 + */ + public boolean has(int index) { + return get(index) != null; + } + + /** + * Method for finding a JSON Object field with specified name in this + * node or its child nodes, and returning value it has. + * If no matching field is found in this node or its descendants, returns null. + * + * @param fieldName Name of field to look for + * + * @return Value of first matching node found, if any; null if none + * + * @since 1.6 + */ + public abstract JsonNode findValue(String fieldName); + + /** + * Method for finding JSON Object fields with specified name, and returning + * found ones as a List. Note that sub-tree search ends if a field is found, + * so possible children of result nodes are <b>not</b> included. + * If no matching fields are found in this node or its descendants, returns + * an empty List. + * + * @param fieldName Name of field to look for + * + * @since 1.6 + */ + public final List<JsonNode> findValues(String fieldName) + { + List<JsonNode> result = findValues(fieldName, null); + if (result == null) { + return Collections.emptyList(); + } + return result; + } + + /** + * Similar to {@link #findValues}, but will additionally convert + * values into Strings, calling {@link #getValueAsText}. + * + * @since 1.6 + */ + public final List<String> findValuesAsText(String fieldName) + { + List<String> result = findValuesAsText(fieldName, null); + if (result == null) { + return Collections.emptyList(); + } + return result; + } + + /** + * Method similar to {@link #findValue}, but that will return a + * "missing node" instead of null if no field is found. Missing node + * is a specific kind of node for which {@link #isMissingNode} + * returns true; and all value access methods return empty or + * missing value. + * + * @param fieldName Name of field to look for + * + * @return Value of first matching node found; or if not found, a + * "missing node" (non-null instance that has no value) + * + * @since 1.6 + */ + public abstract JsonNode findPath(String fieldName); + + /** + * Method for finding a JSON Object that contains specified field, + * within this node or its descendants. + * If no matching field is found in this node or its descendants, returns null. + * + * @param fieldName Name of field to look for + * + * @return Value of first matching node found, if any; null if none + * + * @since 1.6 + */ + public abstract JsonNode findParent(String fieldName); + + /** + * Method for finding a JSON Object that contains specified field, + * within this node or its descendants. + * If no matching field is found in this node or its descendants, returns null. + * + * @param fieldName Name of field to look for + * + * @return Value of first matching node found, if any; null if none + * + * @since 1.6 + */ + public final List<JsonNode> findParents(String fieldName) + { + List<JsonNode> result = findParents(fieldName, null); + if (result == null) { + return Collections.emptyList(); + } + return result; + } + + public abstract List<JsonNode> findValues(String fieldName, List<JsonNode> foundSoFar); + public abstract List<String> findValuesAsText(String fieldName, List<String> foundSoFar); + public abstract List<JsonNode> findParents(String fieldName, List<JsonNode> foundSoFar); + + /* + /********************************************************** + /* Public API, container access + /********************************************************** + */ + + /** + * Method that returns number of child nodes this node contains: + * for Array nodes, number of child elements, for Object nodes, + * number of fields, and for all other nodes 0. + * + * @return For non-container nodes returns 0; for arrays number of + * contained elements, and for objects number of fields. + */ + public int size() { return 0; } + + /** + * Same as calling {@link #getElements}; implemented so that + * convenience "for-each" loop can be used for looping over elements + * of JSON Array constructs. + */ + @Override + public final Iterator<JsonNode> iterator() { return getElements(); } + + /** + * Method for accessing all value nodes of this Node, iff + * this node is a JSON Array or Object node. In case of Object node, + * field names (keys) are not included, only values. + * For other types of nodes, returns empty iterator. + */ + public Iterator<JsonNode> getElements() { return NO_NODES.iterator(); } + + /** + * Method for accessing names of all fields for this Node, iff + * this node is a JSON Object node. + */ + public Iterator<String> getFieldNames() { return NO_STRINGS.iterator(); } + + /** + * @return Iterator that can be used to traverse all key/value pairs for + * object nodes; empty iterator (no contents) for other types + * + * @since 1.8 (although existed in ObjectNode since 1.0 or so) + */ + public Iterator<Map.Entry<String, JsonNode>> getFields() { + Collection<Map.Entry<String, JsonNode>> coll = Collections.emptyList(); + return coll.iterator(); + } + + /* + /********************************************************** + /* Public API, path handling + /********************************************************** + */ + + /** + * This method is similar to {@link #get(String)}, except + * that instead of returning null if no such value exists (due + * to this node not being an object, or object not having value + * for the specified field), + * a "missing node" (node that returns true for + * {@link #isMissingNode}) will be returned. This allows for + * convenient and safe chained access via path calls. + */ + public abstract JsonNode path(String fieldName); + + /** + * Alias of {@link #path(String)}. + * + * @deprecated Use {@link #path(String)} instead + */ + @Deprecated + public final JsonNode getPath(String fieldName) { return path(fieldName); } + + /** + * This method is similar to {@link #get(int)}, except + * that instead of returning null if no such element exists (due + * to index being out of range, or this node not being an array), + * a "missing node" (node that returns true for + * {@link #isMissingNode}) will be returned. This allows for + * convenient and safe chained access via path calls. + */ + public abstract JsonNode path(int index); + + /** + * Alias of {@link #path(int)}. + * + * @deprecated Use {@link #path(int)} instead + */ + @Deprecated + public final JsonNode getPath(int index) { return path(index); } + + /** + * Method that can be called on object nodes, to access a property + * that has object value; or if no such property exists, to create and + * return such object node. + * If node method is called on is not Object node, + * or if property exists and has value that is not object node, + * {@link UnsupportedOperationException} is thrown + * + * @since 1.8 + */ + public JsonNode with(String propertyName) { + throw new UnsupportedOperationException("JsonNode not of type ObjectNode (but " + +getClass().getName()+"), can not call with() on it"); + } + + /* + /********************************************************** + /* Public API: converting to/from Streaming API + /********************************************************** + */ + + /** + * Method for constructing a {@link JsonParser} instance for + * iterating over contents of the tree that this + * node is root of. + * Functionally equivalent to first serializing tree using + * {@link ObjectCodec} and then re-parsing but + * more efficient. + */ + public abstract JsonParser traverse(); + + /* + /********************************************************** + /* Overridden standard methods + /********************************************************** + */ + + /** + *<p> + * Note: marked as abstract to ensure all implementation + * classes define it properly. + */ + @Override + public abstract String toString(); + + /** + * Equality for node objects is defined as full (deep) value + * equality. This means that it is possible to compare complete + * JSON trees for equality by comparing equality of root nodes. + *<p> + * Note: marked as abstract to ensure all implementation + * classes define it properly and not rely on definition + * from {@link java.lang.Object}. + */ + @Override + public abstract boolean equals(Object o); +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/JsonParseException.java b/1.9.10/src/java/org/codehaus/jackson/JsonParseException.java new file mode 100644 index 0000000..6241a54 --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/JsonParseException.java
@@ -0,0 +1,23 @@ +package org.codehaus.jackson; + +/** + * Exception type for parsing problems, used when non-well-formed content + * (content that does not conform to JSON syntax as per specification) + * is encountered. + */ +public class JsonParseException + extends JsonProcessingException +{ + @SuppressWarnings("hiding") + final static long serialVersionUID = 123; // Stupid eclipse... + + public JsonParseException(String msg, JsonLocation loc) + { + super(msg, loc); + } + + public JsonParseException(String msg, JsonLocation loc, Throwable root) + { + super(msg, loc, root); + } +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/JsonParser.java b/1.9.10/src/java/org/codehaus/jackson/JsonParser.java new file mode 100644 index 0000000..e0b2dde --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/JsonParser.java
@@ -0,0 +1,1435 @@ +/* Jackson JSON-processor. + * + * Copyright (c) 2007- Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in file LICENSE, included with + * the source code and binary code bundles. + * You may not use this file except in compliance with the License. + * + * 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.codehaus.jackson; + +import java.io.*; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.Iterator; + +import org.codehaus.jackson.type.TypeReference; + +/** + * Base class that defines public API for reading JSON content. + * Instances are created using factory methods of + * a {@link JsonFactory} instance. + * + * @author Tatu Saloranta + */ +public abstract class JsonParser + implements Closeable, Versioned +{ + private final static int MIN_BYTE_I = (int) Byte.MIN_VALUE; + // [JACKSON-804]: allow range up to 255 (instead of Java's 127) for better interoperability + private final static int MAX_BYTE_I = 255; + + private final static int MIN_SHORT_I = (int) Short.MIN_VALUE; + private final static int MAX_SHORT_I = (int) Short.MAX_VALUE; + + /** + * Enumeration of possible "native" (optimal) types that can be + * used for numbers. + */ + public enum NumberType { + INT, LONG, BIG_INTEGER, FLOAT, DOUBLE, BIG_DECIMAL + }; + + /** + * Enumeration that defines all togglable features for parsers. + */ + public enum Feature { + + // // // Low-level I/O handling features: + + /** + * Feature that determines whether parser will automatically + * close underlying input source that is NOT owned by the + * parser. If disabled, calling application has to separately + * close the underlying {@link InputStream} and {@link Reader} + * instances used to create the parser. If enabled, parser + * will handle closing, as long as parser itself gets closed: + * this happens when end-of-input is encountered, or parser + * is closed by a call to {@link JsonParser#close}. + *<p> + * Feature is enabled by default. + */ + AUTO_CLOSE_SOURCE(true), + + // // // Support for non-standard data format constructs + + /** + * Feature that determines whether parser will allow use + * of Java/C++ style comments (both '/'+'*' and + * '//' varieties) within parsed content or not. + *<p> + * Since JSON specification does not mention comments as legal + * construct, + * this is a non-standard feature; however, in the wild + * this is extensively used. As such, feature is + * <b>disabled by default</b> for parsers and must be + * explicitly enabled (via factory or parser instance). + *<p> + * This feature can be changed for parser instances. + */ + ALLOW_COMMENTS(false), + + /** + * Feature that determines whether parser will allow use + * of unquoted field names (which is allowed by Javascript, + * but not by JSON specification). + *<p> + * Since JSON specification requires use of double quotes for + * field names, + * this is a non-standard feature, and as such disabled by + * default. + *<p> + * This feature can be changed for parser instances. + * + * @since 1.2 + */ + ALLOW_UNQUOTED_FIELD_NAMES(false), + + /** + * Feature that determines whether parser will allow use + * of single quotes (apostrophe, character '\'') for + * quoting Strings (names and String values). If so, + * this is in addition to other acceptabl markers. + * but not by JSON specification). + *<p> + * Since JSON specification requires use of double quotes for + * field names, + * this is a non-standard feature, and as such disabled by + * default. + *<p> + * This feature can be changed for parser instances. + * + * @since 1.3 + */ + ALLOW_SINGLE_QUOTES(false), + + /** + * Feature that determines whether parser will allow + * JSON Strings to contain unquoted control characters + * (ASCII characters with value less than 32, including + * tab and line feed characters) or not. + * If feature is set false, an exception is thrown if such a + * character is encountered. + *<p> + * Since JSON specification requires quoting for all control characters, + * this is a non-standard feature, and as such disabled by default. + *<p> + * This feature can be changed for parser instances. + * + * @since 1.4 + */ + ALLOW_UNQUOTED_CONTROL_CHARS(false), + + /** + * Feature that can be enabled to accept quoting of all character + * using backslash qooting mechanism: if not enabled, only characters + * that are explicitly listed by JSON specification can be thus + * escaped (see JSON spec for small list of these characters) + *<p> + * Since JSON specification requires quoting for all control characters, + * this is a non-standard feature, and as such disabled by default. + *<p> + * This feature can be changed for parser instances. + * + * @since 1.6 + */ + ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER(false), + + /** + * Feature that determines whether parser will allow + * JSON integral numbers to start with additional (ignorable) + * zeroes (like: 000001). If enabled, no exception is thrown, and extra + * nulls are silently ignored (and not included in textual representation + * exposed via {@link JsonParser#getText}). + *<p> + * Since JSON specification does not allow leading zeroes, + * this is a non-standard feature, and as such disabled by default. + *<p> + * This feature can be changed for parser instances. + * + * @since 1.8 + */ + ALLOW_NUMERIC_LEADING_ZEROS(false), + + /** + * Feature that allows parser to recognize set of + * "Not-a-Number" (NaN) tokens as legal floating number + * values (similar to how many other data formats and + * programming language source code allows it). + * Specific subset contains values that + * <a href="http://www.w3.org/TR/xmlschema-2/">XML Schema</a> + * (see section 3.2.4.1, Lexical Representation) + * allows (tokens are quoted contents, not including quotes): + *<ul> + * <li>"INF" (for positive infinity), as well as alias of "Infinity" + * <li>"-INF" (for negative infinity), alias "-Infinity" + * <li>"NaN" (for other not-a-numbers, like result of division by zero) + *</ul> + */ + + ALLOW_NON_NUMERIC_NUMBERS(false), + + // // // Controlling canonicalization (interning etc) + + /** + * Feature that determines whether JSON object field names are + * to be canonicalized using {@link String#intern} or not: + * if enabled, all field names will be intern()ed (and caller + * can count on this being true for all such names); if disabled, + * no intern()ing is done. There may still be basic + * canonicalization (that is, same String will be used to represent + * all identical object property names for a single document). + *<p> + * Note: this setting only has effect if + * {@link #CANONICALIZE_FIELD_NAMES} is true -- otherwise no + * canonicalization of any sort is done. + * + * @since 1.3 + */ + INTERN_FIELD_NAMES(true), + + /** + * Feature that determines whether JSON object field names are + * to be canonicalized (details of how canonicalization is done + * then further specified by + * {@link #INTERN_FIELD_NAMES}). + * + * @since 1.5 + */ + CANONICALIZE_FIELD_NAMES(true), + + + ; + + final boolean _defaultState; + + /** + * Method that calculates bit set (flags) of all features that + * are enabled by default. + */ + public static int collectDefaults() + { + int flags = 0; + for (Feature f : values()) { + if (f.enabledByDefault()) { + flags |= f.getMask(); + } + } + return flags; + } + + private Feature(boolean defaultState) { + _defaultState = defaultState; + } + + public boolean enabledByDefault() { return _defaultState; } + + public boolean enabledIn(int flags) { return (flags & getMask()) != 0; } + + public int getMask() { return (1 << ordinal()); } + }; + + /* + /********************************************************** + /* Minimal configuration state + /********************************************************** + */ + + /** + * Bit flag composed of bits that indicate which + * {@link org.codehaus.jackson.JsonParser.Feature}s + * are enabled. + */ + protected int _features; + + /* + /********************************************************** + /* Minimal generic state + /********************************************************** + */ + + /** + * Last token retrieved via {@link #nextToken}, if any. + * Null before the first call to <code>nextToken()</code>, + * as well as if token has been explicitly cleared + * (by call to {@link #clearCurrentToken}) + */ + protected JsonToken _currToken; + + /** + * Last cleared token, if any: that is, value that was in + * effect when {@link #clearCurrentToken} was called. + */ + protected JsonToken _lastClearedToken; + + /* + /********************************************************** + /* Construction, configuration, initialization + /********************************************************** + */ + + protected JsonParser() { } + protected JsonParser(int features) { + _features = features; + } + + /** + * Accessor for {@link ObjectCodec} associated with this + * parser, if any. Codec is used by {@link #readValueAs(Class)} + * method (and its variants). + * + * @since 1.3 + */ + public abstract ObjectCodec getCodec(); + + /** + * Setter that allows defining {@link ObjectCodec} associated with this + * parser, if any. Codec is used by {@link #readValueAs(Class)} + * method (and its variants). + * + * @since 1.3 + */ + public abstract void setCodec(ObjectCodec c); + + /** + * Method to call to make this parser use specified schema. Method must + * be called before trying to parse any content, right after parser instance + * has been created. + * Note that not all parsers support schemas; and those that do usually only + * accept specific types of schemas: ones defined for data format parser can read. + *<p> + * If parser does not support specified schema, {@link UnsupportedOperationException} + * is thrown. + * + * @param schema Schema to use + * + * @throws UnsupportedOperationException if parser does not support schema + * + * @since 1.8 + */ + public void setSchema(FormatSchema schema) + { + throw new UnsupportedOperationException("Parser of type "+getClass().getName()+" does not support schema of type '" + +schema.getSchemaType()+"'"); + } + + /** + * Method that can be used to verify that given schema can be used with + * this parser (using {@link #setSchema}). + * + * @param schema Schema to check + * + * @return True if this parser can use given schema; false if not + * + * @since 1.8 + */ + public boolean canUseSchema(FormatSchema schema) { + return false; + } + + /** + * @since 1.6 + */ + @Override + public Version version() { + return Version.unknownVersion(); + } + + /** + * Method that can be used to get access to object that is used + * to access input being parsed; this is usually either + * {@link InputStream} or {@link Reader}, depending on what + * parser was constructed with. + * Note that returned value may be null in some cases; including + * case where parser implementation does not want to exposed raw + * source to caller. + * In cases where input has been decorated, object returned here + * is the decorated version; this allows some level of interaction + * between users of parser and decorator object. + *<p> + * In general use of this accessor should be considered as + * "last effort", i.e. only used if no other mechanism is applicable. + * + * @since 1.8 + */ + public Object getInputSource() { + return null; + } + + /* + /********************************************************** + /* Closeable implementation + /********************************************************** + */ + + /** + * Closes the parser so that no further iteration or data access + * can be made; will also close the underlying input source + * if parser either <b>owns</b> the input source, or feature + * {@link Feature#AUTO_CLOSE_SOURCE} is enabled. + * Whether parser owns the input source depends on factory + * method that was used to construct instance (so check + * {@link org.codehaus.jackson.JsonFactory} for details, + * but the general + * idea is that if caller passes in closable resource (such + * as {@link InputStream} or {@link Reader}) parser does NOT + * own the source; but if it passes a reference (such as + * {@link java.io.File} or {@link java.net.URL} and creates + * stream or reader it does own them. + */ + @Override + public abstract void close() throws IOException; + + /* + /********************************************************** + /* Buffer handling + /********************************************************** + */ + + /** + * Method that can be called to push back any content that + * has been read but not consumed by the parser. This is usually + * done after reading all content of interest using parser. + * Content is released by writing it to given stream if possible; + * if underlying input is byte-based it can released, if not (char-based) + * it can not. + * + * @return -1 if the underlying content source is not byte based + * (that is, input can not be sent to {@link OutputStream}; + * otherwise number of bytes released (0 if there was nothing to release) + * + * @throws IOException if write to stream threw exception + * + * @since 1.6 + */ + public int releaseBuffered(OutputStream out) throws IOException + { + return -1; + } + + /** + * Method that can be called to push back any content that + * has been read but not consumed by the parser. + * This is usually + * done after reading all content of interest using parser. + * Content is released by writing it to given writer if possible; + * if underlying input is char-based it can released, if not (byte-based) + * it can not. + * + * @return -1 if the underlying content source is not char-based + * (that is, input can not be sent to {@link Writer}; + * otherwise number of chars released (0 if there was nothing to release) + * + * @throws IOException if write using Writer threw exception + * + * @since 1.6 + */ + public int releaseBuffered(Writer w) throws IOException + { + return -1; + } + + /* + /*************************************************** + /* Public API, configuration + /*************************************************** + */ + + /** + * Method for enabling specified parser feature + * (check {@link Feature} for list of features) + * + * @since 1.2 + */ + public JsonParser enable(Feature f) + { + _features |= f.getMask(); + return this; + } + + /** + * Method for disabling specified feature + * (check {@link Feature} for list of features) + * + * @since 1.2 + */ + public JsonParser disable(Feature f) + { + _features &= ~f.getMask(); + return this; + } + + /** + * Method for enabling or disabling specified feature + * (check {@link Feature} for list of features) + * + * @since 1.2 + */ + public JsonParser configure(Feature f, boolean state) + { + if (state) { + enableFeature(f); + } else { + disableFeature(f); + } + return this; + } + + /** + * Method for checking whether specified {@link Feature} + * is enabled. + * + * @since 1.2 + */ + public boolean isEnabled(Feature f) { + return (_features & f.getMask()) != 0; + } + + /** @deprecated Use {@link #configure} instead + */ + @SuppressWarnings("dep-ann") + public void setFeature(Feature f, boolean state) { configure(f, state); } + + /** @deprecated Use {@link #enable(Feature)} instead + */ + @SuppressWarnings("dep-ann") + public void enableFeature(Feature f) { enable(f); } + + /** @deprecated Use {@link #disable(Feature)} instead + */ + @SuppressWarnings("dep-ann") + public void disableFeature(Feature f) { disable(f); } + + /** @deprecated Use {@link #isEnabled(Feature)} instead + */ + @SuppressWarnings("dep-ann") + public final boolean isFeatureEnabled(Feature f) { return isEnabled(f); } + + + /* + /********************************************************** + /* Public API, traversal + /********************************************************** + */ + + /** + * Main iteration method, which will advance stream enough + * to determine type of the next token, if any. If none + * remaining (stream has no content other than possible + * white space before ending), null will be returned. + * + * @return Next token from the stream, if any found, or null + * to indicate end-of-input + */ + public abstract JsonToken nextToken() + throws IOException, JsonParseException; + + /** + * Iteration method that will advance stream enough + * to determine type of the next token that is a value type + * (including JSON Array and Object start/end markers). + * Or put another way, nextToken() will be called once, + * and if {@link JsonToken#FIELD_NAME} is returned, another + * time to get the value for the field. + * Method is most useful for iterating over value entries + * of JSON objects; field name will still be available + * by calling {@link #getCurrentName} when parser points to + * the value. + * + * @return Next non-field-name token from the stream, if any found, + * or null to indicate end-of-input (or, for non-blocking + * parsers, {@link JsonToken#NOT_AVAILABLE} if no tokens were + * available yet) + */ + public JsonToken nextValue() + throws IOException, JsonParseException + { + /* Implementation should be as trivial as follows; only + * needs to change if we are to skip other tokens (for + * example, if comments were exposed as tokens) + */ + JsonToken t = nextToken(); + if (t == JsonToken.FIELD_NAME) { + t = nextToken(); + } + return t; + } + + /** + * Method that fetches next token (as if calling {@link #nextToken}) and + * verifies whether it is {@link JsonToken#FIELD_NAME} with specified name + * and returns result of that comparison. + * It is functionally equivalent to: + *<pre> + * return (nextToken() == JsonToken.FIELD_NAME) && str.getValue().equals(getCurrentName()); + *</pre> + * but may be faster for parser to verify, and can therefore be used if caller + * expects to get such a property name from input next. + * + * @param str Property name to compare next token to (if next token is <code>JsonToken.FIELD_NAME<code>) + * + * @since 1.9 + */ + public boolean nextFieldName(SerializableString str) + throws IOException, JsonParseException + { + return (nextToken() == JsonToken.FIELD_NAME) && str.getValue().equals(getCurrentName()); + } + + /** + * Method that fetches next token (as if calling {@link #nextToken}) and + * if it is {@link JsonToken#VALUE_STRING} returns contained String value; + * otherwise returns null. + * It is functionally equivalent to: + *<pre> + * return (nextToken() == JsonToken.VALUE_STRING) ? getText() : null; + *</pre> + * but may be faster for parser to process, and can therefore be used if caller + * expects to get a String value next from input. + * + * @since 1.9 + */ + public String nextTextValue() + throws IOException, JsonParseException + { + return (nextToken() == JsonToken.VALUE_STRING) ? getText() : null; + } + + /** + * Method that fetches next token (as if calling {@link #nextToken}) and + * if it is {@link JsonToken#VALUE_NUMBER_INT} returns 32-bit int value; + * otherwise returns specified default value + * It is functionally equivalent to: + *<pre> + * return (nextToken() == JsonToken.VALUE_NUMBER_INT) ? getIntValue() : defaultValue; + *</pre> + * but may be faster for parser to process, and can therefore be used if caller + * expects to get a String value next from input. + * + * @since 1.9 + */ + public int nextIntValue(int defaultValue) + throws IOException, JsonParseException + { + return (nextToken() == JsonToken.VALUE_NUMBER_INT) ? getIntValue() : defaultValue; + } + + /** + * Method that fetches next token (as if calling {@link #nextToken}) and + * if it is {@link JsonToken#VALUE_NUMBER_INT} returns 64-bit long value; + * otherwise returns specified default value + * It is functionally equivalent to: + *<pre> + * return (nextToken() == JsonToken.VALUE_NUMBER_INT) ? getLongValue() : defaultValue; + *</pre> + * but may be faster for parser to process, and can therefore be used if caller + * expects to get a String value next from input. + * + * @since 1.9 + */ + public long nextLongValue(long defaultValue) + throws IOException, JsonParseException + { + return (nextToken() == JsonToken.VALUE_NUMBER_INT) ? getLongValue() : defaultValue; + } + + /** + * Method that fetches next token (as if calling {@link #nextToken}) and + * if it is {@link JsonToken#VALUE_TRUE} or {@link JsonToken#VALUE_FALSE} + * returns matching Boolean value; otherwise return null. + * It is functionally equivalent to: + *<pre> + * JsonToken t = nextToken(); + * if (t == JsonToken.VALUE_TRUE) return Boolean.TRUE; + * if (t == JsonToken.VALUE_FALSE) return Boolean.FALSE; + * return null; + *</pre> + * but may be faster for parser to process, and can therefore be used if caller + * expects to get a String value next from input. + * + * @since 1.9 + */ + public Boolean nextBooleanValue() + throws IOException, JsonParseException + { + switch (nextToken()) { + case VALUE_TRUE: + return Boolean.TRUE; + case VALUE_FALSE: + return Boolean.FALSE; + } + return null; + } + + /** + * Method that will skip all child tokens of an array or + * object token that the parser currently points to, + * iff stream points to + * {@link JsonToken#START_OBJECT} or {@link JsonToken#START_ARRAY}. + * If not, it will do nothing. + * After skipping, stream will point to <b>matching</b> + * {@link JsonToken#END_OBJECT} or {@link JsonToken#END_ARRAY} + * (possibly skipping nested pairs of START/END OBJECT/ARRAY tokens + * as well as value tokens). + * The idea is that after calling this method, application + * will call {@link #nextToken} to point to the next + * available token, if any. + */ + public abstract JsonParser skipChildren() + throws IOException, JsonParseException; + + /** + * Method that can be called to determine whether this parser + * is closed or not. If it is closed, no new tokens can be + * retrieved by calling {@link #nextToken} (and the underlying + * stream may be closed). Closing may be due to an explicit + * call to {@link #close} or because parser has encountered + * end of input. + */ + public abstract boolean isClosed(); + + /* + /********************************************************** + /* Public API, token accessors + /********************************************************** + */ + + /** + * Accessor to find which token parser currently points to, if any; + * null will be returned if none. + * If return value is non-null, data associated with the token + * is available via other accessor methods. + * + * @return Type of the token this parser currently points to, + * if any: null before any tokens have been read, and + * after end-of-input has been encountered, as well as + * if the current token has been explicitly cleared. + */ + public JsonToken getCurrentToken() { + return _currToken; + } + + /** + * Method for checking whether parser currently points to + * a token (and data for that token is available). + * Equivalent to check for <code>parser.getCurrentToken() != null</code>. + * + * @return True if the parser just returned a valid + * token via {@link #nextToken}; false otherwise (parser + * was just constructed, encountered end-of-input + * and returned null from {@link #nextToken}, or the token + * has been consumed) + */ + public boolean hasCurrentToken() { + return _currToken != null; + } + + + /** + * Method called to "consume" the current token by effectively + * removing it so that {@link #hasCurrentToken} returns false, and + * {@link #getCurrentToken} null). + * Cleared token value can still be accessed by calling + * {@link #getLastClearedToken} (if absolutely needed), but + * usually isn't. + *<p> + * Method was added to be used by the optional data binder, since + * it has to be able to consume last token used for binding (so that + * it will not be used again). + */ + public void clearCurrentToken() { + if (_currToken != null) { + _lastClearedToken = _currToken; + _currToken = null; + } + } + + /** + * Method that can be called to get the name associated with + * the current token: for {@link JsonToken#FIELD_NAME}s it will + * be the same as what {@link #getText} returns; + * for field values it will be preceding field name; + * and for others (array values, root-level values) null. + */ + public abstract String getCurrentName() + throws IOException, JsonParseException; + + /** + * Method that can be used to access current parsing context reader + * is in. There are 3 different types: root, array and object contexts, + * with slightly different available information. Contexts are + * hierarchically nested, and can be used for example for figuring + * out part of the input document that correspond to specific + * array or object (for highlighting purposes, or error reporting). + * Contexts can also be used for simple xpath-like matching of + * input, if so desired. + */ + public abstract JsonStreamContext getParsingContext(); + + /** + * Method that return the <b>starting</b> location of the current + * token; that is, position of the first character from input + * that starts the current token. + */ + public abstract JsonLocation getTokenLocation(); + + /** + * Method that returns location of the last processed character; + * usually for error reporting purposes. + */ + public abstract JsonLocation getCurrentLocation(); + + /** + * Method that can be called to get the last token that was + * cleared using {@link #clearCurrentToken}. This is not necessarily + * the latest token read. + * Will return null if no tokens have been cleared, + * or if parser has been closed. + */ + public JsonToken getLastClearedToken() { + return _lastClearedToken; + } + + /** + * Specialized accessor that can be used to verify that the current + * token indicates start array (usually meaning that current token + * is {@link JsonToken#START_ARRAY}) when start array is expected. + * For some specialized parsers this can return true for other cases + * as well; this is usually done to emulate arrays. + *<p> + * Default implementation is equivalent to: + *<pre> + * getCurrentToken() == JsonToken.START_ARRAY + *</pre> + * but may be overridden by custom parser implementations. + * + * @return True if the current token can be considered as a + * start-array marker (such {@link JsonToken#START_ARRAY}); + * false if not. + * + * @since 1.7 + */ + public boolean isExpectedStartArrayToken() { + return getCurrentToken() == JsonToken.START_ARRAY; + } + + /* + /********************************************************** + /* Public API, access to token information, text + /********************************************************** + */ + + /** + * Method for accessing textual representation of the current token; + * if no current token (before first call to {@link #nextToken}, or + * after encountering end-of-input), returns null. + * Method can be called for any token type. + */ + public abstract String getText() + throws IOException, JsonParseException; + + /** + * Method similar to {@link #getText}, but that will return + * underlying (unmodifiable) character array that contains + * textual value, instead of constructing a String object + * to contain this information. + * Note, however, that: + *<ul> + * <li>Textual contents are not guaranteed to start at + * index 0 (rather, call {@link #getTextOffset}) to + * know the actual offset + * </li> + * <li>Length of textual contents may be less than the + * length of returned buffer: call {@link #getTextLength} + * for actual length of returned content. + * </li> + * </ul> + *<p> + * Note that caller <b>MUST NOT</b> modify the returned + * character array in any way -- doing so may corrupt + * current parser state and render parser instance useless. + *<p> + * The only reason to call this method (over {@link #getText}) + * is to avoid construction of a String object (which + * will make a copy of contents). + */ + public abstract char[] getTextCharacters() + throws IOException, JsonParseException; + + /** + * Accessor used with {@link #getTextCharacters}, to know length + * of String stored in returned buffer. + * + * @return Number of characters within buffer returned + * by {@link #getTextCharacters} that are part of + * textual content of the current token. + */ + public abstract int getTextLength() + throws IOException, JsonParseException; + + /** + * Accessor used with {@link #getTextCharacters}, to know offset + * of the first text content character within buffer. + * + * @return Offset of the first character within buffer returned + * by {@link #getTextCharacters} that is part of + * textual content of the current token. + */ + public abstract int getTextOffset() + throws IOException, JsonParseException; + + /** + * Method that can be used to determine whether calling of + * {@link #getTextCharacters} would be the most efficient + * way to access textual content for the event parser currently + * points to. + *<p> + * Default implementation simply returns false since only actual + * implementation class has knowledge of its internal buffering + * state. + * Implementations are strongly encouraged to properly override + * this method, to allow efficient copying of content by other + * code. + * + * @return True if parser currently has character array that can + * be efficiently returned via {@link #getTextCharacters}; false + * means that it may or may not exist + * + * @since 1.6 + */ + public boolean hasTextCharacters() { + return false; + } + + /* + /********************************************************** + /* Public API, access to token information, numeric + /********************************************************** + */ + + /** + * Generic number value accessor method that will work for + * all kinds of numeric values. It will return the optimal + * (simplest/smallest possible) wrapper object that can + * express the numeric value just parsed. + */ + public abstract Number getNumberValue() + throws IOException, JsonParseException; + + /** + * If current token is of type + * {@link JsonToken#VALUE_NUMBER_INT} or + * {@link JsonToken#VALUE_NUMBER_FLOAT}, returns + * one of {@link NumberType} constants; otherwise returns null. + */ + public abstract NumberType getNumberType() + throws IOException, JsonParseException; + + /** + * Numeric accessor that can be called when the current + * token is of type {@link JsonToken#VALUE_NUMBER_INT} and + * it can be expressed as a value of Java byte primitive type. + * It can also be called for {@link JsonToken#VALUE_NUMBER_FLOAT}; + * if so, it is equivalent to calling {@link #getDoubleValue} + * and then casting; except for possible overflow/underflow + * exception. + *<p> + * Note: if the resulting integer value falls outside range of + * Java byte, a {@link JsonParseException} + * will be thrown to indicate numeric overflow/underflow. + */ + public byte getByteValue() + throws IOException, JsonParseException + { + int value = getIntValue(); + // So far so good: but does it fit? + if (value < MIN_BYTE_I || value > MAX_BYTE_I) { + throw _constructError("Numeric value ("+getText()+") out of range of Java byte"); + } + return (byte) value; + } + + /** + * Numeric accessor that can be called when the current + * token is of type {@link JsonToken#VALUE_NUMBER_INT} and + * it can be expressed as a value of Java short primitive type. + * It can also be called for {@link JsonToken#VALUE_NUMBER_FLOAT}; + * if so, it is equivalent to calling {@link #getDoubleValue} + * and then casting; except for possible overflow/underflow + * exception. + *<p> + * Note: if the resulting integer value falls outside range of + * Java short, a {@link JsonParseException} + * will be thrown to indicate numeric overflow/underflow. + */ + public short getShortValue() + throws IOException, JsonParseException + { + int value = getIntValue(); + if (value < MIN_SHORT_I || value > MAX_SHORT_I) { + throw _constructError("Numeric value ("+getText()+") out of range of Java short"); + } + return (short) value; + } + + /** + * Numeric accessor that can be called when the current + * token is of type {@link JsonToken#VALUE_NUMBER_INT} and + * it can be expressed as a value of Java int primitive type. + * It can also be called for {@link JsonToken#VALUE_NUMBER_FLOAT}; + * if so, it is equivalent to calling {@link #getDoubleValue} + * and then casting; except for possible overflow/underflow + * exception. + *<p> + * Note: if the resulting integer value falls outside range of + * Java int, a {@link JsonParseException} + * may be thrown to indicate numeric overflow/underflow. + */ + public abstract int getIntValue() + throws IOException, JsonParseException; + + /** + * Numeric accessor that can be called when the current + * token is of type {@link JsonToken#VALUE_NUMBER_INT} and + * it can be expressed as a Java long primitive type. + * It can also be called for {@link JsonToken#VALUE_NUMBER_FLOAT}; + * if so, it is equivalent to calling {@link #getDoubleValue} + * and then casting to int; except for possible overflow/underflow + * exception. + *<p> + * Note: if the token is an integer, but its value falls + * outside of range of Java long, a {@link JsonParseException} + * may be thrown to indicate numeric overflow/underflow. + */ + public abstract long getLongValue() + throws IOException, JsonParseException; + + /** + * Numeric accessor that can be called when the current + * token is of type {@link JsonToken#VALUE_NUMBER_INT} and + * it can not be used as a Java long primitive type due to its + * magnitude. + * It can also be called for {@link JsonToken#VALUE_NUMBER_FLOAT}; + * if so, it is equivalent to calling {@link #getDecimalValue} + * and then constructing a {@link BigInteger} from that value. + */ + public abstract BigInteger getBigIntegerValue() + throws IOException, JsonParseException; + + /** + * Numeric accessor that can be called when the current + * token is of type {@link JsonToken#VALUE_NUMBER_FLOAT} and + * it can be expressed as a Java float primitive type. + * It can also be called for {@link JsonToken#VALUE_NUMBER_INT}; + * if so, it is equivalent to calling {@link #getLongValue} + * and then casting; except for possible overflow/underflow + * exception. + *<p> + * Note: if the value falls + * outside of range of Java float, a {@link JsonParseException} + * will be thrown to indicate numeric overflow/underflow. + */ + public abstract float getFloatValue() + throws IOException, JsonParseException; + + /** + * Numeric accessor that can be called when the current + * token is of type {@link JsonToken#VALUE_NUMBER_FLOAT} and + * it can be expressed as a Java double primitive type. + * It can also be called for {@link JsonToken#VALUE_NUMBER_INT}; + * if so, it is equivalent to calling {@link #getLongValue} + * and then casting; except for possible overflow/underflow + * exception. + *<p> + * Note: if the value falls + * outside of range of Java double, a {@link JsonParseException} + * will be thrown to indicate numeric overflow/underflow. + */ + public abstract double getDoubleValue() + throws IOException, JsonParseException; + + /** + * Numeric accessor that can be called when the current + * token is of type {@link JsonToken#VALUE_NUMBER_FLOAT} or + * {@link JsonToken#VALUE_NUMBER_INT}. No under/overflow exceptions + * are ever thrown. + */ + public abstract BigDecimal getDecimalValue() + throws IOException, JsonParseException; + + /* + /********************************************************** + /* Public API, access to token information, other + /********************************************************** + */ + + /** + * Convenience accessor that can be called when the current + * token is {@link JsonToken#VALUE_TRUE} or + * {@link JsonToken#VALUE_FALSE}. + *<p> + * Note: if the token is not of above-mentioned boolean types, + an integer, but its value falls + * outside of range of Java long, a {@link JsonParseException} + * may be thrown to indicate numeric overflow/underflow. + * + * @since 1.3 + */ + public boolean getBooleanValue() + throws IOException, JsonParseException + { + if (getCurrentToken() == JsonToken.VALUE_TRUE) return true; + if (getCurrentToken() == JsonToken.VALUE_FALSE) return false; + throw new JsonParseException("Current token ("+_currToken+") not of boolean type", getCurrentLocation()); + } + + /** + * Accessor that can be called if (and only if) the current token + * is {@link JsonToken#VALUE_EMBEDDED_OBJECT}. For other token types, + * null is returned. + *<p> + * Note: only some specialized parser implementations support + * embedding of objects (usually ones that are facades on top + * of non-streaming sources, such as object trees). + * + * @since 1.3 + */ + public Object getEmbeddedObject() + throws IOException, JsonParseException + { + // By default we will always return null + return null; + } + + /* + /********************************************************** + /* Public API, access to token information, binary + /********************************************************** + */ + + /** + * Method that can be used to read (and consume -- results + * may not be accessible using other methods after the call) + * base64-encoded binary data + * included in the current textual JSON value. + * It works similar to getting String value via {@link #getText} + * and decoding result (except for decoding part), + * but should be significantly more performant. + *<p> + * Note that non-decoded textual contents of the current token + * are not guaranteed to be accessible after this method + * is called. Current implementation, for example, clears up + * textual content during decoding. + * Decoded binary content, however, will be retained until + * parser is advanced to the next event. + * + * @param b64variant Expected variant of base64 encoded + * content (see {@link Base64Variants} for definitions + * of "standard" variants). + * + * @return Decoded binary data + */ + public abstract byte[] getBinaryValue(Base64Variant b64variant) throws IOException, JsonParseException; + + /** + * Convenience alternative to {@link #getBinaryValue(Base64Variant)} + * that defaults to using + * {@link Base64Variants#getDefaultVariant} as the default encoding. + */ + public byte[] getBinaryValue() throws IOException, JsonParseException + { + return getBinaryValue(Base64Variants.getDefaultVariant()); + } + + /* + /********************************************************** + /* Public API, access to token information, coercion/conversion + /********************************************************** + */ + + /** + * Method that will try to convert value of current token to a + * <b>int</b>. + * Numbers are coerced using default Java rules; booleans convert to 0 (false) + * and 1 (true), and Strings are parsed using default Java language integer + * parsing rules. + *<p> + * If representation can not be converted to an int (including structured type + * markers like start/end Object/Array) + * default value of <b>0</b> will be returned; no exceptions are thrown. + * + * @since 1.6 + */ + public int getValueAsInt() throws IOException, JsonParseException { + return getValueAsInt(0); + } + + /** + * Method that will try to convert value of current token to a + * <b>int</b>. + * Numbers are coerced using default Java rules; booleans convert to 0 (false) + * and 1 (true), and Strings are parsed using default Java language integer + * parsing rules. + *<p> + * If representation can not be converted to an int (including structured type + * markers like start/end Object/Array) + * specified <b>defaultValue</b> will be returned; no exceptions are thrown. + * + * @since 1.6 + */ + public int getValueAsInt(int defaultValue) throws IOException, JsonParseException { + return defaultValue; + } + + /** + * Method that will try to convert value of current token to a + * <b>long</b>. + * Numbers are coerced using default Java rules; booleans convert to 0 (false) + * and 1 (true), and Strings are parsed using default Java language integer + * parsing rules. + *<p> + * If representation can not be converted to an int (including structured type + * markers like start/end Object/Array) + * default value of <b>0</b> will be returned; no exceptions are thrown. + * + * @since 1.6 + */ + public long getValueAsLong() throws IOException, JsonParseException { + return getValueAsLong(0L); + } + + /** + * Method that will try to convert value of current token to a + * <b>long</b>. + * Numbers are coerced using default Java rules; booleans convert to 0 (false) + * and 1 (true), and Strings are parsed using default Java language integer + * parsing rules. + *<p> + * If representation can not be converted to an int (including structured type + * markers like start/end Object/Array) + * specified <b>defaultValue</b> will be returned; no exceptions are thrown. + * + * @since 1.6 + */ + public long getValueAsLong(long defaultValue) throws IOException, JsonParseException { + return defaultValue; + } + + /** + * Method that will try to convert value of current token to a Java + * <b>double</b>. + * Numbers are coerced using default Java rules; booleans convert to 0.0 (false) + * and 1.0 (true), and Strings are parsed using default Java language integer + * parsing rules. + *<p> + * If representation can not be converted to an int (including structured types + * like Objects and Arrays), + * default value of <b>0.0</b> will be returned; no exceptions are thrown. + * + * @since 1.6 + */ + public double getValueAsDouble() throws IOException, JsonParseException { + return getValueAsDouble(0.0); + } + + /** + * Method that will try to convert value of current token to a + * Java <b>double</b>. + * Numbers are coerced using default Java rules; booleans convert to 0.0 (false) + * and 1.0 (true), and Strings are parsed using default Java language integer + * parsing rules. + *<p> + * If representation can not be converted to an int (including structured types + * like Objects and Arrays), + * specified <b>defaultValue</b> will be returned; no exceptions are thrown. + * + * @since 1.6 + */ + public double getValueAsDouble(double defaultValue) throws IOException, JsonParseException { + return defaultValue; + } + + /** + * Method that will try to convert value of current token to a + * <b>boolean</b>. + * JSON booleans map naturally; integer numbers other than 0 map to true, and + * 0 maps to false + * and Strings 'true' and 'false' map to corresponding values. + *<p> + * If representation can not be converted to a boolean value (including structured types + * like Objects and Arrays), + * default value of <b>false</b> will be returned; no exceptions are thrown. + * + * @since 1.7 + */ + public boolean getValueAsBoolean() throws IOException, JsonParseException { + return getValueAsBoolean(false); + } + + /** + * Method that will try to convert value of current token to a + * <b>boolean</b>. + * JSON booleans map naturally; integer numbers other than 0 map to true, and + * 0 maps to false + * and Strings 'true' and 'false' map to corresponding values. + *<p> + * If representation can not be converted to a boolean value (including structured types + * like Objects and Arrays), + * specified <b>defaultValue</b> will be returned; no exceptions are thrown. + * + * @since 1.7 + */ + public boolean getValueAsBoolean(boolean defaultValue) throws IOException, JsonParseException { + return defaultValue; + } + + /* + /********************************************************** + /* Public API, optional data binding functionality + /********************************************************** + */ + + /** + * Method to deserialize JSON content into a non-container + * type (it can be an array type, however): typically a bean, array + * or a wrapper type (like {@link java.lang.Boolean}). + * <b>Note</b>: method can only be called if the parser has + * an object codec assigned; this is true for parsers constructed + * by {@link org.codehaus.jackson.map.MappingJsonFactory} but + * not for {@link JsonFactory} (unless its <code>setCodec</code> + * method has been explicitly called). + *<p> + * This method may advance the event stream, for structured types + * the current token will be the closing end marker (END_ARRAY, + * END_OBJECT) of the bound structure. For non-structured Json types + * (and for {@link JsonToken#VALUE_EMBEDDED_OBJECT}) + * stream is not advanced. + *<p> + * Note: this method should NOT be used if the result type is a + * container ({@link java.util.Collection} or {@link java.util.Map}. + * The reason is that due to type erasure, key and value types + * can not be introspected when using this method. + */ + public <T> T readValueAs(Class<T> valueType) + throws IOException, JsonProcessingException + { + ObjectCodec codec = getCodec(); + if (codec == null) { + throw new IllegalStateException("No ObjectCodec defined for the parser, can not deserialize JSON into Java objects"); + } + return codec.readValue(this, valueType); + } + + /** + * Method to deserialize JSON content into a Java type, reference + * to which is passed as argument. Type is passed using so-called + * "super type token" + * and specifically needs to be used if the root type is a + * parameterized (generic) container type. + * <b>Note</b>: method can only be called if the parser has + * an object codec assigned; this is true for parsers constructed + * by {@link org.codehaus.jackson.map.MappingJsonFactory} but + * not for {@link JsonFactory} (unless its <code>setCodec</code> + * method has been explicitly called). + *<p> + * This method may advance the event stream, for structured types + * the current token will be the closing end marker (END_ARRAY, + * END_OBJECT) of the bound structure. For non-structured Json types + * (and for {@link JsonToken#VALUE_EMBEDDED_OBJECT}) + * stream is not advanced. + */ + @SuppressWarnings("unchecked") + public <T> T readValueAs(TypeReference<?> valueTypeRef) + throws IOException, JsonProcessingException + { + ObjectCodec codec = getCodec(); + if (codec == null) { + throw new IllegalStateException("No ObjectCodec defined for the parser, can not deserialize JSON into Java objects"); + } + /* Ugh. Stupid Java type erasure... can't just chain call,s + * must cast here also. + */ + return (T) codec.readValue(this, valueTypeRef); + } + + /** + * Method for reading sequence of Objects from parser stream, + * all with same specified value type. + * + * @since 1.9 + */ + public <T> Iterator<T> readValuesAs(Class<T> valueType) + throws IOException, JsonProcessingException + { + ObjectCodec codec = getCodec(); + if (codec == null) { + throw new IllegalStateException("No ObjectCodec defined for the parser, can not deserialize JSON into Java objects"); + } + return codec.readValues(this, valueType); + } + + /** + * Method for reading sequence of Objects from parser stream, + * all with same specified value type. + * + * @since 1.9 + */ + public <T> Iterator<T> readValuesAs(TypeReference<?> valueTypeRef) + throws IOException, JsonProcessingException + { + ObjectCodec codec = getCodec(); + if (codec == null) { + throw new IllegalStateException("No ObjectCodec defined for the parser, can not deserialize JSON into Java objects"); + } + return codec.readValues(this, valueTypeRef); + } + + /** + * Method to deserialize JSON content into equivalent "tree model", + * represented by root {@link JsonNode} of resulting model. + * For JSON Arrays it will an array node (with child nodes), + * for objects object node (with child nodes), and for other types + * matching leaf node type + */ + public JsonNode readValueAsTree() + throws IOException, JsonProcessingException + { + ObjectCodec codec = getCodec(); + if (codec == null) { + throw new IllegalStateException("No ObjectCodec defined for the parser, can not deserialize JSON into JsonNode tree"); + } + return codec.readTree(this); + } + + /* + /********************************************************** + /* Internal methods + /********************************************************** + */ + + /** + * Helper method for constructing {@link JsonParseException}s + * based on current state of the parser + */ + protected JsonParseException _constructError(String msg) + { + return new JsonParseException(msg, getCurrentLocation()); + } +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/JsonProcessingException.java b/1.9.10/src/java/org/codehaus/jackson/JsonProcessingException.java new file mode 100644 index 0000000..329b471 --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/JsonProcessingException.java
@@ -0,0 +1,80 @@ +package org.codehaus.jackson; + +/** + * Intermediate base class for all problems encountered when + * processing (parsing, generating) JSON content + * that are not pure I/O problems. + * Regular {@link java.io.IOException}s will be passed through as is. + * Sub-class of {@link java.io.IOException} for convenience. + */ +public class JsonProcessingException + extends java.io.IOException +{ + final static long serialVersionUID = 123; // Stupid eclipse... + + protected JsonLocation mLocation; + + protected JsonProcessingException(String msg, JsonLocation loc, Throwable rootCause) + { + /* Argh. IOException(Throwable,String) is only available starting + * with JDK 1.6... + */ + super(msg); + if (rootCause != null) { + initCause(rootCause); + } + mLocation = loc; + } + + protected JsonProcessingException(String msg) + { + super(msg); + } + + protected JsonProcessingException(String msg, JsonLocation loc) + { + this(msg, loc, null); + } + + protected JsonProcessingException(String msg, Throwable rootCause) + { + this(msg, null, rootCause); + } + + protected JsonProcessingException(Throwable rootCause) + { + this(null, null, rootCause); + } + + public JsonLocation getLocation() + { + return mLocation; + } + + /** + * Default method overridden so that we can add location information + */ + @Override + public String getMessage() + { + String msg = super.getMessage(); + if (msg == null) { + msg = "N/A"; + } + JsonLocation loc = getLocation(); + if (loc != null) { + StringBuilder sb = new StringBuilder(); + sb.append(msg); + sb.append('\n'); + sb.append(" at "); + sb.append(loc.toString()); + return sb.toString(); + } + return msg; + } + + @Override + public String toString() { + return getClass().getName()+": "+getMessage(); + } +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/JsonStreamContext.java b/1.9.10/src/java/org/codehaus/jackson/JsonStreamContext.java new file mode 100644 index 0000000..d807c1d --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/JsonStreamContext.java
@@ -0,0 +1,122 @@ +/* Jackson JSON-processor. + * + * Copyright (c) 2007- Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in file LICENSE, included with + * the source code and binary code bundles. + * You may not use this file except in compliance with the License. + * + * 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.codehaus.jackson; + +/** + * Shared base class for streaming processing contexts used during + * reading and writing of Json content using Streaming API. + * This context is also exposed to applications: + * context object can be used by applications to get an idea of + * relative position of the parser/generator within json content + * being processed. This allows for some contextual processing: for + * example, output within Array context can differ from that of + * Object context. + */ +public abstract class JsonStreamContext +{ + // // // Type constants used internally + + protected final static int TYPE_ROOT = 0; + protected final static int TYPE_ARRAY = 1; + protected final static int TYPE_OBJECT = 2; + + protected int _type; + + /** + * Index of the currently processed entry. Starts with -1 to signal + * that no entries have been started, and gets advanced each + * time a new entry is started, either by encountering an expected + * separator, or with new values if no separators are expected + * (the case for root context). + */ + protected int _index; + + /* + /********************************************************** + /* Life-cycle + /********************************************************** + */ + + protected JsonStreamContext() { } + + /* + /********************************************************** + /* Public API, accessors + /********************************************************** + */ + + /** + * Accessor for finding parent context of this context; will + * return null for root context. + */ + public abstract JsonStreamContext getParent(); + + /** + * Method that returns true if this context is an Array context; + * that is, content is being read from or written to a Json Array. + */ + public final boolean inArray() { return _type == TYPE_ARRAY; } + + /** + * Method that returns true if this context is a Root context; + * that is, content is being read from or written to without + * enclosing array or object structure. + */ + public final boolean inRoot() { return _type == TYPE_ROOT; } + + /** + * Method that returns true if this context is an Object context; + * that is, content is being read from or written to a Json Object. + */ + public final boolean inObject() { return _type == TYPE_OBJECT; } + + /** + * Method for accessing simple type description of current context; + * either ROOT (for root-level values), OBJECT (for field names and + * values of JSON Objects) or ARRAY (for values of JSON Arrays) + */ + public final String getTypeDesc() { + switch (_type) { + case TYPE_ROOT: return "ROOT"; + case TYPE_ARRAY: return "ARRAY"; + case TYPE_OBJECT: return "OBJECT"; + } + return "?"; + } + + /** + * @return Number of entries that are complete and started. + */ + public final int getEntryCount() + { + return _index + 1; + } + + /** + * @return Index of the currently processed entry, if any + */ + public final int getCurrentIndex() + { + return (_index < 0) ? 0 : _index; + } + + /** + * Method for accessing name associated with the current location. + * Non-null for <code>FIELD_NAME</code> and value events that directly + * follow field names; null for root level and array values. + */ + public abstract String getCurrentName(); +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/JsonToken.java b/1.9.10/src/java/org/codehaus/jackson/JsonToken.java new file mode 100644 index 0000000..268f6ca --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/JsonToken.java
@@ -0,0 +1,161 @@ +package org.codehaus.jackson; + +/** + * Enumeration for basic token types used for returning results + * of parsing JSON content. + */ +public enum JsonToken +{ + /* Some notes on implementation: + * + * - Entries are to be ordered such that start/end array/object + * markers come first, then field name marker (if any), and + * finally scalar value tokens. This is assumed by some + * typing checks. + */ + + /** + * NOT_AVAILABLE can be returned if {@link JsonParser} + * implementation can not currently return the requested + * token (usually next one), or even if any will be + * available, but that may be able to determine this in + * future. This is the case with non-blocking parsers -- + * they can not block to wait for more data to parse and + * must return something. + * + * @since 0.9.7 + */ + NOT_AVAILABLE(null), + + /** + * START_OBJECT is returned when encountering '{' + * which signals starting of an Object value. + */ + START_OBJECT("{"), + + /** + * START_OBJECT is returned when encountering '}' + * which signals ending of an Object value + */ + END_OBJECT("}"), + + /** + * START_OBJECT is returned when encountering '[' + * which signals starting of an Array value + */ + START_ARRAY("["), + + /** + * START_OBJECT is returned when encountering ']' + * which signals ending of an Array value + */ + END_ARRAY("]"), + + /** + * FIELD_NAME is returned when a String token is encountered + * as a field name (same lexical value, different function) + */ + FIELD_NAME(null), + + /** + * Placeholder token returned when the input source has a concept + * of embedded Object that are not accessible as usual structure + * (of starting with {@link #START_OBJECT}, having values, ending with + * {@link #END_OBJECT}), but as "raw" objects. + *<p> + * Note: this token is never returned by regular JSON readers, but + * only by readers that expose other kinds of source (like + * {@link JsonNode}-based JSON trees, Maps, Lists and such). + * + * @since 1.1 + */ + VALUE_EMBEDDED_OBJECT(null), + + /** + * VALUE_STRING is returned when a String token is encountered + * in value context (array element, field value, or root-level + * stand-alone value) + */ + VALUE_STRING(null), + + /** + * VALUE_NUMBER_INT is returned when an integer numeric token is + * encountered in value context: that is, a number that does + * not have floating point or exponent marker in it (consists + * only of an optional sign, followed by one or more digits) + */ + VALUE_NUMBER_INT(null), + + /** + * VALUE_NUMBER_INT is returned when a numeric token other + * that is not an integer is encountered: that is, a number that does + * have floating point or exponent marker in it, in addition + * to one or more digits. + */ + VALUE_NUMBER_FLOAT(null), + + /** + * VALUE_TRUE is returned when encountering literal "true" in + * value context + */ + VALUE_TRUE("true"), + + /** + * VALUE_FALSE is returned when encountering literal "false" in + * value context + */ + VALUE_FALSE("false"), + + /** + * VALUE_NULL is returned when encountering literal "null" in + * value context + */ + VALUE_NULL("null") + ; + + final String _serialized; + + final char[] _serializedChars; + + final byte[] _serializedBytes; + + /** + * @param Textual representation for this token, if there is a + * single static representation; null otherwise + */ + JsonToken(String token) + { + if (token == null) { + _serialized = null; + _serializedChars = null; + _serializedBytes = null; + } else { + _serialized = token; + _serializedChars = token.toCharArray(); + // It's all in ascii, can just case... + int len = _serializedChars.length; + _serializedBytes = new byte[len]; + for (int i = 0; i < len; ++i) { + _serializedBytes[i] = (byte) _serializedChars[i]; + } + } + } + + public String asString() { return _serialized; } + public char[] asCharArray() { return _serializedChars; } + public byte[] asByteArray() { return _serializedBytes; } + + public boolean isNumeric() { + return (this == VALUE_NUMBER_INT) || (this == VALUE_NUMBER_FLOAT); + } + + /** + * Method that can be used to check whether this token represents + * a valid non-structured value. This means all tokens other than + * Object/Array start/end markers all field names. + */ + public boolean isScalarValue() { + // note: up to 1.5, VALUE_EMBEDDED_OBJECT was incorrectly considered non-scalar! + return ordinal() >= VALUE_EMBEDDED_OBJECT.ordinal(); + } +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/ObjectCodec.java b/1.9.10/src/java/org/codehaus/jackson/ObjectCodec.java new file mode 100644 index 0000000..f4ab963 --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/ObjectCodec.java
@@ -0,0 +1,157 @@ +package org.codehaus.jackson; + +import java.io.IOException; +import java.util.Iterator; + +import org.codehaus.jackson.type.JavaType; +import org.codehaus.jackson.type.TypeReference; + +/** + * Abstract class that defines the interface that {@link JsonParser} and + * {@link JsonGenerator} use to serialize and deserialize regular + * Java objects (POJOs aka Beans). + *<p> + * The standard implementation of this class is + * {@link org.codehaus.jackson.map.ObjectMapper}. + */ +public abstract class ObjectCodec +{ + protected ObjectCodec() { } + + /* + /********************************************************** + /* API for de-serialization (JSON-to-Object) + /********************************************************** + */ + + /** + * Method to deserialize JSON content into a non-container + * type (it can be an array type, however): typically a bean, array + * or a wrapper type (like {@link java.lang.Boolean}). + *<p> + * Note: this method should NOT be used if the result type is a + * container ({@link java.util.Collection} or {@link java.util.Map}. + * The reason is that due to type erasure, key and value types + * can not be introspected when using this method. + */ + public abstract <T> T readValue(JsonParser jp, Class<T> valueType) + throws IOException, JsonProcessingException; + + /** + * Method to deserialize JSON content into a Java type, reference + * to which is passed as argument. Type is passed using so-called + * "super type token" + * and specifically needs to be used if the root type is a + * parameterized (generic) container type. + */ + public abstract <T> T readValue(JsonParser jp, TypeReference<?> valueTypeRef) + throws IOException, JsonProcessingException; + + /** + * Method to deserialize JSON content as tree expressed + * using set of {@link JsonNode} instances. Returns + * root of the resulting tree (where root can consist + * of just a single node if the current event is a + * value event, not container). + */ + public abstract <T> T readValue(JsonParser jp, JavaType valueType) + throws IOException, JsonProcessingException; + + /** + * Method to deserialize JSON content as tree expressed + * using set of {@link JsonNode} instances. Returns + * root of the resulting tree (where root can consist + * of just a single node if the current event is a + * value event, not container). + */ + public abstract JsonNode readTree(JsonParser jp) + throws IOException, JsonProcessingException; + + /** + * Method for reading sequence of Objects from parser stream, + * all with same specified value type. + * + * @since 1.9 + */ + public abstract <T> Iterator<T> readValues(JsonParser jp, Class<T> valueType) + throws IOException, JsonProcessingException; + + /** + * Method for reading sequence of Objects from parser stream, + * all with same specified value type. + * + * @since 1.9 + */ + public abstract <T> Iterator<T> readValues(JsonParser jp, TypeReference<?> valueTypeRef) + throws IOException, JsonProcessingException; + + /** + * Method for reading sequence of Objects from parser stream, + * all with same specified value type. + * + * @since 1.9 + */ + public abstract <T> Iterator<T> readValues(JsonParser jp, JavaType valueType) + throws IOException, JsonProcessingException; + + /* + /********************************************************** + /* API for serialization (Object-to-JSON) + /********************************************************** + */ + + /** + * Method to serialize given Java Object, using generator + * provided. + */ + public abstract void writeValue(JsonGenerator jgen, Object value) + throws IOException, JsonProcessingException; + + /** + * Method to serialize given Json Tree, using generator + * provided. + */ + public abstract void writeTree(JsonGenerator jgen, JsonNode rootNode) + throws IOException, JsonProcessingException; + + /* + /********************************************************** + /* API for Tree Model handling + /********************************************************** + */ + + /** + * Method for construct root level Object nodes + * for Tree Model instances. + * + * @since 1.2 + */ + public abstract JsonNode createObjectNode(); + + /** + * Method for construct root level Array nodes + * for Tree Model instances. + * + * @since 1.2 + */ + public abstract JsonNode createArrayNode(); + + /** + * Method for constructing a {@link JsonParser} for reading + * contents of a JSON tree, as if it was external serialized + * JSON content. + * + * @since 1.3 + */ + public abstract JsonParser treeAsTokens(JsonNode n); + + /** + * Convenience method for converting given JSON tree into instance of specified + * value type. This is equivalent to first constructing a {@link JsonParser} to + * iterate over contents of the tree, and using that parser for data binding. + * + * @since 1.3 + */ + public abstract <T> T treeToValue(JsonNode n, Class<T> valueType) + throws IOException, JsonProcessingException; +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/PrettyPrinter.java b/1.9.10/src/java/org/codehaus/jackson/PrettyPrinter.java new file mode 100644 index 0000000..f02aeaa --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/PrettyPrinter.java
@@ -0,0 +1,166 @@ +package org.codehaus.jackson; + +import java.io.IOException; + +/** + * Interface for objects that implement pretty printer functionality, such + * as indentation. + * Pretty printers are used to add white space in output JSON content, + * to make results more human readable. Usually this means things like adding + * linefeeds and indentation. + */ +public interface PrettyPrinter +{ + /* + /********************************************************** + /* First methods that act both as events, and expect + /* output for correct functioning (i.e something gets + /* output even when not pretty-printing) + /********************************************************** + */ + + // // // Root-level handling: + + /** + * Method called after a root-level value has been completely + * output, and before another value is to be output. + *<p> + * Default + * handling (without pretty-printing) will output a space, to + * allow values to be parsed correctly. Pretty-printer is + * to output some other suitable and nice-looking separator + * (tab(s), space(s), linefeed(s) or any combination thereof). + */ + public void writeRootValueSeparator(JsonGenerator jg) + throws IOException, JsonGenerationException; + + // // Object handling + + /** + * Method called when an Object value is to be output, before + * any fields are output. + *<p> + * Default handling (without pretty-printing) will output + * the opening curly bracket. + * Pretty-printer is + * to output a curly bracket as well, but can surround that + * with other (white-space) decoration. + */ + public void writeStartObject(JsonGenerator jg) + throws IOException, JsonGenerationException; + + /** + * Method called after an Object value has been completely output + * (minus closing curly bracket). + *<p> + * Default handling (without pretty-printing) will output + * the closing curly bracket. + * Pretty-printer is + * to output a curly bracket as well, but can surround that + * with other (white-space) decoration. + * + * @param nrOfEntries Number of direct members of the array that + * have been output + */ + public void writeEndObject(JsonGenerator jg, int nrOfEntries) + throws IOException, JsonGenerationException; + + /** + * Method called after an object entry (field:value) has been completely + * output, and before another value is to be output. + *<p> + * Default handling (without pretty-printing) will output a single + * comma to separate the two. Pretty-printer is + * to output a comma as well, but can surround that with other + * (white-space) decoration. + */ + public void writeObjectEntrySeparator(JsonGenerator jg) + throws IOException, JsonGenerationException; + + /** + * Method called after an object field has been output, but + * before the value is output. + *<p> + * Default handling (without pretty-printing) will output a single + * colon to separate the two. Pretty-printer is + * to output a colon as well, but can surround that with other + * (white-space) decoration. + */ + public void writeObjectFieldValueSeparator(JsonGenerator jg) + throws IOException, JsonGenerationException; + + // // // Array handling + + /** + * Method called when an Array value is to be output, before + * any member/child values are output. + *<p> + * Default handling (without pretty-printing) will output + * the opening bracket. + * Pretty-printer is + * to output a bracket as well, but can surround that + * with other (white-space) decoration. + */ + public void writeStartArray(JsonGenerator jg) + throws IOException, JsonGenerationException; + + /** + * Method called after an Array value has been completely output + * (minus closing bracket). + *<p> + * Default handling (without pretty-printing) will output + * the closing bracket. + * Pretty-printer is + * to output a bracket as well, but can surround that + * with other (white-space) decoration. + * + * @param nrOfValues Number of direct members of the array that + * have been output + */ + public void writeEndArray(JsonGenerator jg, int nrOfValues) + throws IOException, JsonGenerationException; + + /** + * Method called after an array value has been completely + * output, and before another value is to be output. + *<p> + * Default handling (without pretty-printing) will output a single + * comma to separate the two. Pretty-printer is + * to output a comma as well, but can surround that with other + * (white-space) decoration. + */ + public void writeArrayValueSeparator(JsonGenerator jg) + throws IOException, JsonGenerationException; + + /* + /********************************************************** + /* Then events that by default do not produce any output + /* but that are often overridden to add white space + /* in pretty-printing mode + /********************************************************** + */ + + /** + * Method called after array start marker has been output, + * and right before the first value is to be output. + * It is <b>not</b> called for arrays with no values. + *<p> + * Default handling does not output anything, but pretty-printer + * is free to add any white space decoration. + */ + public void beforeArrayValues(JsonGenerator jg) + throws IOException, JsonGenerationException; + + /** + * Method called after object start marker has been output, + * and right before the field name of the first entry is + * to be output. + * It is <b>not</b> called for objects without entries. + *<p> + * Default handling does not output anything, but pretty-printer + * is free to add any white space decoration. + */ + public void beforeObjectEntries(JsonGenerator jg) + throws IOException, JsonGenerationException; +} +
diff --git a/1.9.10/src/java/org/codehaus/jackson/SerializableString.java b/1.9.10/src/java/org/codehaus/jackson/SerializableString.java new file mode 100644 index 0000000..de2e747 --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/SerializableString.java
@@ -0,0 +1,54 @@ +package org.codehaus.jackson; + +/** + * Interface that defines how Jackson package can interact with efficient + * pre-serialized or lazily-serialized and reused String representations. + * Typically implementations store possible serialized version(s) so that + * serialization of String can be done more efficiently, especially when + * used multiple times. + * + * @since 1.7 (1.6 introduced implementation, but interface extracted later) + * + * @see org.codehaus.jackson.io.SerializedString + */ +public interface SerializableString +{ + /** + * Returns unquoted String that this object represents (and offers + * serialized forms for) + */ + public String getValue(); + + /** + * Returns length of the (unquoted) String as characters. + * Functionally equvalent to: + *<pre> + * getValue().length(); + *</pre> + */ + public int charLength(); + + /** + * Returns JSON quoted form of the String, as character array. Result + * can be embedded as-is in textual JSON as property name or JSON String. + */ + public char[] asQuotedChars(); + + /** + * Returns UTF-8 encoded version of unquoted String. + * Functionally equivalent to (but more efficient than): + *<pre> + * getValue().getBytes("UTF-8"); + *</pre> + */ + public byte[] asUnquotedUTF8(); + + /** + * Returns UTF-8 encoded version of JSON-quoted String. + * Functionally equivalent to (but more efficient than): + *<pre> + * new String(asQuotedChars()).getBytes("UTF-8"); + *</pre> + */ + public byte[] asQuotedUTF8(); +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/Version.java b/1.9.10/src/java/org/codehaus/jackson/Version.java new file mode 100644 index 0000000..f8435f2 --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/Version.java
@@ -0,0 +1,90 @@ +package org.codehaus.jackson; + +/** + * Object that encapsulates version information of a component, + * and is return by {@link Versioned#version}. + * + * @since 1.6 + */ +public class Version + implements Comparable<Version> +{ + private final static Version UNKNOWN_VERSION = new Version(0, 0, 0, null); + + protected final int _majorVersion; + + protected final int _minorVersion; + + protected final int _patchLevel; + + /** + * Additional information for snapshot versions; null for non-snapshot + * (release) versions. + */ + protected final String _snapshotInfo; + + public Version(int major, int minor, int patchLevel, + String snapshotInfo) + { + _majorVersion = major; + _minorVersion = minor; + _patchLevel = patchLevel; + _snapshotInfo = snapshotInfo; + } + + /** + * Method returns canonical "not known" version, which is used as version + * in cases where actual version information is not known (instead of null). + */ + public static Version unknownVersion() { return UNKNOWN_VERSION; } + + public boolean isUknownVersion() { return (this == UNKNOWN_VERSION); } + public boolean isSnapshot() { return (_snapshotInfo != null && _snapshotInfo.length() > 0); } + + public int getMajorVersion() { return _majorVersion; } + public int getMinorVersion() { return _minorVersion; } + public int getPatchLevel() { return _patchLevel; } + + @Override + public String toString() + { + StringBuilder sb = new StringBuilder(); + sb.append(_majorVersion).append('.'); + sb.append(_minorVersion).append('.'); + sb.append(_patchLevel); + if (isSnapshot()) { + sb.append('-').append(_snapshotInfo); + } + return sb.toString(); + } + + @Override + public int hashCode() { + return _majorVersion + _minorVersion + _patchLevel; + } + + @Override + public boolean equals(Object o) + { + if (o == this) return true; + if (o == null) return false; + if (o.getClass() != getClass()) return false; + Version other = (Version) o; + return (other._majorVersion == _majorVersion) + && (other._minorVersion == _minorVersion) + && (other._patchLevel == _patchLevel); + } + + @Override + public int compareTo(Version other) + { + int diff = _majorVersion - other._majorVersion; + if (diff == 0) { + diff = _minorVersion - other._minorVersion; + if (diff == 0) { + diff = _patchLevel - other._patchLevel; + } + } + return diff; + } +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/Versioned.java b/1.9.10/src/java/org/codehaus/jackson/Versioned.java new file mode 100644 index 0000000..1fa39ad --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/Versioned.java
@@ -0,0 +1,20 @@ +package org.codehaus.jackson; + +/** + * Interface that those Jackson components that are explicitly versioned will implement. + * Intention is to allow both plug-in components (custom extensions) and applications and + * frameworks that use Jackson to detect exact version of Jackson in use. + * This may be useful for example for ensuring that proper Jackson version is deployed + * (beyond mechanisms that deployment system may have), as well as for possible + * workarounds. + * + * @since 1.6 + */ +public interface Versioned { + /** + * Method called to detect version of the component that implements this interface; + * returned version should never be null, but may return specific "not available" + * instance (see {@link Version} for details). + */ + public Version version(); +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/annotate/JacksonAnnotation.java b/1.9.10/src/java/org/codehaus/jackson/annotate/JacksonAnnotation.java new file mode 100644 index 0000000..25bf61e --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/annotate/JacksonAnnotation.java
@@ -0,0 +1,20 @@ +package org.codehaus.jackson.annotate; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Meta-annotation (annotations used on other annotations) + * used for marking all annotations that are + * part of Jackson package. Can be used for recognizing all + * Jackson annotations generically, and in future also for + * passing other generic annotation configuration. + */ +@Target({ElementType.ANNOTATION_TYPE}) +@Retention(RetentionPolicy.RUNTIME) +public @interface JacksonAnnotation +{ + // for now, a pure tag annotation, no parameters +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/annotate/JsonAnyGetter.java b/1.9.10/src/java/org/codehaus/jackson/annotate/JsonAnyGetter.java new file mode 100644 index 0000000..9fc8dc7 --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/annotate/JsonAnyGetter.java
@@ -0,0 +1,25 @@ +package org.codehaus.jackson.annotate; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Marker annotation that can be used to define a non-static, + * no-argument method or member field as something of a reverse of + * {@link JsonAnySetter} method; basically being used like a + * getter but such that contents of the returned Map (type <b>must</b> be + * {@link java.util.Map}) are serialized as if they were actual properties + * of the bean that contains method/field with this annotations. + * As with {@link JsonAnySetter}, only one property should be annotated + * with this annotation. + * + * @since 1.6 + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@JacksonAnnotation +public @interface JsonAnyGetter +{ +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/annotate/JsonAnySetter.java b/1.9.10/src/java/org/codehaus/jackson/annotate/JsonAnySetter.java new file mode 100644 index 0000000..04aa3ca --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/annotate/JsonAnySetter.java
@@ -0,0 +1,24 @@ +package org.codehaus.jackson.annotate; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Marker annotation that can be used to define a non-static, + * single-argument method, to be used as a "fallback" handler + * for all otherwise unrecognized properties found from Json content. + * It is similar to {@link javax.xml.bind.annotation.XmlAnyElement} + * in behavior; and can only be used to denote a single property + * per type. + *<p> + * If used, all otherwise unmapped key-value pairs from Json Object + * structs are added to the property (of type Map or bean). + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@JacksonAnnotation +public @interface JsonAnySetter +{ +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/annotate/JsonAutoDetect.java b/1.9.10/src/java/org/codehaus/jackson/annotate/JsonAutoDetect.java new file mode 100644 index 0000000..9c82265 --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/annotate/JsonAutoDetect.java
@@ -0,0 +1,148 @@ +package org.codehaus.jackson.annotate; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.reflect.Member; +import java.lang.reflect.Modifier; + +/** + * Class annotation that can be used to define which kinds of Methods + * are to be detected by auto-detection. + * Auto-detection means using name conventions + * and/or signature templates to find methods to use for data binding. + * For example, so-called "getters" can be auto-detected by looking for + * public member methods that return a value, do not take argument, + * and have prefix "get" in their name. + *<p> + * Pseudo-value <code>NONE</code> means that all auto-detection is disabled + * for the <b>specific</b> class that annotation is applied to (including + * its super-types, but only when resolving that class). + * Pseudo-value <code>ALWAYS</code> means that auto-detection is enabled + * for all method types for the class in similar way. + *<p> + * The default value is <code>ALWAYS</code>: that is, by default, auto-detection + * is enabled for all classes unless instructed otherwise. + *<p> + * Starting with version 1.5, it is also possible to use more fine-grained + * definitions, to basically define minimum visibility level needed. Defaults + * are different for different types (getters need to be public; setters can + * have any access modifier, for example). + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@JacksonAnnotation +public @interface JsonAutoDetect +{ + /** + * Enumeration for possible visibility thresholds (minimum visibility) + * that can be used to limit which methods (and fields) are + * auto-detected. + * + * @since 1.5 + */ + public enum Visibility { + /** + * Value that means that all kinds of access modifiers are acceptable, + * from private to public. + */ + ANY, + /** + * Value that means that any other access modifier other than 'private' + * is considered auto-detectable. + */ + NON_PRIVATE, + /** + * Value that means access modifiers 'protected' and 'public' are + * auto-detectable (and 'private' and "package access" == no modifiers + * are not) + */ + PROTECTED_AND_PUBLIC, + /** + * Value to indicate that only 'public' access modifier is considered + * auto-detectable. + */ + PUBLIC_ONLY, + /** + * Value that indicates that no access modifiers are auto-detectable: + * this can be used to explicitly disable auto-detection for specified + * types. + */ + NONE, + + /** + * Value that indicates that default visibility level (whatever it is, + * depends on context) is to be used. This usually means that inherited + * value (from parent visibility settings) is to be used. + */ + DEFAULT; + + public boolean isVisible(Member m) { + switch (this) { + case ANY: + return true; + case NONE: + return false; + case NON_PRIVATE: + return !Modifier.isPrivate(m.getModifiers()); + case PROTECTED_AND_PUBLIC: + if (Modifier.isProtected(m.getModifiers())) { + return true; + } + // fall through to public case: + case PUBLIC_ONLY: + return Modifier.isPublic(m.getModifiers()); + } + return false; + } + } + + /** + * Types of property elements (getters, setters, fields, creators) that + * can be auto-detected. + * NOTE: as of 1.5, it is recommended that instead of defining this property, + * distinct visibility properties are used instead. This because levels + * used with this method are not explicit, but global defaults that differ for different + * methods. As such, this property can be considered <b>deprecated</b> and + * only retained for backwards compatibility. + */ + JsonMethod[] value() default { JsonMethod.ALL }; + + /** + * Minimum visibility required for auto-detecting regular getter methods. + * + * @since 1.5 + */ + Visibility getterVisibility() default Visibility.DEFAULT; + + /** + * Minimum visibility required for auto-detecting is-getter methods. + * + * @since 1.5 + */ + Visibility isGetterVisibility() default Visibility.DEFAULT; + + /** + * Minimum visibility required for auto-detecting setter methods. + * + * @since 1.5 + */ + Visibility setterVisibility() default Visibility.DEFAULT; + + /** + * Minimum visibility required for auto-detecting Creator methods, + * except for no-argument constructors (which are always detected + * no matter what). + * + * @since 1.5 + */ + Visibility creatorVisibility() default Visibility.DEFAULT; + + /** + * Minimum visibility required for auto-detecting member fields. + * + * @since 1.5 + */ + Visibility fieldVisibility() default Visibility.DEFAULT; +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/annotate/JsonBackReference.java b/1.9.10/src/java/org/codehaus/jackson/annotate/JsonBackReference.java new file mode 100644 index 0000000..d3e79cb --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/annotate/JsonBackReference.java
@@ -0,0 +1,41 @@ +package org.codehaus.jackson.annotate; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotation used to indicate that associated property is part of + * two-way linkage between fields; and that its role is "child" (or "back") link. + * Value type of the property must be a bean: it can not be a Collection, Map, + * Array or enumeration. + * Linkage is handled such that the property + * annotated with this annotation is not serialized; and during deserialization, + * its value is set to instance that has the "managed" (forward) link. + *<p> + * All references have logical name to allow handling multiple linkages; typical case + * would be that where nodes have both parent/child and sibling linkages. If so, + * pairs of references should be named differently. + * It is an error for a class to have multiple back references with same name, + * even if types pointed are different. + *<p> + * Note: only methods and fields can be annotated with this annotation: constructor + * arguments should NOT be annotated, as they can not be either managed or back + * references. + * + * @author tatu + */ +@Target({ElementType.FIELD, ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@JacksonAnnotation +public @interface JsonBackReference +{ + /** + * Logical have for the reference property pair; used to link managed and + * back references. Default name can be used if there is just single + * reference pair (for example, node class that just has parent/child linkage, + * consisting of one managed reference and matching back reference) + */ + public String value() default "defaultReference"; +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/annotate/JsonCreator.java b/1.9.10/src/java/org/codehaus/jackson/annotate/JsonCreator.java new file mode 100644 index 0000000..72feac8 --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/annotate/JsonCreator.java
@@ -0,0 +1,19 @@ +package org.codehaus.jackson.annotate; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Marker annotation that can be used to define constructors and factory + * methods as one to use for instantiating new instances of the associated + * class. + */ +@Target({ElementType.METHOD, ElementType.CONSTRUCTOR}) +@Retention(RetentionPolicy.RUNTIME) +@JacksonAnnotation +public @interface JsonCreator +{ + // no values, since there's no property +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/annotate/JsonGetter.java b/1.9.10/src/java/org/codehaus/jackson/annotate/JsonGetter.java new file mode 100644 index 0000000..312ac98 --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/annotate/JsonGetter.java
@@ -0,0 +1,35 @@ +package org.codehaus.jackson.annotate; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Marker annotation that can be used to define a non-static, + * no-argument value-returning (non-void) method to be used as a "getter" + * for a logical property, + * as an alternative to recommended + * {@link JsonProperty} annotation (which was introduced in version 1.1). + *<p> + * Getter means that when serializing Object instance of class that has + * this method (possibly inherited from a super class), a call is made + * through the method, and return value will be serialized as value of + * the property. + * + * @deprecated Use {@link JsonProperty} instead (deprecated since version 1.5) + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@JacksonAnnotation +@Deprecated +public @interface JsonGetter +{ + /** + * Defines name of the logical property this + * method is used to access ("get"); empty String means that + * name should be derived from the underlying method (using + * standard Bean name detection rules) + */ + String value() default ""; +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/annotate/JsonIgnore.java b/1.9.10/src/java/org/codehaus/jackson/annotate/JsonIgnore.java new file mode 100644 index 0000000..bf194d7 --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/annotate/JsonIgnore.java
@@ -0,0 +1,57 @@ +package org.codehaus.jackson.annotate; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Marker annotation that indicates that the annotated method or field is to be + * ignored by introspection-based + * serialization and deserialization functionality. That is, it should + * not be consider a "getter", "setter" or "creator". + *<p> + * In addition, starting with Jackson 1.9, if this is the only annotation + * associated with a property, it will also cause cause the whole + * property to be ignored: that is, if setter has this annotation and + * getter has no annotations, getter is also effectively ignored. + * It is still possible for different accessors to use different + * annotations; so if only "getter" is to be ignored, other accessors + * (setter or field) would need explicit annotation to prevent + * ignoral (usually {@link JsonProperty}). + * <p> + * For example, a "getter" method that would otherwise denote + * a property (like, say, "getValue" to suggest property "value") + * to serialize, would be ignored and no such property would + * be output unless another annotation defines alternative method to use. + *<p> + * Before version 1.9, this annotation worked purely on method-by-method (or field-by-field) + * basis; annotation on one method or field does not imply ignoring other methods + * or fields. However, with version 1.9 and above, annotations associated + * with various accessors (getter, setter, field, constructor parameter) of + * a logical property are combined; meaning that annotations may be effectly + * combined. + *<p> + * Annotation is usually used just a like a marker annotation, that + * is, without explicitly defining 'value' argument (which defaults + * to <code>true</code>): but argument can be explicitly defined. + * This can be done to override an existing JsonIgnore by explictly + * defining one with 'false' argument. + *<p> + * Annotation is similar to {@link javax.xml.bind.annotation.XmlTransient} + */ +@Target({ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +@JacksonAnnotation +public @interface JsonIgnore +{ + /** + * Optional argument that defines whether this annotation is active + * or not. The only use for value 'false' if for overriding purposes + * (which is not needed often); most likely it is needed for use + * with "mix-in annotations" (aka "annotation overrides"). + * For most cases, however, default value of "true" is just fine + * and should be omitted. + */ + boolean value() default true; +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/annotate/JsonIgnoreProperties.java b/1.9.10/src/java/org/codehaus/jackson/annotate/JsonIgnoreProperties.java new file mode 100644 index 0000000..aa825e8 --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/annotate/JsonIgnoreProperties.java
@@ -0,0 +1,48 @@ +package org.codehaus.jackson.annotate; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotation that can be used to either suppress serialization of + * properties (during serialization), or ignore processing of + * JSON properties read (during deserialization). + *<p> + * Example: + *<pre> + * // to prevent specified fields from being serialized or deserialized + * // (i.e. not include in JSON output; or being set even if they were included) + * \@JsonIgnoreProperties({ "internalId", "secretKey" }) + * // To ignore any unknown properties in JSON input without exception: + * \@JsonIgnoreProperties(ignoreUnknown=true) + *</pre> + *<p> + * Only applicable to classes, not for properties (getters, setters, fields). + * + * @since 1.4 + */ +@Target({ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@JacksonAnnotation +public @interface JsonIgnoreProperties +{ + /** + * Names of properties to ignore. + */ + public String[] value() default { }; + + /** + * Property that defines whether it is ok to just ignore any + * unrecognized properties during deserialization. + * If true, all properties that are unrecognized -- that is, + * there are no setters or creators that accept them -- are + * ignored without warnings (although handlers for unknown + * properties, if any, will still be called) without + * exception. + *<p> + * Does not have any effect on serialization. + */ + public boolean ignoreUnknown() default false; +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/annotate/JsonIgnoreType.java b/1.9.10/src/java/org/codehaus/jackson/annotate/JsonIgnoreType.java new file mode 100644 index 0000000..cd3d10e --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/annotate/JsonIgnoreType.java
@@ -0,0 +1,33 @@ +package org.codehaus.jackson.annotate; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Marker annotation that indicates that all properties of annotated + * type are to be ignored during serialization and deserialization. + *<p> + * Note: annotation does have boolean 'value' property (which defaults + * to 'true'), so that it is actually possible to override value + * using mix-in annotations. + * + * @since 1.7 + */ +@Target({ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@JacksonAnnotation +public @interface JsonIgnoreType +{ + /** + * Optional argument that defines whether this annotation is active + * or not. The only use for value 'false' if for overriding purposes + * (which is not needed often); most likely it is needed for use + * with "mix-in annotations" ("annotation overrides"). + * For most cases, however, default value of "true" is just fine + * and should be omitted. + */ + boolean value() default true; + +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/annotate/JsonManagedReference.java b/1.9.10/src/java/org/codehaus/jackson/annotate/JsonManagedReference.java new file mode 100644 index 0000000..ddb670a --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/annotate/JsonManagedReference.java
@@ -0,0 +1,41 @@ +package org.codehaus.jackson.annotate; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotation used to indicate that annotated property is part of + * two-way linkage between fields; and that its role is "parent" (or "forward") link. + * Value type (class) of property must have a single compatible property annotated with + * {@link JsonBackReference}. Linkage is handled such that the property + * annotated with this annotation is handled normally (serialized normally, no + * special handling for deserialization); it is the matching back reference + * that requires special handling + *<p> + * All references have logical name to allow handling multiple linkages; typical case + * would be that where nodes have both parent/child and sibling linkages. If so, + * pairs of references should be named differently. + * It is an error for a class too have multiple managed references with same name, + * even if types pointed are different. + *<p> + * Note: only methods and fields can be annotated with this annotation: constructor + * arguments should NOT be annotated, as they can not be either managed or back + * references. + * + * @author tatu + */ +@Target({ElementType.FIELD, ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@JacksonAnnotation +public @interface JsonManagedReference +{ + /** + * Logical have for the reference property pair; used to link managed and + * back references. Default name can be used if there is just single + * reference pair (for example, node class that just has parent/child linkage, + * consisting of one managed reference and matching back reference) + */ + public String value() default "defaultReference"; +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/annotate/JsonMethod.java b/1.9.10/src/java/org/codehaus/jackson/annotate/JsonMethod.java new file mode 100644 index 0000000..2588b1f --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/annotate/JsonMethod.java
@@ -0,0 +1,90 @@ +package org.codehaus.jackson.annotate; + +/** + * Enumeration used to define kinds of methods that annotations like + * {@link JsonAutoDetect} apply to. + *<p> + * In addition to actual method types (GETTER, SETTER, CREATOR; and + * sort-of-method, FIELD), 2 pseudo-types + * are defined for convenience: <code>ALWAYS</code> and <code>NONE</code>. These + * can be used to indicate, all or none of available method types (respectively), + * for use by annotations that takes <code>JsonMethod</code> argument. + */ +public enum JsonMethod +{ + /** + * Getters are methods used to get a POJO field value for serialization, + * or, under certain conditions also for de-serialization. Latter + * can be used for effectively setting Collection or Map values + * in absence of setters, iff returned value is not a copy but + * actual value of the logical property. + *<p> + * Since version 1.3, this does <b>NOT</b> include "is getters" (methods + * that return boolean and named 'isXxx' for property 'xxx'); instead, + * {@link #IS_GETTER} is used}. + */ + GETTER, + + /** + * Setters are methods used to set a POJO value for deserialization. + */ + SETTER, + + /** + * Creators are constructors and (static) factory methods used to + * construct POJO instances for deserialization + */ + CREATOR, + + /** + * Field refers to fields of regular Java objects. Although + * they are not really methods, addition of optional field-discovery + * in version 1.1 meant that there was need to enable/disable + * their auto-detection, and this is the place to add it in. + * + * @since 1.1 + */ + FIELD, + + /** + * "Is getters" are getter-like methods that are named "isXxx" + * (instead of "getXxx" for getters) and return boolean value + * (either primitive, or {@link java.lang.Boolean}). + * + * @since 1.3 + */ + IS_GETTER, + + /** + * This pseudo-type indicates that none of real types is included + */ + NONE, + + /** + * This pseudo-type indicates that all of real types are included + */ + ALL + ; + + private JsonMethod() { } + + public boolean creatorEnabled() { + return (this == CREATOR) || (this == ALL); + } + + public boolean getterEnabled() { + return (this == GETTER) || (this == ALL); + } + + public boolean isGetterEnabled() { + return (this == IS_GETTER) || (this == ALL); + } + + public boolean setterEnabled() { + return (this == SETTER) || (this == ALL); + } + + public boolean fieldEnabled() { + return (this == FIELD) || (this == ALL); + } +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/annotate/JsonProperty.java b/1.9.10/src/java/org/codehaus/jackson/annotate/JsonProperty.java new file mode 100644 index 0000000..fdad341 --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/annotate/JsonProperty.java
@@ -0,0 +1,38 @@ +package org.codehaus.jackson.annotate; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Marker annotation that can be used to define a non-static + * method as a "setter" or "getter" for a logical property + * (depending on its signature), + * or non-static object field to be used (serialized, deserialized) as + * a logical property. + *<p> + * Default value ("") indicates that the field name is used + * as the property name without any modifications, but it + * can be specified to non-empty value to specify different + * name. Property name refers to name used externally, as + * the field name in Json objects. + *<p> + * NOTE: since version 1.1, annotation has also been applicable + * to fields (not with 1.0). + *<p> + * NOTE: since version 1.2, annotation has also been applicable + * to (constructor) parameters + */ +@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +@JacksonAnnotation +public @interface JsonProperty +{ + /** + * Defines name of the logical property, i.e. Json object field + * name to use for the property: if empty String (which is the + * default), will use name of the field that is annotated. + */ + String value() default ""; +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/annotate/JsonPropertyOrder.java b/1.9.10/src/java/org/codehaus/jackson/annotate/JsonPropertyOrder.java new file mode 100644 index 0000000..b86ec16 --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/annotate/JsonPropertyOrder.java
@@ -0,0 +1,46 @@ +package org.codehaus.jackson.annotate; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotation that can be used to define ordering (possibly partial) to use + * when serializing object properties. Properties included in annotation + * declaration will be serialized first (in defined order), followed by + * any properties not included in the definition. + * Annotation definition will override any implicit orderings (such as + * guarantee that Creator-properties are serialized before non-creator + * properties) + *<p> + * Examples: + *<pre> + * // ensure that "id" and "name" are output before other properties + * <div>@</div>JsonPropertyOrder({ "id", "name" }) + * // order any properties that don't have explicit setting using alphabetic order + * <div>@</div>JsonPropertyOrder(alphabetic=true) + *</pre> + *<p> + * This annotation has no effect on deserialization. + * + * @since 1.4 + */ +@Target({ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@JacksonAnnotation +public @interface JsonPropertyOrder +{ + /** + * Order in which properties of annotated object are to be serialized in. + */ + public String[] value() default { }; + + /** + * Property that defines what to do regarding ordering of properties + * not explicitly included in annotation instance. If set to true, + * they will be alphabetically ordered; if false, order is + * undefined (default setting) + */ + public boolean alphabetic() default false; +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/annotate/JsonRawValue.java b/1.9.10/src/java/org/codehaus/jackson/annotate/JsonRawValue.java new file mode 100644 index 0000000..38bb58a --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/annotate/JsonRawValue.java
@@ -0,0 +1,33 @@ +package org.codehaus.jackson.annotate; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Marker annotation that indicates that the annotated method + * or field should be serialized by including literal String value + * of the property as is, without quoting of characters. + * This can be useful for injecting values already serialized in JSON or + * passing javascript function definitions from server to a javascript client. + *<p> + * Warning: the resulting JSON stream may be invalid depending on your input value. + * + * @since 1.7.0 + */ +@Target( { ElementType.METHOD, ElementType.FIELD }) +@Retention(RetentionPolicy.RUNTIME) +@JacksonAnnotation +public @interface JsonRawValue +{ + /** + * Optional argument that defines whether this annotation is active + * or not. The only use for value 'false' if for overriding purposes + * (which is not needed often); most likely it is needed for use + * with "mix-in annotations" (aka "annotation overrides"). + * For most cases, however, default value of "true" is just fine + * and should be omitted. + */ + boolean value() default true; +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/annotate/JsonSetter.java b/1.9.10/src/java/org/codehaus/jackson/annotate/JsonSetter.java new file mode 100644 index 0000000..c96bd03 --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/annotate/JsonSetter.java
@@ -0,0 +1,33 @@ +package org.codehaus.jackson.annotate; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Marker annotation that can be used to define a non-static, + * single-argument method to be used as a "setter" for a logical property + * as an alternative to recommended + * {@link JsonProperty} annotation (which was introduced in version 1.1). + *<p> + * Setter means that when a property with matching name is encountered in + * JSON content, this method will be used to set value of the property. + *<p> + * NOTE: this annotation was briefly deprecated for version 1.5; but has + * since been un-deprecated to both allow for asymmetric naming (possibly + * different name when reading and writing JSON), and more importantly to + * allow multi-argument setter method in future. + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +@JacksonAnnotation +public @interface JsonSetter +{ + /** + * Optional default argument that defines logical property this + * method is used to modify ("set"); this is the property + * name used in JSON content. + */ + String value() default ""; +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/annotate/JsonSubTypes.java b/1.9.10/src/java/org/codehaus/jackson/annotate/JsonSubTypes.java new file mode 100644 index 0000000..ae873bc --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/annotate/JsonSubTypes.java
@@ -0,0 +1,44 @@ +package org.codehaus.jackson.annotate; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotation used with {@link JsonTypeInfo} to indicate sub types of serializable + * polymorphic types, and to associate logical names used within JSON content + * (which is more portable than using physical Java class names). + * + * @since 1.5 (but available to fields, methods and constructor params only since 1.8) + */ +@Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +@JacksonAnnotation +public @interface JsonSubTypes { + /** + * Subtypes of the annotated type (annotated class, or property value type + * associated with the annotated method). These will be checked recursively + * so that types can be defined by only including direct subtypes. + */ + public Type[] value(); + + /** + * Definition of a subtype, along with optional name. If name is missing, class + * of the type will be checked for {@link JsonTypeName} annotation; and if that + * is also missing or empty, a default + * name will be constructed by type id mechanism. + * Default name is usually based on class name. + */ + public @interface Type { + /** + * Class of the subtype + */ + public Class<?> value(); + + /** + * Logical type name used as the type identifier for the class + */ + public String name() default ""; + } +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/annotate/JsonTypeInfo.java b/1.9.10/src/java/org/codehaus/jackson/annotate/JsonTypeInfo.java new file mode 100644 index 0000000..244a7fe --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/annotate/JsonTypeInfo.java
@@ -0,0 +1,236 @@ +package org.codehaus.jackson.annotate; + +import java.lang.annotation.*; + +/** + * Annotation used for configuring details of if and how type information is + * used with JSON serialization and deserialization, to preserve information + * about actual class of Object instances. This is necessarily for polymorphic + * types, and may also be needed to link abstract declared types and matching + * concrete implementation. + *<p> + * Some examples of typical annotations: + *<pre> + * // Include Java class name ("com.myempl.ImplClass") as JSON property "class" + * @JsonTypeInfo(use=Id.CLASS, include=As.PROPERTY, property="class") + * + * // Include logical type name (defined in impl classes) as wrapper; 2 annotations + * @JsonTypeInfo(use=Id.NAME, include=As.WRAPPER_OBJECT) + * @JsonSubTypes({com.myemp.Impl1.class, com.myempl.Impl2.class}) + *</pre> + * Alternatively you can also define fully customized type handling by using + * {@link org.codehaus.jackson.map.annotate.JsonTypeResolver} annotation. + *<p> + * NOTE: originally this annotation was only available to use with types (classes), + * but starting with 1.7, it is also allowed for properties (fields, methods, + * constructor parameters). + *<p> + * When used for properties (fields, methods), this annotation applies + * to <b>values</b>: so when applied to structure types + * (like {@link java.util.Collection}, {@link java.util.Map}, arrays), + * will apply to contained values, not the container; + * for non-structured types there is no difference. + * This is identical to how JAXB handles type information + * annotations; and is chosen since it is the dominant use case. + * There is no per-property way to force type information to be included + * for type of container (structured type); for container types one has + * to use annotation for type declaration. + * + * @see org.codehaus.jackson.map.annotate.JsonTypeResolver + * + * @since 1.5 (but available to fields, methods and constructor parameters since 1.7) + * + * @author tatu + */ +@Target({ElementType.TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +@JacksonAnnotation +public @interface JsonTypeInfo +{ + /* + /********************************************************** + /* Value enumerations used for properties + /********************************************************** + */ + + /** + * Definition of different type identifiers that can be included in JSON + * during serialization, and used for deserialization. + */ + public enum Id { + /** + * This means that no explicit type metadata is included, and typing is + * purely done using contextual information possibly augmented with other + * annotations. + *<p> + * Note: no {@link org.codehaus.jackson.map.jsontype.TypeIdResolver} + * is constructed if this value is used. + */ + NONE(null), + + /** + * Means that fully-qualified Java class name is used as the type identifier. + */ + CLASS("@class"), + + /** + * Means that Java class name with minimal path is used as the type identifier. + * Minimal means that only the class name, and that part of preceding Java + * package name is included that is needed to construct fully-qualified name + * given fully-qualified name of the declared supertype; additionally a single + * leading dot ('.') must be used to indicate that partial class name is used. + * For example, for supertype "com.foobar.Base", and concrete type + * "com.foo.Impl", only ".Impl" would be included; and for "com.foo.impl.Impl2" + * only ".impl.Impl2" would be included.<br /> + * <b>NOTE</b>: leading dot ('.') MUST be used to denote partial (minimal) name; + * if it is missing, value is assumed to be fully-qualified name. Fully-qualified + * name is used in cases where subtypes are not in same package (or sub-package + * thereof) as base class. + *<p> + * If all related classes are in the same Java package, this option can reduce + * amount of type information overhead, especially for small types. + * However, please note that using this alternative is inherently risky since it + * assumes that the + * supertype can be reliably detected. Given that it is based on declared type + * (since ultimate supertype, <code>java.lang.Object</code> would not be very + * useful reference point), this may not always work as expected. + */ + MINIMAL_CLASS("@c"), + + /** + * Means that logical type name is used as type information; name will then need + * to be separately resolved to actual concrete type (Class). + */ + NAME("@type"), + + /** + * Means that typing mechanism uses customized handling, with possibly + * custom configuration. This means that semantics of other properties is + * not defined by Jackson package, but by the custom implementation. + */ + CUSTOM(null) + ; + + private final String _defaultPropertyName; + + private Id(String defProp) { + _defaultPropertyName = defProp; + } + + public String getDefaultPropertyName() { return _defaultPropertyName; } + } + + /** + * Definition of standard type inclusion mechanisms for type metadata. + * Used for standard metadata types, except for {@link Id#NONE}. + * May or may not be used for custom types ({@link Id#CUSTOM}). + */ + public enum As { + /** + * Inclusion mechanism that uses a single configurable property, included + * along with actual data (POJO properties) as a separate meta-property. + * <p> + * Default choice for inclusion. + */ + PROPERTY, + + /** + * Inclusion mechanism that wraps typed JSON value (POJO + * serialized as JSON) in + * a JSON Object that has a single entry, + * where field name is serialized type identifier, + * and value is the actual JSON value. + *<p> + * Note: can only be used if type information can be serialized as + * String. This is true for standard type metadata types, but not + * necessarily for custom types. + */ + WRAPPER_OBJECT, + + /** + * Inclusion mechanism that wraps typed JSON value (POJO + * serialized as JSON) in + * a 2-element JSON array: first element is the serialized + * type identifier, and second element the serialized POJO + * as JSON Object. + */ + WRAPPER_ARRAY, + + /** + * Inclusion mechanism similar to <code>PROPERTY</code>, except that + * property is included one-level higher in hierarchy, i.e. as sibling + * property at same level as JSON Object to type. + * Note that this choice <b>can only be used for properties</b>, not + * for types (classes). Trying to use it for classes will result in + * inclusion strategy of basic <code>PROPERTY</code> instead. + * + * @since 1.9 + */ + EXTERNAL_PROPERTY + ; + } + + /* + /********************************************************** + /* Annotation properties + /********************************************************** + */ + + /** + * What kind of type metadata is to be used for serializing and deserializing + * type information for instances of annotated type (and its subtypes + * unless overridden) + */ + public Id use(); + + /** + * What mechanism is used for including type metadata (if any; for + * {@link Id#NONE} nothing is included). Default + *<p> + * Note that for type metadata type of {@link Id#CUSTOM}, + * this setting may or may not have any effect. + */ + public As include() default As.PROPERTY; + + /** + * Property names used when type inclusion method ({@link As#PROPERTY}) is used + * (or possibly when using type metadata of type {@link Id#CUSTOM}). + *<p> + * Default property name used if this property is not explicitly defined + * (or is set to empty String) is based on + * type metadata type ({@link #use}) used. + */ + public String property() default ""; + + /** + * Optional property that can be used to specify default implementation + * class to use if type identifier is either not present, or can not + * be mapped to a registered type (which can occur for ids, but not when + * specifying explicit class to use). + *<p> + * Note that while this property allows specification of the default + * implementation to use, it does not help with structural issues that + * may arise if type information is missing. This means that most often + * this is used with type-name -based resolution, to cover cases + * where new sub-types are added, but base type is not changed to + * reference new sub-types. + * + * @since 1.9 + */ + public Class<?> defaultImpl() default None.class; + + /* + /********************************************************** + /* Helper classes + /********************************************************** + */ + + /** + * This marker class that is only to be used with <code>defaultImpl</code> + * annotation property, to indicate that there is no default implementation + * specified. + * + * @since 1.9 + */ + public abstract static class None { } +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/annotate/JsonTypeName.java b/1.9.10/src/java/org/codehaus/jackson/annotate/JsonTypeName.java new file mode 100644 index 0000000..228fbcf --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/annotate/JsonTypeName.java
@@ -0,0 +1,28 @@ +package org.codehaus.jackson.annotate; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + + +/** + * Annotation used for binding logical name that the annotated class + * has. Used with {@link JsonTypeInfo} (and specifically its + * {@link JsonTypeInfo#use} property) to establish relationship + * between type names and types. + * + * @since 1.5 + * + * @author tatu + */ +@Target({ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@JacksonAnnotation +public @interface JsonTypeName { + /** + * Logical type name for annotated type. If missing (or defined as Empty String), + * defaults to using non-qualified class name as the type. + */ + public String value() default ""; +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/annotate/JsonUnwrapped.java b/1.9.10/src/java/org/codehaus/jackson/annotate/JsonUnwrapped.java new file mode 100644 index 0000000..779361a --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/annotate/JsonUnwrapped.java
@@ -0,0 +1,76 @@ +package org.codehaus.jackson.annotate; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotation used to indicate that a property should be serialized + * "unwrapped"; that is, if it would be serialized as JSON Object, its + * properties are instead included as properties of its containing + * Object. For example, consider case of POJO like: + * + *<pre> + * public class Parent { + * public int age; + * public Name name; + * } + * public class Name { + * public String first, last; + * } + *</pre> + * which would normally be serialized as follows (assuming @JsonUnwrapped + * had no effect): + *<pre> + * { + * "age" : 18, + * "name" : { + * "first" : "Joey", + * "last" : "Sixpack" + * } + * } + *</pre> + * can be changed to this: + *<pre> + * { + * "age" : 18, + * "first" : "Joey", + * "last" : "Sixpack" + * } + *</pre> + * by changing Parent class to: + *<pre> + * public class Parent { + * public int age; + * \@JsonUnwrapped + * public Name name; + * } + *</pre> + * Annotation can only be added to properties, and not classes, as it is contextual. + *<p> + * Also note that annotation only applies if + *<ul> + * <li>Value is serialized as JSON Object + * </li> + * <li>Serialization is done using <code>BeanSerializer</code>, not a custom serializer + * </li> + * <li>No type information is added; if type information needs to be added, structure can + * not be altered regardless of inclusion strategy; so annotation is basically ignored. + * </li> + * </ul> + * + * @since 1.9 + */ +@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +@JacksonAnnotation +public @interface JsonUnwrapped +{ + /** + * Property that is usually only used when overriding (masking) annotations, + * using mix-in annotations. Otherwise default value of 'true' is fine, and + * value need not be explicitly included. + */ + boolean enabled() default true; +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/annotate/JsonValue.java b/1.9.10/src/java/org/codehaus/jackson/annotate/JsonValue.java new file mode 100644 index 0000000..53b1be5 --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/annotate/JsonValue.java
@@ -0,0 +1,46 @@ +package org.codehaus.jackson.annotate; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Marker annotation similar to + * {@link javax.xml.bind.annotation.XmlValue} + * that indicates that results of the annotated "getter" method + * (which means signature must be that of getters; non-void return + * type, no args) is to be used as the single value to serialize + * for the instance. Usually value will be of a simple scalar type + * (String or Number), but it can be any serializable type (Collection, + * Map or Bean). + *<p> + * At most one method of a Class can be annotated with this annotation; + * if more than one is found, an exception may be thrown. + * Also, if method signature is not compatible with Getters, an exception + * may be thrown. + * Whether exception is thrown or not is an implementation detail (due + * to filtering during introspection, some annotations may be skipped) + * and applications should not rely on specific behavior. + *<p> + * A typical use case is that of annotating <code>toString()</code> + * method so that returned String value is Object's Json serialization. + *<p> + * Boolean argument is only used so that sub-classes can "disable" + * annotation if necessary. + */ +@Target({ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@JacksonAnnotation +public @interface JsonValue +{ + /** + * Optional argument that defines whether this annotation is active + * or not. The only use for value 'false' if for overriding purposes. + * Overriding may be necessary when used + * with "mix-in annotations" (aka "annotation overrides"). + * For most cases, however, default value of "true" is just fine + * and should be omitted. + */ + boolean value() default true; +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/annotate/JsonWriteNullProperties.java b/1.9.10/src/java/org/codehaus/jackson/annotate/JsonWriteNullProperties.java new file mode 100644 index 0000000..40e1bd7 --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/annotate/JsonWriteNullProperties.java
@@ -0,0 +1,34 @@ +package org.codehaus.jackson.annotate; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Annotation that can be used to define whether object properties + * that have null values are to be written out when serializing + * content as JSON. This affects Bean and Map serialization. + *<p> + * Annotation can be used with Classes (all instances of + * given class) and Methods. + *<p> + * Default value for this property is 'true', meaning that null + * properties are written. + *<p> + * @deprecated (since 1.6) Currently recommended annotation to use is + * {@link org.codehaus.jackson.map.annotate.JsonSerialize#include()} + * (with values <code>ALWAYS</code> or <code>NON_NULL</code>) + */ +@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +@JacksonAnnotation +@Deprecated +public @interface JsonWriteNullProperties +{ + /** + * Whether properties for beans of annotated type will always be + * written (true), or only if not null (false). + */ + boolean value() default true; +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/annotate/package-info.java b/1.9.10/src/java/org/codehaus/jackson/annotate/package-info.java new file mode 100644 index 0000000..75abfd2 --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/annotate/package-info.java
@@ -0,0 +1,16 @@ +/** + * Public core annotations, most of which are used to configure how + * Data Mapping/Binding works. Annotations in this package can only + * have dependencies to non-annotation classes in Core package; + * annotations that have dependencies to Mapper classes are included + * in Mapper module (under <code>org.codehaus.jackson.map.annotate</code>). + * Also contains parameter types (mostly enums) needed by annotations. + *<p> + * In future (version 2.0?), this package will probably be split off + * as a separate jar/module, to allow use of annotations without + * including core module. This would be useful for third party value + * classes that themselves do not depend on Jackson, but may want to + * be annotated to be automatically and conveniently serializable by + * Jackson. + */ +package org.codehaus.jackson.annotate;
diff --git a/1.9.10/src/java/org/codehaus/jackson/format/DataFormatDetector.java b/1.9.10/src/java/org/codehaus/jackson/format/DataFormatDetector.java new file mode 100644 index 0000000..5c3a507 --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/format/DataFormatDetector.java
@@ -0,0 +1,176 @@ +package org.codehaus.jackson.format; + +import java.io.*; +import java.util.*; + +import org.codehaus.jackson.*; + +/** + * Simple helper class that allows data format (content type) auto-detection, + * given an ordered set of {@link JsonFactory} instances to use for actual low-level + * detection. + * + * @since 1.7 + */ +public class DataFormatDetector +{ + /** + * By default we will look ahead at most 64 bytes; in most cases, + * much less (4 bytes or so) is needed, but we will allow bit more + * leniency to support data formats that need more complex heuristics. + */ + public final static int DEFAULT_MAX_INPUT_LOOKAHEAD = 64; + + /** + * Ordered list of factories which both represent data formats to + * detect (in precedence order, starting with highest) and are used + * for actual detection. + */ + protected final JsonFactory[] _detectors; + + /** + * Strength of match we consider to be good enough to be used + * without checking any other formats. + * Default value is {@link MatchStrength#SOLID_MATCH}, + */ + protected final MatchStrength _optimalMatch; + + /** + * Strength of minimal match we accept as the answer, unless + * better matches are found. + * Default value is {@link MatchStrength#WEAK_MATCH}, + */ + protected final MatchStrength _minimalMatch; + + /** + * Maximum number of leading bytes of the input that we can read + * to determine data format. + *<p> + * Default value is {@link #DEFAULT_MAX_INPUT_LOOKAHEAD}. + */ + protected final int _maxInputLookahead; + + /* + /********************************************************** + /* Construction + /********************************************************** + */ + + public DataFormatDetector(JsonFactory... detectors) { + this(detectors, MatchStrength.SOLID_MATCH, MatchStrength.WEAK_MATCH, + DEFAULT_MAX_INPUT_LOOKAHEAD); + } + + public DataFormatDetector(Collection<JsonFactory> detectors) { + this(detectors.toArray(new JsonFactory[detectors.size()])); + } + + /** + * Method that will return a detector instance that uses given + * optimal match level (match that is considered sufficient to return, without + * trying to find stronger matches with other formats). + */ + public DataFormatDetector withOptimalMatch(MatchStrength optMatch) { + if (optMatch == _optimalMatch) { + return this; + } + return new DataFormatDetector(_detectors, optMatch, _minimalMatch, _maxInputLookahead); + } + /** + * Method that will return a detector instance that uses given + * minimal match level; match that may be returned unless a stronger match + * is found with other format detectors. + */ + public DataFormatDetector withMinimalMatch(MatchStrength minMatch) { + if (minMatch == _minimalMatch) { + return this; + } + return new DataFormatDetector(_detectors, _optimalMatch, minMatch, _maxInputLookahead); + } + + /** + * Method that will return a detector instance that allows detectors to + * read up to specified number of bytes when determining format match strength. + */ + public DataFormatDetector withMaxInputLookahead(int lookaheadBytes) + { + if (lookaheadBytes == _maxInputLookahead) { + return this; + } + return new DataFormatDetector(_detectors, _optimalMatch, _minimalMatch, lookaheadBytes); + } + + private DataFormatDetector(JsonFactory[] detectors, + MatchStrength optMatch, MatchStrength minMatch, + int maxInputLookahead) + { + _detectors = detectors; + _optimalMatch = optMatch; + _minimalMatch = minMatch; + _maxInputLookahead = maxInputLookahead; + } + + /* + /********************************************************** + /* Public API + /********************************************************** + */ + + /** + * Method to call to find format that content (accessible via given + * {@link InputStream}) given has, as per configuration of this detector + * instance. + * + * @return Matcher object which contains result; never null, even in cases + * where no match (with specified minimal match strength) is found. + */ + public DataFormatMatcher findFormat(InputStream in) throws IOException + { + return _findFormat(new InputAccessor.Std(in, new byte[_maxInputLookahead])); + } + + /** + * Method to call to find format that given content (full document) + * has, as per configuration of this detector instance. + * + * @return Matcher object which contains result; never null, even in cases + * where no match (with specified minimal match strength) is found. + */ + public DataFormatMatcher findFormat(byte[] fullInputData) throws IOException + { + return _findFormat(new InputAccessor.Std(fullInputData)); + } + + /* + /********************************************************** + /* Internal methods + /********************************************************** + */ + + private DataFormatMatcher _findFormat(InputAccessor.Std acc) throws IOException + { + JsonFactory bestMatch = null; + MatchStrength bestMatchStrength = null; + for (JsonFactory f : _detectors) { + acc.reset(); + MatchStrength strength = f.hasFormat(acc); + // if not better than what we have so far (including minimal level limit), skip + if (strength == null || strength.ordinal() < _minimalMatch.ordinal()) { + continue; + } + // also, needs to better match than before + if (bestMatch != null) { + if (bestMatchStrength.ordinal() >= strength.ordinal()) { + continue; + } + } + // finally: if it's good enough match, we are done + bestMatch = f; + bestMatchStrength = strength; + if (strength.ordinal() >= _optimalMatch.ordinal()) { + break; + } + } + return acc.createMatcher(bestMatch, bestMatchStrength); + } +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/format/DataFormatMatcher.java b/1.9.10/src/java/org/codehaus/jackson/format/DataFormatMatcher.java new file mode 100644 index 0000000..c152904 --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/format/DataFormatMatcher.java
@@ -0,0 +1,117 @@ +package org.codehaus.jackson.format; + +import java.io.*; + +import org.codehaus.jackson.JsonFactory; +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.io.MergedStream; + +/** + * Result object constructed by {@link DataFormatDetector} when requested + * to detect format of given input data. + */ +public class DataFormatMatcher +{ + protected final InputStream _originalStream; + + /** + * Content read during format matching process + */ + protected final byte[] _bufferedData; + + /** + * Number of bytes in {@link #_bufferedData} that were read. + */ + protected final int _bufferedLength; + + /** + * Factory that produced sufficient match (if any) + */ + protected final JsonFactory _match; + + /** + * Strength of match with {@link #_match} + */ + protected final MatchStrength _matchStrength; + + protected DataFormatMatcher(InputStream in, byte[] buffered, int bufferedLength, + JsonFactory match, MatchStrength strength) + { + _originalStream = in; + _bufferedData = buffered; + _bufferedLength = bufferedLength; + _match = match; + _matchStrength = strength; + } + + /* + /********************************************************** + /* Public API, simple accessors + /********************************************************** + */ + + /** + * Accessor to use to see if any formats matched well enough with + * the input data. + */ + public boolean hasMatch() { return _match != null; } + + /** + * Method for accessing strength of the match, if any; if no match, + * will return {@link MatchStrength#INCONCLUSIVE}. + */ + public MatchStrength getMatchStrength() { + return (_matchStrength == null) ? MatchStrength.INCONCLUSIVE : _matchStrength; + } + + /** + * Accessor for {@link JsonFactory} that represents format that data matched. + */ + public JsonFactory getMatch() { return _match; } + + /** + * Accessor for getting brief textual name of matched format if any (null + * if none). Equivalent to: + *<pre> + * return hasMatch() ? getMatch().getFormatName() : null; + *</pre> + */ + public String getMatchedFormatName() { + return _match.getFormatName(); + } + + /* + /********************************************************** + /* Public API, factory methods + /********************************************************** + */ + + /** + * Convenience method for trying to construct a {@link JsonParser} for + * parsing content which is assumed to be in detected data format. + * If no match was found, returns null. + */ + public JsonParser createParserWithMatch() throws IOException { + if (_match == null) { + return null; + } + if (_originalStream == null) { + return _match.createJsonParser(_bufferedData, 0, _bufferedLength); + } + return _match.createJsonParser(getDataStream()); + } + + /** + * Method to use for accessing input for which format detection has been done. + * This <b>must</b> be used instead of using stream passed to detector + * unless given stream itself can do buffering. + * Stream will return all content that was read during matching process, as well + * as remaining contents of the underlying stream. + */ + public InputStream getDataStream() { + if (_originalStream == null) { + return new ByteArrayInputStream(_bufferedData, 0, _bufferedLength); + } + return new MergedStream(null, _originalStream, _bufferedData, 0, _bufferedLength); + } +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/format/InputAccessor.java b/1.9.10/src/java/org/codehaus/jackson/format/InputAccessor.java new file mode 100644 index 0000000..e99d2a5 --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/format/InputAccessor.java
@@ -0,0 +1,130 @@ +package org.codehaus.jackson.format; + +import java.io.*; + +import org.codehaus.jackson.JsonFactory; + +/** + * Interface used to expose beginning of a data file to data format + * detection code. + * + * @since 1.8 + */ +public interface InputAccessor +{ + /** + * Method to call to check if more input is available. + * Since this may result in more content to be read (at least + * one more byte), a {@link IOException} may get thrown. + */ + public boolean hasMoreBytes() throws IOException; + + /** + * Returns next byte available, if any; if no more bytes are + * available, will throw {@link java.io.EOFException}. + */ + public byte nextByte() throws IOException; + + /** + * Method that can be called to reset accessor to read from beginning + * of input. + */ + public void reset(); + + /* + /********************************************************** + /* Standard implementation + /********************************************************** + */ + + /** + * Basic implementation that reads data from given + * {@link InputStream} and buffers it as necessary. + */ + public class Std implements InputAccessor + { + protected final InputStream _in; + + protected final byte[] _buffer; + + /** + * Number of bytes in {@link #_buffer} that are valid + * buffered content. + */ + protected int _bufferedAmount; + + /** + * Pointer to next available buffered byte in {@link #_buffer}. + */ + protected int _ptr; + + /** + * Constructor used when content to check is available via + * input stream and must be read. + */ + public Std(InputStream in, byte[] buffer) + { + _in = in; + _buffer = buffer; + _bufferedAmount = 0; + } + + /** + * Constructor used when the full input (or at least enough leading bytes + * of full input) is available. + */ + public Std(byte[] inputDocument) + { + _in = null; + _buffer = inputDocument; + // we have it all: + _bufferedAmount = inputDocument.length; + } + + @Override + public boolean hasMoreBytes() throws IOException + { + if (_ptr < _bufferedAmount) { // already got more + return true; + } + int amount = _buffer.length - _ptr; + if (amount < 1) { // can not load any more + return false; + } + int count = _in.read(_buffer, _ptr, amount); + if (count <= 0) { // EOF + return false; + } + _bufferedAmount += count; + return true; + } + + @Override + public byte nextByte() throws IOException + { + // should we just try loading more automatically? + if (_ptr >- _bufferedAmount) { + if (!hasMoreBytes()) { + throw new EOFException("Could not read more than "+_ptr+" bytes (max buffer size: "+_buffer.length+")"); + } + } + return _buffer[_ptr++]; + } + + @Override + public void reset() { + _ptr = 0; + } + + /* + /********************************************************** + /* Extended API for DataFormatDetector/Matcher + /********************************************************** + */ + + public DataFormatMatcher createMatcher(JsonFactory match, MatchStrength matchStrength) + { + return new DataFormatMatcher(_in, _buffer, _bufferedAmount, match, matchStrength); + } + } +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/format/MatchStrength.java b/1.9.10/src/java/org/codehaus/jackson/format/MatchStrength.java new file mode 100644 index 0000000..02cbba4 --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/format/MatchStrength.java
@@ -0,0 +1,64 @@ +package org.codehaus.jackson.format; + +/** + * Enumeration used to indicate strength of match between data format + * and piece of data (typically beginning of a data file). + * Values are in increasing match strength; and detectors should return + * "strongest" value: that is, it should start with strongest match + * criteria, and downgrading if criteria is not fulfilled. + * + * @since 1.8 + */ +public enum MatchStrength +{ + /** + * Value that indicates that given data can not be in given format. + */ + NO_MATCH, + + /** + * Value that indicates that detector can not find out whether could + * be a match or not. + * This can occur for example for textual data formats t + * when there are so many leading spaces that detector can not + * find the first data byte (because detectors typically limit lookahead + * to some smallish value). + */ + INCONCLUSIVE, + + /** + * Value that indicates that given data could be of specified format (i.e. + * it can not be ruled out). This can occur for example when seen data + * is both not in canonical formats (for example: JSON data should be a JSON Array or Object + * not a scalar value, as per JSON specification) and there are known use case + * where a format detected is actually used (plain JSON Strings are actually used, even + * though specification does not indicate that as valid usage: as such, seeing a leading + * double-quote could indicate a JSON String, which plausibly <b>could</b> indicate + * non-standard JSON usage). + */ + WEAK_MATCH, + + /** + * Value that indicates that given data conforms to (one of) canonical form(s) of + * the data format. + *<p> + * For example, when testing for XML data format, + * seeing a less-than character ("<") alone (with possible leading spaces) + * would be a strong indication that data could + * be in xml format (but see below for {@link #FULL_MATCH} description for more) + */ + SOLID_MATCH, + + /** + * Value that indicates that given data contains a signature that is deemed + * specific enough to uniquely indicate data format used. + *<p> + * For example, when testing for XML data format, + * seing "<xml" as the first data bytes ("XML declaration", as per XML specification) + * could give full confidence that data is indeed in XML format. + * Not all data formats have unique leading identifiers to allow full matches; for example, + * JSON only has heuristic matches and can have at most {@link #SOLID_MATCH}) match. + */ + FULL_MATCH + ; +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/format/package-info.java b/1.9.10/src/java/org/codehaus/jackson/format/package-info.java new file mode 100644 index 0000000..0862f9e --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/format/package-info.java
@@ -0,0 +1,8 @@ +/** + * Package that contains interfaces needed for dynamic, pluggable + * format (auto)detection; as well as basic utility classes for + * simple format detection functionality. + * + * @since 1.8 + */ +package org.codehaus.jackson.format;
diff --git a/1.9.10/src/java/org/codehaus/jackson/impl/ByteSourceBootstrapper.java b/1.9.10/src/java/org/codehaus/jackson/impl/ByteSourceBootstrapper.java new file mode 100644 index 0000000..50094b0 --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/impl/ByteSourceBootstrapper.java
@@ -0,0 +1,518 @@ +package org.codehaus.jackson.impl; + +import java.io.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.format.InputAccessor; +import org.codehaus.jackson.format.MatchStrength; +import org.codehaus.jackson.io.*; +import org.codehaus.jackson.sym.BytesToNameCanonicalizer; +import org.codehaus.jackson.sym.CharsToNameCanonicalizer; + +/** + * This class is used to determine the encoding of byte stream + * that is to contain JSON content. Rules are fairly simple, and + * defined in JSON specification (RFC-4627 or newer), except + * for BOM handling, which is a property of underlying + * streams. + */ +public final class ByteSourceBootstrapper +{ + final static byte UTF8_BOM_1 = (byte) 0xEF; + final static byte UTF8_BOM_2 = (byte) 0xBB; + final static byte UTF8_BOM_3 = (byte) 0xBF; + + /* + /********************************************************** + /* Configuration + /********************************************************** + */ + + protected final IOContext _context; + + protected final InputStream _in; + + /* + /********************************************************** + /* Input buffering + /********************************************************** + */ + + protected final byte[] _inputBuffer; + + private int _inputPtr; + + private int _inputEnd; + + /** + * Flag that indicates whether buffer above is to be recycled + * after being used or not. + */ + private final boolean _bufferRecyclable; + + /* + /********************************************************** + /* Input location + /********************************************************** + */ + + /** + * Current number of input units (bytes or chars) that were processed in + * previous blocks, + * before contents of current input buffer. + *<p> + * Note: includes possible BOMs, if those were part of the input. + */ + protected int _inputProcessed; + + /* + /********************************************************** + /* Data gathered + /********************************************************** + */ + + protected boolean _bigEndian = true; + + protected int _bytesPerChar = 0; // 0 means "dunno yet" + + /* + /********************************************************** + /* Life-cycle + /********************************************************** + */ + + public ByteSourceBootstrapper(IOContext ctxt, InputStream in) + { + _context = ctxt; + _in = in; + _inputBuffer = ctxt.allocReadIOBuffer(); + _inputEnd = _inputPtr = 0; + _inputProcessed = 0; + _bufferRecyclable = true; + } + + public ByteSourceBootstrapper(IOContext ctxt, byte[] inputBuffer, int inputStart, int inputLen) + { + _context = ctxt; + _in = null; + _inputBuffer = inputBuffer; + _inputPtr = inputStart; + _inputEnd = (inputStart + inputLen); + // Need to offset this for correct location info + _inputProcessed = -inputStart; + _bufferRecyclable = false; + } + + /* + /********************************************************** + /* Encoding detection during bootstrapping + /********************************************************** + */ + + /** + * Method that should be called after constructing an instace. + * It will figure out encoding that content uses, to allow + * for instantiating a proper scanner object. + */ + public JsonEncoding detectEncoding() + throws IOException, JsonParseException + { + boolean foundEncoding = false; + + // First things first: BOM handling + /* Note: we can require 4 bytes to be read, since no + * combination of BOM + valid JSON content can have + * shorter length (shortest valid JSON content is single + * digit char, but BOMs are chosen such that combination + * is always at least 4 chars long) + */ + if (ensureLoaded(4)) { + int quad = (_inputBuffer[_inputPtr] << 24) + | ((_inputBuffer[_inputPtr+1] & 0xFF) << 16) + | ((_inputBuffer[_inputPtr+2] & 0xFF) << 8) + | (_inputBuffer[_inputPtr+3] & 0xFF); + + if (handleBOM(quad)) { + foundEncoding = true; + } else { + /* If no BOM, need to auto-detect based on first char; + * this works since it must be 7-bit ascii (wrt. unicode + * compatible encodings, only ones JSON can be transferred + * over) + */ + // UTF-32? + if (checkUTF32(quad)) { + foundEncoding = true; + } else if (checkUTF16(quad >>> 16)) { + foundEncoding = true; + } + } + } else if (ensureLoaded(2)) { + int i16 = ((_inputBuffer[_inputPtr] & 0xFF) << 8) + | (_inputBuffer[_inputPtr+1] & 0xFF); + if (checkUTF16(i16)) { + foundEncoding = true; + } + } + + JsonEncoding enc; + + /* Not found yet? As per specs, this means it must be UTF-8. */ + if (!foundEncoding) { + enc = JsonEncoding.UTF8; + } else { + switch (_bytesPerChar) { + case 1: + enc = JsonEncoding.UTF8; + break; + case 2: + enc = _bigEndian ? JsonEncoding.UTF16_BE : JsonEncoding.UTF16_LE; + break; + case 4: + enc = _bigEndian ? JsonEncoding.UTF32_BE : JsonEncoding.UTF32_LE; + break; + default: + throw new RuntimeException("Internal error"); // should never get here + } + } + _context.setEncoding(enc); + return enc; + } + + /* + /********************************************************** + /* Constructing a Reader + /********************************************************** + */ + + public Reader constructReader() + throws IOException + { + JsonEncoding enc = _context.getEncoding(); + switch (enc) { + case UTF32_BE: + case UTF32_LE: + return new UTF32Reader(_context, _in, _inputBuffer, _inputPtr, _inputEnd, + _context.getEncoding().isBigEndian()); + + case UTF16_BE: + case UTF16_LE: + case UTF8: // only in non-common case where we don't want to do direct mapping + { + // First: do we have a Stream? If not, need to create one: + InputStream in = _in; + + if (in == null) { + in = new ByteArrayInputStream(_inputBuffer, _inputPtr, _inputEnd); + } else { + /* Also, if we have any read but unused input (usually true), + * need to merge that input in: + */ + if (_inputPtr < _inputEnd) { + in = new MergedStream(_context, in, _inputBuffer, _inputPtr, _inputEnd); + } + } + return new InputStreamReader(in, enc.getJavaName()); + } + } + throw new RuntimeException("Internal error"); // should never get here + } + + public JsonParser constructParser(int features, ObjectCodec codec, BytesToNameCanonicalizer rootByteSymbols, CharsToNameCanonicalizer rootCharSymbols) + throws IOException, JsonParseException + { + JsonEncoding enc = detectEncoding(); + + // As per [JACKSON-259], may want to fully disable canonicalization: + boolean canonicalize = JsonParser.Feature.CANONICALIZE_FIELD_NAMES.enabledIn(features); + boolean intern = JsonParser.Feature.INTERN_FIELD_NAMES.enabledIn(features); + if (enc == JsonEncoding.UTF8) { + /* and without canonicalization, byte-based approach is not performance; just use std UTF-8 reader + * (which is ok for larger input; not so hot for smaller; but this is not a common case) + */ + if (canonicalize) { + BytesToNameCanonicalizer can = rootByteSymbols.makeChild(canonicalize, intern); + return new Utf8StreamParser(_context, features, _in, codec, can, _inputBuffer, _inputPtr, _inputEnd, _bufferRecyclable); + } + } + return new ReaderBasedParser(_context, features, constructReader(), codec, rootCharSymbols.makeChild(canonicalize, intern)); + } + + /* + /********************************************************** + /* Encoding detection for data format auto-detection + /********************************************************** + */ + + /** + * Current implementation is not as thorough as other functionality + * ({@link org.codehaus.jackson.impl.ByteSourceBootstrapper}); + * supports UTF-8, for example. But it should work, for now, and can + * be improved as necessary. + * + * @since 1.8 + */ + public static MatchStrength hasJSONFormat(InputAccessor acc) throws IOException + { + // Ideally we should see "[" or "{"; but if not, we'll accept double-quote (String) + // in future could also consider accepting non-standard matches? + + if (!acc.hasMoreBytes()) { + return MatchStrength.INCONCLUSIVE; + } + byte b = acc.nextByte(); + // Very first thing, a UTF-8 BOM? + if (b == UTF8_BOM_1) { // yes, looks like UTF-8 BOM + if (!acc.hasMoreBytes()) { + return MatchStrength.INCONCLUSIVE; + } + if (acc.nextByte() != UTF8_BOM_2) { + return MatchStrength.NO_MATCH; + } + if (!acc.hasMoreBytes()) { + return MatchStrength.INCONCLUSIVE; + } + if (acc.nextByte() != UTF8_BOM_3) { + return MatchStrength.NO_MATCH; + } + if (!acc.hasMoreBytes()) { + return MatchStrength.INCONCLUSIVE; + } + b = acc.nextByte(); + } + // Then possible leading space + int ch = skipSpace(acc, b); + if (ch < 0) { + return MatchStrength.INCONCLUSIVE; + } + // First, let's see if it looks like a structured type: + if (ch == '{') { // JSON object? + // Ideally we need to find either double-quote or closing bracket + ch = skipSpace(acc); + if (ch < 0) { + return MatchStrength.INCONCLUSIVE; + } + if (ch == '"' || ch == '}') { + return MatchStrength.SOLID_MATCH; + } + // ... should we allow non-standard? Let's not yet... can add if need be + return MatchStrength.NO_MATCH; + } + MatchStrength strength; + + if (ch == '[') { + ch = skipSpace(acc); + if (ch < 0) { + return MatchStrength.INCONCLUSIVE; + } + // closing brackets is easy; but for now, let's also accept opening... + if (ch == ']' || ch == '[') { + return MatchStrength.SOLID_MATCH; + } + return MatchStrength.SOLID_MATCH; + } else { + // plain old value is not very convincing... + strength = MatchStrength.WEAK_MATCH; + } + + if (ch == '"') { // string value + return strength; + } + if (ch <= '9' && ch >= '0') { // number + return strength; + } + if (ch == '-') { // negative number + ch = skipSpace(acc); + if (ch < 0) { + return MatchStrength.INCONCLUSIVE; + } + return (ch <= '9' && ch >= '0') ? strength : MatchStrength.NO_MATCH; + } + // or one of literals + if (ch == 'n') { // null + return tryMatch(acc, "ull", strength); + } + if (ch == 't') { // true + return tryMatch(acc, "rue", strength); + } + if (ch == 'f') { // false + return tryMatch(acc, "alse", strength); + } + return MatchStrength.NO_MATCH; + } + + private final static MatchStrength tryMatch(InputAccessor acc, String matchStr, MatchStrength fullMatchStrength) + throws IOException + { + for (int i = 0, len = matchStr.length(); i < len; ++i) { + if (!acc.hasMoreBytes()) { + return MatchStrength.INCONCLUSIVE; + } + if (acc.nextByte() != matchStr.charAt(i)) { + return MatchStrength.NO_MATCH; + } + } + return fullMatchStrength; + } + + private final static int skipSpace(InputAccessor acc) throws IOException + { + if (!acc.hasMoreBytes()) { + return -1; + } + return skipSpace(acc, acc.nextByte()); + } + + private final static int skipSpace(InputAccessor acc, byte b) throws IOException + { + while (true) { + int ch = (int) b & 0xFF; + if (!(ch == ' ' || ch == '\r' || ch == '\n' || ch == '\t')) { + return ch; + } + if (!acc.hasMoreBytes()) { + return -1; + } + b = acc.nextByte(); + ch = (int) b & 0xFF; + } + } + + /* + /********************************************************** + /* Internal methods, parsing + /********************************************************** + */ + + /** + * @return True if a BOM was succesfully found, and encoding + * thereby recognized. + */ + private boolean handleBOM(int quad) + throws IOException + { + /* Handling of (usually) optional BOM (required for + * multi-byte formats); first 32-bit charsets: + */ + switch (quad) { + case 0x0000FEFF: + _bigEndian = true; + _inputPtr += 4; + _bytesPerChar = 4; + return true; + case 0xFFFE0000: // UCS-4, LE? + _inputPtr += 4; + _bytesPerChar = 4; + _bigEndian = false; + return true; + case 0x0000FFFE: // UCS-4, in-order... + reportWeirdUCS4("2143"); // throws exception + case 0xFEFF0000: // UCS-4, in-order... + reportWeirdUCS4("3412"); // throws exception + } + // Ok, if not, how about 16-bit encoding BOMs? + int msw = quad >>> 16; + if (msw == 0xFEFF) { // UTF-16, BE + _inputPtr += 2; + _bytesPerChar = 2; + _bigEndian = true; + return true; + } + if (msw == 0xFFFE) { // UTF-16, LE + _inputPtr += 2; + _bytesPerChar = 2; + _bigEndian = false; + return true; + } + // And if not, then UTF-8 BOM? + if ((quad >>> 8) == 0xEFBBBF) { // UTF-8 + _inputPtr += 3; + _bytesPerChar = 1; + _bigEndian = true; // doesn't really matter + return true; + } + return false; + } + + private boolean checkUTF32(int quad) + throws IOException + { + /* Handling of (usually) optional BOM (required for + * multi-byte formats); first 32-bit charsets: + */ + if ((quad >> 8) == 0) { // 0x000000?? -> UTF32-BE + _bigEndian = true; + } else if ((quad & 0x00FFFFFF) == 0) { // 0x??000000 -> UTF32-LE + _bigEndian = false; + } else if ((quad & ~0x00FF0000) == 0) { // 0x00??0000 -> UTF32-in-order + reportWeirdUCS4("3412"); + } else if ((quad & ~0x0000FF00) == 0) { // 0x0000??00 -> UTF32-in-order + reportWeirdUCS4("2143"); + } else { + // Can not be valid UTF-32 encoded JSON... + return false; + } + // Not BOM (just regular content), nothing to skip past: + //_inputPtr += 4; + _bytesPerChar = 4; + return true; + } + + private boolean checkUTF16(int i16) + { + if ((i16 & 0xFF00) == 0) { // UTF-16BE + _bigEndian = true; + } else if ((i16 & 0x00FF) == 0) { // UTF-16LE + _bigEndian = false; + } else { // nope, not UTF-16 + return false; + } + // Not BOM (just regular content), nothing to skip past: + //_inputPtr += 2; + _bytesPerChar = 2; + return true; + } + + /* + /********************************************************** + /* Internal methods, problem reporting + /********************************************************** + */ + + private void reportWeirdUCS4(String type) + throws IOException + { + throw new CharConversionException("Unsupported UCS-4 endianness ("+type+") detected"); + } + + /* + /********************************************************** + /* Internal methods, raw input access + /********************************************************** + */ + + protected boolean ensureLoaded(int minimum) + throws IOException + { + /* Let's assume here buffer has enough room -- this will always + * be true for the limited used this method gets + */ + int gotten = (_inputEnd - _inputPtr); + while (gotten < minimum) { + int count; + + if (_in == null) { // block source + count = -1; + } else { + count = _in.read(_inputBuffer, _inputEnd, _inputBuffer.length - _inputEnd); + } + if (count < 1) { + return false; + } + _inputEnd += count; + gotten += count; + } + return true; + } +} +
diff --git a/1.9.10/src/java/org/codehaus/jackson/impl/DefaultPrettyPrinter.java b/1.9.10/src/java/org/codehaus/jackson/impl/DefaultPrettyPrinter.java new file mode 100644 index 0000000..7b12d3a --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/impl/DefaultPrettyPrinter.java
@@ -0,0 +1,13 @@ +package org.codehaus.jackson.impl; + +/** + * Deprecated version of the default pretty printer. + * + * @deprecated Moved to {@link org.codehaus.jackson.util.DefaultPrettyPrinter}; will be removed in Jackson 2.0 + */ +@Deprecated +public class DefaultPrettyPrinter + extends org.codehaus.jackson.util.DefaultPrettyPrinter +{ + +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/impl/Indenter.java b/1.9.10/src/java/org/codehaus/jackson/impl/Indenter.java new file mode 100644 index 0000000..6249f55 --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/impl/Indenter.java
@@ -0,0 +1,23 @@ +package org.codehaus.jackson.impl; + +import java.io.IOException; + +import org.codehaus.jackson.*; + +/** + * Interface that defines objects that can produce indentation used + * to separate object entries and array values. Indentation in this + * context just means insertion of white space, independent of whether + * linefeeds are output. + */ +public interface Indenter +{ + public void writeIndentation(JsonGenerator jg, int level) + throws IOException, JsonGenerationException; + + /** + * @return True if indenter is considered inline (does not add linefeeds), + * false otherwise + */ + public boolean isInline(); +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/impl/JsonGeneratorBase.java b/1.9.10/src/java/org/codehaus/jackson/impl/JsonGeneratorBase.java new file mode 100644 index 0000000..3db4260 --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/impl/JsonGeneratorBase.java
@@ -0,0 +1,570 @@ +package org.codehaus.jackson.impl; + +import java.io.*; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.util.DefaultPrettyPrinter; +import org.codehaus.jackson.util.VersionUtil; + +/** + * This base class implements part of API that a JSON generator exposes + * to applications, adds shared internal methods that sub-classes + * can use and adds some abstract methods sub-classes must implement. + */ +public abstract class JsonGeneratorBase + extends JsonGenerator +{ + /* + /********************************************************** + /* Configuration + /********************************************************** + */ + + protected ObjectCodec _objectCodec; + + /** + * Bit flag composed of bits that indicate which + * {@link org.codehaus.jackson.JsonGenerator.Feature}s + * are enabled. + */ + protected int _features; + + /** + * Flag set to indicate that implicit conversion from number + * to JSON String is needed (as per + * {@link org.codehaus.jackson.JsonGenerator.Feature#WRITE_NUMBERS_AS_STRINGS}). + */ + protected boolean _cfgNumbersAsStrings; + + /* + /********************************************************** + /* State + /********************************************************** + */ + + /** + * Object that keeps track of the current contextual state + * of the generator. + */ + protected JsonWriteContext _writeContext; + + /** + * Flag that indicates whether generator is closed or not. Gets + * set when it is closed by an explicit call + * ({@link #close}). + */ + protected boolean _closed; + + /* + /********************************************************** + /* Life-cycle + /********************************************************** + */ + + protected JsonGeneratorBase(int features, ObjectCodec codec) + { + super(); + _features = features; + _writeContext = JsonWriteContext.createRootContext(); + _objectCodec = codec; + _cfgNumbersAsStrings = isEnabled(Feature.WRITE_NUMBERS_AS_STRINGS); + } + + @Override + public Version version() { + return VersionUtil.versionFor(getClass()); + } + + /* + /********************************************************** + /* Configuration + /********************************************************** + */ + + @Override + public JsonGenerator enable(Feature f) { + _features |= f.getMask(); + if (f == Feature.WRITE_NUMBERS_AS_STRINGS) { + _cfgNumbersAsStrings = true; + } else if (f == Feature.ESCAPE_NON_ASCII) { + setHighestNonEscapedChar(127); + } + return this; + } + + @Override + public JsonGenerator disable(Feature f) { + _features &= ~f.getMask(); + if (f == Feature.WRITE_NUMBERS_AS_STRINGS) { + _cfgNumbersAsStrings = false; + } else if (f == Feature.ESCAPE_NON_ASCII) { + setHighestNonEscapedChar(0); + } + return this; + } + + //public JsonGenerator configure(Feature f, boolean state) { } + + @Override + public final boolean isEnabled(Feature f) { + return (_features & f.getMask()) != 0; + } + + @Override + public JsonGenerator useDefaultPrettyPrinter() { + return setPrettyPrinter(new DefaultPrettyPrinter()); + } + + @Override + public JsonGenerator setCodec(ObjectCodec oc) { + _objectCodec = oc; + return this; + } + + @Override + public final ObjectCodec getCodec() { return _objectCodec; } + + /* + /********************************************************** + /* Public API, accessors + /********************************************************** + */ + + /** + * Note: co-variant return type. + */ + @Override + public final JsonWriteContext getOutputContext() { return _writeContext; } + + /* + /********************************************************** + /* Public API, write methods, structural + /********************************************************** + */ + + @Override + public void writeStartArray() throws IOException, JsonGenerationException + { + // Array is a value, need to verify it's allowed + _verifyValueWrite("start an array"); + _writeContext = _writeContext.createChildArrayContext(); + if (_cfgPrettyPrinter != null) { + _cfgPrettyPrinter.writeStartArray(this); + } else { + _writeStartArray(); + } + } + + /** + * @deprecated since 1.7, should just override {@link #writeStartArray} instead + * of defining this method + */ + @Deprecated + protected void _writeStartArray() throws IOException, JsonGenerationException { + } + + @Override + public void writeEndArray() throws IOException, JsonGenerationException + { + if (!_writeContext.inArray()) { + _reportError("Current context not an ARRAY but "+_writeContext.getTypeDesc()); + } + if (_cfgPrettyPrinter != null) { + _cfgPrettyPrinter.writeEndArray(this, _writeContext.getEntryCount()); + } else { + _writeEndArray(); + } + _writeContext = _writeContext.getParent(); + } + + /** + * @deprecated since 1.7, should just override {@link #writeEndArray} instead + * of defining this method + */ + @Deprecated + protected void _writeEndArray() throws IOException, JsonGenerationException { + } + + @Override + public void writeStartObject() throws IOException, JsonGenerationException + { + _verifyValueWrite("start an object"); + _writeContext = _writeContext.createChildObjectContext(); + if (_cfgPrettyPrinter != null) { + _cfgPrettyPrinter.writeStartObject(this); + } else { + _writeStartObject(); + } + } + + /** + * @deprecated since 1.7, should just override {@link #writeStartObject} instead + * of defining this method + */ + @Deprecated + protected void _writeStartObject() throws IOException, JsonGenerationException { + } + + @Override + public void writeEndObject() throws IOException, JsonGenerationException + { + if (!_writeContext.inObject()) { + _reportError("Current context not an object but "+_writeContext.getTypeDesc()); + } + _writeContext = _writeContext.getParent(); + if (_cfgPrettyPrinter != null) { + _cfgPrettyPrinter.writeEndObject(this, _writeContext.getEntryCount()); + } else { + _writeEndObject(); + } + } + + /** + * @deprecated since 1.7, should just override {@link #writeEndObject} instead + * of defining this method + */ + @Deprecated + protected void _writeEndObject() throws IOException, JsonGenerationException { + } + + /* + /********************************************************** + /* Public API, write methods, textual + /********************************************************** + */ + + //public abstract void writeString(String text) throws IOException, JsonGenerationException; + + //public abstract void writeString(char[] text, int offset, int len) throws IOException, JsonGenerationException; + + //public abstract void writeRaw(String text) throws IOException, JsonGenerationException; + + //public abstract void writeRaw(char[] text, int offset, int len) throws IOException, JsonGenerationException; + + @Override + public void writeRawValue(String text) + throws IOException, JsonGenerationException + { + _verifyValueWrite("write raw value"); + writeRaw(text); + } + + @Override + public void writeRawValue(String text, int offset, int len) + throws IOException, JsonGenerationException + { + _verifyValueWrite("write raw value"); + writeRaw(text, offset, len); + } + + @Override + public void writeRawValue(char[] text, int offset, int len) + throws IOException, JsonGenerationException + { + _verifyValueWrite("write raw value"); + writeRaw(text, offset, len); + } + + //public abstract void writeBinary(byte[] data, int offset, int len, boolean includeLFs) throws IOException, JsonGenerationException; + + + /* + /********************************************************** + /* Public API, write methods, primitive + /********************************************************** + */ + + // Not implemented at this level, added as placeholders + + /* + public abstract void writeNumber(int i) + public abstract void writeNumber(long l) + public abstract void writeNumber(double d) + public abstract void writeNumber(float f) + public abstract void writeNumber(BigDecimal dec) + public abstract void writeBoolean(boolean state) + public abstract void writeNull() + */ + + /* + /********************************************************** + /* Public API, write methods, POJOs, trees + /********************************************************** + */ + + @Override + public void writeObject(Object value) + throws IOException, JsonProcessingException + { + if (value == null) { + // important: call method that does check value write: + writeNull(); + } else { + /* 02-Mar-2009, tatu: we are NOT to call _verifyValueWrite here, + * because that will be done when codec actually serializes + * contained POJO. If we did call it it would advance state + * causing exception later on + */ + if (_objectCodec != null) { + _objectCodec.writeValue(this, value); + return; + } + _writeSimpleObject(value); + } + } + + @Override + public void writeTree(JsonNode rootNode) + throws IOException, JsonProcessingException + { + // As with 'writeObject()', we are not check if write would work + if (rootNode == null) { + writeNull(); + } else { + if (_objectCodec == null) { + throw new IllegalStateException("No ObjectCodec defined for the generator, can not serialize JsonNode-based trees"); + } + _objectCodec.writeTree(this, rootNode); + } + } + + /* + /********************************************************** + /* Public API, low-level output handling + /********************************************************** + */ + + @Override + public abstract void flush() throws IOException; + + @Override + public void close() throws IOException + { + _closed = true; + } + + @Override + public boolean isClosed() { return _closed; } + + /* + /********************************************************** + /* Public API, copy-through methods + /********************************************************** + */ + + @Override + public final void copyCurrentEvent(JsonParser jp) + throws IOException, JsonProcessingException + { + JsonToken t = jp.getCurrentToken(); + // sanity check; what to do? + if (t == null) { + _reportError("No current event to copy"); + } + switch(t) { + case START_OBJECT: + writeStartObject(); + break; + case END_OBJECT: + writeEndObject(); + break; + case START_ARRAY: + writeStartArray(); + break; + case END_ARRAY: + writeEndArray(); + break; + case FIELD_NAME: + writeFieldName(jp.getCurrentName()); + break; + case VALUE_STRING: + if (jp.hasTextCharacters()) { + writeString(jp.getTextCharacters(), jp.getTextOffset(), jp.getTextLength()); + } else { + writeString(jp.getText()); + } + break; + case VALUE_NUMBER_INT: + switch (jp.getNumberType()) { + case INT: + writeNumber(jp.getIntValue()); + break; + case BIG_INTEGER: + writeNumber(jp.getBigIntegerValue()); + break; + default: + writeNumber(jp.getLongValue()); + } + break; + case VALUE_NUMBER_FLOAT: + switch (jp.getNumberType()) { + case BIG_DECIMAL: + writeNumber(jp.getDecimalValue()); + break; + case FLOAT: + writeNumber(jp.getFloatValue()); + break; + default: + writeNumber(jp.getDoubleValue()); + } + break; + case VALUE_TRUE: + writeBoolean(true); + break; + case VALUE_FALSE: + writeBoolean(false); + break; + case VALUE_NULL: + writeNull(); + break; + case VALUE_EMBEDDED_OBJECT: + writeObject(jp.getEmbeddedObject()); + break; + default: + _cantHappen(); + } + } + + @Override + public final void copyCurrentStructure(JsonParser jp) + throws IOException, JsonProcessingException + { + JsonToken t = jp.getCurrentToken(); + + // Let's handle field-name separately first + if (t == JsonToken.FIELD_NAME) { + writeFieldName(jp.getCurrentName()); + t = jp.nextToken(); + // fall-through to copy the associated value + } + + switch (t) { + case START_ARRAY: + writeStartArray(); + while (jp.nextToken() != JsonToken.END_ARRAY) { + copyCurrentStructure(jp); + } + writeEndArray(); + break; + case START_OBJECT: + writeStartObject(); + while (jp.nextToken() != JsonToken.END_OBJECT) { + copyCurrentStructure(jp); + } + writeEndObject(); + break; + default: // others are simple: + copyCurrentEvent(jp); + } + } + + /* + /********************************************************** + /* Package methods for this, sub-classes + /********************************************************** + */ + + protected abstract void _releaseBuffers(); + + protected abstract void _verifyValueWrite(String typeMsg) + throws IOException, JsonGenerationException; + + protected void _reportError(String msg) + throws JsonGenerationException + { + throw new JsonGenerationException(msg); + } + + protected void _cantHappen() + { + throw new RuntimeException("Internal error: should never end up through this code path"); + } + + /** + * Helper method to try to call appropriate write method for given + * untyped Object. At this point, no structural conversions should be done, + * only simple basic types are to be coerced as necessary. + * + * @param value Non-null value to write + */ + protected void _writeSimpleObject(Object value) + throws IOException, JsonGenerationException + { + /* 31-Dec-2009, tatu: Actually, we could just handle some basic + * types even without codec. This can improve interoperability, + * and specifically help with TokenBuffer. + */ + if (value == null) { + writeNull(); + return; + } + if (value instanceof String) { + writeString((String) value); + return; + } + if (value instanceof Number) { + Number n = (Number) value; + if (n instanceof Integer) { + writeNumber(n.intValue()); + return; + } else if (n instanceof Long) { + writeNumber(n.longValue()); + return; + } else if (n instanceof Double) { + writeNumber(n.doubleValue()); + return; + } else if (n instanceof Float) { + writeNumber(n.floatValue()); + return; + } else if (n instanceof Short) { + writeNumber(n.shortValue()); + return; + } else if (n instanceof Byte) { + writeNumber(n.byteValue()); + return; + } else if (n instanceof BigInteger) { + writeNumber((BigInteger) n); + return; + } else if (n instanceof BigDecimal) { + writeNumber((BigDecimal) n); + return; + + // then Atomic types + + } else if (n instanceof AtomicInteger) { + writeNumber(((AtomicInteger) n).get()); + return; + } else if (n instanceof AtomicLong) { + writeNumber(((AtomicLong) n).get()); + return; + } + } else if (value instanceof byte[]) { + writeBinary((byte[]) value); + return; + } else if (value instanceof Boolean) { + writeBoolean(((Boolean) value).booleanValue()); + return; + } else if (value instanceof AtomicBoolean) { + writeBoolean(((AtomicBoolean) value).get()); + return; + } + throw new IllegalStateException("No ObjectCodec defined for the generator, can only serialize simple wrapper types (type passed " + +value.getClass().getName()+")"); + } + + protected final void _throwInternal() { + throw new RuntimeException("Internal error: this code path should never get executed"); + } + + /** + * @since 1.7 + */ + protected void _reportUnsupportedOperation() { + throw new UnsupportedOperationException("Operation not supported by generator of type "+getClass().getName()); + } +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/impl/JsonNumericParserBase.java b/1.9.10/src/java/org/codehaus/jackson/impl/JsonNumericParserBase.java new file mode 100644 index 0000000..6dd062d --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/impl/JsonNumericParserBase.java
@@ -0,0 +1,20 @@ +package org.codehaus.jackson.impl; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.io.IOContext; + +/** + * Another intermediate base class used by all Jackson {@link JsonParser} + * implementations. Contains shared functionality for dealing with + * number parsing aspects, independent of input source decoding. + * + * @deprecated Since 1.9.0: functionality demoted down to JsonParserBase + */ +@Deprecated +public abstract class JsonNumericParserBase + extends JsonParserBase +{ + protected JsonNumericParserBase(IOContext ctxt, int features) { + super(ctxt, features); + } +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/impl/JsonParserBase.java b/1.9.10/src/java/org/codehaus/jackson/impl/JsonParserBase.java new file mode 100644 index 0000000..4103677 --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/impl/JsonParserBase.java
@@ -0,0 +1,1079 @@ +package org.codehaus.jackson.impl; + +import java.io.*; +import java.math.BigDecimal; +import java.math.BigInteger; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.io.IOContext; +import org.codehaus.jackson.io.NumberInput; +import org.codehaus.jackson.util.ByteArrayBuilder; +import org.codehaus.jackson.util.TextBuffer; +import org.codehaus.jackson.util.VersionUtil; + +/** + * Intermediate base class used by all Jackson {@link JsonParser} + * implementations. Contains most common things that are independent + * of actual underlying input source + * + * @author Tatu Saloranta + */ +public abstract class JsonParserBase + extends JsonParserMinimalBase +{ + /* + /********************************************************** + /* Generic I/O state + /********************************************************** + */ + + /** + * I/O context for this reader. It handles buffer allocation + * for the reader. + */ + final protected IOContext _ioContext; + + /** + * Flag that indicates whether parser is closed or not. Gets + * set when parser is either closed by explicit call + * ({@link #close}) or when end-of-input is reached. + */ + protected boolean _closed; + + /* + /********************************************************** + /* Current input data + /********************************************************** + */ + + // Note: type of actual buffer depends on sub-class, can't include + + /** + * Pointer to next available character in buffer + */ + protected int _inputPtr = 0; + + /** + * Index of character after last available one in the buffer. + */ + protected int _inputEnd = 0; + + /* + /********************************************************** + /* Current input location information + /********************************************************** + */ + + /** + * Number of characters/bytes that were contained in previous blocks + * (blocks that were already processed prior to the current buffer). + */ + protected long _currInputProcessed = 0L; + + /** + * Current row location of current point in input buffer, starting + * from 1, if available. + */ + protected int _currInputRow = 1; + + /** + * Current index of the first character of the current row in input + * buffer. Needed to calculate column position, if necessary; benefit + * of not having column itself is that this only has to be updated + * once per line. + */ + protected int _currInputRowStart = 0; + + /* + /********************************************************** + /* Information about starting location of event + /* Reader is pointing to; updated on-demand + /********************************************************** + */ + + // // // Location info at point when current token was started + + /** + * Total number of bytes/characters read before start of current token. + * For big (gigabyte-sized) sizes are possible, needs to be long, + * unlike pointers and sizes related to in-memory buffers. + */ + protected long _tokenInputTotal = 0; + + /** + * Input row on which current token starts, 1-based + */ + protected int _tokenInputRow = 1; + + /** + * Column on input row that current token starts; 0-based (although + * in the end it'll be converted to 1-based) + */ + protected int _tokenInputCol = 0; + + /* + /********************************************************** + /* Parsing state + /********************************************************** + */ + + /** + * Information about parser context, context in which + * the next token is to be parsed (root, array, object). + */ + protected JsonReadContext _parsingContext; + + /** + * Secondary token related to the next token after current one; + * used if its type is known. This may be value token that + * follows FIELD_NAME, for example. + */ + protected JsonToken _nextToken; + + /* + /********************************************************** + /* Buffer(s) for local name(s) and text content + /********************************************************** + */ + + /** + * Buffer that contains contents of String values, including + * field names if necessary (name split across boundary, + * contains escape sequence, or access needed to char array) + */ + protected final TextBuffer _textBuffer; + + /** + * Temporary buffer that is needed if field name is accessed + * using {@link #getTextCharacters} method (instead of String + * returning alternatives) + */ + protected char[] _nameCopyBuffer = null; + + /** + * Flag set to indicate whether the field name is available + * from the name copy buffer or not (in addition to its String + * representation being available via read context) + */ + protected boolean _nameCopied = false; + + /** + * ByteArrayBuilder is needed if 'getBinaryValue' is called. If so, + * we better reuse it for remainder of content. + */ + protected ByteArrayBuilder _byteArrayBuilder = null; + + /** + * We will hold on to decoded binary data, for duration of + * current event, so that multiple calls to + * {@link #getBinaryValue} will not need to decode data more + * than once. + */ + protected byte[] _binaryValue; + + /* + /********************************************************** + /* Constants and fields of former 'JsonNumericParserBase' + /********************************************************** + */ + + final protected static int NR_UNKNOWN = 0; + + // First, integer types + + final protected static int NR_INT = 0x0001; + final protected static int NR_LONG = 0x0002; + final protected static int NR_BIGINT = 0x0004; + + // And then floating point types + + final protected static int NR_DOUBLE = 0x008; + final protected static int NR_BIGDECIMAL = 0x0010; + + // Also, we need some numeric constants + + final static BigInteger BI_MIN_INT = BigInteger.valueOf(Integer.MIN_VALUE); + final static BigInteger BI_MAX_INT = BigInteger.valueOf(Integer.MAX_VALUE); + + final static BigInteger BI_MIN_LONG = BigInteger.valueOf(Long.MIN_VALUE); + final static BigInteger BI_MAX_LONG = BigInteger.valueOf(Long.MAX_VALUE); + + final static BigDecimal BD_MIN_LONG = new BigDecimal(BI_MIN_LONG); + final static BigDecimal BD_MAX_LONG = new BigDecimal(BI_MAX_LONG); + + final static BigDecimal BD_MIN_INT = new BigDecimal(BI_MIN_INT); + final static BigDecimal BD_MAX_INT = new BigDecimal(BI_MAX_INT); + + final static long MIN_INT_L = (long) Integer.MIN_VALUE; + final static long MAX_INT_L = (long) Integer.MAX_VALUE; + + // These are not very accurate, but have to do... (for bounds checks) + + final static double MIN_LONG_D = (double) Long.MIN_VALUE; + final static double MAX_LONG_D = (double) Long.MAX_VALUE; + + final static double MIN_INT_D = (double) Integer.MIN_VALUE; + final static double MAX_INT_D = (double) Integer.MAX_VALUE; + + + // Digits, numeric + final protected static int INT_0 = '0'; + final protected static int INT_1 = '1'; + final protected static int INT_2 = '2'; + final protected static int INT_3 = '3'; + final protected static int INT_4 = '4'; + final protected static int INT_5 = '5'; + final protected static int INT_6 = '6'; + final protected static int INT_7 = '7'; + final protected static int INT_8 = '8'; + final protected static int INT_9 = '9'; + + final protected static int INT_MINUS = '-'; + final protected static int INT_PLUS = '+'; + final protected static int INT_DECIMAL_POINT = '.'; + + final protected static int INT_e = 'e'; + final protected static int INT_E = 'E'; + + final protected static char CHAR_NULL = '\0'; + + // Numeric value holders: multiple fields used for + // for efficiency + + /** + * Bitfield that indicates which numeric representations + * have been calculated for the current type + */ + protected int _numTypesValid = NR_UNKNOWN; + + // First primitives + + protected int _numberInt; + + protected long _numberLong; + + protected double _numberDouble; + + // And then object types + + protected BigInteger _numberBigInt; + + protected BigDecimal _numberBigDecimal; + + // And then other information about value itself + + /** + * Flag that indicates whether numeric value has a negative + * value. That is, whether its textual representation starts + * with minus character. + */ + protected boolean _numberNegative; + + /** + * Length of integer part of the number, in characters + */ + protected int _intLength; + + /** + * Length of the fractional part (not including decimal + * point or exponent), in characters. + * Not used for pure integer values. + */ + protected int _fractLength; + + /** + * Length of the exponent part of the number, if any, not + * including 'e' marker or sign, just digits. + * Not used for pure integer values. + */ + protected int _expLength; + + /* + /********************************************************** + /* Life-cycle + /********************************************************** + */ + + protected JsonParserBase(IOContext ctxt, int features) + { + super(); + _features = features; + _ioContext = ctxt; + _textBuffer = ctxt.constructTextBuffer(); + _parsingContext = JsonReadContext.createRootContext(); + } + + @Override + public Version version() { + return VersionUtil.versionFor(getClass()); + } + + /* + /********************************************************** + /* JsonParser impl + /********************************************************** + */ + + /** + * Method that can be called to get the name associated with + * the current event. + */ + @Override + public String getCurrentName() + throws IOException, JsonParseException + { + // [JACKSON-395]: start markers require information from parent + if (_currToken == JsonToken.START_OBJECT || _currToken == JsonToken.START_ARRAY) { + JsonReadContext parent = _parsingContext.getParent(); + return parent.getCurrentName(); + } + return _parsingContext.getCurrentName(); + } + + @Override + public void close() throws IOException + { + if (!_closed) { + _closed = true; + try { + _closeInput(); + } finally { + // as per [JACKSON-324], do in finally block + // Also, internal buffer(s) can now be released as well + _releaseBuffers(); + } + } + } + + @Override + public boolean isClosed() { return _closed; } + + @Override + public JsonReadContext getParsingContext() + { + return _parsingContext; + } + + /** + * Method that return the <b>starting</b> location of the current + * token; that is, position of the first character from input + * that starts the current token. + */ + @Override + public JsonLocation getTokenLocation() + { + return new JsonLocation(_ioContext.getSourceReference(), + getTokenCharacterOffset(), + getTokenLineNr(), + getTokenColumnNr()); + } + + /** + * Method that returns location of the last processed character; + * usually for error reporting purposes + */ + @Override + public JsonLocation getCurrentLocation() + { + int col = _inputPtr - _currInputRowStart + 1; // 1-based + return new JsonLocation(_ioContext.getSourceReference(), + _currInputProcessed + _inputPtr - 1, + _currInputRow, col); + } + + /* + /********************************************************** + /* Public API, access to token information, text + /********************************************************** + */ + + @Override + public boolean hasTextCharacters() + { + if (_currToken == JsonToken.VALUE_STRING) { + return true; // usually true + } + if (_currToken == JsonToken.FIELD_NAME) { + return _nameCopied; + } + return false; + } + + /* + /********************************************************** + /* Public low-level accessors + /********************************************************** + */ + + public final long getTokenCharacterOffset() { return _tokenInputTotal; } + public final int getTokenLineNr() { return _tokenInputRow; } + public final int getTokenColumnNr() { + // note: value of -1 means "not available"; otherwise convert from 0-based to 1-based + int col = _tokenInputCol; + return (col < 0) ? col : (col + 1); + } + + /* + /********************************************************** + /* Low-level reading, other + /********************************************************** + */ + + protected final void loadMoreGuaranteed() + throws IOException + { + if (!loadMore()) { + _reportInvalidEOF(); + } + } + + /* + /********************************************************** + /* Abstract methods needed from sub-classes + /********************************************************** + */ + + protected abstract boolean loadMore() throws IOException; + + protected abstract void _finishString() throws IOException, JsonParseException; + + protected abstract void _closeInput() throws IOException; + + /* + /********************************************************** + /* Low-level reading, other + /********************************************************** + */ + + /** + * Method called to release internal buffers owned by the base + * reader. This may be called along with {@link #_closeInput} (for + * example, when explicitly closing this reader instance), or + * separately (if need be). + */ + protected void _releaseBuffers() throws IOException + { + _textBuffer.releaseBuffers(); + char[] buf = _nameCopyBuffer; + if (buf != null) { + _nameCopyBuffer = null; + _ioContext.releaseNameCopyBuffer(buf); + } + } + + /** + * Method called when an EOF is encountered between tokens. + * If so, it may be a legitimate EOF, but only iff there + * is no open non-root context. + */ + @Override + protected void _handleEOF() throws JsonParseException + { + if (!_parsingContext.inRoot()) { + _reportInvalidEOF(": expected close marker for "+_parsingContext.getTypeDesc()+" (from "+_parsingContext.getStartLocation(_ioContext.getSourceReference())+")"); + } + } + + /* + /********************************************************** + /* Internal/package methods: Error reporting + /********************************************************** + */ + + protected void _reportMismatchedEndMarker(int actCh, char expCh) + throws JsonParseException + { + String startDesc = ""+_parsingContext.getStartLocation(_ioContext.getSourceReference()); + _reportError("Unexpected close marker '"+((char) actCh)+"': expected '"+expCh+"' (for "+_parsingContext.getTypeDesc()+" starting at "+startDesc+")"); + } + + /* + /********************************************************** + /* Internal/package methods: shared/reusable builders + /********************************************************** + */ + + public ByteArrayBuilder _getByteArrayBuilder() + { + if (_byteArrayBuilder == null) { + _byteArrayBuilder = new ByteArrayBuilder(); + } else { + _byteArrayBuilder.reset(); + } + return _byteArrayBuilder; + } + + /* + /********************************************************** + /* Methods from former JsonNumericParserBase + /********************************************************** + */ + + // // // Life-cycle of number-parsing + + protected final JsonToken reset(boolean negative, int intLen, int fractLen, int expLen) + { + if (fractLen < 1 && expLen < 1) { // integer + return resetInt(negative, intLen); + } + return resetFloat(negative, intLen, fractLen, expLen); + } + + protected final JsonToken resetInt(boolean negative, int intLen) + { + _numberNegative = negative; + _intLength = intLen; + _fractLength = 0; + _expLength = 0; + _numTypesValid = NR_UNKNOWN; // to force parsing + return JsonToken.VALUE_NUMBER_INT; + } + + protected final JsonToken resetFloat(boolean negative, int intLen, int fractLen, int expLen) + { + _numberNegative = negative; + _intLength = intLen; + _fractLength = fractLen; + _expLength = expLen; + _numTypesValid = NR_UNKNOWN; // to force parsing + return JsonToken.VALUE_NUMBER_FLOAT; + } + + protected final JsonToken resetAsNaN(String valueStr, double value) + { + _textBuffer.resetWithString(valueStr); + _numberDouble = value; + _numTypesValid = NR_DOUBLE; + return JsonToken.VALUE_NUMBER_FLOAT; + } + + /* + /********************************************************** + /* Numeric accessors of public API + /********************************************************** + */ + + @Override + public Number getNumberValue() throws IOException, JsonParseException + { + if (_numTypesValid == NR_UNKNOWN) { + _parseNumericValue(NR_UNKNOWN); // will also check event type + } + // Separate types for int types + if (_currToken == JsonToken.VALUE_NUMBER_INT) { + if ((_numTypesValid & NR_INT) != 0) { + return Integer.valueOf(_numberInt); + } + if ((_numTypesValid & NR_LONG) != 0) { + return Long.valueOf(_numberLong); + } + if ((_numTypesValid & NR_BIGINT) != 0) { + return _numberBigInt; + } + // Shouldn't get this far but if we do + return _numberBigDecimal; + } + + /* And then floating point types. But here optimal type + * needs to be big decimal, to avoid losing any data? + */ + if ((_numTypesValid & NR_BIGDECIMAL) != 0) { + return _numberBigDecimal; + } + if ((_numTypesValid & NR_DOUBLE) == 0) { // sanity check + _throwInternal(); + } + return Double.valueOf(_numberDouble); + } + + @Override + public NumberType getNumberType() throws IOException, JsonParseException + { + if (_numTypesValid == NR_UNKNOWN) { + _parseNumericValue(NR_UNKNOWN); // will also check event type + } + if (_currToken == JsonToken.VALUE_NUMBER_INT) { + if ((_numTypesValid & NR_INT) != 0) { + return NumberType.INT; + } + if ((_numTypesValid & NR_LONG) != 0) { + return NumberType.LONG; + } + return NumberType.BIG_INTEGER; + } + + /* And then floating point types. Here optimal type + * needs to be big decimal, to avoid losing any data? + * However... using BD is slow, so let's allow returning + * double as type if no explicit call has been made to access + * data as BD? + */ + if ((_numTypesValid & NR_BIGDECIMAL) != 0) { + return NumberType.BIG_DECIMAL; + } + return NumberType.DOUBLE; + } + + @Override + public int getIntValue() throws IOException, JsonParseException + { + if ((_numTypesValid & NR_INT) == 0) { + if (_numTypesValid == NR_UNKNOWN) { // not parsed at all + _parseNumericValue(NR_INT); // will also check event type + } + if ((_numTypesValid & NR_INT) == 0) { // wasn't an int natively? + convertNumberToInt(); // let's make it so, if possible + } + } + return _numberInt; + } + + @Override + public long getLongValue() throws IOException, JsonParseException + { + if ((_numTypesValid & NR_LONG) == 0) { + if (_numTypesValid == NR_UNKNOWN) { + _parseNumericValue(NR_LONG); + } + if ((_numTypesValid & NR_LONG) == 0) { + convertNumberToLong(); + } + } + return _numberLong; + } + + @Override + public BigInteger getBigIntegerValue() throws IOException, JsonParseException + { + if ((_numTypesValid & NR_BIGINT) == 0) { + if (_numTypesValid == NR_UNKNOWN) { + _parseNumericValue(NR_BIGINT); + } + if ((_numTypesValid & NR_BIGINT) == 0) { + convertNumberToBigInteger(); + } + } + return _numberBigInt; + } + + @Override + public float getFloatValue() throws IOException, JsonParseException + { + double value = getDoubleValue(); + /* 22-Jan-2009, tatu: Bounds/range checks would be tricky + * here, so let's not bother even trying... + */ + /* + if (value < -Float.MAX_VALUE || value > MAX_FLOAT_D) { + _reportError("Numeric value ("+getText()+") out of range of Java float"); + } + */ + return (float) value; + } + + @Override + public double getDoubleValue() throws IOException, JsonParseException + { + if ((_numTypesValid & NR_DOUBLE) == 0) { + if (_numTypesValid == NR_UNKNOWN) { + _parseNumericValue(NR_DOUBLE); + } + if ((_numTypesValid & NR_DOUBLE) == 0) { + convertNumberToDouble(); + } + } + return _numberDouble; + } + + @Override + public BigDecimal getDecimalValue() throws IOException, JsonParseException + { + if ((_numTypesValid & NR_BIGDECIMAL) == 0) { + if (_numTypesValid == NR_UNKNOWN) { + _parseNumericValue(NR_BIGDECIMAL); + } + if ((_numTypesValid & NR_BIGDECIMAL) == 0) { + convertNumberToBigDecimal(); + } + } + return _numberBigDecimal; + } + + /* + /********************************************************** + /* Conversion from textual to numeric representation + /********************************************************** + */ + + /** + * Method that will parse actual numeric value out of a syntactically + * valid number value. Type it will parse into depends on whether + * it is a floating point number, as well as its magnitude: smallest + * legal type (of ones available) is used for efficiency. + * + * @param expType Numeric type that we will immediately need, if any; + * mostly necessary to optimize handling of floating point numbers + */ + protected void _parseNumericValue(int expType) + throws IOException, JsonParseException + { + // Int or float? + if (_currToken == JsonToken.VALUE_NUMBER_INT) { + char[] buf = _textBuffer.getTextBuffer(); + int offset = _textBuffer.getTextOffset(); + int len = _intLength; + if (_numberNegative) { + ++offset; + } + if (len <= 9) { // definitely fits in int + int i = NumberInput.parseInt(buf, offset, len); + _numberInt = _numberNegative ? -i : i; + _numTypesValid = NR_INT; + return; + } + if (len <= 18) { // definitely fits AND is easy to parse using 2 int parse calls + long l = NumberInput.parseLong(buf, offset, len); + if (_numberNegative) { + l = -l; + } + // [JACKSON-230] Could still fit in int, need to check + if (len == 10) { + if (_numberNegative) { + if (l >= MIN_INT_L) { + _numberInt = (int) l; + _numTypesValid = NR_INT; + return; + } + } else { + if (l <= MAX_INT_L) { + _numberInt = (int) l; + _numTypesValid = NR_INT; + return; + } + } + } + _numberLong = l; + _numTypesValid = NR_LONG; + return; + } + _parseSlowIntValue(expType, buf, offset, len); + return; + } + if (_currToken == JsonToken.VALUE_NUMBER_FLOAT) { + _parseSlowFloatValue(expType); + return; + } + _reportError("Current token ("+_currToken+") not numeric, can not use numeric value accessors"); + } + + private final void _parseSlowFloatValue(int expType) + throws IOException, JsonParseException + { + /* Nope: floating point. Here we need to be careful to get + * optimal parsing strategy: choice is between accurate but + * slow (BigDecimal) and lossy but fast (Double). For now + * let's only use BD when explicitly requested -- it can + * still be constructed correctly at any point since we do + * retain textual representation + */ + try { + if (expType == NR_BIGDECIMAL) { + _numberBigDecimal = _textBuffer.contentsAsDecimal(); + _numTypesValid = NR_BIGDECIMAL; + } else { + // Otherwise double has to do + _numberDouble = _textBuffer.contentsAsDouble(); + _numTypesValid = NR_DOUBLE; + } + } catch (NumberFormatException nex) { + // Can this ever occur? Due to overflow, maybe? + _wrapError("Malformed numeric value '"+_textBuffer.contentsAsString()+"'", nex); + } + } + + private final void _parseSlowIntValue(int expType, char[] buf, int offset, int len) + throws IOException, JsonParseException + { + String numStr = _textBuffer.contentsAsString(); + try { + // [JACKSON-230] Some long cases still... + if (NumberInput.inLongRange(buf, offset, len, _numberNegative)) { + // Probably faster to construct a String, call parse, than to use BigInteger + _numberLong = Long.parseLong(numStr); + _numTypesValid = NR_LONG; + } else { + // nope, need the heavy guns... (rare case) + _numberBigInt = new BigInteger(numStr); + _numTypesValid = NR_BIGINT; + } + } catch (NumberFormatException nex) { + // Can this ever occur? Due to overflow, maybe? + _wrapError("Malformed numeric value '"+numStr+"'", nex); + } + } + + /* + /********************************************************** + /* Numeric conversions + /********************************************************** + */ + + protected void convertNumberToInt() + throws IOException, JsonParseException + { + // First, converting from long ought to be easy + if ((_numTypesValid & NR_LONG) != 0) { + // Let's verify it's lossless conversion by simple roundtrip + int result = (int) _numberLong; + if (((long) result) != _numberLong) { + _reportError("Numeric value ("+getText()+") out of range of int"); + } + _numberInt = result; + } else if ((_numTypesValid & NR_BIGINT) != 0) { + if (BI_MIN_INT.compareTo(_numberBigInt) > 0 + || BI_MAX_INT.compareTo(_numberBigInt) < 0) { + reportOverflowInt(); + } + _numberInt = _numberBigInt.intValue(); + } else if ((_numTypesValid & NR_DOUBLE) != 0) { + // Need to check boundaries + if (_numberDouble < MIN_INT_D || _numberDouble > MAX_INT_D) { + reportOverflowInt(); + } + _numberInt = (int) _numberDouble; + } else if ((_numTypesValid & NR_BIGDECIMAL) != 0) { + if (BD_MIN_INT.compareTo(_numberBigDecimal) > 0 + || BD_MAX_INT.compareTo(_numberBigDecimal) < 0) { + reportOverflowInt(); + } + _numberInt = _numberBigDecimal.intValue(); + } else { + _throwInternal(); // should never get here + } + + _numTypesValid |= NR_INT; + } + + protected void convertNumberToLong() + throws IOException, JsonParseException + { + if ((_numTypesValid & NR_INT) != 0) { + _numberLong = (long) _numberInt; + } else if ((_numTypesValid & NR_BIGINT) != 0) { + if (BI_MIN_LONG.compareTo(_numberBigInt) > 0 + || BI_MAX_LONG.compareTo(_numberBigInt) < 0) { + reportOverflowLong(); + } + _numberLong = _numberBigInt.longValue(); + } else if ((_numTypesValid & NR_DOUBLE) != 0) { + // Need to check boundaries + if (_numberDouble < MIN_LONG_D || _numberDouble > MAX_LONG_D) { + reportOverflowLong(); + } + _numberLong = (long) _numberDouble; + } else if ((_numTypesValid & NR_BIGDECIMAL) != 0) { + if (BD_MIN_LONG.compareTo(_numberBigDecimal) > 0 + || BD_MAX_LONG.compareTo(_numberBigDecimal) < 0) { + reportOverflowLong(); + } + _numberLong = _numberBigDecimal.longValue(); + } else { + _throwInternal(); // should never get here + } + + _numTypesValid |= NR_LONG; + } + + protected void convertNumberToBigInteger() + throws IOException, JsonParseException + { + if ((_numTypesValid & NR_BIGDECIMAL) != 0) { + // here it'll just get truncated, no exceptions thrown + _numberBigInt = _numberBigDecimal.toBigInteger(); + } else if ((_numTypesValid & NR_LONG) != 0) { + _numberBigInt = BigInteger.valueOf(_numberLong); + } else if ((_numTypesValid & NR_INT) != 0) { + _numberBigInt = BigInteger.valueOf(_numberInt); + } else if ((_numTypesValid & NR_DOUBLE) != 0) { + _numberBigInt = BigDecimal.valueOf(_numberDouble).toBigInteger(); + } else { + _throwInternal(); // should never get here + } + _numTypesValid |= NR_BIGINT; + } + + protected void convertNumberToDouble() + throws IOException, JsonParseException + { + /* 05-Aug-2008, tatus: Important note: this MUST start with + * more accurate representations, since we don't know which + * value is the original one (others get generated when + * requested) + */ + + if ((_numTypesValid & NR_BIGDECIMAL) != 0) { + _numberDouble = _numberBigDecimal.doubleValue(); + } else if ((_numTypesValid & NR_BIGINT) != 0) { + _numberDouble = _numberBigInt.doubleValue(); + } else if ((_numTypesValid & NR_LONG) != 0) { + _numberDouble = (double) _numberLong; + } else if ((_numTypesValid & NR_INT) != 0) { + _numberDouble = (double) _numberInt; + } else { + _throwInternal(); // should never get here + } + + _numTypesValid |= NR_DOUBLE; + } + + protected void convertNumberToBigDecimal() + throws IOException, JsonParseException + { + /* 05-Aug-2008, tatus: Important note: this MUST start with + * more accurate representations, since we don't know which + * value is the original one (others get generated when + * requested) + */ + + if ((_numTypesValid & NR_DOUBLE) != 0) { + /* Let's actually parse from String representation, + * to avoid rounding errors that non-decimal floating operations + * would incur + */ + _numberBigDecimal = new BigDecimal(getText()); + } else if ((_numTypesValid & NR_BIGINT) != 0) { + _numberBigDecimal = new BigDecimal(_numberBigInt); + } else if ((_numTypesValid & NR_LONG) != 0) { + _numberBigDecimal = BigDecimal.valueOf(_numberLong); + } else if ((_numTypesValid & NR_INT) != 0) { + _numberBigDecimal = BigDecimal.valueOf((long) _numberInt); + } else { + _throwInternal(); // should never get here + } + _numTypesValid |= NR_BIGDECIMAL; + } + + /* + /********************************************************** + /* Number handling exceptions + /********************************************************** + */ + + protected void reportUnexpectedNumberChar(int ch, String comment) + throws JsonParseException + { + String msg = "Unexpected character ("+_getCharDesc(ch)+") in numeric value"; + if (comment != null) { + msg += ": "+comment; + } + _reportError(msg); + } + + protected void reportInvalidNumber(String msg) + throws JsonParseException + { + _reportError("Invalid numeric value: "+msg); + } + + protected void reportOverflowInt() + throws IOException, JsonParseException + { + _reportError("Numeric value ("+getText()+") out of range of int ("+Integer.MIN_VALUE+" - "+Integer.MAX_VALUE+")"); + } + + protected void reportOverflowLong() + throws IOException, JsonParseException + { + _reportError("Numeric value ("+getText()+") out of range of long ("+Long.MIN_VALUE+" - "+Long.MAX_VALUE+")"); + } + + /* + /********************************************************** + /* Base64 handling support + /********************************************************** + */ + + /** + * Method that sub-classes must implement to support escaped sequences + * in base64-encoded sections. + * Sub-classes that do not need base64 support can leave this as is + */ + protected char _decodeEscaped() + throws IOException, JsonParseException { + throw new UnsupportedOperationException(); + } + + protected final int _decodeBase64Escape(Base64Variant b64variant, int ch, int index) + throws IOException, JsonParseException + { + // 17-May-2011, tatu: As per [JACKSON-xxx], need to handle escaped chars + if (ch != '\\') { + throw reportInvalidBase64Char(b64variant, ch, index); + } + int unescaped = _decodeEscaped(); + // if white space, skip if first triplet; otherwise errors + if (unescaped <= INT_SPACE) { + if (index == 0) { // whitespace only allowed to be skipped between triplets + return -1; + } + } + // otherwise try to find actual triplet value + int bits = b64variant.decodeBase64Char(unescaped); + if (bits < 0) { + throw reportInvalidBase64Char(b64variant, unescaped, index); + } + return bits; + } + + protected final int _decodeBase64Escape(Base64Variant b64variant, char ch, int index) + throws IOException, JsonParseException + { + // 17-May-2011, tatu: As per [JACKSON-xxx], need to handle escaped chars + if (ch != '\\') { + throw reportInvalidBase64Char(b64variant, ch, index); + } + char unescaped = _decodeEscaped(); + // if white space, skip if first triplet; otherwise errors + if (unescaped <= INT_SPACE) { + if (index == 0) { // whitespace only allowed to be skipped between triplets + return -1; + } + } + // otherwise try to find actual triplet value + int bits = b64variant.decodeBase64Char(unescaped); + if (bits < 0) { + throw reportInvalidBase64Char(b64variant, unescaped, index); + } + return bits; + } + + protected IllegalArgumentException reportInvalidBase64Char(Base64Variant b64variant, int ch, int bindex) + throws IllegalArgumentException + { + return reportInvalidBase64Char(b64variant, ch, bindex, null); + } + + /** + * @param bindex Relative index within base64 character unit; between 0 + * and 3 (as unit has exactly 4 characters) + */ + protected IllegalArgumentException reportInvalidBase64Char(Base64Variant b64variant, int ch, int bindex, String msg) + throws IllegalArgumentException + { + String base; + if (ch <= INT_SPACE) { + base = "Illegal white space character (code 0x"+Integer.toHexString(ch)+") as character #"+(bindex+1)+" of 4-char base64 unit: can only used between units"; + } else if (b64variant.usesPaddingChar(ch)) { + base = "Unexpected padding character ('"+b64variant.getPaddingChar()+"') as character #"+(bindex+1)+" of 4-char base64 unit: padding only legal as 3rd or 4th character"; + } else if (!Character.isDefined(ch) || Character.isISOControl(ch)) { + // Not sure if we can really get here... ? (most illegal xml chars are caught at lower level) + base = "Illegal character (code 0x"+Integer.toHexString(ch)+") in base64 content"; + } else { + base = "Illegal character '"+((char)ch)+"' (code 0x"+Integer.toHexString(ch)+") in base64 content"; + } + if (msg != null) { + base = base + ": " + msg; + } + return new IllegalArgumentException(base); + } +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/impl/JsonParserMinimalBase.java b/1.9.10/src/java/org/codehaus/jackson/impl/JsonParserMinimalBase.java new file mode 100644 index 0000000..1e5f6d0 --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/impl/JsonParserMinimalBase.java
@@ -0,0 +1,539 @@ +package org.codehaus.jackson.impl; + +import java.io.IOException; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.JsonParser.Feature; +import org.codehaus.jackson.io.NumberInput; +import org.codehaus.jackson.util.ByteArrayBuilder; + +/** + * Intermediate base class used by all Jackson {@link JsonParser} + * implementations, but does not add any additional fields that depend + * on particular method of obtaining input. + *<p> + * Note that 'minimal' here mostly refers to minimal number of fields + * (size) and functionality that is specific to certain types + * of parser implementations; but not necessarily to number of methods. + * + * @since 1.6 + * + * @author Tatu Saloranta + */ +public abstract class JsonParserMinimalBase + extends JsonParser +{ + // Control chars: + protected final static int INT_TAB = '\t'; + protected final static int INT_LF = '\n'; + protected final static int INT_CR = '\r'; + protected final static int INT_SPACE = 0x0020; + + // Markup + protected final static int INT_LBRACKET = '['; + protected final static int INT_RBRACKET = ']'; + protected final static int INT_LCURLY = '{'; + protected final static int INT_RCURLY = '}'; + protected final static int INT_QUOTE = '"'; + protected final static int INT_BACKSLASH = '\\'; + protected final static int INT_SLASH = '/'; + protected final static int INT_COLON = ':'; + protected final static int INT_COMMA = ','; + protected final static int INT_ASTERISK = '*'; + protected final static int INT_APOSTROPHE = '\''; + + // Letters we need + protected final static int INT_b = 'b'; + protected final static int INT_f = 'f'; + protected final static int INT_n = 'n'; + protected final static int INT_r = 'r'; + protected final static int INT_t = 't'; + protected final static int INT_u = 'u'; + + /* + /********************************************************** + /* Life-cycle + /********************************************************** + */ + + protected JsonParserMinimalBase() { } + protected JsonParserMinimalBase(int features) { + super(features); + } + + /* + /********************************************************** + /* Configuration overrides if any + /********************************************************** + */ + + // from base class: + + //public void enableFeature(Feature f) + //public void disableFeature(Feature f) + //public void setFeature(Feature f, boolean state) + //public boolean isFeatureEnabled(Feature f) + + /* + /********************************************************** + /* JsonParser impl + /********************************************************** + */ + + @Override + public abstract JsonToken nextToken() throws IOException, JsonParseException; + + //public final JsonToken nextValue() + + @Override + public JsonParser skipChildren() throws IOException, JsonParseException + { + if (_currToken != JsonToken.START_OBJECT + && _currToken != JsonToken.START_ARRAY) { + return this; + } + int open = 1; + + /* Since proper matching of start/end markers is handled + * by nextToken(), we'll just count nesting levels here + */ + while (true) { + JsonToken t = nextToken(); + if (t == null) { + _handleEOF(); + /* given constraints, above should never return; + * however, FindBugs doesn't know about it and + * complains... so let's add dummy break here + */ + return this; + } + switch (t) { + case START_OBJECT: + case START_ARRAY: + ++open; + break; + case END_OBJECT: + case END_ARRAY: + if (--open == 0) { + return this; + } + break; + } + } + } + + /** + * Method sub-classes need to implement + */ + protected abstract void _handleEOF() throws JsonParseException; + + //public JsonToken getCurrentToken() + + //public boolean hasCurrentToken() + + @Override + public abstract String getCurrentName() throws IOException, JsonParseException; + + @Override + public abstract void close() throws IOException; + + @Override + public abstract boolean isClosed(); + + @Override + public abstract JsonStreamContext getParsingContext(); + +// public abstract JsonLocation getTokenLocation(); + +// public abstract JsonLocation getCurrentLocation(); + + /* + /********************************************************** + /* Public API, access to token information, text + /********************************************************** + */ + + @Override + public abstract String getText() throws IOException, JsonParseException; + + @Override + public abstract char[] getTextCharacters() throws IOException, JsonParseException; + + @Override + public abstract boolean hasTextCharacters(); + + @Override + public abstract int getTextLength() throws IOException, JsonParseException; + + @Override + public abstract int getTextOffset() throws IOException, JsonParseException; + + /* + /********************************************************** + /* Public API, access to token information, binary + /********************************************************** + */ + + @Override + public abstract byte[] getBinaryValue(Base64Variant b64variant) + throws IOException, JsonParseException; + + /* + /********************************************************** + /* Public API, access with conversion/coercion + /********************************************************** + */ + + @Override + public boolean getValueAsBoolean(boolean defaultValue) throws IOException, JsonParseException + { + if (_currToken != null) { + switch (_currToken) { + case VALUE_NUMBER_INT: + return getIntValue() != 0; + case VALUE_TRUE: + return true; + case VALUE_FALSE: + case VALUE_NULL: + return false; + case VALUE_EMBEDDED_OBJECT: + { + Object value = this.getEmbeddedObject(); + if (value instanceof Boolean) { + return ((Boolean) value).booleanValue(); + } + } + case VALUE_STRING: + String str = getText().trim(); + if ("true".equals(str)) { + return true; + } + break; + } + } + return defaultValue; + } + + @Override + public int getValueAsInt(int defaultValue) throws IOException, JsonParseException + { + if (_currToken != null) { + switch (_currToken) { + case VALUE_NUMBER_INT: + case VALUE_NUMBER_FLOAT: + return getIntValue(); + case VALUE_TRUE: + return 1; + case VALUE_FALSE: + case VALUE_NULL: + return 0; + case VALUE_STRING: + return NumberInput.parseAsInt(getText(), defaultValue); + case VALUE_EMBEDDED_OBJECT: + { + Object value = this.getEmbeddedObject(); + if (value instanceof Number) { + return ((Number) value).intValue(); + } + } + } + } + return defaultValue; + } + + @Override + public long getValueAsLong(long defaultValue) throws IOException, JsonParseException + { + if (_currToken != null) { + switch (_currToken) { + case VALUE_NUMBER_INT: + case VALUE_NUMBER_FLOAT: + return getLongValue(); + case VALUE_TRUE: + return 1; + case VALUE_FALSE: + case VALUE_NULL: + return 0; + case VALUE_STRING: + return NumberInput.parseAsLong(getText(), defaultValue); + case VALUE_EMBEDDED_OBJECT: + { + Object value = this.getEmbeddedObject(); + if (value instanceof Number) { + return ((Number) value).longValue(); + } + } + } + } + return defaultValue; + } + + @Override + public double getValueAsDouble(double defaultValue) throws IOException, JsonParseException + { + if (_currToken != null) { + switch (_currToken) { + case VALUE_NUMBER_INT: + case VALUE_NUMBER_FLOAT: + return getDoubleValue(); + case VALUE_TRUE: + return 1; + case VALUE_FALSE: + case VALUE_NULL: + return 0; + case VALUE_STRING: + return NumberInput.parseAsDouble(getText(), defaultValue); + case VALUE_EMBEDDED_OBJECT: + { + Object value = this.getEmbeddedObject(); + if (value instanceof Number) { + return ((Number) value).doubleValue(); + } + } + } + } + return defaultValue; + } + + /* + /********************************************************** + /* Base64 decoding + /********************************************************** + */ + + /** + * Helper method that can be used for base64 decoding in cases where + * encoded content has already been read as a String. + * + * @since 1.9.3 + */ + protected void _decodeBase64(String str, ByteArrayBuilder builder, Base64Variant b64variant) + throws IOException, JsonParseException + { + int ptr = 0; + int len = str.length(); + + main_loop: + while (ptr < len) { + // first, we'll skip preceding white space, if any + char ch; + do { + ch = str.charAt(ptr++); + if (ptr >= len) { + break main_loop; + } + } while (ch <= INT_SPACE); + int bits = b64variant.decodeBase64Char(ch); + if (bits < 0) { + _reportInvalidBase64(b64variant, ch, 0, null); + } + int decodedData = bits; + // then second base64 char; can't get padding yet, nor ws + if (ptr >= len) { + _reportBase64EOF(); + } + ch = str.charAt(ptr++); + bits = b64variant.decodeBase64Char(ch); + if (bits < 0) { + _reportInvalidBase64(b64variant, ch, 1, null); + } + decodedData = (decodedData << 6) | bits; + // third base64 char; can be padding, but not ws + if (ptr >= len) { + // but as per [JACKSON-631] can be end-of-input, iff not using padding + if (!b64variant.usesPadding()) { + decodedData >>= 4; + builder.append(decodedData); + break; + } + _reportBase64EOF(); + } + ch = str.charAt(ptr++); + bits = b64variant.decodeBase64Char(ch); + + // First branch: can get padding (-> 1 byte) + if (bits < 0) { + if (bits != Base64Variant.BASE64_VALUE_PADDING) { + _reportInvalidBase64(b64variant, ch, 2, null); + } + // Ok, must get padding + if (ptr >= len) { + _reportBase64EOF(); + } + ch = str.charAt(ptr++); + if (!b64variant.usesPaddingChar(ch)) { + _reportInvalidBase64(b64variant, ch, 3, "expected padding character '"+b64variant.getPaddingChar()+"'"); + } + // Got 12 bits, only need 8, need to shift + decodedData >>= 4; + builder.append(decodedData); + continue; + } + // Nope, 2 or 3 bytes + decodedData = (decodedData << 6) | bits; + // fourth and last base64 char; can be padding, but not ws + if (ptr >= len) { + // but as per [JACKSON-631] can be end-of-input, iff not using padding + if (!b64variant.usesPadding()) { + decodedData >>= 2; + builder.appendTwoBytes(decodedData); + break; + } + _reportBase64EOF(); + } + ch = str.charAt(ptr++); + bits = b64variant.decodeBase64Char(ch); + if (bits < 0) { + if (bits != Base64Variant.BASE64_VALUE_PADDING) { + _reportInvalidBase64(b64variant, ch, 3, null); + } + decodedData >>= 2; + builder.appendTwoBytes(decodedData); + } else { + // otherwise, our triple is now complete + decodedData = (decodedData << 6) | bits; + builder.appendThreeBytes(decodedData); + } + } + } + + /** + * @param bindex Relative index within base64 character unit; between 0 + * and 3 (as unit has exactly 4 characters) + */ + protected void _reportInvalidBase64(Base64Variant b64variant, char ch, int bindex, String msg) + throws JsonParseException + { + String base; + if (ch <= INT_SPACE) { + base = "Illegal white space character (code 0x"+Integer.toHexString(ch)+") as character #"+(bindex+1)+" of 4-char base64 unit: can only used between units"; + } else if (b64variant.usesPaddingChar(ch)) { + base = "Unexpected padding character ('"+b64variant.getPaddingChar()+"') as character #"+(bindex+1)+" of 4-char base64 unit: padding only legal as 3rd or 4th character"; + } else if (!Character.isDefined(ch) || Character.isISOControl(ch)) { + // Not sure if we can really get here... ? (most illegal xml chars are caught at lower level) + base = "Illegal character (code 0x"+Integer.toHexString(ch)+") in base64 content"; + } else { + base = "Illegal character '"+ch+"' (code 0x"+Integer.toHexString(ch)+") in base64 content"; + } + if (msg != null) { + base = base + ": " + msg; + } + throw _constructError(base); + } + + protected void _reportBase64EOF() throws JsonParseException { + throw _constructError("Unexpected end-of-String in base64 content"); + } + + + /* + /********************************************************** + /* Error reporting + /********************************************************** + */ + + protected void _reportUnexpectedChar(int ch, String comment) + throws JsonParseException + { + String msg = "Unexpected character ("+_getCharDesc(ch)+")"; + if (comment != null) { + msg += ": "+comment; + } + _reportError(msg); + } + + protected void _reportInvalidEOF() + throws JsonParseException + { + _reportInvalidEOF(" in "+_currToken); + } + + protected void _reportInvalidEOF(String msg) + throws JsonParseException + { + _reportError("Unexpected end-of-input"+msg); + } + + protected void _reportInvalidEOFInValue() throws JsonParseException + { + _reportInvalidEOF(" in a value"); + } + + protected void _throwInvalidSpace(int i) + throws JsonParseException + { + char c = (char) i; + String msg = "Illegal character ("+_getCharDesc(c)+"): only regular white space (\\r, \\n, \\t) is allowed between tokens"; + _reportError(msg); + } + + /** + * Method called to report a problem with unquoted control character. + * Note: starting with version 1.4, it is possible to suppress + * exception by enabling {@link Feature#ALLOW_UNQUOTED_CONTROL_CHARS}. + */ + protected void _throwUnquotedSpace(int i, String ctxtDesc) + throws JsonParseException + { + // JACKSON-208; possible to allow unquoted control chars: + if (!isEnabled(Feature.ALLOW_UNQUOTED_CONTROL_CHARS) || i >= INT_SPACE) { + char c = (char) i; + String msg = "Illegal unquoted character ("+_getCharDesc(c)+"): has to be escaped using backslash to be included in "+ctxtDesc; + _reportError(msg); + } + } + + protected char _handleUnrecognizedCharacterEscape(char ch) throws JsonProcessingException + { + // as per [JACKSON-300] + if (isEnabled(Feature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER)) { + return ch; + } + // and [JACKSON-548] + if (ch == '\'' && isEnabled(Feature.ALLOW_SINGLE_QUOTES)) { + return ch; + } + _reportError("Unrecognized character escape "+_getCharDesc(ch)); + return ch; + } + + /* + /********************************************************** + /* Error reporting, generic + /********************************************************** + */ + + protected final static String _getCharDesc(int ch) + { + char c = (char) ch; + if (Character.isISOControl(c)) { + return "(CTRL-CHAR, code "+ch+")"; + } + if (ch > 255) { + return "'"+c+"' (code "+ch+" / 0x"+Integer.toHexString(ch)+")"; + } + return "'"+c+"' (code "+ch+")"; + } + + protected final void _reportError(String msg) + throws JsonParseException + { + throw _constructError(msg); + } + + protected final void _wrapError(String msg, Throwable t) + throws JsonParseException + { + throw _constructError(msg, t); + } + + protected final void _throwInternal() + { + throw new RuntimeException("Internal error: this code path should never get executed"); + } + + protected final JsonParseException _constructError(String msg, Throwable t) + { + return new JsonParseException(msg, getCurrentLocation(), t); + } +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/impl/JsonReadContext.java b/1.9.10/src/java/org/codehaus/jackson/impl/JsonReadContext.java new file mode 100644 index 0000000..7904cc3 --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/impl/JsonReadContext.java
@@ -0,0 +1,188 @@ +package org.codehaus.jackson.impl; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.util.CharTypes; + +/** + * Extension of {@link JsonStreamContext}, which implements + * core methods needed, and also exposes + * more complete API to parser implementation classes. + */ +public final class JsonReadContext + extends JsonStreamContext +{ + // // // Configuration + + protected final JsonReadContext _parent; + + // // // Location information (minus source reference) + + protected int _lineNr; + protected int _columnNr; + + protected String _currentName; + + /* + /********************************************************** + /* Simple instance reuse slots; speeds up things + /* a bit (10-15%) for docs with lots of small + /* arrays/objects (for which allocation was + /* visible in profile stack frames) + /********************************************************** + */ + + protected JsonReadContext _child = null; + + /* + /********************************************************** + /* Instance construction, reuse + /********************************************************** + */ + + public JsonReadContext(JsonReadContext parent, int type, int lineNr, int colNr) + { + super(); + _type = type; + _parent = parent; + _lineNr = lineNr; + _columnNr = colNr; + _index = -1; + } + + protected final void reset(int type, int lineNr, int colNr) + { + _type = type; + _index = -1; + _lineNr = lineNr; + _columnNr = colNr; + _currentName = null; + } + + // // // Factory methods + + public static JsonReadContext createRootContext(int lineNr, int colNr) + { + return new JsonReadContext(null, TYPE_ROOT, lineNr, colNr); + } + + /** + * @since 1.9 + */ + public static JsonReadContext createRootContext() + { + return new JsonReadContext(null, TYPE_ROOT, 1, 0); + } + + public final JsonReadContext createChildArrayContext(int lineNr, int colNr) + { + JsonReadContext ctxt = _child; + if (ctxt == null) { + _child = ctxt = new JsonReadContext(this, TYPE_ARRAY, lineNr, colNr); + return ctxt; + } + ctxt.reset(TYPE_ARRAY, lineNr, colNr); + return ctxt; + } + + public final JsonReadContext createChildObjectContext(int lineNr, int colNr) + { + JsonReadContext ctxt = _child; + if (ctxt == null) { + _child = ctxt = new JsonReadContext(this, TYPE_OBJECT, lineNr, colNr); + return ctxt; + } + ctxt.reset(TYPE_OBJECT, lineNr, colNr); + return ctxt; + } + + /* + /********************************************************** + /* Abstract method implementation + /********************************************************** + */ + + @Override + public final String getCurrentName() { return _currentName; } + + @Override + public final JsonReadContext getParent() { return _parent; } + + /* + /********************************************************** + /* Extended API + /********************************************************** + */ + + /** + * @return Location pointing to the point where the context + * start marker was found + */ + public final JsonLocation getStartLocation(Object srcRef) + { + /* We don't keep track of offsets at this level (only + * reader does) + */ + long totalChars = -1L; + + return new JsonLocation(srcRef, totalChars, _lineNr, _columnNr); + } + + /* + /********************************************************** + /* State changes + /********************************************************** + */ + + public final boolean expectComma() + { + /* Assumption here is that we will be getting a value (at least + * before calling this method again), and + * so will auto-increment index to avoid having to do another call + */ + int ix = ++_index; // starts from -1 + return (_type != TYPE_ROOT && ix > 0); + } + + public void setCurrentName(String name) + { + _currentName = name; + } + + /* + /********************************************************** + /* Overridden standard methods + /********************************************************** + */ + + /** + * Overridden to provide developer readable "JsonPath" representation + * of the context. + */ + @Override + public final String toString() + { + StringBuilder sb = new StringBuilder(64); + switch (_type) { + case TYPE_ROOT: + sb.append("/"); + break; + case TYPE_ARRAY: + sb.append('['); + sb.append(getCurrentIndex()); + sb.append(']'); + break; + case TYPE_OBJECT: + sb.append('{'); + if (_currentName != null) { + sb.append('"'); + CharTypes.appendQuoted(sb, _currentName); + sb.append('"'); + } else { + sb.append('?'); + } + sb.append('}'); + break; + } + return sb.toString(); + } +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/impl/JsonWriteContext.java b/1.9.10/src/java/org/codehaus/jackson/impl/JsonWriteContext.java new file mode 100644 index 0000000..ef73916 --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/impl/JsonWriteContext.java
@@ -0,0 +1,178 @@ +package org.codehaus.jackson.impl; + +import org.codehaus.jackson.*; + +/** + * Extension of {@link JsonStreamContext}, which implements + * core methods needed, and also exposes + * more complete API to generator implementation classes. + */ +public class JsonWriteContext + extends JsonStreamContext +{ + // // // Return values for writeValue() + + public final static int STATUS_OK_AS_IS = 0; + public final static int STATUS_OK_AFTER_COMMA = 1; + public final static int STATUS_OK_AFTER_COLON = 2; + public final static int STATUS_OK_AFTER_SPACE = 3; // in root context + public final static int STATUS_EXPECT_VALUE = 4; + public final static int STATUS_EXPECT_NAME = 5; + + protected final JsonWriteContext _parent; + + /** + * Name of the field of which value is to be parsed; only + * used for OBJECT contexts + */ + protected String _currentName; + + /* + /********************************************************** + /* Simple instance reuse slots; speed up things + /* a bit (10-15%) for docs with lots of small + /* arrays/objects + /********************************************************** + */ + + protected JsonWriteContext _child = null; + + /* + /********************************************************** + /* Life-cycle + /********************************************************** + */ + + protected JsonWriteContext(int type, JsonWriteContext parent) + { + super(); + _type = type; + _parent = parent; + _index = -1; + } + + // // // Factory methods + + public static JsonWriteContext createRootContext() + { + return new JsonWriteContext(TYPE_ROOT, null); + } + + private final JsonWriteContext reset(int type) { + _type = type; + _index = -1; + _currentName = null; + return this; + } + + public final JsonWriteContext createChildArrayContext() + { + JsonWriteContext ctxt = _child; + if (ctxt == null) { + _child = ctxt = new JsonWriteContext(TYPE_ARRAY, this); + return ctxt; + } + return ctxt.reset(TYPE_ARRAY); + } + + public final JsonWriteContext createChildObjectContext() + { + JsonWriteContext ctxt = _child; + if (ctxt == null) { + _child = ctxt = new JsonWriteContext(TYPE_OBJECT, this); + return ctxt; + } + return ctxt.reset(TYPE_OBJECT); + } + + // // // Shared API + + @Override + public final JsonWriteContext getParent() { return _parent; } + + @Override + public final String getCurrentName() { return _currentName; } + + // // // API sub-classes are to implement + + /** + * Method that writer is to call before it writes a field name. + * + * @return Index of the field entry (0-based) + */ + public final int writeFieldName(String name) + { + if (_type == TYPE_OBJECT) { + if (_currentName != null) { // just wrote a name... + return STATUS_EXPECT_VALUE; + } + _currentName = name; + return (_index < 0) ? STATUS_OK_AS_IS : STATUS_OK_AFTER_COMMA; + } + return STATUS_EXPECT_VALUE; + } + + public final int writeValue() + { + // Most likely, object: + if (_type == TYPE_OBJECT) { + if (_currentName == null) { + return STATUS_EXPECT_NAME; + } + _currentName = null; + ++_index; + return STATUS_OK_AFTER_COLON; + } + + // Ok, array? + if (_type == TYPE_ARRAY) { + int ix = _index; + ++_index; + return (ix < 0) ? STATUS_OK_AS_IS : STATUS_OK_AFTER_COMMA; + } + + // Nope, root context + // No commas within root context, but need space + ++_index; + return (_index == 0) ? STATUS_OK_AS_IS : STATUS_OK_AFTER_SPACE; + } + + // // // Internally used abstract methods + + protected final void appendDesc(StringBuilder sb) + { + if (_type == TYPE_OBJECT) { + sb.append('{'); + if (_currentName != null) { + sb.append('"'); + // !!! TODO: Name chars should be escaped? + sb.append(_currentName); + sb.append('"'); + } else { + sb.append('?'); + } + sb.append('}'); + } else if (_type == TYPE_ARRAY) { + sb.append('['); + sb.append(getCurrentIndex()); + sb.append(']'); + } else { + // nah, ROOT: + sb.append("/"); + } + } + + // // // Overridden standard methods + + /** + * Overridden to provide developer writeable "JsonPath" representation + * of the context. + */ + @Override + public final String toString() + { + StringBuilder sb = new StringBuilder(64); + appendDesc(sb); + return sb.toString(); + } +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/impl/ReaderBasedParser.java b/1.9.10/src/java/org/codehaus/jackson/impl/ReaderBasedParser.java new file mode 100644 index 0000000..091f4fb --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/impl/ReaderBasedParser.java
@@ -0,0 +1,1814 @@ +package org.codehaus.jackson.impl; + +import java.io.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.io.IOContext; +import org.codehaus.jackson.sym.CharsToNameCanonicalizer; +import org.codehaus.jackson.util.*; + +/** + * This is a concrete implementation of {@link JsonParser}, which is + * based on a {@link java.io.Reader} to handle low-level character + * conversion tasks. + */ +public final class ReaderBasedParser + extends JsonParserBase +{ + /* + /********************************************************** + /* Input configuration + /********************************************************** + */ + + /** + * Reader that can be used for reading more content, if one + * buffer from input source, but in some cases pre-loaded buffer + * is handed to the parser. + */ + protected Reader _reader; + + /** + * Current buffer from which data is read; generally data is read into + * buffer from input source. + */ + protected char[] _inputBuffer; + + /* + /********************************************************** + /* Configuration + /********************************************************** + */ + + protected ObjectCodec _objectCodec; + + final protected CharsToNameCanonicalizer _symbols; + + /* + /********************************************************** + /* Parsing state + /********************************************************** + */ + + /** + * Flag that indicates that the current token has not yet + * been fully processed, and needs to be finished for + * some access (or skipped to obtain the next token) + */ + protected boolean _tokenIncomplete = false; + + /* + /********************************************************** + /* Life-cycle + /********************************************************** + */ + + public ReaderBasedParser(IOContext ctxt, int features, Reader r, + ObjectCodec codec, CharsToNameCanonicalizer st) + { + super(ctxt, features); + _reader = r; + _inputBuffer = ctxt.allocTokenBuffer(); + _objectCodec = codec; + _symbols = st; + } + + /* + /********************************************************** + /* Base method defs, overrides + /********************************************************** + */ + + @Override + public ObjectCodec getCodec() { + return _objectCodec; + } + + @Override + public void setCodec(ObjectCodec c) { + _objectCodec = c; + } + + @Override + public int releaseBuffered(Writer w) throws IOException + { + int count = _inputEnd - _inputPtr; + if (count < 1) { + return 0; + } + // let's just advance ptr to end + int origPtr = _inputPtr; + w.write(_inputBuffer, origPtr, count); + return count; + } + + @Override + public Object getInputSource() { + return _reader; + } + + @Override + protected final boolean loadMore() throws IOException + { + _currInputProcessed += _inputEnd; + _currInputRowStart -= _inputEnd; + + if (_reader != null) { + int count = _reader.read(_inputBuffer, 0, _inputBuffer.length); + if (count > 0) { + _inputPtr = 0; + _inputEnd = count; + return true; + } + // End of input + _closeInput(); + // Should never return 0, so let's fail + if (count == 0) { + throw new IOException("Reader returned 0 characters when trying to read "+_inputEnd); + } + } + return false; + } + + protected char getNextChar(String eofMsg) + throws IOException, JsonParseException + { + if (_inputPtr >= _inputEnd) { + if (!loadMore()) { + _reportInvalidEOF(eofMsg); + } + } + return _inputBuffer[_inputPtr++]; + } + + @Override + protected void _closeInput() throws IOException + { + /* 25-Nov-2008, tatus: As per [JACKSON-16] we are not to call close() + * on the underlying Reader, unless we "own" it, or auto-closing + * feature is enabled. + * One downside is that when using our optimized + * Reader (granted, we only do that for UTF-32...) this + * means that buffer recycling won't work correctly. + */ + if (_reader != null) { + if (_ioContext.isResourceManaged() || isEnabled(Feature.AUTO_CLOSE_SOURCE)) { + _reader.close(); + } + _reader = null; + } + } + + /** + * Method called to release internal buffers owned by the base + * reader. This may be called along with {@link #_closeInput} (for + * example, when explicitly closing this reader instance), or + * separately (if need be). + */ + @Override + protected void _releaseBuffers() + throws IOException + { + super._releaseBuffers(); + char[] buf = _inputBuffer; + if (buf != null) { + _inputBuffer = null; + _ioContext.releaseTokenBuffer(buf); + } + } + + /* + /********************************************************** + /* Public API, data access + /********************************************************** + */ + + /** + * Method for accessing textual representation of the current event; + * if no current event (before first call to {@link #nextToken}, or + * after encountering end-of-input), returns null. + * Method can be called for any event. + */ + @Override + public final String getText() + throws IOException, JsonParseException + { + JsonToken t = _currToken; + if (t == JsonToken.VALUE_STRING) { + if (_tokenIncomplete) { + _tokenIncomplete = false; + _finishString(); // only strings can be incomplete + } + return _textBuffer.contentsAsString(); + } + return _getText2(t); + } + + protected final String _getText2(JsonToken t) + { + if (t == null) { + return null; + } + switch (t) { + case FIELD_NAME: + return _parsingContext.getCurrentName(); + + case VALUE_STRING: + // fall through + case VALUE_NUMBER_INT: + case VALUE_NUMBER_FLOAT: + return _textBuffer.contentsAsString(); + } + return t.asString(); + } + + @Override + public char[] getTextCharacters() + throws IOException, JsonParseException + { + if (_currToken != null) { // null only before/after document + switch (_currToken) { + + case FIELD_NAME: + if (!_nameCopied) { + String name = _parsingContext.getCurrentName(); + int nameLen = name.length(); + if (_nameCopyBuffer == null) { + _nameCopyBuffer = _ioContext.allocNameCopyBuffer(nameLen); + } else if (_nameCopyBuffer.length < nameLen) { + _nameCopyBuffer = new char[nameLen]; + } + name.getChars(0, nameLen, _nameCopyBuffer, 0); + _nameCopied = true; + } + return _nameCopyBuffer; + + case VALUE_STRING: + if (_tokenIncomplete) { + _tokenIncomplete = false; + _finishString(); // only strings can be incomplete + } + // fall through + case VALUE_NUMBER_INT: + case VALUE_NUMBER_FLOAT: + return _textBuffer.getTextBuffer(); + + default: + return _currToken.asCharArray(); + } + } + return null; + } + + @Override + public int getTextLength() + throws IOException, JsonParseException + { + if (_currToken != null) { // null only before/after document + switch (_currToken) { + + case FIELD_NAME: + return _parsingContext.getCurrentName().length(); + case VALUE_STRING: + if (_tokenIncomplete) { + _tokenIncomplete = false; + _finishString(); // only strings can be incomplete + } + // fall through + case VALUE_NUMBER_INT: + case VALUE_NUMBER_FLOAT: + return _textBuffer.size(); + + default: + return _currToken.asCharArray().length; + } + } + return 0; + } + + @Override + public int getTextOffset() throws IOException, JsonParseException + { + // Most have offset of 0, only some may have other values: + if (_currToken != null) { + switch (_currToken) { + case FIELD_NAME: + return 0; + case VALUE_STRING: + if (_tokenIncomplete) { + _tokenIncomplete = false; + _finishString(); // only strings can be incomplete + } + // fall through + case VALUE_NUMBER_INT: + case VALUE_NUMBER_FLOAT: + return _textBuffer.getTextOffset(); + } + } + return 0; + } + + @Override + public byte[] getBinaryValue(Base64Variant b64variant) + throws IOException, JsonParseException + { + if (_currToken != JsonToken.VALUE_STRING && + (_currToken != JsonToken.VALUE_EMBEDDED_OBJECT || _binaryValue == null)) { + _reportError("Current token ("+_currToken+") not VALUE_STRING or VALUE_EMBEDDED_OBJECT, can not access as binary"); + } + /* To ensure that we won't see inconsistent data, better clear up + * state... + */ + if (_tokenIncomplete) { + try { + _binaryValue = _decodeBase64(b64variant); + } catch (IllegalArgumentException iae) { + throw _constructError("Failed to decode VALUE_STRING as base64 ("+b64variant+"): "+iae.getMessage()); + } + /* let's clear incomplete only now; allows for accessing other + * textual content in error cases + */ + _tokenIncomplete = false; + } else { // may actually require conversion... + if (_binaryValue == null) { + ByteArrayBuilder builder = _getByteArrayBuilder(); + _decodeBase64(getText(), builder, b64variant); + _binaryValue = builder.toByteArray(); + } + } + return _binaryValue; + } + + /* + /********************************************************** + /* Public API, traversal + /********************************************************** + */ + + /** + * @return Next token from the stream, if any found, or null + * to indicate end-of-input + */ + @Override + public JsonToken nextToken() + throws IOException, JsonParseException + { + _numTypesValid = NR_UNKNOWN; + + /* First: field names are special -- we will always tokenize + * (part of) value along with field name to simplify + * state handling. If so, can and need to use secondary token: + */ + if (_currToken == JsonToken.FIELD_NAME) { + return _nextAfterName(); + } + if (_tokenIncomplete) { + _skipString(); // only strings can be partial + } + int i = _skipWSOrEnd(); + if (i < 0) { // end-of-input + /* 19-Feb-2009, tatu: Should actually close/release things + * like input source, symbol table and recyclable buffers now. + */ + close(); + return (_currToken = null); + } + + /* First, need to ensure we know the starting location of token + * after skipping leading white space + */ + _tokenInputTotal = _currInputProcessed + _inputPtr - 1; + _tokenInputRow = _currInputRow; + _tokenInputCol = _inputPtr - _currInputRowStart - 1; + + // finally: clear any data retained so far + _binaryValue = null; + + // Closing scope? + if (i == INT_RBRACKET) { + if (!_parsingContext.inArray()) { + _reportMismatchedEndMarker(i, '}'); + } + _parsingContext = _parsingContext.getParent(); + return (_currToken = JsonToken.END_ARRAY); + } + if (i == INT_RCURLY) { + if (!_parsingContext.inObject()) { + _reportMismatchedEndMarker(i, ']'); + } + _parsingContext = _parsingContext.getParent(); + return (_currToken = JsonToken.END_OBJECT); + } + + // Nope: do we then expect a comma? + if (_parsingContext.expectComma()) { + if (i != INT_COMMA) { + _reportUnexpectedChar(i, "was expecting comma to separate "+_parsingContext.getTypeDesc()+" entries"); + } + i = _skipWS(); + } + + /* And should we now have a name? Always true for + * Object contexts, since the intermediate 'expect-value' + * state is never retained. + */ + boolean inObject = _parsingContext.inObject(); + if (inObject) { + // First, field name itself: + String name = _parseFieldName(i); + _parsingContext.setCurrentName(name); + _currToken = JsonToken.FIELD_NAME; + i = _skipWS(); + if (i != INT_COLON) { + _reportUnexpectedChar(i, "was expecting a colon to separate field name and value"); + } + i = _skipWS(); + } + + // Ok: we must have a value... what is it? + + JsonToken t; + + switch (i) { + case INT_QUOTE: + _tokenIncomplete = true; + t = JsonToken.VALUE_STRING; + break; + case INT_LBRACKET: + if (!inObject) { + _parsingContext = _parsingContext.createChildArrayContext(_tokenInputRow, _tokenInputCol); + } + t = JsonToken.START_ARRAY; + break; + case INT_LCURLY: + if (!inObject) { + _parsingContext = _parsingContext.createChildObjectContext(_tokenInputRow, _tokenInputCol); + } + t = JsonToken.START_OBJECT; + break; + case INT_RBRACKET: + case INT_RCURLY: + // Error: neither is valid at this point; valid closers have + // been handled earlier + _reportUnexpectedChar(i, "expected a value"); + case INT_t: + _matchToken("true", 1); + t = JsonToken.VALUE_TRUE; + break; + case INT_f: + _matchToken("false", 1); + t = JsonToken.VALUE_FALSE; + break; + case INT_n: + _matchToken("null", 1); + t = JsonToken.VALUE_NULL; + break; + + case INT_MINUS: + /* Should we have separate handling for plus? Although + * it is not allowed per se, it may be erroneously used, + * and could be indicate by a more specific error message. + */ + case INT_0: + case INT_1: + case INT_2: + case INT_3: + case INT_4: + case INT_5: + case INT_6: + case INT_7: + case INT_8: + case INT_9: + t = parseNumberText(i); + break; + default: + t = _handleUnexpectedValue(i); + break; + } + + if (inObject) { + _nextToken = t; + return _currToken; + } + _currToken = t; + return t; + } + + private final JsonToken _nextAfterName() + { + _nameCopied = false; // need to invalidate if it was copied + JsonToken t = _nextToken; + _nextToken = null; + // Also: may need to start new context? + if (t == JsonToken.START_ARRAY) { + _parsingContext = _parsingContext.createChildArrayContext(_tokenInputRow, _tokenInputCol); + } else if (t == JsonToken.START_OBJECT) { + _parsingContext = _parsingContext.createChildObjectContext(_tokenInputRow, _tokenInputCol); + } + return (_currToken = t); + } + + /* + @Override + public boolean nextFieldName(SerializableString str) + throws IOException, JsonParseException + */ + + // note: identical to one in Utf8StreamParser + @Override + public String nextTextValue() + throws IOException, JsonParseException + { + if (_currToken == JsonToken.FIELD_NAME) { // mostly copied from '_nextAfterName' + _nameCopied = false; + JsonToken t = _nextToken; + _nextToken = null; + _currToken = t; + if (t == JsonToken.VALUE_STRING) { + if (_tokenIncomplete) { + _tokenIncomplete = false; + _finishString(); + } + return _textBuffer.contentsAsString(); + } + if (t == JsonToken.START_ARRAY) { + _parsingContext = _parsingContext.createChildArrayContext(_tokenInputRow, _tokenInputCol); + } else if (t == JsonToken.START_OBJECT) { + _parsingContext = _parsingContext.createChildObjectContext(_tokenInputRow, _tokenInputCol); + } + return null; + } + // !!! TODO: optimize this case as well + return (nextToken() == JsonToken.VALUE_STRING) ? getText() : null; + } + + // note: identical to one in Utf8StreamParser + @Override + public int nextIntValue(int defaultValue) + throws IOException, JsonParseException + { + if (_currToken == JsonToken.FIELD_NAME) { + _nameCopied = false; + JsonToken t = _nextToken; + _nextToken = null; + _currToken = t; + if (t == JsonToken.VALUE_NUMBER_INT) { + return getIntValue(); + } + if (t == JsonToken.START_ARRAY) { + _parsingContext = _parsingContext.createChildArrayContext(_tokenInputRow, _tokenInputCol); + } else if (t == JsonToken.START_OBJECT) { + _parsingContext = _parsingContext.createChildObjectContext(_tokenInputRow, _tokenInputCol); + } + return defaultValue; + } + // !!! TODO: optimize this case as well + return (nextToken() == JsonToken.VALUE_NUMBER_INT) ? getIntValue() : defaultValue; + } + + // note: identical to one in Utf8StreamParser + @Override + public long nextLongValue(long defaultValue) + throws IOException, JsonParseException + { + if (_currToken == JsonToken.FIELD_NAME) { // mostly copied from '_nextAfterName' + _nameCopied = false; + JsonToken t = _nextToken; + _nextToken = null; + _currToken = t; + if (t == JsonToken.VALUE_NUMBER_INT) { + return getLongValue(); + } + if (t == JsonToken.START_ARRAY) { + _parsingContext = _parsingContext.createChildArrayContext(_tokenInputRow, _tokenInputCol); + } else if (t == JsonToken.START_OBJECT) { + _parsingContext = _parsingContext.createChildObjectContext(_tokenInputRow, _tokenInputCol); + } + return defaultValue; + } + // !!! TODO: optimize this case as well + return (nextToken() == JsonToken.VALUE_NUMBER_INT) ? getLongValue() : defaultValue; + } + + // note: identical to one in Utf8StreamParser + @Override + public Boolean nextBooleanValue() + throws IOException, JsonParseException + { + if (_currToken == JsonToken.FIELD_NAME) { // mostly copied from '_nextAfterName' + _nameCopied = false; + JsonToken t = _nextToken; + _nextToken = null; + _currToken = t; + if (t == JsonToken.VALUE_TRUE) { + return Boolean.TRUE; + } + if (t == JsonToken.VALUE_FALSE) { + return Boolean.FALSE; + } + if (t == JsonToken.START_ARRAY) { + _parsingContext = _parsingContext.createChildArrayContext(_tokenInputRow, _tokenInputCol); + } else if (t == JsonToken.START_OBJECT) { + _parsingContext = _parsingContext.createChildObjectContext(_tokenInputRow, _tokenInputCol); + } + return null; + } + switch (nextToken()) { + case VALUE_TRUE: + return Boolean.TRUE; + case VALUE_FALSE: + return Boolean.FALSE; + } + return null; + } + + @Override + public void close() throws IOException + { + super.close(); + _symbols.release(); + } + + /* + /********************************************************** + /* Internal methods, number parsing + /* (note: in 1.8 and prior, part of "ReaderBasedNumericParser" + /********************************************************** + */ + + /** + * Initial parsing method for number values. It needs to be able + * to parse enough input to be able to determine whether the + * value is to be considered a simple integer value, or a more + * generic decimal value: latter of which needs to be expressed + * as a floating point number. The basic rule is that if the number + * has no fractional or exponential part, it is an integer; otherwise + * a floating point number. + *<p> + * Because much of input has to be processed in any case, no partial + * parsing is done: all input text will be stored for further + * processing. However, actual numeric value conversion will be + * deferred, since it is usually the most complicated and costliest + * part of processing. + */ + protected final JsonToken parseNumberText(int ch) + throws IOException, JsonParseException + { + /* Although we will always be complete with respect to textual + * representation (that is, all characters will be parsed), + * actual conversion to a number is deferred. Thus, need to + * note that no representations are valid yet + */ + boolean negative = (ch == INT_MINUS); + int ptr = _inputPtr; + int startPtr = ptr-1; // to include sign/digit already read + final int inputLen = _inputEnd; + + dummy_loop: + do { // dummy loop, to be able to break out + if (negative) { // need to read the next digit + if (ptr >= _inputEnd) { + break dummy_loop; + } + ch = _inputBuffer[ptr++]; + // First check: must have a digit to follow minus sign + if (ch > INT_9 || ch < INT_0) { + _inputPtr = ptr; + return _handleInvalidNumberStart(ch, true); + } + /* (note: has been checked for non-negative already, in + * the dispatching code that determined it should be + * a numeric value) + */ + } + // One special case, leading zero(es): + if (ch == INT_0) { + break dummy_loop; + } + + /* First, let's see if the whole number is contained within + * the input buffer unsplit. This should be the common case; + * and to simplify processing, we will just reparse contents + * in the alternative case (number split on buffer boundary) + */ + + int intLen = 1; // already got one + + // First let's get the obligatory integer part: + + int_loop: + while (true) { + if (ptr >= _inputEnd) { + break dummy_loop; + } + ch = (int) _inputBuffer[ptr++]; + if (ch < INT_0 || ch > INT_9) { + break int_loop; + } + ++intLen; + } + + int fractLen = 0; + + // And then see if we get other parts + if (ch == INT_DECIMAL_POINT) { // yes, fraction + fract_loop: + while (true) { + if (ptr >= inputLen) { + break dummy_loop; + } + ch = (int) _inputBuffer[ptr++]; + if (ch < INT_0 || ch > INT_9) { + break fract_loop; + } + ++fractLen; + } + // must be followed by sequence of ints, one minimum + if (fractLen == 0) { + reportUnexpectedNumberChar(ch, "Decimal point not followed by a digit"); + } + } + + int expLen = 0; + if (ch == INT_e || ch == INT_E) { // and/or exponent + if (ptr >= inputLen) { + break dummy_loop; + } + // Sign indicator? + ch = (int) _inputBuffer[ptr++]; + if (ch == INT_MINUS || ch == INT_PLUS) { // yup, skip for now + if (ptr >= inputLen) { + break dummy_loop; + } + ch = (int) _inputBuffer[ptr++]; + } + while (ch <= INT_9 && ch >= INT_0) { + ++expLen; + if (ptr >= inputLen) { + break dummy_loop; + } + ch = (int) _inputBuffer[ptr++]; + } + // must be followed by sequence of ints, one minimum + if (expLen == 0) { + reportUnexpectedNumberChar(ch, "Exponent indicator not followed by a digit"); + } + } + + // Got it all: let's add to text buffer for parsing, access + --ptr; // need to push back following separator + _inputPtr = ptr; + int len = ptr-startPtr; + _textBuffer.resetWithShared(_inputBuffer, startPtr, len); + return reset(negative, intLen, fractLen, expLen); + } while (false); + + _inputPtr = negative ? (startPtr+1) : startPtr; + return parseNumberText2(negative); + } + + /** + * Method called to parse a number, when the primary parse + * method has failed to parse it, due to it being split on + * buffer boundary. As a result code is very similar, except + * that it has to explicitly copy contents to the text buffer + * instead of just sharing the main input buffer. + */ + private final JsonToken parseNumberText2(boolean negative) + throws IOException, JsonParseException + { + char[] outBuf = _textBuffer.emptyAndGetCurrentSegment(); + int outPtr = 0; + + // Need to prepend sign? + if (negative) { + outBuf[outPtr++] = '-'; + } + + // This is the place to do leading-zero check(s) too: + int intLen = 0; + char c = (_inputPtr < _inputEnd) ? _inputBuffer[_inputPtr++] : getNextChar("No digit following minus sign"); + if (c == '0') { + c = _verifyNoLeadingZeroes(); + } + boolean eof = false; + + // Ok, first the obligatory integer part: + int_loop: + while (c >= '0' && c <= '9') { + ++intLen; + if (outPtr >= outBuf.length) { + outBuf = _textBuffer.finishCurrentSegment(); + outPtr = 0; + } + outBuf[outPtr++] = c; + if (_inputPtr >= _inputEnd && !loadMore()) { + // EOF is legal for main level int values + c = CHAR_NULL; + eof = true; + break int_loop; + } + c = _inputBuffer[_inputPtr++]; + } + // Also, integer part is not optional + if (intLen == 0) { + reportInvalidNumber("Missing integer part (next char "+_getCharDesc(c)+")"); + } + + int fractLen = 0; + // And then see if we get other parts + if (c == '.') { // yes, fraction + outBuf[outPtr++] = c; + + fract_loop: + while (true) { + if (_inputPtr >= _inputEnd && !loadMore()) { + eof = true; + break fract_loop; + } + c = _inputBuffer[_inputPtr++]; + if (c < INT_0 || c > INT_9) { + break fract_loop; + } + ++fractLen; + if (outPtr >= outBuf.length) { + outBuf = _textBuffer.finishCurrentSegment(); + outPtr = 0; + } + outBuf[outPtr++] = c; + } + // must be followed by sequence of ints, one minimum + if (fractLen == 0) { + reportUnexpectedNumberChar(c, "Decimal point not followed by a digit"); + } + } + + int expLen = 0; + if (c == 'e' || c == 'E') { // exponent? + if (outPtr >= outBuf.length) { + outBuf = _textBuffer.finishCurrentSegment(); + outPtr = 0; + } + outBuf[outPtr++] = c; + // Not optional, can require that we get one more char + c = (_inputPtr < _inputEnd) ? _inputBuffer[_inputPtr++] + : getNextChar("expected a digit for number exponent"); + // Sign indicator? + if (c == '-' || c == '+') { + if (outPtr >= outBuf.length) { + outBuf = _textBuffer.finishCurrentSegment(); + outPtr = 0; + } + outBuf[outPtr++] = c; + // Likewise, non optional: + c = (_inputPtr < _inputEnd) ? _inputBuffer[_inputPtr++] + : getNextChar("expected a digit for number exponent"); + } + + exp_loop: + while (c <= INT_9 && c >= INT_0) { + ++expLen; + if (outPtr >= outBuf.length) { + outBuf = _textBuffer.finishCurrentSegment(); + outPtr = 0; + } + outBuf[outPtr++] = c; + if (_inputPtr >= _inputEnd && !loadMore()) { + eof = true; + break exp_loop; + } + c = _inputBuffer[_inputPtr++]; + } + // must be followed by sequence of ints, one minimum + if (expLen == 0) { + reportUnexpectedNumberChar(c, "Exponent indicator not followed by a digit"); + } + } + + // Ok; unless we hit end-of-input, need to push last char read back + if (!eof) { + --_inputPtr; + } + _textBuffer.setCurrentLength(outPtr); + // And there we have it! + return reset(negative, intLen, fractLen, expLen); + } + + /** + * Method called when we have seen one zero, and want to ensure + * it is not followed by another + */ + private final char _verifyNoLeadingZeroes() + throws IOException, JsonParseException + { + // Ok to have plain "0" + if (_inputPtr >= _inputEnd && !loadMore()) { + return '0'; + } + char ch = _inputBuffer[_inputPtr]; + // if not followed by a number (probably '.'); return zero as is, to be included + if (ch < '0' || ch > '9') { + return '0'; + } + if (!isEnabled(Feature.ALLOW_NUMERIC_LEADING_ZEROS)) { + reportInvalidNumber("Leading zeroes not allowed"); + } + // if so, just need to skip either all zeroes (if followed by number); or all but one (if non-number) + ++_inputPtr; // Leading zero to be skipped + if (ch == INT_0) { + while (_inputPtr < _inputEnd || loadMore()) { + ch = _inputBuffer[_inputPtr]; + if (ch < '0' || ch > '9') { // followed by non-number; retain one zero + return '0'; + } + ++_inputPtr; // skip previous zero + if (ch != '0') { // followed by other number; return + break; + } + } + } + return ch; + } + + /** + * Method called if expected numeric value (due to leading sign) does not + * look like a number + */ + protected JsonToken _handleInvalidNumberStart(int ch, boolean negative) + throws IOException, JsonParseException + { + if (ch == 'I') { + if (_inputPtr >= _inputEnd) { + if (!loadMore()) { + _reportInvalidEOFInValue(); + } + } + ch = _inputBuffer[_inputPtr++]; + if (ch == 'N') { + String match = negative ? "-INF" :"+INF"; + _matchToken(match, 3); + if (isEnabled(Feature.ALLOW_NON_NUMERIC_NUMBERS)) { + return resetAsNaN(match, negative ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY); + } + _reportError("Non-standard token '"+match+"': enable JsonParser.Feature.ALLOW_NON_NUMERIC_NUMBERS to allow"); + } else if (ch == 'n') { + String match = negative ? "-Infinity" :"+Infinity"; + _matchToken(match, 3); + if (isEnabled(Feature.ALLOW_NON_NUMERIC_NUMBERS)) { + return resetAsNaN(match, negative ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY); + } + _reportError("Non-standard token '"+match+"': enable JsonParser.Feature.ALLOW_NON_NUMERIC_NUMBERS to allow"); + } + } + reportUnexpectedNumberChar(ch, "expected digit (0-9) to follow minus sign, for valid numeric value"); + return null; + } + + /* + /********************************************************** + /* Internal methods, secondary parsing + /********************************************************** + */ + + protected final String _parseFieldName(int i) + throws IOException, JsonParseException + { + if (i != INT_QUOTE) { + return _handleUnusualFieldName(i); + } + /* First: let's try to see if we have a simple name: one that does + * not cross input buffer boundary, and does not contain escape + * sequences. + */ + int ptr = _inputPtr; + int hash = 0; + final int inputLen = _inputEnd; + + if (ptr < inputLen) { + final int[] codes = CharTypes.getInputCodeLatin1(); + final int maxCode = codes.length; + + do { + int ch = _inputBuffer[ptr]; + if (ch < maxCode && codes[ch] != 0) { + if (ch == '"') { + int start = _inputPtr; + _inputPtr = ptr+1; // to skip the quote + return _symbols.findSymbol(_inputBuffer, start, ptr - start, hash); + } + break; + } + hash = (hash * 31) + ch; + ++ptr; + } while (ptr < inputLen); + } + + int start = _inputPtr; + _inputPtr = ptr; + return _parseFieldName2(start, hash, INT_QUOTE); + } + + private String _parseFieldName2(int startPtr, int hash, int endChar) + throws IOException, JsonParseException + { + _textBuffer.resetWithShared(_inputBuffer, startPtr, (_inputPtr - startPtr)); + + /* Output pointers; calls will also ensure that the buffer is + * not shared and has room for at least one more char. + */ + char[] outBuf = _textBuffer.getCurrentSegment(); + int outPtr = _textBuffer.getCurrentSegmentSize(); + + while (true) { + if (_inputPtr >= _inputEnd) { + if (!loadMore()) { + _reportInvalidEOF(": was expecting closing '"+((char) endChar)+"' for name"); + } + } + char c = _inputBuffer[_inputPtr++]; + int i = (int) c; + if (i <= INT_BACKSLASH) { + if (i == INT_BACKSLASH) { + /* Although chars outside of BMP are to be escaped as + * an UTF-16 surrogate pair, does that affect decoding? + * For now let's assume it does not. + */ + c = _decodeEscaped(); + } else if (i <= endChar) { + if (i == endChar) { + break; + } + if (i < INT_SPACE) { + _throwUnquotedSpace(i, "name"); + } + } + } + hash = (hash * 31) + i; + // Ok, let's add char to output: + outBuf[outPtr++] = c; + + // Need more room? + if (outPtr >= outBuf.length) { + outBuf = _textBuffer.finishCurrentSegment(); + outPtr = 0; + } + } + _textBuffer.setCurrentLength(outPtr); + { + TextBuffer tb = _textBuffer; + char[] buf = tb.getTextBuffer(); + int start = tb.getTextOffset(); + int len = tb.size(); + + return _symbols.findSymbol(buf, start, len, hash); + } + } + + /** + * Method called when we see non-white space character other + * than double quote, when expecting a field name. + * In standard mode will just throw an expection; but + * in non-standard modes may be able to parse name. + * + * @since 1.2 + */ + protected final String _handleUnusualFieldName(int i) + throws IOException, JsonParseException + { + // [JACKSON-173]: allow single quotes + if (i == INT_APOSTROPHE && isEnabled(Feature.ALLOW_SINGLE_QUOTES)) { + return _parseApostropheFieldName(); + } + // [JACKSON-69]: allow unquoted names if feature enabled: + if (!isEnabled(Feature.ALLOW_UNQUOTED_FIELD_NAMES)) { + _reportUnexpectedChar(i, "was expecting double-quote to start field name"); + } + final int[] codes = CharTypes.getInputCodeLatin1JsNames(); + final int maxCode = codes.length; + + // Also: first char must be a valid name char, but NOT be number + boolean firstOk; + + if (i < maxCode) { // identifier, and not a number + firstOk = (codes[i] == 0) && (i < INT_0 || i > INT_9); + } else { + firstOk = Character.isJavaIdentifierPart((char) i); + } + if (!firstOk) { + _reportUnexpectedChar(i, "was expecting either valid name character (for unquoted name) or double-quote (for quoted) to start field name"); + } + int ptr = _inputPtr; + int hash = 0; + final int inputLen = _inputEnd; + + if (ptr < inputLen) { + do { + int ch = _inputBuffer[ptr]; + if (ch < maxCode) { + if (codes[ch] != 0) { + int start = _inputPtr-1; // -1 to bring back first char + _inputPtr = ptr; + return _symbols.findSymbol(_inputBuffer, start, ptr - start, hash); + } + } else if (!Character.isJavaIdentifierPart((char) ch)) { + int start = _inputPtr-1; // -1 to bring back first char + _inputPtr = ptr; + return _symbols.findSymbol(_inputBuffer, start, ptr - start, hash); + } + hash = (hash * 31) + ch; + ++ptr; + } while (ptr < inputLen); + } + int start = _inputPtr-1; + _inputPtr = ptr; + return _parseUnusualFieldName2(start, hash, codes); + } + + protected final String _parseApostropheFieldName() + throws IOException, JsonParseException + { + // Note: mostly copy of_parseFieldName + int ptr = _inputPtr; + int hash = 0; + final int inputLen = _inputEnd; + + if (ptr < inputLen) { + final int[] codes = CharTypes.getInputCodeLatin1(); + final int maxCode = codes.length; + + do { + int ch = _inputBuffer[ptr]; + if (ch == '\'') { + int start = _inputPtr; + _inputPtr = ptr+1; // to skip the quote + return _symbols.findSymbol(_inputBuffer, start, ptr - start, hash); + } + if (ch < maxCode && codes[ch] != 0) { + break; + } + hash = (hash * 31) + ch; + ++ptr; + } while (ptr < inputLen); + } + + int start = _inputPtr; + _inputPtr = ptr; + + return _parseFieldName2(start, hash, INT_APOSTROPHE); + } + + /** + * Method for handling cases where first non-space character + * of an expected value token is not legal for standard JSON content. + * + * @since 1.3 + */ + protected final JsonToken _handleUnexpectedValue(int i) + throws IOException, JsonParseException + { + // Most likely an error, unless we are to allow single-quote-strings + switch (i) { + case '\'': + /* [JACKSON-173]: allow single quotes. Unlike with regular + * Strings, we'll eagerly parse contents; this so that there's + * no need to store information on quote char used. + * + * Also, no separation to fast/slow parsing; we'll just do + * one regular (~= slowish) parsing, to keep code simple + */ + if (isEnabled(Feature.ALLOW_SINGLE_QUOTES)) { + return _handleApostropheValue(); + } + break; + case 'N': + _matchToken("NaN", 1); + if (isEnabled(Feature.ALLOW_NON_NUMERIC_NUMBERS)) { + return resetAsNaN("NaN", Double.NaN); + } + _reportError("Non-standard token 'NaN': enable JsonParser.Feature.ALLOW_NON_NUMERIC_NUMBERS to allow"); + break; + case '+': // note: '-' is taken as number + if (_inputPtr >= _inputEnd) { + if (!loadMore()) { + _reportInvalidEOFInValue(); + } + } + return _handleInvalidNumberStart(_inputBuffer[_inputPtr++], false); + } + _reportUnexpectedChar(i, "expected a valid value (number, String, array, object, 'true', 'false' or 'null')"); + return null; + } + + /** + * @since 1.8 + */ + protected final JsonToken _handleApostropheValue() + throws IOException, JsonParseException + { + char[] outBuf = _textBuffer.emptyAndGetCurrentSegment(); + int outPtr = _textBuffer.getCurrentSegmentSize(); + + while (true) { + if (_inputPtr >= _inputEnd) { + if (!loadMore()) { + _reportInvalidEOF(": was expecting closing quote for a string value"); + } + } + char c = _inputBuffer[_inputPtr++]; + int i = (int) c; + if (i <= INT_BACKSLASH) { + if (i == INT_BACKSLASH) { + /* Although chars outside of BMP are to be escaped as + * an UTF-16 surrogate pair, does that affect decoding? + * For now let's assume it does not. + */ + c = _decodeEscaped(); + } else if (i <= INT_APOSTROPHE) { + if (i == INT_APOSTROPHE) { + break; + } + if (i < INT_SPACE) { + _throwUnquotedSpace(i, "string value"); + } + } + } + // Need more room? + if (outPtr >= outBuf.length) { + outBuf = _textBuffer.finishCurrentSegment(); + outPtr = 0; + } + // Ok, let's add char to output: + outBuf[outPtr++] = c; + } + _textBuffer.setCurrentLength(outPtr); + return JsonToken.VALUE_STRING; + } + + /** + * @since 1.2 + */ + private String _parseUnusualFieldName2(int startPtr, int hash, int[] codes) + throws IOException, JsonParseException + { + _textBuffer.resetWithShared(_inputBuffer, startPtr, (_inputPtr - startPtr)); + char[] outBuf = _textBuffer.getCurrentSegment(); + int outPtr = _textBuffer.getCurrentSegmentSize(); + final int maxCode = codes.length; + + while (true) { + if (_inputPtr >= _inputEnd) { + if (!loadMore()) { // acceptable for now (will error out later) + break; + } + } + char c = _inputBuffer[_inputPtr]; + int i = (int) c; + if (i <= maxCode) { + if (codes[i] != 0) { + break; + } + } else if (!Character.isJavaIdentifierPart(c)) { + break; + } + ++_inputPtr; + hash = (hash * 31) + i; + // Ok, let's add char to output: + outBuf[outPtr++] = c; + + // Need more room? + if (outPtr >= outBuf.length) { + outBuf = _textBuffer.finishCurrentSegment(); + outPtr = 0; + } + } + _textBuffer.setCurrentLength(outPtr); + { + TextBuffer tb = _textBuffer; + char[] buf = tb.getTextBuffer(); + int start = tb.getTextOffset(); + int len = tb.size(); + + return _symbols.findSymbol(buf, start, len, hash); + } + } + + @Override + protected void _finishString() + throws IOException, JsonParseException + { + /* First: let's try to see if we have simple String value: one + * that does not cross input buffer boundary, and does not + * contain escape sequences. + */ + int ptr = _inputPtr; + final int inputLen = _inputEnd; + + if (ptr < inputLen) { + final int[] codes = CharTypes.getInputCodeLatin1(); + final int maxCode = codes.length; + + do { + int ch = _inputBuffer[ptr]; + if (ch < maxCode && codes[ch] != 0) { + if (ch == '"') { + _textBuffer.resetWithShared(_inputBuffer, _inputPtr, (ptr-_inputPtr)); + _inputPtr = ptr+1; + // Yes, we got it all + return; + } + break; + } + ++ptr; + } while (ptr < inputLen); + } + + /* Either ran out of input, or bumped into an escape + * sequence... + */ + _textBuffer.resetWithCopy(_inputBuffer, _inputPtr, (ptr-_inputPtr)); + _inputPtr = ptr; + _finishString2(); + } + + protected void _finishString2() + throws IOException, JsonParseException + { + char[] outBuf = _textBuffer.getCurrentSegment(); + int outPtr = _textBuffer.getCurrentSegmentSize(); + + while (true) { + if (_inputPtr >= _inputEnd) { + if (!loadMore()) { + _reportInvalidEOF(": was expecting closing quote for a string value"); + } + } + char c = _inputBuffer[_inputPtr++]; + int i = (int) c; + if (i <= INT_BACKSLASH) { + if (i == INT_BACKSLASH) { + /* Although chars outside of BMP are to be escaped as + * an UTF-16 surrogate pair, does that affect decoding? + * For now let's assume it does not. + */ + c = _decodeEscaped(); + } else if (i <= INT_QUOTE) { + if (i == INT_QUOTE) { + break; + } + if (i < INT_SPACE) { + _throwUnquotedSpace(i, "string value"); + } + } + } + // Need more room? + if (outPtr >= outBuf.length) { + outBuf = _textBuffer.finishCurrentSegment(); + outPtr = 0; + } + // Ok, let's add char to output: + outBuf[outPtr++] = c; + } + _textBuffer.setCurrentLength(outPtr); + } + + /** + * Method called to skim through rest of unparsed String value, + * if it is not needed. This can be done bit faster if contents + * need not be stored for future access. + */ + protected void _skipString() + throws IOException, JsonParseException + { + _tokenIncomplete = false; + + int inputPtr = _inputPtr; + int inputLen = _inputEnd; + char[] inputBuffer = _inputBuffer; + + while (true) { + if (inputPtr >= inputLen) { + _inputPtr = inputPtr; + if (!loadMore()) { + _reportInvalidEOF(": was expecting closing quote for a string value"); + } + inputPtr = _inputPtr; + inputLen = _inputEnd; + } + char c = inputBuffer[inputPtr++]; + int i = (int) c; + if (i <= INT_BACKSLASH) { + if (i == INT_BACKSLASH) { + /* Although chars outside of BMP are to be escaped as + * an UTF-16 surrogate pair, does that affect decoding? + * For now let's assume it does not. + */ + _inputPtr = inputPtr; + c = _decodeEscaped(); + inputPtr = _inputPtr; + inputLen = _inputEnd; + } else if (i <= INT_QUOTE) { + if (i == INT_QUOTE) { + _inputPtr = inputPtr; + break; + } + if (i < INT_SPACE) { + _inputPtr = inputPtr; + _throwUnquotedSpace(i, "string value"); + } + } + } + } + } + + /* + /********************************************************** + /* Internal methods, other parsing + /********************************************************** + */ + + /** + * We actually need to check the character value here + * (to see if we have \n following \r). + */ + protected final void _skipCR() throws IOException + { + if (_inputPtr < _inputEnd || loadMore()) { + if (_inputBuffer[_inputPtr] == '\n') { + ++_inputPtr; + } + } + ++_currInputRow; + _currInputRowStart = _inputPtr; + } + + protected final void _skipLF() throws IOException + { + ++_currInputRow; + _currInputRowStart = _inputPtr; + } + + private final int _skipWS() + throws IOException, JsonParseException + { + while (_inputPtr < _inputEnd || loadMore()) { + int i = (int) _inputBuffer[_inputPtr++]; + if (i > INT_SPACE) { + if (i != INT_SLASH) { + return i; + } + _skipComment(); + } else if (i != INT_SPACE) { + if (i == INT_LF) { + _skipLF(); + } else if (i == INT_CR) { + _skipCR(); + } else if (i != INT_TAB) { + _throwInvalidSpace(i); + } + } + } + throw _constructError("Unexpected end-of-input within/between "+_parsingContext.getTypeDesc()+" entries"); + } + + private final int _skipWSOrEnd() + throws IOException, JsonParseException + { + while ((_inputPtr < _inputEnd) || loadMore()) { + int i = (int) _inputBuffer[_inputPtr++]; + if (i > INT_SPACE) { + if (i == INT_SLASH) { + _skipComment(); + continue; + } + return i; + } + if (i != INT_SPACE) { + if (i == INT_LF) { + _skipLF(); + } else if (i == INT_CR) { + _skipCR(); + } else if (i != INT_TAB) { + _throwInvalidSpace(i); + } + } + } + // We ran out of input... + _handleEOF(); + return -1; + } + + private final void _skipComment() + throws IOException, JsonParseException + { + if (!isEnabled(Feature.ALLOW_COMMENTS)) { + _reportUnexpectedChar('/', "maybe a (non-standard) comment? (not recognized as one since Feature 'ALLOW_COMMENTS' not enabled for parser)"); + } + // First: check which comment (if either) it is: + if (_inputPtr >= _inputEnd && !loadMore()) { + _reportInvalidEOF(" in a comment"); + } + char c = _inputBuffer[_inputPtr++]; + if (c == '/') { + _skipCppComment(); + } else if (c == '*') { + _skipCComment(); + } else { + _reportUnexpectedChar(c, "was expecting either '*' or '/' for a comment"); + } + } + + private final void _skipCComment() + throws IOException, JsonParseException + { + // Ok: need the matching '*/' + main_loop: + while ((_inputPtr < _inputEnd) || loadMore()) { + int i = (int) _inputBuffer[_inputPtr++]; + if (i <= INT_ASTERISK) { + if (i == INT_ASTERISK) { // end? + if ((_inputPtr >= _inputEnd) && !loadMore()) { + break main_loop; + } + if (_inputBuffer[_inputPtr] == INT_SLASH) { + ++_inputPtr; + return; + } + continue; + } + if (i < INT_SPACE) { + if (i == INT_LF) { + _skipLF(); + } else if (i == INT_CR) { + _skipCR(); + } else if (i != INT_TAB) { + _throwInvalidSpace(i); + } + } + } + } + _reportInvalidEOF(" in a comment"); + } + + private final void _skipCppComment() + throws IOException, JsonParseException + { + // Ok: need to find EOF or linefeed + while ((_inputPtr < _inputEnd) || loadMore()) { + int i = (int) _inputBuffer[_inputPtr++]; + if (i < INT_SPACE) { + if (i == INT_LF) { + _skipLF(); + break; + } else if (i == INT_CR) { + _skipCR(); + break; + } else if (i != INT_TAB) { + _throwInvalidSpace(i); + } + } + } + } + + @Override + protected final char _decodeEscaped() + throws IOException, JsonParseException + { + if (_inputPtr >= _inputEnd) { + if (!loadMore()) { + _reportInvalidEOF(" in character escape sequence"); + } + } + char c = _inputBuffer[_inputPtr++]; + + switch ((int) c) { + // First, ones that are mapped + case INT_b: + return '\b'; + case INT_t: + return '\t'; + case INT_n: + return '\n'; + case INT_f: + return '\f'; + case INT_r: + return '\r'; + + // And these are to be returned as they are + case INT_QUOTE: + case INT_SLASH: + case INT_BACKSLASH: + return c; + + case INT_u: // and finally hex-escaped + break; + + default: + return _handleUnrecognizedCharacterEscape(c); + } + + // Ok, a hex escape. Need 4 characters + int value = 0; + for (int i = 0; i < 4; ++i) { + if (_inputPtr >= _inputEnd) { + if (!loadMore()) { + _reportInvalidEOF(" in character escape sequence"); + } + } + int ch = (int) _inputBuffer[_inputPtr++]; + int digit = CharTypes.charToHex(ch); + if (digit < 0) { + _reportUnexpectedChar(ch, "expected a hex-digit for character escape sequence"); + } + value = (value << 4) | digit; + } + return (char) value; + } + + /** + * Helper method for checking whether input matches expected token + * + * @since 1.8 + */ + protected final void _matchToken(String matchStr, int i) + throws IOException, JsonParseException + { + final int len = matchStr.length(); + + do { + if (_inputPtr >= _inputEnd) { + if (!loadMore()) { + _reportInvalidEOFInValue(); + } + } + if (_inputBuffer[_inputPtr] != matchStr.charAt(i)) { + _reportInvalidToken(matchStr.substring(0, i), "'null', 'true', 'false' or NaN"); + } + ++_inputPtr; + } while (++i < len); + + // but let's also ensure we either get EOF, or non-alphanum char... + if (_inputPtr >= _inputEnd) { + if (!loadMore()) { + return; + } + } + char c = _inputBuffer[_inputPtr]; + if (c < '0' || c == ']' || c == '}') { // expected/allowed chars + return; + } + // if Java letter, it's a problem tho + if (Character.isJavaIdentifierPart(c)) { + _reportInvalidToken(matchStr.substring(0, i), "'null', 'true', 'false' or NaN"); + } + return; + } + + /* + /********************************************************** + /* Binary access + /********************************************************** + */ + + /** + * Efficient handling for incremental parsing of base64-encoded + * textual content. + */ + protected byte[] _decodeBase64(Base64Variant b64variant) + throws IOException, JsonParseException + { + ByteArrayBuilder builder = _getByteArrayBuilder(); + + //main_loop: + while (true) { + // first, we'll skip preceding white space, if any + char ch; + do { + if (_inputPtr >= _inputEnd) { + loadMoreGuaranteed(); + } + ch = _inputBuffer[_inputPtr++]; + } while (ch <= INT_SPACE); + int bits = b64variant.decodeBase64Char(ch); + if (bits < 0) { + if (ch == '"') { // reached the end, fair and square? + return builder.toByteArray(); + } + bits = _decodeBase64Escape(b64variant, ch, 0); + if (bits < 0) { // white space to skip + continue; + } + } + int decodedData = bits; + + // then second base64 char; can't get padding yet, nor ws + + if (_inputPtr >= _inputEnd) { + loadMoreGuaranteed(); + } + ch = _inputBuffer[_inputPtr++]; + bits = b64variant.decodeBase64Char(ch); + if (bits < 0) { + bits = _decodeBase64Escape(b64variant, ch, 1); + } + decodedData = (decodedData << 6) | bits; + + // third base64 char; can be padding, but not ws + if (_inputPtr >= _inputEnd) { + loadMoreGuaranteed(); + } + ch = _inputBuffer[_inputPtr++]; + bits = b64variant.decodeBase64Char(ch); + + // First branch: can get padding (-> 1 byte) + if (bits < 0) { + if (bits != Base64Variant.BASE64_VALUE_PADDING) { + // as per [JACKSON-631], could also just be 'missing' padding + if (ch == '"' && !b64variant.usesPadding()) { + decodedData >>= 4; + builder.append(decodedData); + return builder.toByteArray(); + } + bits = _decodeBase64Escape(b64variant, ch, 2); + } + if (bits == Base64Variant.BASE64_VALUE_PADDING) { + // Ok, must get more padding chars, then + if (_inputPtr >= _inputEnd) { + loadMoreGuaranteed(); + } + ch = _inputBuffer[_inputPtr++]; + if (!b64variant.usesPaddingChar(ch)) { + throw reportInvalidBase64Char(b64variant, ch, 3, "expected padding character '"+b64variant.getPaddingChar()+"'"); + } + // Got 12 bits, only need 8, need to shift + decodedData >>= 4; + builder.append(decodedData); + continue; + } + // otherwise we got escaped other char, to be processed below + } + // Nope, 2 or 3 bytes + decodedData = (decodedData << 6) | bits; + // fourth and last base64 char; can be padding, but not ws + if (_inputPtr >= _inputEnd) { + loadMoreGuaranteed(); + } + ch = _inputBuffer[_inputPtr++]; + bits = b64variant.decodeBase64Char(ch); + if (bits < 0) { + if (bits != Base64Variant.BASE64_VALUE_PADDING) { + // as per [JACKSON-631], could also just be 'missing' padding + if (ch == '"' && !b64variant.usesPadding()) { + decodedData >>= 2; + builder.appendTwoBytes(decodedData); + return builder.toByteArray(); + } + bits = _decodeBase64Escape(b64variant, ch, 3); + } + if (bits == Base64Variant.BASE64_VALUE_PADDING) { + // With padding we only get 2 bytes; but we have + // to shift it a bit so it is identical to triplet + // case with partial output. + // 3 chars gives 3x6 == 18 bits, of which 2 are + // dummies, need to discard: + decodedData >>= 2; + builder.appendTwoBytes(decodedData); + continue; + } + // otherwise we got escaped other char, to be processed below + } + // otherwise, our triplet is now complete + decodedData = (decodedData << 6) | bits; + builder.appendThreeBytes(decodedData); + } + } + + /* + /********************************************************** + /* Error reporting + /********************************************************** + */ + + protected void _reportInvalidToken(String matchedPart, String msg) + throws IOException, JsonParseException + { + StringBuilder sb = new StringBuilder(matchedPart); + /* Let's just try to find what appears to be the token, using + * regular Java identifier character rules. It's just a heuristic, + * nothing fancy here. + */ + while (true) { + if (_inputPtr >= _inputEnd) { + if (!loadMore()) { + break; + } + } + char c = _inputBuffer[_inputPtr]; + if (!Character.isJavaIdentifierPart(c)) { + break; + } + ++_inputPtr; + sb.append(c); + } + _reportError("Unrecognized token '"+sb.toString()+"': was expecting "); + } +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/impl/ReaderBasedParserBase.java b/1.9.10/src/java/org/codehaus/jackson/impl/ReaderBasedParserBase.java new file mode 100644 index 0000000..8771bc9 --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/impl/ReaderBasedParserBase.java
@@ -0,0 +1,228 @@ +package org.codehaus.jackson.impl; + +import java.io.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.io.IOContext; + +/** + * This is a simple low-level input reader base class, used by + * JSON parser. + * The reason for sub-classing (over composition) + * is due to need for direct access to character buffers + * and positions. + * + * @author Tatu Saloranta + * + * @deprecated Since 1.9 sub-classes should just include code + * from here as is. + */ +@Deprecated +public abstract class ReaderBasedParserBase + extends JsonParserBase +{ + /* + /********************************************************** + /* Configuration + /********************************************************** + */ + + /** + * Reader that can be used for reading more content, if one + * buffer from input source, but in some cases pre-loaded buffer + * is handed to the parser. + */ + protected Reader _reader; + + /* + /********************************************************** + /* Current input data + /********************************************************** + */ + + /** + * Current buffer from which data is read; generally data is read into + * buffer from input source. + */ + protected char[] _inputBuffer; + + /* + /********************************************************** + /* Life-cycle + /********************************************************** + */ + + protected ReaderBasedParserBase(IOContext ctxt, int features, Reader r) + { + super(ctxt, features); + _reader = r; + _inputBuffer = ctxt.allocTokenBuffer(); + } + + /* + /********************************************************** + /* Overrides + /********************************************************** + */ + + @Override + public int releaseBuffered(Writer w) throws IOException + { + int count = _inputEnd - _inputPtr; + if (count < 1) { + return 0; + } + // let's just advance ptr to end + int origPtr = _inputPtr; + w.write(_inputBuffer, origPtr, count); + return count; + } + + @Override + public Object getInputSource() { + return _reader; + } + + /* + /********************************************************** + /* Low-level reading, other + /********************************************************** + */ + + @Override + protected final boolean loadMore() throws IOException + { + _currInputProcessed += _inputEnd; + _currInputRowStart -= _inputEnd; + + if (_reader != null) { + int count = _reader.read(_inputBuffer, 0, _inputBuffer.length); + if (count > 0) { + _inputPtr = 0; + _inputEnd = count; + return true; + } + // End of input + _closeInput(); + // Should never return 0, so let's fail + if (count == 0) { + throw new IOException("Reader returned 0 characters when trying to read "+_inputEnd); + } + } + return false; + } + + protected char getNextChar(String eofMsg) + throws IOException, JsonParseException + { + if (_inputPtr >= _inputEnd) { + if (!loadMore()) { + _reportInvalidEOF(eofMsg); + } + } + return _inputBuffer[_inputPtr++]; + } + + @Override + protected void _closeInput() throws IOException + { + /* 25-Nov-2008, tatus: As per [JACKSON-16] we are not to call close() + * on the underlying Reader, unless we "own" it, or auto-closing + * feature is enabled. + * One downside is that when using our optimized + * Reader (granted, we only do that for UTF-32...) this + * means that buffer recycling won't work correctly. + */ + if (_reader != null) { + if (_ioContext.isResourceManaged() || isEnabled(Feature.AUTO_CLOSE_SOURCE)) { + _reader.close(); + } + _reader = null; + } + } + + /** + * Method called to release internal buffers owned by the base + * reader. This may be called along with {@link #_closeInput} (for + * example, when explicitly closing this reader instance), or + * separately (if need be). + */ + @Override + protected void _releaseBuffers() + throws IOException + { + super._releaseBuffers(); + char[] buf = _inputBuffer; + if (buf != null) { + _inputBuffer = null; + _ioContext.releaseTokenBuffer(buf); + } + } + + /* + /********************************************************** + /* Helper methods for subclasses + /********************************************************** + */ + + /** + * Helper method for checking whether input matches expected token + * + * @since 1.8 + */ + protected final boolean _matchToken(String matchStr, int i) + throws IOException, JsonParseException + { + final int len = matchStr.length(); + + do { + if (_inputPtr >= _inputEnd) { + if (!loadMore()) { + _reportInvalidEOFInValue(); + } + } + if (_inputBuffer[_inputPtr] != matchStr.charAt(i)) { + _reportInvalidToken(matchStr.substring(0, i), "'null', 'true', 'false' or NaN"); + } + ++_inputPtr; + } while (++i < len); + + // but let's also ensure we either get EOF, or non-alphanum char... + if (_inputPtr >= _inputEnd) { + if (!loadMore()) { + return true; + } + } + char c = _inputBuffer[_inputPtr]; + // if Java letter, it's a problem tho + if (Character.isJavaIdentifierPart(c)) { + ++_inputPtr; + _reportInvalidToken(matchStr.substring(0, i), "'null', 'true', 'false' or NaN"); + } + return true; + } + + protected void _reportInvalidToken(String matchedPart, String msg) + throws IOException, JsonParseException + { + StringBuilder sb = new StringBuilder(matchedPart); + /* Let's just try to find what appears to be the token, using + * regular Java identifier character rules. It's just a heuristic, + * nothing fancy here. + */ + while (true) { + if (_inputPtr >= _inputEnd) { + if (!loadMore()) { + break; + } + } + char c = _inputBuffer[_inputPtr]; + if (!Character.isJavaIdentifierPart(c)) { + break; + } + ++_inputPtr; + sb.append(c); + } + _reportError("Unrecognized token '"+sb.toString()+"': was expecting "); + } +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/impl/StreamBasedParserBase.java b/1.9.10/src/java/org/codehaus/jackson/impl/StreamBasedParserBase.java new file mode 100644 index 0000000..ea42033 --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/impl/StreamBasedParserBase.java
@@ -0,0 +1,197 @@ +package org.codehaus.jackson.impl; + +import java.io.*; + +import org.codehaus.jackson.io.IOContext; + +/** + * This is a simple low-level input reader base class, used by + * JSON parser. It is used when underlying input source is + * a byte stream such as {@link InputStream}. + * The reason for sub-classing (over composition) + * is due to need for direct access to low-level byte buffers + * and positions. + * + * @author Tatu Saloranta + * + * @deprecated Since 1.9, sub-classes should just embed code from here + */ +@Deprecated +public abstract class StreamBasedParserBase + extends JsonParserBase +{ + /* + /********************************************************** + /* Configuration + /********************************************************** + */ + + /** + * Input stream that can be used for reading more content, if one + * in use. May be null, if input comes just as a full buffer, + * or if the stream has been closed. + */ + protected InputStream _inputStream; + + /* + /********************************************************** + /* Current input data + /********************************************************** + */ + + /** + * Current buffer from which data is read; generally data is read into + * buffer from input source, but in some cases pre-loaded buffer + * is handed to the parser. + */ + protected byte[] _inputBuffer; + + /** + * Flag that indicates whether the input buffer is recycable (and + * needs to be returned to recycler once we are done) or not. + *<p> + * If it is not, it also means that parser can NOT modify underlying + * buffer. + */ + protected boolean _bufferRecyclable; + + /* + /********************************************************** + /* Life-cycle + /********************************************************** + */ + + protected StreamBasedParserBase(IOContext ctxt, int features, + InputStream in, byte[] inputBuffer, int start, int end, + boolean bufferRecyclable) + { + super(ctxt, features); + _inputStream = in; + _inputBuffer = inputBuffer; + _inputPtr = start; + _inputEnd = end; + _bufferRecyclable = bufferRecyclable; + } + + /* + /********************************************************** + /* Overrides + /********************************************************** + */ + + @Override + public int releaseBuffered(OutputStream out) throws IOException + { + int count = _inputEnd - _inputPtr; + if (count < 1) { + return 0; + } + // let's just advance ptr to end + int origPtr = _inputPtr; + out.write(_inputBuffer, origPtr, count); + return count; + } + + @Override + public Object getInputSource() { + return _inputStream; + } + + /* + /********************************************************** + /* Low-level reading, other + /********************************************************** + */ + + @Override + protected final boolean loadMore() + throws IOException + { + _currInputProcessed += _inputEnd; + _currInputRowStart -= _inputEnd; + + if (_inputStream != null) { + int count = _inputStream.read(_inputBuffer, 0, _inputBuffer.length); + if (count > 0) { + _inputPtr = 0; + _inputEnd = count; + return true; + } + // End of input + _closeInput(); + // Should never return 0, so let's fail + if (count == 0) { + throw new IOException("InputStream.read() returned 0 characters when trying to read "+_inputBuffer.length+" bytes"); + } + } + return false; + } + + /** + * Helper method that will try to load at least specified number bytes in + * input buffer, possible moving existing data around if necessary + * + * @since 1.6 + */ + protected final boolean _loadToHaveAtLeast(int minAvailable) + throws IOException + { + // No input stream, no leading (either we are closed, or have non-stream input source) + if (_inputStream == null) { + return false; + } + // Need to move remaining data in front? + int amount = _inputEnd - _inputPtr; + if (amount > 0 && _inputPtr > 0) { + _currInputProcessed += _inputPtr; + _currInputRowStart -= _inputPtr; + System.arraycopy(_inputBuffer, _inputPtr, _inputBuffer, 0, amount); + _inputEnd = amount; + } else { + _inputEnd = 0; + } + _inputPtr = 0; + while (_inputEnd < minAvailable) { + int count = _inputStream.read(_inputBuffer, _inputEnd, _inputBuffer.length - _inputEnd); + if (count < 1) { + // End of input + _closeInput(); + // Should never return 0, so let's fail + if (count == 0) { + throw new IOException("InputStream.read() returned 0 characters when trying to read "+amount+" bytes"); + } + return false; + } + _inputEnd += count; + } + return true; + } + + @Override + protected void _closeInput() throws IOException + { + /* 25-Nov-2008, tatus: As per [JACKSON-16] we are not to call close() + * on the underlying InputStream, unless we "own" it, or auto-closing + * feature is enabled. + */ + if (_inputStream != null) { + if (_ioContext.isResourceManaged() || isEnabled(Feature.AUTO_CLOSE_SOURCE)) { + _inputStream.close(); + } + _inputStream = null; + } + } + + @Override + protected void _releaseBuffers() throws IOException + { + super._releaseBuffers(); + if (_bufferRecyclable) { + byte[] buf = _inputBuffer; + if (buf != null) { + _inputBuffer = null; + _ioContext.releaseReadIOBuffer(buf); + } + } + } +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/impl/Utf8Generator.java b/1.9.10/src/java/org/codehaus/jackson/impl/Utf8Generator.java new file mode 100644 index 0000000..ccc25cd --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/impl/Utf8Generator.java
@@ -0,0 +1,1757 @@ +package org.codehaus.jackson.impl; + +import java.io.*; +import java.math.BigDecimal; +import java.math.BigInteger; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.io.CharacterEscapes; +import org.codehaus.jackson.io.IOContext; +import org.codehaus.jackson.io.NumberOutput; +import org.codehaus.jackson.io.SerializedString; +import org.codehaus.jackson.util.CharTypes; + +public class Utf8Generator + extends JsonGeneratorBase +{ + private final static byte BYTE_u = (byte) 'u'; + + private final static byte BYTE_0 = (byte) '0'; + + private final static byte BYTE_LBRACKET = (byte) '['; + private final static byte BYTE_RBRACKET = (byte) ']'; + private final static byte BYTE_LCURLY = (byte) '{'; + private final static byte BYTE_RCURLY = (byte) '}'; + + private final static byte BYTE_BACKSLASH = (byte) '\\'; + private final static byte BYTE_SPACE = (byte) ' '; + private final static byte BYTE_COMMA = (byte) ','; + private final static byte BYTE_COLON = (byte) ':'; + private final static byte BYTE_QUOTE = (byte) '"'; + + protected final static int SURR1_FIRST = 0xD800; + protected final static int SURR1_LAST = 0xDBFF; + protected final static int SURR2_FIRST = 0xDC00; + protected final static int SURR2_LAST = 0xDFFF; + + // intermediate copies only made up to certain length... + private final static int MAX_BYTES_TO_BUFFER = 512; + + final static byte[] HEX_CHARS = CharTypes.copyHexBytes(); + + private final static byte[] NULL_BYTES = { 'n', 'u', 'l', 'l' }; + private final static byte[] TRUE_BYTES = { 't', 'r', 'u', 'e' }; + private final static byte[] FALSE_BYTES = { 'f', 'a', 'l', 's', 'e' }; + + /** + * This is the default set of escape codes, over 7-bit ASCII range + * (first 128 character codes), used for single-byte UTF-8 characters. + */ + protected final static int[] sOutputEscapes = CharTypes.get7BitOutputEscapes(); + + /* + /********************************************************** + /* Configuration, basic I/O + /********************************************************** + */ + + final protected IOContext _ioContext; + + /** + * Underlying output stream used for writing JSON content. + */ + final protected OutputStream _outputStream; + + /* + /********************************************************** + /* Configuration, output escaping + /********************************************************** + */ + + /** + * Currently active set of output escape code definitions (whether + * and how to escape or not) for 7-bit ASCII range (first 128 + * character codes). Defined separately to make potentially + * customizable + */ + protected int[] _outputEscapes = sOutputEscapes; + + /** + * Value between 128 (0x80) and 65535 (0xFFFF) that indicates highest + * Unicode code point that will not need escaping; or 0 to indicate + * that all characters can be represented without escaping. + * Typically used to force escaping of some portion of character set; + * for example to always escape non-ASCII characters (if value was 127). + *<p> + * NOTE: not all sub-classes make use of this setting. + */ + protected int _maximumNonEscapedChar; + + /** + * Definition of custom character escapes to use for generators created + * by this factory, if any. If null, standard data format specific + * escapes are used. + * + * @since 1.8 + */ + protected CharacterEscapes _characterEscapes; + + /* + /********************************************************** + /* Output buffering + /********************************************************** + */ + + /** + * Intermediate buffer in which contents are buffered before + * being written using {@link #_outputStream}. + */ + protected byte[] _outputBuffer; + + /** + * Pointer to the position right beyond the last character to output + * (end marker; may be past the buffer) + */ + protected int _outputTail = 0; + + /** + * End marker of the output buffer; one past the last valid position + * within the buffer. + */ + protected final int _outputEnd; + + /** + * Maximum number of <code>char</code>s that we know will always fit + * in the output buffer after escaping + */ + protected final int _outputMaxContiguous; + + /** + * Intermediate buffer in which characters of a String are copied + * before being encoded. + */ + protected char[] _charBuffer; + + /** + * Length of <code>_charBuffer</code> + */ + protected final int _charBufferLength; + + /** + * 6 character temporary buffer allocated if needed, for constructing + * escape sequences + */ + protected byte[] _entityBuffer; + + /** + * Flag that indicates whether the output buffer is recycable (and + * needs to be returned to recycler once we are done) or not. + */ + protected boolean _bufferRecyclable; + + /* + /********************************************************** + /* Life-cycle + /********************************************************** + */ + + public Utf8Generator(IOContext ctxt, int features, ObjectCodec codec, + OutputStream out) + { + + super(features, codec); + _ioContext = ctxt; + _outputStream = out; + _bufferRecyclable = true; + _outputBuffer = ctxt.allocWriteEncodingBuffer(); + _outputEnd = _outputBuffer.length; + /* To be exact, each char can take up to 6 bytes when escaped (Unicode + * escape with backslash, 'u' and 4 hex digits); but to avoid fluctuation, + * we will actually round down to only do up to 1/8 number of chars + */ + _outputMaxContiguous = _outputEnd >> 3; + _charBuffer = ctxt.allocConcatBuffer(); + _charBufferLength = _charBuffer.length; + + // By default we use this feature to determine additional quoting + if (isEnabled(Feature.ESCAPE_NON_ASCII)) { + setHighestNonEscapedChar(127); + } + } + + public Utf8Generator(IOContext ctxt, int features, ObjectCodec codec, + OutputStream out, byte[] outputBuffer, int outputOffset, boolean bufferRecyclable) + { + + super(features, codec); + _ioContext = ctxt; + _outputStream = out; + _bufferRecyclable = bufferRecyclable; + _outputTail = outputOffset; + _outputBuffer = outputBuffer; + _outputEnd = _outputBuffer.length; + // up to 6 bytes per char (see above), rounded up to 1/8 + _outputMaxContiguous = _outputEnd >> 3; + _charBuffer = ctxt.allocConcatBuffer(); + _charBufferLength = _charBuffer.length; + + if (isEnabled(Feature.ESCAPE_NON_ASCII)) { + setHighestNonEscapedChar(127); + } + } + + /* + /********************************************************** + /* Overridden configuration methods + /********************************************************** + */ + + @Override + public JsonGenerator setHighestNonEscapedChar(int charCode) { + _maximumNonEscapedChar = (charCode < 0) ? 0 : charCode; + return this; + } + + @Override + public int getHighestEscapedChar() { + return _maximumNonEscapedChar; + } + + @Override + public JsonGenerator setCharacterEscapes(CharacterEscapes esc) + { + _characterEscapes = esc; + if (esc == null) { // revert to standard escapes + _outputEscapes = sOutputEscapes; + } else { + _outputEscapes = esc.getEscapeCodesForAscii(); + } + return this; + } + + /** + * Method for accessing custom escapes factory uses for {@link JsonGenerator}s + * it creates. + * + * @since 1.8 + */ + @Override + public CharacterEscapes getCharacterEscapes() { + return _characterEscapes; + } + + @Override + public Object getOutputTarget() { + return _outputStream; + } + + /* + /********************************************************** + /* Overridden methods + /********************************************************** + */ + + /* Most overrides in this section are just to make methods final, + * to allow better inlining... + */ + @Override + public final void writeStringField(String fieldName, String value) + throws IOException, JsonGenerationException + { + writeFieldName(fieldName); + writeString(value); + } + + @Override + public final void writeFieldName(String name) throws IOException, JsonGenerationException + { + int status = _writeContext.writeFieldName(name); + if (status == JsonWriteContext.STATUS_EXPECT_VALUE) { + _reportError("Can not write a field name, expecting a value"); + } + if (_cfgPrettyPrinter != null) { + _writePPFieldName(name, (status == JsonWriteContext.STATUS_OK_AFTER_COMMA)); + return; + } + if (status == JsonWriteContext.STATUS_OK_AFTER_COMMA) { // need comma + if (_outputTail >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = BYTE_COMMA; + } + _writeFieldName(name); + } + + @Override + public final void writeFieldName(SerializedString name) + throws IOException, JsonGenerationException + { + // Object is a value, need to verify it's allowed + int status = _writeContext.writeFieldName(name.getValue()); + if (status == JsonWriteContext.STATUS_EXPECT_VALUE) { + _reportError("Can not write a field name, expecting a value"); + } + if (_cfgPrettyPrinter != null) { + _writePPFieldName(name, (status == JsonWriteContext.STATUS_OK_AFTER_COMMA)); + return; + } + if (status == JsonWriteContext.STATUS_OK_AFTER_COMMA) { + if (_outputTail >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = BYTE_COMMA; + } + _writeFieldName(name); + } + + @Override + public final void writeFieldName(SerializableString name) + throws IOException, JsonGenerationException + { + // Object is a value, need to verify it's allowed + int status = _writeContext.writeFieldName(name.getValue()); + if (status == JsonWriteContext.STATUS_EXPECT_VALUE) { + _reportError("Can not write a field name, expecting a value"); + } + if (_cfgPrettyPrinter != null) { + _writePPFieldName(name, (status == JsonWriteContext.STATUS_OK_AFTER_COMMA)); + return; + } + if (status == JsonWriteContext.STATUS_OK_AFTER_COMMA) { + if (_outputTail >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = BYTE_COMMA; + } + _writeFieldName(name); + } + + /* + /********************************************************** + /* Output method implementations, structural + /********************************************************** + */ + + @Override + public final void writeStartArray() throws IOException, JsonGenerationException + { + _verifyValueWrite("start an array"); + _writeContext = _writeContext.createChildArrayContext(); + if (_cfgPrettyPrinter != null) { + _cfgPrettyPrinter.writeStartArray(this); + } else { + if (_outputTail >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = BYTE_LBRACKET; + } + } + + @Override + public final void writeEndArray() throws IOException, JsonGenerationException + { + if (!_writeContext.inArray()) { + _reportError("Current context not an ARRAY but "+_writeContext.getTypeDesc()); + } + if (_cfgPrettyPrinter != null) { + _cfgPrettyPrinter.writeEndArray(this, _writeContext.getEntryCount()); + } else { + if (_outputTail >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = BYTE_RBRACKET; + } + _writeContext = _writeContext.getParent(); + } + + @Override + public final void writeStartObject() throws IOException, JsonGenerationException + { + _verifyValueWrite("start an object"); + _writeContext = _writeContext.createChildObjectContext(); + if (_cfgPrettyPrinter != null) { + _cfgPrettyPrinter.writeStartObject(this); + } else { + if (_outputTail >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = BYTE_LCURLY; + } + } + + @Override + public final void writeEndObject() throws IOException, JsonGenerationException + { + if (!_writeContext.inObject()) { + _reportError("Current context not an object but "+_writeContext.getTypeDesc()); + } + if (_cfgPrettyPrinter != null) { + _cfgPrettyPrinter.writeEndObject(this, _writeContext.getEntryCount()); + } else { + if (_outputTail >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = BYTE_RCURLY; + } + _writeContext = _writeContext.getParent(); + } + + protected final void _writeFieldName(String name) + throws IOException, JsonGenerationException + { + /* To support [JACKSON-46], we'll do this: + * (Question: should quoting of spaces (etc) still be enabled?) + */ + if (!isEnabled(Feature.QUOTE_FIELD_NAMES)) { + _writeStringSegments(name); + return; + } + if (_outputTail >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = BYTE_QUOTE; + // The beef: + final int len = name.length(); + if (len <= _charBufferLength) { // yes, fits right in + name.getChars(0, len, _charBuffer, 0); + // But as one segment, or multiple? + if (len <= _outputMaxContiguous) { + if ((_outputTail + len) > _outputEnd) { // caller must ensure enough space + _flushBuffer(); + } + _writeStringSegment(_charBuffer, 0, len); + } else { + _writeStringSegments(_charBuffer, 0, len); + } + } else { + _writeStringSegments(name); + } + + // and closing quotes; need room for one more char: + if (_outputTail >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = BYTE_QUOTE; + } + + protected final void _writeFieldName(SerializableString name) + throws IOException, JsonGenerationException + { + byte[] raw = name.asQuotedUTF8(); + if (!isEnabled(Feature.QUOTE_FIELD_NAMES)) { + _writeBytes(raw); + return; + } + if (_outputTail >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = BYTE_QUOTE; + + // Can do it all in buffer? + final int len = raw.length; + if ((_outputTail + len + 1) < _outputEnd) { // yup + System.arraycopy(raw, 0, _outputBuffer, _outputTail, len); + _outputTail += len; + _outputBuffer[_outputTail++] = BYTE_QUOTE; + } else { + _writeBytes(raw); + if (_outputTail >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = BYTE_QUOTE; + } + } + + /** + * Specialized version of <code>_writeFieldName</code>, off-lined + * to keep the "fast path" as simple (and hopefully fast) as possible. + */ + protected final void _writePPFieldName(String name, boolean commaBefore) + throws IOException, JsonGenerationException + { + if (commaBefore) { + _cfgPrettyPrinter.writeObjectEntrySeparator(this); + } else { + _cfgPrettyPrinter.beforeObjectEntries(this); + } + + if (isEnabled(Feature.QUOTE_FIELD_NAMES)) { // standard + if (_outputTail >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = BYTE_QUOTE; + final int len = name.length(); + if (len <= _charBufferLength) { // yes, fits right in + name.getChars(0, len, _charBuffer, 0); + // But as one segment, or multiple? + if (len <= _outputMaxContiguous) { + if ((_outputTail + len) > _outputEnd) { // caller must ensure enough space + _flushBuffer(); + } + _writeStringSegment(_charBuffer, 0, len); + } else { + _writeStringSegments(_charBuffer, 0, len); + } + } else { + _writeStringSegments(name); + } + if (_outputTail >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = BYTE_QUOTE; + } else { // non-standard, omit quotes + _writeStringSegments(name); + } + } + + protected final void _writePPFieldName(SerializableString name, boolean commaBefore) + throws IOException, JsonGenerationException + { + if (commaBefore) { + _cfgPrettyPrinter.writeObjectEntrySeparator(this); + } else { + _cfgPrettyPrinter.beforeObjectEntries(this); + } + + boolean addQuotes = isEnabled(Feature.QUOTE_FIELD_NAMES); // standard + if (addQuotes) { + if (_outputTail >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = BYTE_QUOTE; + } + _writeBytes(name.asQuotedUTF8()); + if (addQuotes) { + if (_outputTail >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = BYTE_QUOTE; + } + } + + /* + /********************************************************** + /* Output method implementations, textual + /********************************************************** + */ + + @Override + public void writeString(String text) + throws IOException, JsonGenerationException + { + _verifyValueWrite("write text value"); + if (text == null) { + _writeNull(); + return; + } + // First: can we make a local copy of chars that make up text? + final int len = text.length(); + if (len > _charBufferLength) { // nope: off-line handling + _writeLongString(text); + return; + } + // yes: good. + text.getChars(0, len, _charBuffer, 0); + // Output: if we can't guarantee it fits in output buffer, off-line as well: + if (len > _outputMaxContiguous) { + _writeLongString(_charBuffer, 0, len); + return; + } + if ((_outputTail + len) >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = BYTE_QUOTE; + _writeStringSegment(_charBuffer, 0, len); // we checked space already above + /* [JACKSON-462] But that method may have had to expand multi-byte Unicode + * chars, so we must check again + */ + if (_outputTail >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = BYTE_QUOTE; + } + + private final void _writeLongString(String text) + throws IOException, JsonGenerationException + { + if (_outputTail >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = BYTE_QUOTE; + _writeStringSegments(text); + if (_outputTail >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = BYTE_QUOTE; + } + + private final void _writeLongString(char[] text, int offset, int len) + throws IOException, JsonGenerationException + { + if (_outputTail >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = BYTE_QUOTE; + _writeStringSegments(_charBuffer, 0, len); + if (_outputTail >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = BYTE_QUOTE; + } + + @Override + public void writeString(char[] text, int offset, int len) + throws IOException, JsonGenerationException + { + _verifyValueWrite("write text value"); + if (_outputTail >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = BYTE_QUOTE; + // One or multiple segments? + if (len <= _outputMaxContiguous) { + if ((_outputTail + len) > _outputEnd) { // caller must ensure enough space + _flushBuffer(); + } + _writeStringSegment(text, offset, len); + } else { + _writeStringSegments(text, offset, len); + } + // And finally, closing quotes + if (_outputTail >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = BYTE_QUOTE; + } + + @Override + public final void writeString(SerializableString text) + throws IOException, JsonGenerationException + { + _verifyValueWrite("write text value"); + if (_outputTail >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = BYTE_QUOTE; + _writeBytes(text.asQuotedUTF8()); + if (_outputTail >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = BYTE_QUOTE; + } + + @Override + public void writeRawUTF8String(byte[] text, int offset, int length) + throws IOException, JsonGenerationException + { + _verifyValueWrite("write text value"); + if (_outputTail >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = BYTE_QUOTE; + _writeBytes(text, offset, length); + if (_outputTail >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = BYTE_QUOTE; + } + + @Override + public void writeUTF8String(byte[] text, int offset, int len) + throws IOException, JsonGenerationException + { + _verifyValueWrite("write text value"); + if (_outputTail >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = BYTE_QUOTE; + // One or multiple segments? + if (len <= _outputMaxContiguous) { + _writeUTF8Segment(text, offset, len); + } else { + _writeUTF8Segments(text, offset, len); + } + if (_outputTail >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = BYTE_QUOTE; + } + + /* + /********************************************************** + /* Output method implementations, unprocessed ("raw") + /********************************************************** + */ + + @Override + public void writeRaw(String text) + throws IOException, JsonGenerationException + { + int start = 0; + int len = text.length(); + while (len > 0) { + char[] buf = _charBuffer; + final int blen = buf.length; + final int len2 = (len < blen) ? len : blen; + text.getChars(start, start+len2, buf, 0); + writeRaw(buf, 0, len2); + start += len2; + len -= len2; + } + } + + @Override + public void writeRaw(String text, int offset, int len) + throws IOException, JsonGenerationException + { + while (len > 0) { + char[] buf = _charBuffer; + final int blen = buf.length; + final int len2 = (len < blen) ? len : blen; + text.getChars(offset, offset+len2, buf, 0); + writeRaw(buf, 0, len2); + offset += len2; + len -= len2; + } + } + + // @TODO: rewrite for speed... + @Override + public final void writeRaw(char[] cbuf, int offset, int len) + throws IOException, JsonGenerationException + { + // First: if we have 3 x charCount spaces, we know it'll fit just fine + { + int len3 = len+len+len; + if ((_outputTail + len3) > _outputEnd) { + // maybe we could flush? + if (_outputEnd < len3) { // wouldn't be enough... + _writeSegmentedRaw(cbuf, offset, len); + return; + } + // yes, flushing brings enough space + _flushBuffer(); + } + } + len += offset; // now marks the end + + // Note: here we know there is enough room, hence no output boundary checks + main_loop: + while (offset < len) { + inner_loop: + while (true) { + int ch = (int) cbuf[offset]; + if (ch > 0x7F) { + break inner_loop; + } + _outputBuffer[_outputTail++] = (byte) ch; + if (++offset >= len) { + break main_loop; + } + } + char ch = cbuf[offset++]; + if (ch < 0x800) { // 2-byte? + _outputBuffer[_outputTail++] = (byte) (0xc0 | (ch >> 6)); + _outputBuffer[_outputTail++] = (byte) (0x80 | (ch & 0x3f)); + } else { + _outputRawMultiByteChar(ch, cbuf, offset, len); + } + } + } + + @Override + public void writeRaw(char ch) + throws IOException, JsonGenerationException + { + if ((_outputTail + 3) >= _outputEnd) { + _flushBuffer(); + } + final byte[] bbuf = _outputBuffer; + if (ch <= 0x7F) { + bbuf[_outputTail++] = (byte) ch; + } else if (ch < 0x800) { // 2-byte? + bbuf[_outputTail++] = (byte) (0xc0 | (ch >> 6)); + bbuf[_outputTail++] = (byte) (0x80 | (ch & 0x3f)); + } else { + _outputRawMultiByteChar(ch, null, 0, 0); + } + } + + /** + * Helper method called when it is possible that output of raw section + * to output may cross buffer boundary + */ + private final void _writeSegmentedRaw(char[] cbuf, int offset, int len) + throws IOException, JsonGenerationException + { + final int end = _outputEnd; + final byte[] bbuf = _outputBuffer; + + main_loop: + while (offset < len) { + inner_loop: + while (true) { + int ch = (int) cbuf[offset]; + if (ch >= 0x80) { + break inner_loop; + } + // !!! TODO: fast(er) writes (roll input, output checks in one) + if (_outputTail >= end) { + _flushBuffer(); + } + bbuf[_outputTail++] = (byte) ch; + if (++offset >= len) { + break main_loop; + } + } + if ((_outputTail + 3) >= _outputEnd) { + _flushBuffer(); + } + char ch = cbuf[offset++]; + if (ch < 0x800) { // 2-byte? + bbuf[_outputTail++] = (byte) (0xc0 | (ch >> 6)); + bbuf[_outputTail++] = (byte) (0x80 | (ch & 0x3f)); + } else { + _outputRawMultiByteChar(ch, cbuf, offset, len); + } + } + } + + /* + /********************************************************** + /* Output method implementations, base64-encoded binary + /********************************************************** + */ + + @Override + public void writeBinary(Base64Variant b64variant, byte[] data, int offset, int len) + throws IOException, JsonGenerationException + { + _verifyValueWrite("write binary value"); + // Starting quotes + if (_outputTail >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = BYTE_QUOTE; + _writeBinary(b64variant, data, offset, offset+len); + // and closing quotes + if (_outputTail >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = BYTE_QUOTE; + } + + /* + /********************************************************** + /* Output method implementations, primitive + /********************************************************** + */ + + @Override + public void writeNumber(int i) + throws IOException, JsonGenerationException + { + _verifyValueWrite("write number"); + // up to 10 digits and possible minus sign + if ((_outputTail + 11) >= _outputEnd) { + _flushBuffer(); + } + if (_cfgNumbersAsStrings) { + _writeQuotedInt(i); + return; + } + _outputTail = NumberOutput.outputInt(i, _outputBuffer, _outputTail); + } + + private final void _writeQuotedInt(int i) throws IOException { + if ((_outputTail + 13) >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = BYTE_QUOTE; + _outputTail = NumberOutput.outputInt(i, _outputBuffer, _outputTail); + _outputBuffer[_outputTail++] = BYTE_QUOTE; + } + + @Override + public void writeNumber(long l) + throws IOException, JsonGenerationException + { + _verifyValueWrite("write number"); + if (_cfgNumbersAsStrings) { + _writeQuotedLong(l); + return; + } + if ((_outputTail + 21) >= _outputEnd) { + // up to 20 digits, minus sign + _flushBuffer(); + } + _outputTail = NumberOutput.outputLong(l, _outputBuffer, _outputTail); + } + + private final void _writeQuotedLong(long l) throws IOException { + if ((_outputTail + 23) >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = BYTE_QUOTE; + _outputTail = NumberOutput.outputLong(l, _outputBuffer, _outputTail); + _outputBuffer[_outputTail++] = BYTE_QUOTE; + } + + @Override + public void writeNumber(BigInteger value) + throws IOException, JsonGenerationException + { + _verifyValueWrite("write number"); + if (value == null) { + _writeNull(); + } else if (_cfgNumbersAsStrings) { + _writeQuotedRaw(value); + } else { + writeRaw(value.toString()); + } + } + + + @Override + public void writeNumber(double d) + throws IOException, JsonGenerationException + { + if (_cfgNumbersAsStrings || + // [JACKSON-139] + (((Double.isNaN(d) || Double.isInfinite(d)) + && isEnabled(Feature.QUOTE_NON_NUMERIC_NUMBERS)))) { + writeString(String.valueOf(d)); + return; + } + // What is the max length for doubles? 40 chars? + _verifyValueWrite("write number"); + writeRaw(String.valueOf(d)); + } + + @Override + public void writeNumber(float f) + throws IOException, JsonGenerationException + { + if (_cfgNumbersAsStrings || + // [JACKSON-139] + (((Float.isNaN(f) || Float.isInfinite(f)) + && isEnabled(Feature.QUOTE_NON_NUMERIC_NUMBERS)))) { + writeString(String.valueOf(f)); + return; + } + // What is the max length for floats? + _verifyValueWrite("write number"); + writeRaw(String.valueOf(f)); + } + + @Override + public void writeNumber(BigDecimal value) + throws IOException, JsonGenerationException + { + // Don't really know max length for big decimal, no point checking + _verifyValueWrite("write number"); + if (value == null) { + _writeNull(); + } else if (_cfgNumbersAsStrings) { + _writeQuotedRaw(value); + } else { + writeRaw(value.toString()); + } + } + + @Override + public void writeNumber(String encodedValue) + throws IOException, JsonGenerationException + { + _verifyValueWrite("write number"); + if (_cfgNumbersAsStrings) { + _writeQuotedRaw(encodedValue); + } else { + writeRaw(encodedValue); + } + } + + private final void _writeQuotedRaw(Object value) throws IOException + { + if (_outputTail >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = BYTE_QUOTE; + writeRaw(value.toString()); + if (_outputTail >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = BYTE_QUOTE; + } + + @Override + public void writeBoolean(boolean state) + throws IOException, JsonGenerationException + { + _verifyValueWrite("write boolean value"); + if ((_outputTail + 5) >= _outputEnd) { + _flushBuffer(); + } + byte[] keyword = state ? TRUE_BYTES : FALSE_BYTES; + int len = keyword.length; + System.arraycopy(keyword, 0, _outputBuffer, _outputTail, len); + _outputTail += len; + } + + @Override + public void writeNull() + throws IOException, JsonGenerationException + { + _verifyValueWrite("write null value"); + _writeNull(); + } + + /* + /********************************************************** + /* Implementations for other methods + /********************************************************** + */ + + @Override + protected final void _verifyValueWrite(String typeMsg) + throws IOException, JsonGenerationException + { + int status = _writeContext.writeValue(); + if (status == JsonWriteContext.STATUS_EXPECT_NAME) { + _reportError("Can not "+typeMsg+", expecting field name"); + } + if (_cfgPrettyPrinter == null) { + byte b; + switch (status) { + case JsonWriteContext.STATUS_OK_AFTER_COMMA: + b = BYTE_COMMA; + break; + case JsonWriteContext.STATUS_OK_AFTER_COLON: + b = BYTE_COLON; + break; + case JsonWriteContext.STATUS_OK_AFTER_SPACE: + b = BYTE_SPACE; + break; + case JsonWriteContext.STATUS_OK_AS_IS: + default: + return; + } + if (_outputTail >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail] = b; + ++_outputTail; + return; + } + // Otherwise, pretty printer knows what to do... + _verifyPrettyValueWrite(typeMsg, status); + } + + protected final void _verifyPrettyValueWrite(String typeMsg, int status) + throws IOException, JsonGenerationException + { + // If we have a pretty printer, it knows what to do: + switch (status) { + case JsonWriteContext.STATUS_OK_AFTER_COMMA: // array + _cfgPrettyPrinter.writeArrayValueSeparator(this); + break; + case JsonWriteContext.STATUS_OK_AFTER_COLON: + _cfgPrettyPrinter.writeObjectFieldValueSeparator(this); + break; + case JsonWriteContext.STATUS_OK_AFTER_SPACE: + _cfgPrettyPrinter.writeRootValueSeparator(this); + break; + case JsonWriteContext.STATUS_OK_AS_IS: + // First entry, but of which context? + if (_writeContext.inArray()) { + _cfgPrettyPrinter.beforeArrayValues(this); + } else if (_writeContext.inObject()) { + _cfgPrettyPrinter.beforeObjectEntries(this); + } + break; + default: + _cantHappen(); + break; + } + } + + /* + /********************************************************** + /* Low-level output handling + /********************************************************** + */ + + @Override + public final void flush() + throws IOException + { + _flushBuffer(); + if (_outputStream != null) { + if (isEnabled(Feature.FLUSH_PASSED_TO_STREAM)) { + _outputStream.flush(); + } + } + } + + @Override + public void close() + throws IOException + { + super.close(); + + /* 05-Dec-2008, tatu: To add [JACKSON-27], need to close open + * scopes. + */ + // First: let's see that we still have buffers... + if (_outputBuffer != null + && isEnabled(Feature.AUTO_CLOSE_JSON_CONTENT)) { + while (true) { + JsonStreamContext ctxt = getOutputContext(); + if (ctxt.inArray()) { + writeEndArray(); + } else if (ctxt.inObject()) { + writeEndObject(); + } else { + break; + } + } + } + _flushBuffer(); + + /* 25-Nov-2008, tatus: As per [JACKSON-16] we are not to call close() + * on the underlying Reader, unless we "own" it, or auto-closing + * feature is enabled. + * One downside: when using UTF8Writer, underlying buffer(s) + * may not be properly recycled if we don't close the writer. + */ + if (_outputStream != null) { + if (_ioContext.isResourceManaged() || isEnabled(Feature.AUTO_CLOSE_TARGET)) { + _outputStream.close(); + } else if (isEnabled(Feature.FLUSH_PASSED_TO_STREAM)) { + // If we can't close it, we should at least flush + _outputStream.flush(); + } + } + // Internal buffer(s) generator has can now be released as well + _releaseBuffers(); + } + + @Override + protected void _releaseBuffers() + { + byte[] buf = _outputBuffer; + if (buf != null && _bufferRecyclable) { + _outputBuffer = null; + _ioContext.releaseWriteEncodingBuffer(buf); + } + char[] cbuf = _charBuffer; + if (cbuf != null) { + _charBuffer = null; + _ioContext.releaseConcatBuffer(cbuf); + } + } + + /* + /********************************************************** + /* Internal methods, low-level writing, raw bytes + /********************************************************** + */ + + private final void _writeBytes(byte[] bytes) throws IOException + { + final int len = bytes.length; + if ((_outputTail + len) > _outputEnd) { + _flushBuffer(); + // still not enough? + if (len > MAX_BYTES_TO_BUFFER) { + _outputStream.write(bytes, 0, len); + return; + } + } + System.arraycopy(bytes, 0, _outputBuffer, _outputTail, len); + _outputTail += len; + } + + private final void _writeBytes(byte[] bytes, int offset, int len) throws IOException + { + if ((_outputTail + len) > _outputEnd) { + _flushBuffer(); + // still not enough? + if (len > MAX_BYTES_TO_BUFFER) { + _outputStream.write(bytes, offset, len); + return; + } + } + System.arraycopy(bytes, offset, _outputBuffer, _outputTail, len); + _outputTail += len; + } + + /* + /********************************************************** + /* Internal methods, mid-level writing, String segments + /********************************************************** + */ + + /** + * Method called when String to write is long enough not to fit + * completely in temporary copy buffer. If so, we will actually + * copy it in small enough chunks so it can be directly fed + * to single-segment writes (instead of maximum slices that + * would fit in copy buffer) + */ + private final void _writeStringSegments(String text) + throws IOException, JsonGenerationException + { + int left = text.length(); + int offset = 0; + final char[] cbuf = _charBuffer; + + while (left > 0) { + int len = Math.min(_outputMaxContiguous, left); + text.getChars(offset, offset+len, cbuf, 0); + if ((_outputTail + len) > _outputEnd) { // caller must ensure enough space + _flushBuffer(); + } + _writeStringSegment(cbuf, 0, len); + offset += len; + left -= len; + } + } + + /** + * Method called when character sequence to write is long enough that + * its maximum encoded and escaped form is not guaranteed to fit in + * the output buffer. If so, we will need to choose smaller output + * chunks to write at a time. + */ + private final void _writeStringSegments(char[] cbuf, int offset, int totalLen) + throws IOException, JsonGenerationException + { + do { + int len = Math.min(_outputMaxContiguous, totalLen); + if ((_outputTail + len) > _outputEnd) { // caller must ensure enough space + _flushBuffer(); + } + _writeStringSegment(cbuf, offset, len); + offset += len; + totalLen -= len; + } while (totalLen > 0); + } + + /* + /********************************************************** + /* Internal methods, low-level writing, text segments + /********************************************************** + */ + + /** + * This method called when the string content is already in + * a char buffer, and its maximum total encoded and escaped length + * can not exceed size of the output buffer. + * Caller must ensure that there is enough space in output buffer, + * assuming case of all non-escaped ASCII characters, as well as + * potentially enough space for other cases (but not necessarily flushed) + */ + private final void _writeStringSegment(char[] cbuf, int offset, int len) + throws IOException, JsonGenerationException + { + // note: caller MUST ensure (via flushing) there's room for ASCII only + + // Fast+tight loop for ASCII-only, no-escaping-needed output + len += offset; // becomes end marker, then + + int outputPtr = _outputTail; + final byte[] outputBuffer = _outputBuffer; + final int[] escCodes = _outputEscapes; + + while (offset < len) { + int ch = cbuf[offset]; + // note: here we know that (ch > 0x7F) will cover case of escaping non-ASCII too: + if (ch > 0x7F || escCodes[ch] != 0) { + break; + } + outputBuffer[outputPtr++] = (byte) ch; + ++offset; + } + _outputTail = outputPtr; + if (offset < len) { + // [JACKSON-106] + if (_characterEscapes != null) { + _writeCustomStringSegment2(cbuf, offset, len); + // [JACKSON-102] + } else if (_maximumNonEscapedChar == 0) { + _writeStringSegment2(cbuf, offset, len); + } else { + _writeStringSegmentASCII2(cbuf, offset, len); + } + + } + } + + /** + * Secondary method called when content contains characters to escape, + * and/or multi-byte UTF-8 characters. + */ + private final void _writeStringSegment2(final char[] cbuf, int offset, final int end) + throws IOException, JsonGenerationException + { + // Ok: caller guarantees buffer can have room; but that may require flushing: + if ((_outputTail + 6 * (end - offset)) > _outputEnd) { + _flushBuffer(); + } + + int outputPtr = _outputTail; + + final byte[] outputBuffer = _outputBuffer; + final int[] escCodes = _outputEscapes; + + while (offset < end) { + int ch = cbuf[offset++]; + if (ch <= 0x7F) { + if (escCodes[ch] == 0) { + outputBuffer[outputPtr++] = (byte) ch; + continue; + } + int escape = escCodes[ch]; + if (escape > 0) { // 2-char escape, fine + outputBuffer[outputPtr++] = BYTE_BACKSLASH; + outputBuffer[outputPtr++] = (byte) escape; + } else { + // ctrl-char, 6-byte escape... + outputPtr = _writeGenericEscape(ch, outputPtr); + } + continue; + } + if (ch <= 0x7FF) { // fine, just needs 2 byte output + outputBuffer[outputPtr++] = (byte) (0xc0 | (ch >> 6)); + outputBuffer[outputPtr++] = (byte) (0x80 | (ch & 0x3f)); + } else { + outputPtr = _outputMultiByteChar(ch, outputPtr); + } + } + _outputTail = outputPtr; + } + + /* + /********************************************************** + /* Internal methods, low-level writing, text segment + /* with additional escaping (ASCII or such) + /* (since 1.8; see [JACKSON-102]) + /********************************************************** + */ + + /** + * Same as <code>_writeStringSegment2(char[], ...)</code., but with + * additional escaping for high-range code points + * + * @since 1.8 + */ + private final void _writeStringSegmentASCII2(final char[] cbuf, int offset, final int end) + throws IOException, JsonGenerationException + { + // Ok: caller guarantees buffer can have room; but that may require flushing: + if ((_outputTail + 6 * (end - offset)) > _outputEnd) { + _flushBuffer(); + } + + int outputPtr = _outputTail; + + final byte[] outputBuffer = _outputBuffer; + final int[] escCodes = _outputEscapes; + final int maxUnescaped = _maximumNonEscapedChar; + + while (offset < end) { + int ch = cbuf[offset++]; + if (ch <= 0x7F) { + if (escCodes[ch] == 0) { + outputBuffer[outputPtr++] = (byte) ch; + continue; + } + int escape = escCodes[ch]; + if (escape > 0) { // 2-char escape, fine + outputBuffer[outputPtr++] = BYTE_BACKSLASH; + outputBuffer[outputPtr++] = (byte) escape; + } else { + // ctrl-char, 6-byte escape... + outputPtr = _writeGenericEscape(ch, outputPtr); + } + continue; + } + if (ch > maxUnescaped) { // [JACKSON-102] Allow forced escaping if non-ASCII (etc) chars: + outputPtr = _writeGenericEscape(ch, outputPtr); + continue; + } + if (ch <= 0x7FF) { // fine, just needs 2 byte output + outputBuffer[outputPtr++] = (byte) (0xc0 | (ch >> 6)); + outputBuffer[outputPtr++] = (byte) (0x80 | (ch & 0x3f)); + } else { + outputPtr = _outputMultiByteChar(ch, outputPtr); + } + } + _outputTail = outputPtr; + } + + /* + /********************************************************** + /* Internal methods, low-level writing, text segment + /* with fully custom escaping (and possibly escaping of non-ASCII + /********************************************************** + */ + + /** + * Same as <code>_writeStringSegmentASCII2(char[], ...)</code., but with + * additional checking for completely custom escapes + * + * @since 1.8 + */ + private final void _writeCustomStringSegment2(final char[] cbuf, int offset, final int end) + throws IOException, JsonGenerationException + { + // Ok: caller guarantees buffer can have room; but that may require flushing: + if ((_outputTail + 6 * (end - offset)) > _outputEnd) { + _flushBuffer(); + } + int outputPtr = _outputTail; + + final byte[] outputBuffer = _outputBuffer; + final int[] escCodes = _outputEscapes; + // may or may not have this limit + final int maxUnescaped = (_maximumNonEscapedChar <= 0) ? 0xFFFF : _maximumNonEscapedChar; + final CharacterEscapes customEscapes = _characterEscapes; // non-null + + while (offset < end) { + int ch = cbuf[offset++]; + if (ch <= 0x7F) { + if (escCodes[ch] == 0) { + outputBuffer[outputPtr++] = (byte) ch; + continue; + } + int escape = escCodes[ch]; + if (escape > 0) { // 2-char escape, fine + outputBuffer[outputPtr++] = BYTE_BACKSLASH; + outputBuffer[outputPtr++] = (byte) escape; + } else if (escape == CharacterEscapes.ESCAPE_CUSTOM) { + SerializableString esc = customEscapes.getEscapeSequence(ch); + if (esc == null) { + throw new JsonGenerationException("Invalid custom escape definitions; custom escape not found for character code 0x" + +Integer.toHexString(ch)+", although was supposed to have one"); + } + outputPtr = _writeCustomEscape(outputBuffer, outputPtr, esc, end-offset); + } else { + // ctrl-char, 6-byte escape... + outputPtr = _writeGenericEscape(ch, outputPtr); + } + continue; + } + if (ch > maxUnescaped) { // [JACKSON-102] Allow forced escaping if non-ASCII (etc) chars: + outputPtr = _writeGenericEscape(ch, outputPtr); + continue; + } + SerializableString esc = customEscapes.getEscapeSequence(ch); + if (esc != null) { + outputPtr = _writeCustomEscape(outputBuffer, outputPtr, esc, end-offset); + continue; + } + if (ch <= 0x7FF) { // fine, just needs 2 byte output + outputBuffer[outputPtr++] = (byte) (0xc0 | (ch >> 6)); + outputBuffer[outputPtr++] = (byte) (0x80 | (ch & 0x3f)); + } else { + outputPtr = _outputMultiByteChar(ch, outputPtr); + } + } + _outputTail = outputPtr; + } + + private int _writeCustomEscape(byte[] outputBuffer, int outputPtr, SerializableString esc, int remainingChars) + throws IOException, JsonGenerationException + { + byte[] raw = esc.asUnquotedUTF8(); // must be escaped at this point, shouldn't double-quote + int len = raw.length; + if (len > 6) { // may violate constraints we have, do offline + return _handleLongCustomEscape(outputBuffer, outputPtr, _outputEnd, raw, remainingChars); + } + // otherwise will fit without issues, so: + System.arraycopy(raw, 0, outputBuffer, outputPtr, len); + return (outputPtr + len); + } + + private int _handleLongCustomEscape(byte[] outputBuffer, int outputPtr, int outputEnd, byte[] raw, + int remainingChars) + throws IOException, JsonGenerationException + { + int len = raw.length; + if ((outputPtr + len) > outputEnd) { + _outputTail = outputPtr; + _flushBuffer(); + outputPtr = _outputTail; + if (len > outputBuffer.length) { // very unlikely, but possible... + _outputStream.write(raw, 0, len); + return outputPtr; + } + System.arraycopy(raw, 0, outputBuffer, outputPtr, len); + outputPtr += len; + } + // but is the invariant still obeyed? If not, flush once more + if ((outputPtr + 6 * remainingChars) > outputEnd) { + _flushBuffer(); + return _outputTail; + } + return outputPtr; + } + + /* + /********************************************************** + /* Internal methods, low-level writing, "raw UTF-8" segments + /********************************************************** + */ + + /** + * Method called when UTF-8 encoded (but NOT yet escaped!) content is not guaranteed + * to fit in the output buffer after escaping; as such, we just need to + * chunk writes. + */ + private final void _writeUTF8Segments(byte[] utf8, int offset, int totalLen) + throws IOException, JsonGenerationException + { + do { + int len = Math.min(_outputMaxContiguous, totalLen); + _writeUTF8Segment(utf8, offset, len); + offset += len; + totalLen -= len; + } while (totalLen > 0); + } + + private final void _writeUTF8Segment(byte[] utf8, final int offset, final int len) + throws IOException, JsonGenerationException + { + // fast loop to see if escaping is needed; don't copy, just look + final int[] escCodes = _outputEscapes; + + for (int ptr = offset, end = offset + len; ptr < end; ) { + // 28-Feb-2011, tatu: escape codes just cover 7-bit range, so: + int ch = utf8[ptr++]; + if ((ch >= 0) && escCodes[ch] != 0) { + _writeUTF8Segment2(utf8, offset, len); + return; + } + } + + // yes, fine, just copy the sucker + if ((_outputTail + len) > _outputEnd) { // enough room or need to flush? + _flushBuffer(); // but yes once we flush (caller guarantees length restriction) + } + System.arraycopy(utf8, offset, _outputBuffer, _outputTail, len); + _outputTail += len; + } + + private final void _writeUTF8Segment2(final byte[] utf8, int offset, int len) + throws IOException, JsonGenerationException + { + int outputPtr = _outputTail; + + // Ok: caller guarantees buffer can have room; but that may require flushing: + if ((outputPtr + (len * 6)) > _outputEnd) { + _flushBuffer(); + outputPtr = _outputTail; + } + + final byte[] outputBuffer = _outputBuffer; + final int[] escCodes = _outputEscapes; + len += offset; // so 'len' becomes 'end' + + while (offset < len) { + byte b = utf8[offset++]; + int ch = b; + if (ch < 0 || escCodes[ch] == 0) { + outputBuffer[outputPtr++] = b; + continue; + } + int escape = escCodes[ch]; + if (escape > 0) { // 2-char escape, fine + outputBuffer[outputPtr++] = BYTE_BACKSLASH; + outputBuffer[outputPtr++] = (byte) escape; + } else { + // ctrl-char, 6-byte escape... + outputPtr = _writeGenericEscape(ch, outputPtr); + } + } + _outputTail = outputPtr; + } + + /* + /********************************************************** + /* Internal methods, low-level writing, base64 encoded + /********************************************************** + */ + + protected void _writeBinary(Base64Variant b64variant, byte[] input, int inputPtr, final int inputEnd) + throws IOException, JsonGenerationException + { + // Encoding is by chunks of 3 input, 4 output chars, so: + int safeInputEnd = inputEnd - 3; + // Let's also reserve room for possible (and quoted) lf char each round + int safeOutputEnd = _outputEnd - 6; + int chunksBeforeLF = b64variant.getMaxLineLength() >> 2; + + // Ok, first we loop through all full triplets of data: + while (inputPtr <= safeInputEnd) { + if (_outputTail > safeOutputEnd) { // need to flush + _flushBuffer(); + } + // First, mash 3 bytes into lsb of 32-bit int + int b24 = ((int) input[inputPtr++]) << 8; + b24 |= ((int) input[inputPtr++]) & 0xFF; + b24 = (b24 << 8) | (((int) input[inputPtr++]) & 0xFF); + _outputTail = b64variant.encodeBase64Chunk(b24, _outputBuffer, _outputTail); + if (--chunksBeforeLF <= 0) { + // note: must quote in JSON value + _outputBuffer[_outputTail++] = '\\'; + _outputBuffer[_outputTail++] = 'n'; + chunksBeforeLF = b64variant.getMaxLineLength() >> 2; + } + } + + // And then we may have 1 or 2 leftover bytes to encode + int inputLeft = inputEnd - inputPtr; // 0, 1 or 2 + if (inputLeft > 0) { // yes, but do we have room for output? + if (_outputTail > safeOutputEnd) { // don't really need 6 bytes but... + _flushBuffer(); + } + int b24 = ((int) input[inputPtr++]) << 16; + if (inputLeft == 2) { + b24 |= (((int) input[inputPtr++]) & 0xFF) << 8; + } + _outputTail = b64variant.encodeBase64Partial(b24, inputLeft, _outputBuffer, _outputTail); + } + } + + /* + /********************************************************** + /* Internal methods, character escapes/encoding + /********************************************************** + */ + + /** + * Method called to output a character that is beyond range of + * 1- and 2-byte UTF-8 encodings, when outputting "raw" + * text (meaning it is not to be escaped or quoted) + */ + private final int _outputRawMultiByteChar(int ch, char[] cbuf, int inputOffset, int inputLen) + throws IOException + { + // Let's handle surrogates gracefully (as 4 byte output): + if (ch >= SURR1_FIRST) { + if (ch <= SURR2_LAST) { // yes, outside of BMP + // Do we have second part? + if (inputOffset >= inputLen) { // nope... have to note down + _reportError("Split surrogate on writeRaw() input (last character)"); + } + _outputSurrogates(ch, cbuf[inputOffset]); + return (inputOffset+1); + } + } + final byte[] bbuf = _outputBuffer; + bbuf[_outputTail++] = (byte) (0xe0 | (ch >> 12)); + bbuf[_outputTail++] = (byte) (0x80 | ((ch >> 6) & 0x3f)); + bbuf[_outputTail++] = (byte) (0x80 | (ch & 0x3f)); + return inputOffset; + } + + protected final void _outputSurrogates(int surr1, int surr2) + throws IOException + { + int c = _decodeSurrogate(surr1, surr2); + if ((_outputTail + 4) > _outputEnd) { + _flushBuffer(); + } + final byte[] bbuf = _outputBuffer; + bbuf[_outputTail++] = (byte) (0xf0 | (c >> 18)); + bbuf[_outputTail++] = (byte) (0x80 | ((c >> 12) & 0x3f)); + bbuf[_outputTail++] = (byte) (0x80 | ((c >> 6) & 0x3f)); + bbuf[_outputTail++] = (byte) (0x80 | (c & 0x3f)); + } + + /** + * + * @param ch + * @param outputPtr Position within output buffer to append multi-byte in + * + * @return New output position after appending + * + * @throws IOException + */ + private final int _outputMultiByteChar(int ch, int outputPtr) + throws IOException + { + byte[] bbuf = _outputBuffer; + if (ch >= SURR1_FIRST && ch <= SURR2_LAST) { // yes, outside of BMP; add an escape + bbuf[outputPtr++] = BYTE_BACKSLASH; + bbuf[outputPtr++] = BYTE_u; + + bbuf[outputPtr++] = HEX_CHARS[(ch >> 12) & 0xF]; + bbuf[outputPtr++] = HEX_CHARS[(ch >> 8) & 0xF]; + bbuf[outputPtr++] = HEX_CHARS[(ch >> 4) & 0xF]; + bbuf[outputPtr++] = HEX_CHARS[ch & 0xF]; + } else { + bbuf[outputPtr++] = (byte) (0xe0 | (ch >> 12)); + bbuf[outputPtr++] = (byte) (0x80 | ((ch >> 6) & 0x3f)); + bbuf[outputPtr++] = (byte) (0x80 | (ch & 0x3f)); + } + return outputPtr; + } + + protected final int _decodeSurrogate(int surr1, int surr2) throws IOException + { + // First is known to be valid, but how about the other? + if (surr2 < SURR2_FIRST || surr2 > SURR2_LAST) { + String msg = "Incomplete surrogate pair: first char 0x"+Integer.toHexString(surr1)+", second 0x"+Integer.toHexString(surr2); + _reportError(msg); + } + int c = 0x10000 + ((surr1 - SURR1_FIRST) << 10) + (surr2 - SURR2_FIRST); + return c; + } + + private final void _writeNull() throws IOException + { + if ((_outputTail + 4) >= _outputEnd) { + _flushBuffer(); + } + System.arraycopy(NULL_BYTES, 0, _outputBuffer, _outputTail, 4); + _outputTail += 4; + } + + /** + * Method called to write a generic Unicode escape for given character. + * + * @param charToEscape Character to escape using escape sequence (\\uXXXX) + */ + private int _writeGenericEscape(int charToEscape, int outputPtr) + throws IOException + { + final byte[] bbuf = _outputBuffer; + bbuf[outputPtr++] = BYTE_BACKSLASH; + bbuf[outputPtr++] = BYTE_u; + if (charToEscape > 0xFF) { + int hi = (charToEscape >> 8) & 0xFF; + bbuf[outputPtr++] = HEX_CHARS[hi >> 4]; + bbuf[outputPtr++] = HEX_CHARS[hi & 0xF]; + charToEscape &= 0xFF; + } else { + bbuf[outputPtr++] = BYTE_0; + bbuf[outputPtr++] = BYTE_0; + } + // We know it's a control char, so only the last 2 chars are non-0 + bbuf[outputPtr++] = HEX_CHARS[charToEscape >> 4]; + bbuf[outputPtr++] = HEX_CHARS[charToEscape & 0xF]; + return outputPtr; + } + + protected final void _flushBuffer() throws IOException + { + int len = _outputTail; + if (len > 0) { + _outputTail = 0; + _outputStream.write(_outputBuffer, 0, len); + } + } +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/impl/Utf8StreamParser.java b/1.9.10/src/java/org/codehaus/jackson/impl/Utf8StreamParser.java new file mode 100644 index 0000000..981001c --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/impl/Utf8StreamParser.java
@@ -0,0 +1,2969 @@ +package org.codehaus.jackson.impl; + +import java.io.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.io.IOContext; +import org.codehaus.jackson.sym.*; +import org.codehaus.jackson.util.*; + +/** + * This is a concrete implementation of {@link JsonParser}, which is + * based on a {@link java.io.InputStream} as the input source. + */ +public final class Utf8StreamParser + extends JsonParserBase +{ + final static byte BYTE_LF = (byte) '\n'; + + private final static int[] sInputCodesUtf8 = CharTypes.getInputCodeUtf8(); + + /** + * Latin1 encoding is not supported, but we do use 8-bit subset for + * pre-processing task, to simplify first pass, keep it fast. + */ + private final static int[] sInputCodesLatin1 = CharTypes.getInputCodeLatin1(); + + /* + /********************************************************** + /* Configuration + /********************************************************** + */ + + /** + * Codec used for data binding when (if) requested; typically full + * <code>ObjectMapper</code>, but that abstract is not part of core + * package. + */ + protected ObjectCodec _objectCodec; + + /** + * Symbol table that contains field names encountered so far + */ + final protected BytesToNameCanonicalizer _symbols; + + /* + /********************************************************** + /* Parsing state + /********************************************************** + */ + + /** + * Temporary buffer used for name parsing. + */ + protected int[] _quadBuffer = new int[16]; + + /** + * Flag that indicates that the current token has not yet + * been fully processed, and needs to be finished for + * some access (or skipped to obtain the next token) + */ + protected boolean _tokenIncomplete = false; + + /** + * Temporary storage for partially parsed name bytes. + */ + private int _quad1; + + /* + /********************************************************** + /* Input buffering (from former 'StreamBasedParserBase') + /********************************************************** + */ + + protected InputStream _inputStream; + + /* + /********************************************************** + /* Current input data + /********************************************************** + */ + + /** + * Current buffer from which data is read; generally data is read into + * buffer from input source, but in some cases pre-loaded buffer + * is handed to the parser. + */ + protected byte[] _inputBuffer; + + /** + * Flag that indicates whether the input buffer is recycable (and + * needs to be returned to recycler once we are done) or not. + *<p> + * If it is not, it also means that parser can NOT modify underlying + * buffer. + */ + protected boolean _bufferRecyclable; + + /* + /********************************************************** + /* Life-cycle + /********************************************************** + */ + + public Utf8StreamParser(IOContext ctxt, int features, InputStream in, + ObjectCodec codec, BytesToNameCanonicalizer sym, + byte[] inputBuffer, int start, int end, + boolean bufferRecyclable) + { + super(ctxt, features); + _inputStream = in; + _objectCodec = codec; + _symbols = sym; + _inputBuffer = inputBuffer; + _inputPtr = start; + _inputEnd = end; + _bufferRecyclable = bufferRecyclable; + // 12-Mar-2010, tatus: Sanity check, related to [JACKSON-259]: + if (!JsonParser.Feature.CANONICALIZE_FIELD_NAMES.enabledIn(features)) { + // should never construct non-canonical UTF-8/byte parser (instead, use Reader) + _throwInternal(); + } + } + + @Override + public ObjectCodec getCodec() { + return _objectCodec; + } + + @Override + public void setCodec(ObjectCodec c) { + _objectCodec = c; + } + + /* + /********************************************************** + /* Former StreamBasedParserBase methods + /********************************************************** + */ + + @Override + public int releaseBuffered(OutputStream out) throws IOException + { + int count = _inputEnd - _inputPtr; + if (count < 1) { + return 0; + } + // let's just advance ptr to end + int origPtr = _inputPtr; + out.write(_inputBuffer, origPtr, count); + return count; + } + + @Override + public Object getInputSource() { + return _inputStream; + } + + /* + /********************************************************** + /* Low-level reading, other + /********************************************************** + */ + + @Override + protected final boolean loadMore() + throws IOException + { + _currInputProcessed += _inputEnd; + _currInputRowStart -= _inputEnd; + + if (_inputStream != null) { + int count = _inputStream.read(_inputBuffer, 0, _inputBuffer.length); + if (count > 0) { + _inputPtr = 0; + _inputEnd = count; + return true; + } + // End of input + _closeInput(); + // Should never return 0, so let's fail + if (count == 0) { + throw new IOException("InputStream.read() returned 0 characters when trying to read "+_inputBuffer.length+" bytes"); + } + } + return false; + } + + /** + * Helper method that will try to load at least specified number bytes in + * input buffer, possible moving existing data around if necessary + * + * @since 1.6 + */ + protected final boolean _loadToHaveAtLeast(int minAvailable) + throws IOException + { + // No input stream, no leading (either we are closed, or have non-stream input source) + if (_inputStream == null) { + return false; + } + // Need to move remaining data in front? + int amount = _inputEnd - _inputPtr; + if (amount > 0 && _inputPtr > 0) { + _currInputProcessed += _inputPtr; + _currInputRowStart -= _inputPtr; + System.arraycopy(_inputBuffer, _inputPtr, _inputBuffer, 0, amount); + _inputEnd = amount; + } else { + _inputEnd = 0; + } + _inputPtr = 0; + while (_inputEnd < minAvailable) { + int count = _inputStream.read(_inputBuffer, _inputEnd, _inputBuffer.length - _inputEnd); + if (count < 1) { + // End of input + _closeInput(); + // Should never return 0, so let's fail + if (count == 0) { + throw new IOException("InputStream.read() returned 0 characters when trying to read "+amount+" bytes"); + } + return false; + } + _inputEnd += count; + } + return true; + } + + @Override + protected void _closeInput() throws IOException + { + /* 25-Nov-2008, tatus: As per [JACKSON-16] we are not to call close() + * on the underlying InputStream, unless we "own" it, or auto-closing + * feature is enabled. + */ + if (_inputStream != null) { + if (_ioContext.isResourceManaged() || isEnabled(Feature.AUTO_CLOSE_SOURCE)) { + _inputStream.close(); + } + _inputStream = null; + } + } + + /** + * Method called to release internal buffers owned by the base + * reader. This may be called along with {@link #_closeInput} (for + * example, when explicitly closing this reader instance), or + * separately (if need be). + */ + @Override + protected void _releaseBuffers() throws IOException + { + super._releaseBuffers(); + if (_bufferRecyclable) { + byte[] buf = _inputBuffer; + if (buf != null) { + _inputBuffer = null; + _ioContext.releaseReadIOBuffer(buf); + } + } + } + + /* + /********************************************************** + /* Public API, data access + /********************************************************** + */ + + @Override + public String getText() + throws IOException, JsonParseException + { + JsonToken t = _currToken; + if (t == JsonToken.VALUE_STRING) { + if (_tokenIncomplete) { + _tokenIncomplete = false; + _finishString(); // only strings can be incomplete + } + return _textBuffer.contentsAsString(); + } + return _getText2(t); + } + + protected final String _getText2(JsonToken t) + { + if (t == null) { + return null; + } + switch (t) { + case FIELD_NAME: + return _parsingContext.getCurrentName(); + + case VALUE_STRING: + // fall through + case VALUE_NUMBER_INT: + case VALUE_NUMBER_FLOAT: + return _textBuffer.contentsAsString(); + } + return t.asString(); + } + + @Override + public char[] getTextCharacters() + throws IOException, JsonParseException + { + if (_currToken != null) { // null only before/after document + switch (_currToken) { + + case FIELD_NAME: + if (!_nameCopied) { + String name = _parsingContext.getCurrentName(); + int nameLen = name.length(); + if (_nameCopyBuffer == null) { + _nameCopyBuffer = _ioContext.allocNameCopyBuffer(nameLen); + } else if (_nameCopyBuffer.length < nameLen) { + _nameCopyBuffer = new char[nameLen]; + } + name.getChars(0, nameLen, _nameCopyBuffer, 0); + _nameCopied = true; + } + return _nameCopyBuffer; + + case VALUE_STRING: + if (_tokenIncomplete) { + _tokenIncomplete = false; + _finishString(); // only strings can be incomplete + } + // fall through + case VALUE_NUMBER_INT: + case VALUE_NUMBER_FLOAT: + return _textBuffer.getTextBuffer(); + + default: + return _currToken.asCharArray(); + } + } + return null; + } + + @Override + public int getTextLength() + throws IOException, JsonParseException + { + if (_currToken != null) { // null only before/after document + switch (_currToken) { + + case FIELD_NAME: + return _parsingContext.getCurrentName().length(); + case VALUE_STRING: + if (_tokenIncomplete) { + _tokenIncomplete = false; + _finishString(); // only strings can be incomplete + } + // fall through + case VALUE_NUMBER_INT: + case VALUE_NUMBER_FLOAT: + return _textBuffer.size(); + + default: + return _currToken.asCharArray().length; + } + } + return 0; + } + + @Override + public int getTextOffset() throws IOException, JsonParseException + { + // Most have offset of 0, only some may have other values: + if (_currToken != null) { + switch (_currToken) { + case FIELD_NAME: + return 0; + case VALUE_STRING: + if (_tokenIncomplete) { + _tokenIncomplete = false; + _finishString(); // only strings can be incomplete + } + // fall through + case VALUE_NUMBER_INT: + case VALUE_NUMBER_FLOAT: + return _textBuffer.getTextOffset(); + } + } + return 0; + } + + @Override + public byte[] getBinaryValue(Base64Variant b64variant) + throws IOException, JsonParseException + { + if (_currToken != JsonToken.VALUE_STRING && + (_currToken != JsonToken.VALUE_EMBEDDED_OBJECT || _binaryValue == null)) { + _reportError("Current token ("+_currToken+") not VALUE_STRING or VALUE_EMBEDDED_OBJECT, can not access as binary"); + } + /* To ensure that we won't see inconsistent data, better clear up + * state... + */ + if (_tokenIncomplete) { + try { + _binaryValue = _decodeBase64(b64variant); + } catch (IllegalArgumentException iae) { + throw _constructError("Failed to decode VALUE_STRING as base64 ("+b64variant+"): "+iae.getMessage()); + } + /* let's clear incomplete only now; allows for accessing other + * textual content in error cases + */ + _tokenIncomplete = false; + } else { // may actually require conversion... + if (_binaryValue == null) { + ByteArrayBuilder builder = _getByteArrayBuilder(); + _decodeBase64(getText(), builder, b64variant); + _binaryValue = builder.toByteArray(); + } + } + return _binaryValue; + } + + /* + /********************************************************** + /* Public API, traversal, basic + /********************************************************** + */ + + /** + * @return Next token from the stream, if any found, or null + * to indicate end-of-input + */ + @Override + public JsonToken nextToken() + throws IOException, JsonParseException + { + _numTypesValid = NR_UNKNOWN; + /* First: field names are special -- we will always tokenize + * (part of) value along with field name to simplify + * state handling. If so, can and need to use secondary token: + */ + if (_currToken == JsonToken.FIELD_NAME) { + return _nextAfterName(); + } + if (_tokenIncomplete) { + _skipString(); // only strings can be partial + } + + int i = _skipWSOrEnd(); + if (i < 0) { // end-of-input + /* 19-Feb-2009, tatu: Should actually close/release things + * like input source, symbol table and recyclable buffers now. + */ + close(); + return (_currToken = null); + } + + /* First, need to ensure we know the starting location of token + * after skipping leading white space + */ + _tokenInputTotal = _currInputProcessed + _inputPtr - 1; + _tokenInputRow = _currInputRow; + _tokenInputCol = _inputPtr - _currInputRowStart - 1; + + // finally: clear any data retained so far + _binaryValue = null; + + // Closing scope? + if (i == INT_RBRACKET) { + if (!_parsingContext.inArray()) { + _reportMismatchedEndMarker(i, '}'); + } + _parsingContext = _parsingContext.getParent(); + return (_currToken = JsonToken.END_ARRAY); + } + if (i == INT_RCURLY) { + if (!_parsingContext.inObject()) { + _reportMismatchedEndMarker(i, ']'); + } + _parsingContext = _parsingContext.getParent(); + return (_currToken = JsonToken.END_OBJECT); + } + + // Nope: do we then expect a comma? + if (_parsingContext.expectComma()) { + if (i != INT_COMMA) { + _reportUnexpectedChar(i, "was expecting comma to separate "+_parsingContext.getTypeDesc()+" entries"); + } + i = _skipWS(); + } + + /* And should we now have a name? Always true for + * Object contexts, since the intermediate 'expect-value' + * state is never retained. + */ + if (!_parsingContext.inObject()) { + return _nextTokenNotInObject(i); + } + // So first parse the field name itself: + Name n = _parseFieldName(i); + _parsingContext.setCurrentName(n.getName()); + _currToken = JsonToken.FIELD_NAME; + i = _skipWS(); + if (i != INT_COLON) { + _reportUnexpectedChar(i, "was expecting a colon to separate field name and value"); + } + i = _skipWS(); + + // Ok: we must have a value... what is it? Strings are very common, check first: + if (i == INT_QUOTE) { + _tokenIncomplete = true; + _nextToken = JsonToken.VALUE_STRING; + return _currToken; + } + JsonToken t; + + switch (i) { + case INT_LBRACKET: + t = JsonToken.START_ARRAY; + break; + case INT_LCURLY: + t = JsonToken.START_OBJECT; + break; + case INT_RBRACKET: + case INT_RCURLY: + // Error: neither is valid at this point; valid closers have + // been handled earlier + _reportUnexpectedChar(i, "expected a value"); + case INT_t: + _matchToken("true", 1); + t = JsonToken.VALUE_TRUE; + break; + case INT_f: + _matchToken("false", 1); + t = JsonToken.VALUE_FALSE; + break; + case INT_n: + _matchToken("null", 1); + t = JsonToken.VALUE_NULL; + break; + + case INT_MINUS: + /* Should we have separate handling for plus? Although + * it is not allowed per se, it may be erroneously used, + * and could be indicate by a more specific error message. + */ + case INT_0: + case INT_1: + case INT_2: + case INT_3: + case INT_4: + case INT_5: + case INT_6: + case INT_7: + case INT_8: + case INT_9: + t = parseNumberText(i); + break; + default: + t = _handleUnexpectedValue(i); + } + _nextToken = t; + return _currToken; + } + + private final JsonToken _nextTokenNotInObject(int i) + throws IOException, JsonParseException + { + if (i == INT_QUOTE) { + _tokenIncomplete = true; + return (_currToken = JsonToken.VALUE_STRING); + } + switch (i) { + case INT_LBRACKET: + _parsingContext = _parsingContext.createChildArrayContext(_tokenInputRow, _tokenInputCol); + return (_currToken = JsonToken.START_ARRAY); + case INT_LCURLY: + _parsingContext = _parsingContext.createChildObjectContext(_tokenInputRow, _tokenInputCol); + return (_currToken = JsonToken.START_OBJECT); + case INT_RBRACKET: + case INT_RCURLY: + // Error: neither is valid at this point; valid closers have + // been handled earlier + _reportUnexpectedChar(i, "expected a value"); + case INT_t: + _matchToken("true", 1); + return (_currToken = JsonToken.VALUE_TRUE); + case INT_f: + _matchToken("false", 1); + return (_currToken = JsonToken.VALUE_FALSE); + case INT_n: + _matchToken("null", 1); + return (_currToken = JsonToken.VALUE_NULL); + case INT_MINUS: + /* Should we have separate handling for plus? Although + * it is not allowed per se, it may be erroneously used, + * and could be indicate by a more specific error message. + */ + case INT_0: + case INT_1: + case INT_2: + case INT_3: + case INT_4: + case INT_5: + case INT_6: + case INT_7: + case INT_8: + case INT_9: + return (_currToken = parseNumberText(i)); + } + return (_currToken = _handleUnexpectedValue(i)); + } + + private final JsonToken _nextAfterName() + { + _nameCopied = false; // need to invalidate if it was copied + JsonToken t = _nextToken; + _nextToken = null; + // Also: may need to start new context? + if (t == JsonToken.START_ARRAY) { + _parsingContext = _parsingContext.createChildArrayContext(_tokenInputRow, _tokenInputCol); + } else if (t == JsonToken.START_OBJECT) { + _parsingContext = _parsingContext.createChildObjectContext(_tokenInputRow, _tokenInputCol); + } + return (_currToken = t); + } + + @Override + public void close() throws IOException + { + super.close(); + // Merge found symbols, if any: + _symbols.release(); + } + + /* + /********************************************************** + /* Public API, traversal, nextXxxValue/nextFieldName + /********************************************************** + */ + + @Override + public boolean nextFieldName(SerializableString str) + throws IOException, JsonParseException + { + // // // Note: most of code below is copied from nextToken() + + _numTypesValid = NR_UNKNOWN; + if (_currToken == JsonToken.FIELD_NAME) { // can't have name right after name + _nextAfterName(); + return false; + } + if (_tokenIncomplete) { + _skipString(); + } + int i = _skipWSOrEnd(); + if (i < 0) { // end-of-input + close(); + _currToken = null; + return false; + } + _tokenInputTotal = _currInputProcessed + _inputPtr - 1; + _tokenInputRow = _currInputRow; + _tokenInputCol = _inputPtr - _currInputRowStart - 1; + + // finally: clear any data retained so far + _binaryValue = null; + + // Closing scope? + if (i == INT_RBRACKET) { + if (!_parsingContext.inArray()) { + _reportMismatchedEndMarker(i, '}'); + } + _parsingContext = _parsingContext.getParent(); + _currToken = JsonToken.END_ARRAY; + return false; + } + if (i == INT_RCURLY) { + if (!_parsingContext.inObject()) { + _reportMismatchedEndMarker(i, ']'); + } + _parsingContext = _parsingContext.getParent(); + _currToken = JsonToken.END_OBJECT; + return false; + } + + // Nope: do we then expect a comma? + if (_parsingContext.expectComma()) { + if (i != INT_COMMA) { + _reportUnexpectedChar(i, "was expecting comma to separate "+_parsingContext.getTypeDesc()+" entries"); + } + i = _skipWS(); + } + + if (!_parsingContext.inObject()) { + _nextTokenNotInObject(i); + return false; + } + + // // // This part differs, name parsing + if (i == INT_QUOTE) { + // when doing literal match, must consider escaping: + byte[] nameBytes = str.asQuotedUTF8(); + final int len = nameBytes.length; + if ((_inputPtr + len) < _inputEnd) { // maybe... + // first check length match by + final int end = _inputPtr+len; + if (_inputBuffer[end] == INT_QUOTE) { + int offset = 0; + final int ptr = _inputPtr; + while (true) { + if (offset == len) { // yes, match! + _inputPtr = end+1; // skip current value first + // First part is simple; setting of name + _parsingContext.setCurrentName(str.getValue()); + _currToken = JsonToken.FIELD_NAME; + // But then we also must handle following value etc + _isNextTokenNameYes(); + return true; + } + if (nameBytes[offset] != _inputBuffer[ptr+offset]) { + break; + } + ++offset; + } + } + } + } + _isNextTokenNameNo(i); + return false; + } + + private final void _isNextTokenNameYes() + throws IOException, JsonParseException + { + // very first thing: common case, colon, value, no white space + int i; + if (_inputPtr < _inputEnd && _inputBuffer[_inputPtr] == INT_COLON) { // fast case first + ++_inputPtr; + i = _inputBuffer[_inputPtr++]; + if (i == INT_QUOTE) { + _tokenIncomplete = true; + _nextToken = JsonToken.VALUE_STRING; + return; + } + if (i == INT_LCURLY) { + _nextToken = JsonToken.START_OBJECT; + return; + } + if (i == INT_LBRACKET) { + _nextToken = JsonToken.START_ARRAY; + return; + } + i &= 0xFF; + if (i <= INT_SPACE || i == INT_SLASH) { + --_inputPtr; + i = _skipWS(); + } + } else { + i = _skipColon(); + } + switch (i) { + case INT_QUOTE: + _tokenIncomplete = true; + _nextToken = JsonToken.VALUE_STRING; + return; + case INT_LBRACKET: + _nextToken = JsonToken.START_ARRAY; + return; + case INT_LCURLY: + _nextToken = JsonToken.START_OBJECT; + return; + case INT_RBRACKET: + case INT_RCURLY: + _reportUnexpectedChar(i, "expected a value"); + case INT_t: + _matchToken("true", 1); + _nextToken = JsonToken.VALUE_TRUE; + return; + case INT_f: + _matchToken("false", 1); + _nextToken = JsonToken.VALUE_FALSE; + return; + case INT_n: + _matchToken("null", 1); + _nextToken = JsonToken.VALUE_NULL; + return; + case INT_MINUS: + case INT_0: + case INT_1: + case INT_2: + case INT_3: + case INT_4: + case INT_5: + case INT_6: + case INT_7: + case INT_8: + case INT_9: + _nextToken = parseNumberText(i); + return; + } + _nextToken = _handleUnexpectedValue(i); + } + + private final void _isNextTokenNameNo(int i) + throws IOException, JsonParseException + { + // // // and this is back to standard nextToken() + + Name n = _parseFieldName(i); + _parsingContext.setCurrentName(n.getName()); + _currToken = JsonToken.FIELD_NAME; + i = _skipWS(); + if (i != INT_COLON) { + _reportUnexpectedChar(i, "was expecting a colon to separate field name and value"); + } + i = _skipWS(); + + // Ok: we must have a value... what is it? Strings are very common, check first: + if (i == INT_QUOTE) { + _tokenIncomplete = true; + _nextToken = JsonToken.VALUE_STRING; + return; + } + JsonToken t; + + switch (i) { + case INT_LBRACKET: + t = JsonToken.START_ARRAY; + break; + case INT_LCURLY: + t = JsonToken.START_OBJECT; + break; + case INT_RBRACKET: + case INT_RCURLY: + _reportUnexpectedChar(i, "expected a value"); + case INT_t: + _matchToken("true", 1); + t = JsonToken.VALUE_TRUE; + break; + case INT_f: + _matchToken("false", 1); + t = JsonToken.VALUE_FALSE; + break; + case INT_n: + _matchToken("null", 1); + t = JsonToken.VALUE_NULL; + break; + + case INT_MINUS: + case INT_0: + case INT_1: + case INT_2: + case INT_3: + case INT_4: + case INT_5: + case INT_6: + case INT_7: + case INT_8: + case INT_9: + t = parseNumberText(i); + break; + default: + t = _handleUnexpectedValue(i); + } + _nextToken = t; + } + + @Override + public String nextTextValue() + throws IOException, JsonParseException + { + // two distinct cases; either got name and we know next type, or 'other' + if (_currToken == JsonToken.FIELD_NAME) { // mostly copied from '_nextAfterName' + _nameCopied = false; + JsonToken t = _nextToken; + _nextToken = null; + _currToken = t; + if (t == JsonToken.VALUE_STRING) { + if (_tokenIncomplete) { + _tokenIncomplete = false; + _finishString(); + } + return _textBuffer.contentsAsString(); + } + if (t == JsonToken.START_ARRAY) { + _parsingContext = _parsingContext.createChildArrayContext(_tokenInputRow, _tokenInputCol); + } else if (t == JsonToken.START_OBJECT) { + _parsingContext = _parsingContext.createChildObjectContext(_tokenInputRow, _tokenInputCol); + } + return null; + } + // !!! TODO: optimize this case as well + return (nextToken() == JsonToken.VALUE_STRING) ? getText() : null; + } + + @Override + public int nextIntValue(int defaultValue) + throws IOException, JsonParseException + { + // two distinct cases; either got name and we know next type, or 'other' + if (_currToken == JsonToken.FIELD_NAME) { // mostly copied from '_nextAfterName' + _nameCopied = false; + JsonToken t = _nextToken; + _nextToken = null; + _currToken = t; + if (t == JsonToken.VALUE_NUMBER_INT) { + return getIntValue(); + } + if (t == JsonToken.START_ARRAY) { + _parsingContext = _parsingContext.createChildArrayContext(_tokenInputRow, _tokenInputCol); + } else if (t == JsonToken.START_OBJECT) { + _parsingContext = _parsingContext.createChildObjectContext(_tokenInputRow, _tokenInputCol); + } + return defaultValue; + } + // !!! TODO: optimize this case as well + return (nextToken() == JsonToken.VALUE_NUMBER_INT) ? getIntValue() : defaultValue; + } + + @Override + public long nextLongValue(long defaultValue) + throws IOException, JsonParseException + { + // two distinct cases; either got name and we know next type, or 'other' + if (_currToken == JsonToken.FIELD_NAME) { // mostly copied from '_nextAfterName' + _nameCopied = false; + JsonToken t = _nextToken; + _nextToken = null; + _currToken = t; + if (t == JsonToken.VALUE_NUMBER_INT) { + return getLongValue(); + } + if (t == JsonToken.START_ARRAY) { + _parsingContext = _parsingContext.createChildArrayContext(_tokenInputRow, _tokenInputCol); + } else if (t == JsonToken.START_OBJECT) { + _parsingContext = _parsingContext.createChildObjectContext(_tokenInputRow, _tokenInputCol); + } + return defaultValue; + } + // !!! TODO: optimize this case as well + return (nextToken() == JsonToken.VALUE_NUMBER_INT) ? getLongValue() : defaultValue; + } + + @Override + public Boolean nextBooleanValue() + throws IOException, JsonParseException + { + // two distinct cases; either got name and we know next type, or 'other' + if (_currToken == JsonToken.FIELD_NAME) { // mostly copied from '_nextAfterName' + _nameCopied = false; + JsonToken t = _nextToken; + _nextToken = null; + _currToken = t; + if (t == JsonToken.VALUE_TRUE) { + return Boolean.TRUE; + } + if (t == JsonToken.VALUE_FALSE) { + return Boolean.FALSE; + } + if (t == JsonToken.START_ARRAY) { + _parsingContext = _parsingContext.createChildArrayContext(_tokenInputRow, _tokenInputCol); + } else if (t == JsonToken.START_OBJECT) { + _parsingContext = _parsingContext.createChildObjectContext(_tokenInputRow, _tokenInputCol); + } + return null; + } + switch (nextToken()) { + case VALUE_TRUE: + return Boolean.TRUE; + case VALUE_FALSE: + return Boolean.FALSE; + } + return null; + } + + /* + /********************************************************** + /* Internal methods, number parsing + /* (note: in 1.6 and prior, part of "Utf8NumericParser" + /********************************************************** + */ + + /** + * Initial parsing method for number values. It needs to be able + * to parse enough input to be able to determine whether the + * value is to be considered a simple integer value, or a more + * generic decimal value: latter of which needs to be expressed + * as a floating point number. The basic rule is that if the number + * has no fractional or exponential part, it is an integer; otherwise + * a floating point number. + *<p> + * Because much of input has to be processed in any case, no partial + * parsing is done: all input text will be stored for further + * processing. However, actual numeric value conversion will be + * deferred, since it is usually the most complicated and costliest + * part of processing. + */ + protected final JsonToken parseNumberText(int c) + throws IOException, JsonParseException + { + char[] outBuf = _textBuffer.emptyAndGetCurrentSegment(); + int outPtr = 0; + boolean negative = (c == INT_MINUS); + + // Need to prepend sign? + if (negative) { + outBuf[outPtr++] = '-'; + // Must have something after sign too + if (_inputPtr >= _inputEnd) { + loadMoreGuaranteed(); + } + c = (int) _inputBuffer[_inputPtr++] & 0xFF; + // Note: must be followed by a digit + if (c < INT_0 || c > INT_9) { + return _handleInvalidNumberStart(c, true); + } + } + + // One special case: if first char is 0, must not be followed by a digit + if (c == INT_0) { + c = _verifyNoLeadingZeroes(); + } + + // Ok: we can first just add digit we saw first: + outBuf[outPtr++] = (char) c; + int intLen = 1; + + // And then figure out how far we can read without further checks: + int end = _inputPtr + outBuf.length; + if (end > _inputEnd) { + end = _inputEnd; + } + + // With this, we have a nice and tight loop: + while (true) { + if (_inputPtr >= end) { + // Long enough to be split across boundary, so: + return _parserNumber2(outBuf, outPtr, negative, intLen); + } + c = (int) _inputBuffer[_inputPtr++] & 0xFF; + if (c < INT_0 || c > INT_9) { + break; + } + ++intLen; + outBuf[outPtr++] = (char) c; + } + if (c == '.' || c == 'e' || c == 'E') { + return _parseFloatText(outBuf, outPtr, c, negative, intLen); + } + + --_inputPtr; // to push back trailing char (comma etc) + _textBuffer.setCurrentLength(outPtr); + + // And there we have it! + return resetInt(negative, intLen); + } + + /** + * Method called to handle parsing when input is split across buffer boundary + * (or output is longer than segment used to store it) + */ + private final JsonToken _parserNumber2(char[] outBuf, int outPtr, boolean negative, + int intPartLength) + throws IOException, JsonParseException + { + // Ok, parse the rest + while (true) { + if (_inputPtr >= _inputEnd && !loadMore()) { + _textBuffer.setCurrentLength(outPtr); + return resetInt(negative, intPartLength); + } + int c = (int) _inputBuffer[_inputPtr++] & 0xFF; + if (c > INT_9 || c < INT_0) { + if (c == '.' || c == 'e' || c == 'E') { + return _parseFloatText(outBuf, outPtr, c, negative, intPartLength); + } + break; + } + if (outPtr >= outBuf.length) { + outBuf = _textBuffer.finishCurrentSegment(); + outPtr = 0; + } + outBuf[outPtr++] = (char) c; + ++intPartLength; + } + --_inputPtr; // to push back trailing char (comma etc) + _textBuffer.setCurrentLength(outPtr); + + // And there we have it! + return resetInt(negative, intPartLength); + + } + + /** + * Method called when we have seen one zero, and want to ensure + * it is not followed by another + */ + private final int _verifyNoLeadingZeroes() + throws IOException, JsonParseException + { + // Ok to have plain "0" + if (_inputPtr >= _inputEnd && !loadMore()) { + return INT_0; + } + int ch = _inputBuffer[_inputPtr] & 0xFF; + // if not followed by a number (probably '.'); return zero as is, to be included + if (ch < INT_0 || ch > INT_9) { + return INT_0; + } + // [JACKSON-358]: we may want to allow them, after all... + if (!isEnabled(Feature.ALLOW_NUMERIC_LEADING_ZEROS)) { + reportInvalidNumber("Leading zeroes not allowed"); + } + // if so, just need to skip either all zeroes (if followed by number); or all but one (if non-number) + ++_inputPtr; // Leading zero to be skipped + if (ch == INT_0) { + while (_inputPtr < _inputEnd || loadMore()) { + ch = _inputBuffer[_inputPtr] & 0xFF; + if (ch < INT_0 || ch > INT_9) { // followed by non-number; retain one zero + return INT_0; + } + ++_inputPtr; // skip previous zeroes + if (ch != INT_0) { // followed by other number; return + break; + } + } + } + return ch; + } + + private final JsonToken _parseFloatText(char[] outBuf, int outPtr, int c, + boolean negative, int integerPartLength) + throws IOException, JsonParseException + { + int fractLen = 0; + boolean eof = false; + + // And then see if we get other parts + if (c == '.') { // yes, fraction + outBuf[outPtr++] = (char) c; + + fract_loop: + while (true) { + if (_inputPtr >= _inputEnd && !loadMore()) { + eof = true; + break fract_loop; + } + c = (int) _inputBuffer[_inputPtr++] & 0xFF; + if (c < INT_0 || c > INT_9) { + break fract_loop; + } + ++fractLen; + if (outPtr >= outBuf.length) { + outBuf = _textBuffer.finishCurrentSegment(); + outPtr = 0; + } + outBuf[outPtr++] = (char) c; + } + // must be followed by sequence of ints, one minimum + if (fractLen == 0) { + reportUnexpectedNumberChar(c, "Decimal point not followed by a digit"); + } + } + + int expLen = 0; + if (c == 'e' || c == 'E') { // exponent? + if (outPtr >= outBuf.length) { + outBuf = _textBuffer.finishCurrentSegment(); + outPtr = 0; + } + outBuf[outPtr++] = (char) c; + // Not optional, can require that we get one more char + if (_inputPtr >= _inputEnd) { + loadMoreGuaranteed(); + } + c = (int) _inputBuffer[_inputPtr++] & 0xFF; + // Sign indicator? + if (c == '-' || c == '+') { + if (outPtr >= outBuf.length) { + outBuf = _textBuffer.finishCurrentSegment(); + outPtr = 0; + } + outBuf[outPtr++] = (char) c; + // Likewise, non optional: + if (_inputPtr >= _inputEnd) { + loadMoreGuaranteed(); + } + c = (int) _inputBuffer[_inputPtr++] & 0xFF; + } + + exp_loop: + while (c <= INT_9 && c >= INT_0) { + ++expLen; + if (outPtr >= outBuf.length) { + outBuf = _textBuffer.finishCurrentSegment(); + outPtr = 0; + } + outBuf[outPtr++] = (char) c; + if (_inputPtr >= _inputEnd && !loadMore()) { + eof = true; + break exp_loop; + } + c = (int) _inputBuffer[_inputPtr++] & 0xFF; + } + // must be followed by sequence of ints, one minimum + if (expLen == 0) { + reportUnexpectedNumberChar(c, "Exponent indicator not followed by a digit"); + } + } + + // Ok; unless we hit end-of-input, need to push last char read back + if (!eof) { + --_inputPtr; + } + _textBuffer.setCurrentLength(outPtr); + + // And there we have it! + return resetFloat(negative, integerPartLength, fractLen, expLen); + } + + /* + /********************************************************** + /* Internal methods, secondary parsing + /********************************************************** + */ + + protected final Name _parseFieldName(int i) + throws IOException, JsonParseException + { + if (i != INT_QUOTE) { + return _handleUnusualFieldName(i); + } + // First: can we optimize out bounds checks? + if ((_inputPtr + 9) > _inputEnd) { // Need 8 chars, plus one trailing (quote) + return slowParseFieldName(); + } + + // If so, can also unroll loops nicely + /* 25-Nov-2008, tatu: This may seem weird, but here we do + * NOT want to worry about UTF-8 decoding. Rather, we'll + * assume that part is ok (if not it will get caught + * later on), and just handle quotes and backslashes here. + */ + final byte[] input = _inputBuffer; + final int[] codes = sInputCodesLatin1; + + int q = input[_inputPtr++] & 0xFF; + + if (codes[q] == 0) { + i = input[_inputPtr++] & 0xFF; + if (codes[i] == 0) { + q = (q << 8) | i; + i = input[_inputPtr++] & 0xFF; + if (codes[i] == 0) { + q = (q << 8) | i; + i = input[_inputPtr++] & 0xFF; + if (codes[i] == 0) { + q = (q << 8) | i; + i = input[_inputPtr++] & 0xFF; + if (codes[i] == 0) { + _quad1 = q; + return parseMediumFieldName(i, codes); + } + if (i == INT_QUOTE) { // one byte/char case or broken + return findName(q, 4); + } + return parseFieldName(q, i, 4); + } + if (i == INT_QUOTE) { // one byte/char case or broken + return findName(q, 3); + } + return parseFieldName(q, i, 3); + } + if (i == INT_QUOTE) { // one byte/char case or broken + return findName(q, 2); + } + return parseFieldName(q, i, 2); + } + if (i == INT_QUOTE) { // one byte/char case or broken + return findName(q, 1); + } + return parseFieldName(q, i, 1); + } + if (q == INT_QUOTE) { // special case, "" + return BytesToNameCanonicalizer.getEmptyName(); + } + return parseFieldName(0, q, 0); // quoting or invalid char + } + + protected final Name parseMediumFieldName(int q2, final int[] codes) + throws IOException, JsonParseException + { + // Ok, got 5 name bytes so far + int i = _inputBuffer[_inputPtr++] & 0xFF; + if (codes[i] != 0) { + if (i == INT_QUOTE) { // 5 bytes + return findName(_quad1, q2, 1); + } + return parseFieldName(_quad1, q2, i, 1); // quoting or invalid char + } + q2 = (q2 << 8) | i; + i = _inputBuffer[_inputPtr++] & 0xFF; + if (codes[i] != 0) { + if (i == INT_QUOTE) { // 6 bytes + return findName(_quad1, q2, 2); + } + return parseFieldName(_quad1, q2, i, 2); + } + q2 = (q2 << 8) | i; + i = _inputBuffer[_inputPtr++] & 0xFF; + if (codes[i] != 0) { + if (i == INT_QUOTE) { // 7 bytes + return findName(_quad1, q2, 3); + } + return parseFieldName(_quad1, q2, i, 3); + } + q2 = (q2 << 8) | i; + i = _inputBuffer[_inputPtr++] & 0xFF; + if (codes[i] != 0) { + if (i == INT_QUOTE) { // 8 bytes + return findName(_quad1, q2, 4); + } + return parseFieldName(_quad1, q2, i, 4); + } + _quadBuffer[0] = _quad1; + _quadBuffer[1] = q2; + return parseLongFieldName(i); + } + + protected Name parseLongFieldName(int q) + throws IOException, JsonParseException + { + // As explained above, will ignore UTF-8 encoding at this point + final int[] codes = sInputCodesLatin1; + int qlen = 2; + + while (true) { + /* Let's offline if we hit buffer boundary (otherwise would + * need to [try to] align input, which is bit complicated + * and may not always be possible) + */ + if ((_inputEnd - _inputPtr) < 4) { + return parseEscapedFieldName(_quadBuffer, qlen, 0, q, 0); + } + // Otherwise can skip boundary checks for 4 bytes in loop + + int i = _inputBuffer[_inputPtr++] & 0xFF; + if (codes[i] != 0) { + if (i == INT_QUOTE) { + return findName(_quadBuffer, qlen, q, 1); + } + return parseEscapedFieldName(_quadBuffer, qlen, q, i, 1); + } + + q = (q << 8) | i; + i = _inputBuffer[_inputPtr++] & 0xFF; + if (codes[i] != 0) { + if (i == INT_QUOTE) { + return findName(_quadBuffer, qlen, q, 2); + } + return parseEscapedFieldName(_quadBuffer, qlen, q, i, 2); + } + + q = (q << 8) | i; + i = _inputBuffer[_inputPtr++] & 0xFF; + if (codes[i] != 0) { + if (i == INT_QUOTE) { + return findName(_quadBuffer, qlen, q, 3); + } + return parseEscapedFieldName(_quadBuffer, qlen, q, i, 3); + } + + q = (q << 8) | i; + i = _inputBuffer[_inputPtr++] & 0xFF; + if (codes[i] != 0) { + if (i == INT_QUOTE) { + return findName(_quadBuffer, qlen, q, 4); + } + return parseEscapedFieldName(_quadBuffer, qlen, q, i, 4); + } + + // Nope, no end in sight. Need to grow quad array etc + if (qlen >= _quadBuffer.length) { + _quadBuffer = growArrayBy(_quadBuffer, qlen); + } + _quadBuffer[qlen++] = q; + q = i; + } + } + + /** + * Method called when not even first 8 bytes are guaranteed + * to come consequtively. Happens rarely, so this is offlined; + * plus we'll also do full checks for escaping etc. + */ + protected Name slowParseFieldName() + throws IOException, JsonParseException + { + if (_inputPtr >= _inputEnd) { + if (!loadMore()) { + _reportInvalidEOF(": was expecting closing '\"' for name"); + } + } + int i = _inputBuffer[_inputPtr++] & 0xFF; + if (i == INT_QUOTE) { // special case, "" + return BytesToNameCanonicalizer.getEmptyName(); + } + return parseEscapedFieldName(_quadBuffer, 0, 0, i, 0); + } + + private final Name parseFieldName(int q1, int ch, int lastQuadBytes) + throws IOException, JsonParseException + { + return parseEscapedFieldName(_quadBuffer, 0, q1, ch, lastQuadBytes); + } + + private final Name parseFieldName(int q1, int q2, int ch, int lastQuadBytes) + throws IOException, JsonParseException + { + _quadBuffer[0] = q1; + return parseEscapedFieldName(_quadBuffer, 1, q2, ch, lastQuadBytes); + } + + /** + * Slower parsing method which is generally branched to when + * an escape sequence is detected (or alternatively for long + * names, or ones crossing input buffer boundary). In any case, + * needs to be able to handle more exceptional cases, gets + * slower, and hance is offlined to a separate method. + */ + protected Name parseEscapedFieldName(int[] quads, int qlen, int currQuad, int ch, + int currQuadBytes) + throws IOException, JsonParseException + { + /* 25-Nov-2008, tatu: This may seem weird, but here we do + * NOT want to worry about UTF-8 decoding. Rather, we'll + * assume that part is ok (if not it will get caught + * later on), and just handle quotes and backslashes here. + */ + final int[] codes = sInputCodesLatin1; + + while (true) { + if (codes[ch] != 0) { + if (ch == INT_QUOTE) { // we are done + break; + } + // Unquoted white space? + if (ch != INT_BACKSLASH) { + // As per [JACKSON-208], call can now return: + _throwUnquotedSpace(ch, "name"); + } else { + // Nope, escape sequence + ch = _decodeEscaped(); + } + /* Oh crap. May need to UTF-8 (re-)encode it, if it's + * beyond 7-bit ascii. Gets pretty messy. + * If this happens often, may want to use different name + * canonicalization to avoid these hits. + */ + if (ch > 127) { + // Ok, we'll need room for first byte right away + if (currQuadBytes >= 4) { + if (qlen >= quads.length) { + _quadBuffer = quads = growArrayBy(quads, quads.length); + } + quads[qlen++] = currQuad; + currQuad = 0; + currQuadBytes = 0; + } + if (ch < 0x800) { // 2-byte + currQuad = (currQuad << 8) | (0xc0 | (ch >> 6)); + ++currQuadBytes; + // Second byte gets output below: + } else { // 3 bytes; no need to worry about surrogates here + currQuad = (currQuad << 8) | (0xe0 | (ch >> 12)); + ++currQuadBytes; + // need room for middle byte? + if (currQuadBytes >= 4) { + if (qlen >= quads.length) { + _quadBuffer = quads = growArrayBy(quads, quads.length); + } + quads[qlen++] = currQuad; + currQuad = 0; + currQuadBytes = 0; + } + currQuad = (currQuad << 8) | (0x80 | ((ch >> 6) & 0x3f)); + ++currQuadBytes; + } + // And same last byte in both cases, gets output below: + ch = 0x80 | (ch & 0x3f); + } + } + // Ok, we have one more byte to add at any rate: + if (currQuadBytes < 4) { + ++currQuadBytes; + currQuad = (currQuad << 8) | ch; + } else { + if (qlen >= quads.length) { + _quadBuffer = quads = growArrayBy(quads, quads.length); + } + quads[qlen++] = currQuad; + currQuad = ch; + currQuadBytes = 1; + } + if (_inputPtr >= _inputEnd) { + if (!loadMore()) { + _reportInvalidEOF(" in field name"); + } + } + ch = _inputBuffer[_inputPtr++] & 0xFF; + } + + if (currQuadBytes > 0) { + if (qlen >= quads.length) { + _quadBuffer = quads = growArrayBy(quads, quads.length); + } + quads[qlen++] = currQuad; + } + Name name = _symbols.findName(quads, qlen); + if (name == null) { + name = addName(quads, qlen, currQuadBytes); + } + return name; + } + + /** + * Method called when we see non-white space character other + * than double quote, when expecting a field name. + * In standard mode will just throw an expection; but + * in non-standard modes may be able to parse name. + */ + protected final Name _handleUnusualFieldName(int ch) + throws IOException, JsonParseException + { + // [JACKSON-173]: allow single quotes + if (ch == INT_APOSTROPHE && isEnabled(Feature.ALLOW_SINGLE_QUOTES)) { + return _parseApostropheFieldName(); + } + // [JACKSON-69]: allow unquoted names if feature enabled: + if (!isEnabled(Feature.ALLOW_UNQUOTED_FIELD_NAMES)) { + _reportUnexpectedChar(ch, "was expecting double-quote to start field name"); + } + /* Also: note that although we use a different table here, + * it does NOT handle UTF-8 decoding. It'll just pass those + * high-bit codes as acceptable for later decoding. + */ + final int[] codes = CharTypes.getInputCodeUtf8JsNames(); + // Also: must start with a valid character... + if (codes[ch] != 0) { + _reportUnexpectedChar(ch, "was expecting either valid name character (for unquoted name) or double-quote (for quoted) to start field name"); + } + + /* Ok, now; instead of ultra-optimizing parsing here (as with + * regular JSON names), let's just use the generic "slow" + * variant. Can measure its impact later on if need be + */ + int[] quads = _quadBuffer; + int qlen = 0; + int currQuad = 0; + int currQuadBytes = 0; + + while (true) { + // Ok, we have one more byte to add at any rate: + if (currQuadBytes < 4) { + ++currQuadBytes; + currQuad = (currQuad << 8) | ch; + } else { + if (qlen >= quads.length) { + _quadBuffer = quads = growArrayBy(quads, quads.length); + } + quads[qlen++] = currQuad; + currQuad = ch; + currQuadBytes = 1; + } + if (_inputPtr >= _inputEnd) { + if (!loadMore()) { + _reportInvalidEOF(" in field name"); + } + } + ch = _inputBuffer[_inputPtr] & 0xFF; + if (codes[ch] != 0) { + break; + } + ++_inputPtr; + } + + if (currQuadBytes > 0) { + if (qlen >= quads.length) { + _quadBuffer = quads = growArrayBy(quads, quads.length); + } + quads[qlen++] = currQuad; + } + Name name = _symbols.findName(quads, qlen); + if (name == null) { + name = addName(quads, qlen, currQuadBytes); + } + return name; + } + + /* Parsing to support [JACKSON-173]. Plenty of duplicated code; + * main reason being to try to avoid slowing down fast path + * for valid JSON -- more alternatives, more code, generally + * bit slower execution. + */ + protected final Name _parseApostropheFieldName() + throws IOException, JsonParseException + { + if (_inputPtr >= _inputEnd) { + if (!loadMore()) { + _reportInvalidEOF(": was expecting closing '\'' for name"); + } + } + int ch = _inputBuffer[_inputPtr++] & 0xFF; + if (ch == INT_APOSTROPHE) { // special case, '' + return BytesToNameCanonicalizer.getEmptyName(); + } + int[] quads = _quadBuffer; + int qlen = 0; + int currQuad = 0; + int currQuadBytes = 0; + + // Copied from parseEscapedFieldName, with minor mods: + + final int[] codes = sInputCodesLatin1; + + while (true) { + if (ch == INT_APOSTROPHE) { + break; + } + // additional check to skip handling of double-quotes + if (ch != INT_QUOTE && codes[ch] != 0) { + if (ch != INT_BACKSLASH) { + // Unquoted white space? + // As per [JACKSON-208], call can now return: + _throwUnquotedSpace(ch, "name"); + } else { + // Nope, escape sequence + ch = _decodeEscaped(); + } + /* Oh crap. May need to UTF-8 (re-)encode it, if it's + * beyond 7-bit ascii. Gets pretty messy. + * If this happens often, may want to use different name + * canonicalization to avoid these hits. + */ + if (ch > 127) { + // Ok, we'll need room for first byte right away + if (currQuadBytes >= 4) { + if (qlen >= quads.length) { + _quadBuffer = quads = growArrayBy(quads, quads.length); + } + quads[qlen++] = currQuad; + currQuad = 0; + currQuadBytes = 0; + } + if (ch < 0x800) { // 2-byte + currQuad = (currQuad << 8) | (0xc0 | (ch >> 6)); + ++currQuadBytes; + // Second byte gets output below: + } else { // 3 bytes; no need to worry about surrogates here + currQuad = (currQuad << 8) | (0xe0 | (ch >> 12)); + ++currQuadBytes; + // need room for middle byte? + if (currQuadBytes >= 4) { + if (qlen >= quads.length) { + _quadBuffer = quads = growArrayBy(quads, quads.length); + } + quads[qlen++] = currQuad; + currQuad = 0; + currQuadBytes = 0; + } + currQuad = (currQuad << 8) | (0x80 | ((ch >> 6) & 0x3f)); + ++currQuadBytes; + } + // And same last byte in both cases, gets output below: + ch = 0x80 | (ch & 0x3f); + } + } + // Ok, we have one more byte to add at any rate: + if (currQuadBytes < 4) { + ++currQuadBytes; + currQuad = (currQuad << 8) | ch; + } else { + if (qlen >= quads.length) { + _quadBuffer = quads = growArrayBy(quads, quads.length); + } + quads[qlen++] = currQuad; + currQuad = ch; + currQuadBytes = 1; + } + if (_inputPtr >= _inputEnd) { + if (!loadMore()) { + _reportInvalidEOF(" in field name"); + } + } + ch = _inputBuffer[_inputPtr++] & 0xFF; + } + + if (currQuadBytes > 0) { + if (qlen >= quads.length) { + _quadBuffer = quads = growArrayBy(quads, quads.length); + } + quads[qlen++] = currQuad; + } + Name name = _symbols.findName(quads, qlen); + if (name == null) { + name = addName(quads, qlen, currQuadBytes); + } + return name; + } + + /* + /********************************************************** + /* Internal methods, symbol (name) handling + /********************************************************** + */ + + private final Name findName(int q1, int lastQuadBytes) + throws JsonParseException + { + // Usually we'll find it from the canonical symbol table already + Name name = _symbols.findName(q1); + if (name != null) { + return name; + } + // If not, more work. We'll need add stuff to buffer + _quadBuffer[0] = q1; + return addName(_quadBuffer, 1, lastQuadBytes); + } + + private final Name findName(int q1, int q2, int lastQuadBytes) + throws JsonParseException + { + // Usually we'll find it from the canonical symbol table already + Name name = _symbols.findName(q1, q2); + if (name != null) { + return name; + } + // If not, more work. We'll need add stuff to buffer + _quadBuffer[0] = q1; + _quadBuffer[1] = q2; + return addName(_quadBuffer, 2, lastQuadBytes); + } + + private final Name findName(int[] quads, int qlen, int lastQuad, int lastQuadBytes) + throws JsonParseException + { + if (qlen >= quads.length) { + _quadBuffer = quads = growArrayBy(quads, quads.length); + } + quads[qlen++] = lastQuad; + Name name = _symbols.findName(quads, qlen); + if (name == null) { + return addName(quads, qlen, lastQuadBytes); + } + return name; + } + + /** + * This is the main workhorse method used when we take a symbol + * table miss. It needs to demultiplex individual bytes, decode + * multi-byte chars (if any), and then construct Name instance + * and add it to the symbol table. + */ + private final Name addName(int[] quads, int qlen, int lastQuadBytes) + throws JsonParseException + { + /* Ok: must decode UTF-8 chars. No other validation is + * needed, since unescaping has been done earlier as necessary + * (as well as error reporting for unescaped control chars) + */ + // 4 bytes per quad, except last one maybe less + int byteLen = (qlen << 2) - 4 + lastQuadBytes; + + /* And last one is not correctly aligned (leading zero bytes instead + * need to shift a bit, instead of trailing). Only need to shift it + * for UTF-8 decoding; need revert for storage (since key will not + * be aligned, to optimize lookup speed) + */ + int lastQuad; + + if (lastQuadBytes < 4) { + lastQuad = quads[qlen-1]; + // 8/16/24 bit left shift + quads[qlen-1] = (lastQuad << ((4 - lastQuadBytes) << 3)); + } else { + lastQuad = 0; + } + + // Need some working space, TextBuffer works well: + char[] cbuf = _textBuffer.emptyAndGetCurrentSegment(); + int cix = 0; + + for (int ix = 0; ix < byteLen; ) { + int ch = quads[ix >> 2]; // current quad, need to shift+mask + int byteIx = (ix & 3); + ch = (ch >> ((3 - byteIx) << 3)) & 0xFF; + ++ix; + + if (ch > 127) { // multi-byte + int needed; + if ((ch & 0xE0) == 0xC0) { // 2 bytes (0x0080 - 0x07FF) + ch &= 0x1F; + needed = 1; + } else if ((ch & 0xF0) == 0xE0) { // 3 bytes (0x0800 - 0xFFFF) + ch &= 0x0F; + needed = 2; + } else if ((ch & 0xF8) == 0xF0) { // 4 bytes; double-char with surrogates and all... + ch &= 0x07; + needed = 3; + } else { // 5- and 6-byte chars not valid xml chars + _reportInvalidInitial(ch); + needed = ch = 1; // never really gets this far + } + if ((ix + needed) > byteLen) { + _reportInvalidEOF(" in field name"); + } + + // Ok, always need at least one more: + int ch2 = quads[ix >> 2]; // current quad, need to shift+mask + byteIx = (ix & 3); + ch2 = (ch2 >> ((3 - byteIx) << 3)); + ++ix; + + if ((ch2 & 0xC0) != 0x080) { + _reportInvalidOther(ch2); + } + ch = (ch << 6) | (ch2 & 0x3F); + if (needed > 1) { + ch2 = quads[ix >> 2]; + byteIx = (ix & 3); + ch2 = (ch2 >> ((3 - byteIx) << 3)); + ++ix; + + if ((ch2 & 0xC0) != 0x080) { + _reportInvalidOther(ch2); + } + ch = (ch << 6) | (ch2 & 0x3F); + if (needed > 2) { // 4 bytes? (need surrogates on output) + ch2 = quads[ix >> 2]; + byteIx = (ix & 3); + ch2 = (ch2 >> ((3 - byteIx) << 3)); + ++ix; + if ((ch2 & 0xC0) != 0x080) { + _reportInvalidOther(ch2 & 0xFF); + } + ch = (ch << 6) | (ch2 & 0x3F); + } + } + if (needed > 2) { // surrogate pair? once again, let's output one here, one later on + ch -= 0x10000; // to normalize it starting with 0x0 + if (cix >= cbuf.length) { + cbuf = _textBuffer.expandCurrentSegment(); + } + cbuf[cix++] = (char) (0xD800 + (ch >> 10)); + ch = 0xDC00 | (ch & 0x03FF); + } + } + if (cix >= cbuf.length) { + cbuf = _textBuffer.expandCurrentSegment(); + } + cbuf[cix++] = (char) ch; + } + + // Ok. Now we have the character array, and can construct the String + String baseName = new String(cbuf, 0, cix); + // And finally, un-align if necessary + if (lastQuadBytes < 4) { + quads[qlen-1] = lastQuad; + } + return _symbols.addName(baseName, quads, qlen); + } + + /* + /********************************************************** + /* Internal methods, String value parsing + /********************************************************** + */ + + @Override + protected void _finishString() + throws IOException, JsonParseException + { + // First, single tight loop for ASCII content, not split across input buffer boundary: + int ptr = _inputPtr; + if (ptr >= _inputEnd) { + loadMoreGuaranteed(); + ptr = _inputPtr; + } + int outPtr = 0; + char[] outBuf = _textBuffer.emptyAndGetCurrentSegment(); + final int[] codes = sInputCodesUtf8; + + final int max = Math.min(_inputEnd, (ptr + outBuf.length)); + final byte[] inputBuffer = _inputBuffer; + while (ptr < max) { + int c = (int) inputBuffer[ptr] & 0xFF; + if (codes[c] != 0) { + if (c == INT_QUOTE) { + _inputPtr = ptr+1; + _textBuffer.setCurrentLength(outPtr); + return; + } + break; + } + ++ptr; + outBuf[outPtr++] = (char) c; + } + _inputPtr = ptr; + _finishString2(outBuf, outPtr); + } + + private final void _finishString2(char[] outBuf, int outPtr) + throws IOException, JsonParseException + { + int c; + + // Here we do want to do full decoding, hence: + final int[] codes = sInputCodesUtf8; + final byte[] inputBuffer = _inputBuffer; + + main_loop: + while (true) { + // Then the tight ASCII non-funny-char loop: + ascii_loop: + while (true) { + int ptr = _inputPtr; + if (ptr >= _inputEnd) { + loadMoreGuaranteed(); + ptr = _inputPtr; + } + if (outPtr >= outBuf.length) { + outBuf = _textBuffer.finishCurrentSegment(); + outPtr = 0; + } + final int max = Math.min(_inputEnd, (ptr + (outBuf.length - outPtr))); + while (ptr < max) { + c = (int) inputBuffer[ptr++] & 0xFF; + if (codes[c] != 0) { + _inputPtr = ptr; + break ascii_loop; + } + outBuf[outPtr++] = (char) c; + } + _inputPtr = ptr; + } + // Ok: end marker, escape or multi-byte? + if (c == INT_QUOTE) { + break main_loop; + } + + switch (codes[c]) { + case 1: // backslash + c = _decodeEscaped(); + break; + case 2: // 2-byte UTF + c = _decodeUtf8_2(c); + break; + case 3: // 3-byte UTF + if ((_inputEnd - _inputPtr) >= 2) { + c = _decodeUtf8_3fast(c); + } else { + c = _decodeUtf8_3(c); + } + break; + case 4: // 4-byte UTF + c = _decodeUtf8_4(c); + // Let's add first part right away: + outBuf[outPtr++] = (char) (0xD800 | (c >> 10)); + if (outPtr >= outBuf.length) { + outBuf = _textBuffer.finishCurrentSegment(); + outPtr = 0; + } + c = 0xDC00 | (c & 0x3FF); + // And let the other char output down below + break; + default: + if (c < INT_SPACE) { + // As per [JACKSON-208], call can now return: + _throwUnquotedSpace(c, "string value"); + } else { + // Is this good enough error message? + _reportInvalidChar(c); + } + } + // Need more room? + if (outPtr >= outBuf.length) { + outBuf = _textBuffer.finishCurrentSegment(); + outPtr = 0; + } + // Ok, let's add char to output: + outBuf[outPtr++] = (char) c; + } + _textBuffer.setCurrentLength(outPtr); + } + + /** + * Method called to skim through rest of unparsed String value, + * if it is not needed. This can be done bit faster if contents + * need not be stored for future access. + */ + protected void _skipString() + throws IOException, JsonParseException + { + _tokenIncomplete = false; + + // Need to be fully UTF-8 aware here: + final int[] codes = sInputCodesUtf8; + final byte[] inputBuffer = _inputBuffer; + + main_loop: + while (true) { + int c; + + ascii_loop: + while (true) { + int ptr = _inputPtr; + int max = _inputEnd; + if (ptr >= max) { + loadMoreGuaranteed(); + ptr = _inputPtr; + max = _inputEnd; + } + while (ptr < max) { + c = (int) inputBuffer[ptr++] & 0xFF; + if (codes[c] != 0) { + _inputPtr = ptr; + break ascii_loop; + } + } + _inputPtr = ptr; + } + // Ok: end marker, escape or multi-byte? + if (c == INT_QUOTE) { + break main_loop; + } + + switch (codes[c]) { + case 1: // backslash + _decodeEscaped(); + break; + case 2: // 2-byte UTF + _skipUtf8_2(c); + break; + case 3: // 3-byte UTF + _skipUtf8_3(c); + break; + case 4: // 4-byte UTF + _skipUtf8_4(c); + break; + default: + if (c < INT_SPACE) { + // As per [JACKSON-208], call can now return: + _throwUnquotedSpace(c, "string value"); + } else { + // Is this good enough error message? + _reportInvalidChar(c); + } + } + } + } + + /** + * Method for handling cases where first non-space character + * of an expected value token is not legal for standard JSON content. + * + * @since 1.3 + */ + protected JsonToken _handleUnexpectedValue(int c) + throws IOException, JsonParseException + { + // Most likely an error, unless we are to allow single-quote-strings + switch (c) { + case '\'': + if (isEnabled(Feature.ALLOW_SINGLE_QUOTES)) { + return _handleApostropheValue(); + } + break; + case 'N': + _matchToken("NaN", 1); + if (isEnabled(Feature.ALLOW_NON_NUMERIC_NUMBERS)) { + return resetAsNaN("NaN", Double.NaN); + } + _reportError("Non-standard token 'NaN': enable JsonParser.Feature.ALLOW_NON_NUMERIC_NUMBERS to allow"); + break; + case '+': // note: '-' is taken as number + if (_inputPtr >= _inputEnd) { + if (!loadMore()) { + _reportInvalidEOFInValue(); + } + } + return _handleInvalidNumberStart(_inputBuffer[_inputPtr++] & 0xFF, false); + } + + _reportUnexpectedChar(c, "expected a valid value (number, String, array, object, 'true', 'false' or 'null')"); + return null; + } + + protected JsonToken _handleApostropheValue() + throws IOException, JsonParseException + { + int c = 0; + // Otherwise almost verbatim copy of _finishString() + int outPtr = 0; + char[] outBuf = _textBuffer.emptyAndGetCurrentSegment(); + + // Here we do want to do full decoding, hence: + final int[] codes = sInputCodesUtf8; + final byte[] inputBuffer = _inputBuffer; + + main_loop: + while (true) { + // Then the tight ascii non-funny-char loop: + ascii_loop: + while (true) { + if (_inputPtr >= _inputEnd) { + loadMoreGuaranteed(); + } + if (outPtr >= outBuf.length) { + outBuf = _textBuffer.finishCurrentSegment(); + outPtr = 0; + } + int max = _inputEnd; + { + int max2 = _inputPtr + (outBuf.length - outPtr); + if (max2 < max) { + max = max2; + } + } + while (_inputPtr < max) { + c = (int) inputBuffer[_inputPtr++] & 0xFF; + if (c == INT_APOSTROPHE || codes[c] != 0) { + break ascii_loop; + } + outBuf[outPtr++] = (char) c; + } + } + + // Ok: end marker, escape or multi-byte? + if (c == INT_APOSTROPHE) { + break main_loop; + } + + switch (codes[c]) { + case 1: // backslash + if (c != INT_QUOTE) { // marked as special, isn't here + c = _decodeEscaped(); + } + break; + case 2: // 2-byte UTF + c = _decodeUtf8_2(c); + break; + case 3: // 3-byte UTF + if ((_inputEnd - _inputPtr) >= 2) { + c = _decodeUtf8_3fast(c); + } else { + c = _decodeUtf8_3(c); + } + break; + case 4: // 4-byte UTF + c = _decodeUtf8_4(c); + // Let's add first part right away: + outBuf[outPtr++] = (char) (0xD800 | (c >> 10)); + if (outPtr >= outBuf.length) { + outBuf = _textBuffer.finishCurrentSegment(); + outPtr = 0; + } + c = 0xDC00 | (c & 0x3FF); + // And let the other char output down below + break; + default: + if (c < INT_SPACE) { + _throwUnquotedSpace(c, "string value"); + } + // Is this good enough error message? + _reportInvalidChar(c); + } + // Need more room? + if (outPtr >= outBuf.length) { + outBuf = _textBuffer.finishCurrentSegment(); + outPtr = 0; + } + // Ok, let's add char to output: + outBuf[outPtr++] = (char) c; + } + _textBuffer.setCurrentLength(outPtr); + + return JsonToken.VALUE_STRING; + } + + /** + * Method called if expected numeric value (due to leading sign) does not + * look like a number + */ + protected JsonToken _handleInvalidNumberStart(int ch, boolean negative) + throws IOException, JsonParseException + { + if (ch == 'I') { + if (_inputPtr >= _inputEnd) { + if (!loadMore()) { + _reportInvalidEOFInValue(); + } + } + ch = _inputBuffer[_inputPtr++]; + if (ch == 'N') { + String match = negative ? "-INF" :"+INF"; + _matchToken(match, 3); + if (isEnabled(Feature.ALLOW_NON_NUMERIC_NUMBERS)) { + return resetAsNaN(match, negative ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY); + } + _reportError("Non-standard token '"+match+"': enable JsonParser.Feature.ALLOW_NON_NUMERIC_NUMBERS to allow"); + } else if (ch == 'n') { + String match = negative ? "-Infinity" :"+Infinity"; + _matchToken(match, 3); + if (isEnabled(Feature.ALLOW_NON_NUMERIC_NUMBERS)) { + return resetAsNaN(match, negative ? Double.NEGATIVE_INFINITY : Double.POSITIVE_INFINITY); + } + _reportError("Non-standard token '"+match+"': enable JsonParser.Feature.ALLOW_NON_NUMERIC_NUMBERS to allow"); + } + } + reportUnexpectedNumberChar(ch, "expected digit (0-9) to follow minus sign, for valid numeric value"); + return null; + } + + protected final void _matchToken(String matchStr, int i) + throws IOException, JsonParseException + { + final int len = matchStr.length(); + + do { + if (_inputPtr >= _inputEnd) { + if (!loadMore()) { + _reportInvalidEOF(" in a value"); + } + } + if (_inputBuffer[_inputPtr] != matchStr.charAt(i)) { + _reportInvalidToken(matchStr.substring(0, i), "'null', 'true', 'false' or NaN"); + } + ++_inputPtr; + } while (++i < len); + + // but let's also ensure we either get EOF, or non-alphanum char... + if (_inputPtr >= _inputEnd) { + if (!loadMore()) { + return; + } + } + int ch = _inputBuffer[_inputPtr] & 0xFF; + if (ch < '0' || ch == ']' || ch == '}') { // expected/allowed chars + return; + } + // but actually only alphanums are problematic + char c = (char) _decodeCharForError(ch); + if (Character.isJavaIdentifierPart(c)) { + ++_inputPtr; + _reportInvalidToken(matchStr.substring(0, i), "'null', 'true', 'false' or NaN"); + } + } + + protected void _reportInvalidToken(String matchedPart, String msg) + throws IOException, JsonParseException + { + StringBuilder sb = new StringBuilder(matchedPart); + /* Let's just try to find what appears to be the token, using + * regular Java identifier character rules. It's just a heuristic, + * nothing fancy here (nor fast). + */ + while (true) { + if (_inputPtr >= _inputEnd && !loadMore()) { + break; + } + int i = (int) _inputBuffer[_inputPtr++]; + char c = (char) _decodeCharForError(i); + if (!Character.isJavaIdentifierPart(c)) { + break; + } + sb.append(c); + } + _reportError("Unrecognized token '"+sb.toString()+"': was expecting "+msg); + } + + /* + /********************************************************** + /* Internal methods, ws skipping, escape/unescape + /********************************************************** + */ + + private final int _skipWS() + throws IOException, JsonParseException + { + while (_inputPtr < _inputEnd || loadMore()) { + int i = _inputBuffer[_inputPtr++] & 0xFF; + if (i > INT_SPACE) { + if (i != INT_SLASH) { + return i; + } + _skipComment(); + } else if (i != INT_SPACE) { + if (i == INT_LF) { + _skipLF(); + } else if (i == INT_CR) { + _skipCR(); + } else if (i != INT_TAB) { + _throwInvalidSpace(i); + } + } + } + throw _constructError("Unexpected end-of-input within/between "+_parsingContext.getTypeDesc()+" entries"); + } + + private final int _skipWSOrEnd() + throws IOException, JsonParseException + { + while ((_inputPtr < _inputEnd) || loadMore()) { + int i = _inputBuffer[_inputPtr++] & 0xFF; + if (i > INT_SPACE) { + if (i != INT_SLASH) { + return i; + } + _skipComment(); + } else if (i != INT_SPACE) { + if (i == INT_LF) { + _skipLF(); + } else if (i == INT_CR) { + _skipCR(); + } else if (i != INT_TAB) { + _throwInvalidSpace(i); + } + } + } + // We ran out of input... + _handleEOF(); + return -1; + } + + /** + * Helper method for matching and skipping a colon character, + * optionally surrounded by white space + * + * @since 1.9 + */ + private final int _skipColon() + throws IOException, JsonParseException + { + if (_inputPtr >= _inputEnd) { + loadMoreGuaranteed(); + } + // first fast case: we just got a colon without white space: + int i = _inputBuffer[_inputPtr++]; + if (i == INT_COLON) { + if (_inputPtr < _inputEnd) { + i = _inputBuffer[_inputPtr] & 0xFF; + if (i > INT_SPACE && i != INT_SLASH) { + ++_inputPtr; + return i; + } + } + } else { + // need to skip potential leading space + i &= 0xFF; + + space_loop: + while (true) { + switch (i) { + case INT_SPACE: + case INT_TAB: + case INT_CR: + _skipCR(); + break; + case INT_LF: + _skipLF(); + break; + case INT_SLASH: + _skipComment(); + break; + default: + if (i < INT_SPACE) { + _throwInvalidSpace(i); + } + break space_loop; + } + } + if (_inputPtr >= _inputEnd) { + loadMoreGuaranteed(); + } + i = _inputBuffer[_inputPtr++] & 0xFF; + if (i != INT_COLON) { + _reportUnexpectedChar(i, "was expecting a colon to separate field name and value"); + } + } + + // either way, found colon, skip through trailing WS + while (_inputPtr < _inputEnd || loadMore()) { + i = _inputBuffer[_inputPtr++] & 0xFF; + if (i > INT_SPACE) { + if (i != INT_SLASH) { + return i; + } + _skipComment(); + } else if (i != INT_SPACE) { + if (i == INT_LF) { + _skipLF(); + } else if (i == INT_CR) { + _skipCR(); + } else if (i != INT_TAB) { + _throwInvalidSpace(i); + } + } + } + throw _constructError("Unexpected end-of-input within/between "+_parsingContext.getTypeDesc()+" entries"); + } + + private final void _skipComment() + throws IOException, JsonParseException + { + if (!isEnabled(Feature.ALLOW_COMMENTS)) { + _reportUnexpectedChar('/', "maybe a (non-standard) comment? (not recognized as one since Feature 'ALLOW_COMMENTS' not enabled for parser)"); + } + // First: check which comment (if either) it is: + if (_inputPtr >= _inputEnd && !loadMore()) { + _reportInvalidEOF(" in a comment"); + } + int c = _inputBuffer[_inputPtr++] & 0xFF; + if (c == INT_SLASH) { + _skipCppComment(); + } else if (c == INT_ASTERISK) { + _skipCComment(); + } else { + _reportUnexpectedChar(c, "was expecting either '*' or '/' for a comment"); + } + } + + private final void _skipCComment() + throws IOException, JsonParseException + { + // Need to be UTF-8 aware here to decode content (for skipping) + final int[] codes = CharTypes.getInputCodeComment(); + + // Ok: need the matching '*/' + main_loop: + while ((_inputPtr < _inputEnd) || loadMore()) { + int i = (int) _inputBuffer[_inputPtr++] & 0xFF; + int code = codes[i]; + if (code != 0) { + switch (code) { + case INT_ASTERISK: + if (_inputPtr >= _inputEnd && !loadMore()) { + break main_loop; + } + if (_inputBuffer[_inputPtr] == INT_SLASH) { + ++_inputPtr; + return; + } + break; + case INT_LF: + _skipLF(); + break; + case INT_CR: + _skipCR(); + break; + case 2: // 2-byte UTF + _skipUtf8_2(i); + break; + case 3: // 3-byte UTF + _skipUtf8_3(i); + break; + case 4: // 4-byte UTF + _skipUtf8_4(i); + break; + default: // e.g. -1 + // Is this good enough error message? + _reportInvalidChar(i); + } + } + } + _reportInvalidEOF(" in a comment"); + } + + private final void _skipCppComment() + throws IOException, JsonParseException + { + // Ok: need to find EOF or linefeed + final int[] codes = CharTypes.getInputCodeComment(); + while ((_inputPtr < _inputEnd) || loadMore()) { + int i = (int) _inputBuffer[_inputPtr++] & 0xFF; + int code = codes[i]; + if (code != 0) { + switch (code) { + case INT_LF: + _skipLF(); + return; + case INT_CR: + _skipCR(); + return; + case INT_ASTERISK: // nop for these comments + break; + case 2: // 2-byte UTF + _skipUtf8_2(i); + break; + case 3: // 3-byte UTF + _skipUtf8_3(i); + break; + case 4: // 4-byte UTF + _skipUtf8_4(i); + break; + default: // e.g. -1 + // Is this good enough error message? + _reportInvalidChar(i); + } + } + } + } + + @Override + protected final char _decodeEscaped() + throws IOException, JsonParseException + { + if (_inputPtr >= _inputEnd) { + if (!loadMore()) { + _reportInvalidEOF(" in character escape sequence"); + } + } + int c = (int) _inputBuffer[_inputPtr++]; + + switch ((int) c) { + // First, ones that are mapped + case INT_b: + return '\b'; + case INT_t: + return '\t'; + case INT_n: + return '\n'; + case INT_f: + return '\f'; + case INT_r: + return '\r'; + + // And these are to be returned as they are + case INT_QUOTE: + case INT_SLASH: + case INT_BACKSLASH: + return (char) c; + + case INT_u: // and finally hex-escaped + break; + + default: + return _handleUnrecognizedCharacterEscape((char) _decodeCharForError(c)); + } + + // Ok, a hex escape. Need 4 characters + int value = 0; + for (int i = 0; i < 4; ++i) { + if (_inputPtr >= _inputEnd) { + if (!loadMore()) { + _reportInvalidEOF(" in character escape sequence"); + } + } + int ch = (int) _inputBuffer[_inputPtr++]; + int digit = CharTypes.charToHex(ch); + if (digit < 0) { + _reportUnexpectedChar(ch, "expected a hex-digit for character escape sequence"); + } + value = (value << 4) | digit; + } + return (char) value; + } + + protected int _decodeCharForError(int firstByte) + throws IOException, JsonParseException + { + int c = (int) firstByte; + if (c < 0) { // if >= 0, is ascii and fine as is + int needed; + + // Ok; if we end here, we got multi-byte combination + if ((c & 0xE0) == 0xC0) { // 2 bytes (0x0080 - 0x07FF) + c &= 0x1F; + needed = 1; + } else if ((c & 0xF0) == 0xE0) { // 3 bytes (0x0800 - 0xFFFF) + c &= 0x0F; + needed = 2; + } else if ((c & 0xF8) == 0xF0) { + // 4 bytes; double-char with surrogates and all... + c &= 0x07; + needed = 3; + } else { + _reportInvalidInitial(c & 0xFF); + needed = 1; // never gets here + } + + int d = nextByte(); + if ((d & 0xC0) != 0x080) { + _reportInvalidOther(d & 0xFF); + } + c = (c << 6) | (d & 0x3F); + + if (needed > 1) { // needed == 1 means 2 bytes total + d = nextByte(); // 3rd byte + if ((d & 0xC0) != 0x080) { + _reportInvalidOther(d & 0xFF); + } + c = (c << 6) | (d & 0x3F); + if (needed > 2) { // 4 bytes? (need surrogates) + d = nextByte(); + if ((d & 0xC0) != 0x080) { + _reportInvalidOther(d & 0xFF); + } + c = (c << 6) | (d & 0x3F); + } + } + } + return c; + } + + /* + /********************************************************** + /* Internal methods,UTF8 decoding + /********************************************************** + */ + + private final int _decodeUtf8_2(int c) + throws IOException, JsonParseException + { + if (_inputPtr >= _inputEnd) { + loadMoreGuaranteed(); + } + int d = (int) _inputBuffer[_inputPtr++]; + if ((d & 0xC0) != 0x080) { + _reportInvalidOther(d & 0xFF, _inputPtr); + } + return ((c & 0x1F) << 6) | (d & 0x3F); + } + + private final int _decodeUtf8_3(int c1) + throws IOException, JsonParseException + { + if (_inputPtr >= _inputEnd) { + loadMoreGuaranteed(); + } + c1 &= 0x0F; + int d = (int) _inputBuffer[_inputPtr++]; + if ((d & 0xC0) != 0x080) { + _reportInvalidOther(d & 0xFF, _inputPtr); + } + int c = (c1 << 6) | (d & 0x3F); + if (_inputPtr >= _inputEnd) { + loadMoreGuaranteed(); + } + d = (int) _inputBuffer[_inputPtr++]; + if ((d & 0xC0) != 0x080) { + _reportInvalidOther(d & 0xFF, _inputPtr); + } + c = (c << 6) | (d & 0x3F); + return c; + } + + private final int _decodeUtf8_3fast(int c1) + throws IOException, JsonParseException + { + c1 &= 0x0F; + int d = (int) _inputBuffer[_inputPtr++]; + if ((d & 0xC0) != 0x080) { + _reportInvalidOther(d & 0xFF, _inputPtr); + } + int c = (c1 << 6) | (d & 0x3F); + d = (int) _inputBuffer[_inputPtr++]; + if ((d & 0xC0) != 0x080) { + _reportInvalidOther(d & 0xFF, _inputPtr); + } + c = (c << 6) | (d & 0x3F); + return c; + } + + /** + * @return Character value <b>minus 0x10000</c>; this so that caller + * can readily expand it to actual surrogates + */ + private final int _decodeUtf8_4(int c) + throws IOException, JsonParseException + { + if (_inputPtr >= _inputEnd) { + loadMoreGuaranteed(); + } + int d = (int) _inputBuffer[_inputPtr++]; + if ((d & 0xC0) != 0x080) { + _reportInvalidOther(d & 0xFF, _inputPtr); + } + c = ((c & 0x07) << 6) | (d & 0x3F); + + if (_inputPtr >= _inputEnd) { + loadMoreGuaranteed(); + } + d = (int) _inputBuffer[_inputPtr++]; + if ((d & 0xC0) != 0x080) { + _reportInvalidOther(d & 0xFF, _inputPtr); + } + c = (c << 6) | (d & 0x3F); + if (_inputPtr >= _inputEnd) { + loadMoreGuaranteed(); + } + d = (int) _inputBuffer[_inputPtr++]; + if ((d & 0xC0) != 0x080) { + _reportInvalidOther(d & 0xFF, _inputPtr); + } + + /* note: won't change it to negative here, since caller + * already knows it'll need a surrogate + */ + return ((c << 6) | (d & 0x3F)) - 0x10000; + } + + private final void _skipUtf8_2(int c) + throws IOException, JsonParseException + { + if (_inputPtr >= _inputEnd) { + loadMoreGuaranteed(); + } + c = (int) _inputBuffer[_inputPtr++]; + if ((c & 0xC0) != 0x080) { + _reportInvalidOther(c & 0xFF, _inputPtr); + } + } + + /* Alas, can't heavily optimize skipping, since we still have to + * do validity checks... + */ + private final void _skipUtf8_3(int c) + throws IOException, JsonParseException + { + if (_inputPtr >= _inputEnd) { + loadMoreGuaranteed(); + } + //c &= 0x0F; + c = (int) _inputBuffer[_inputPtr++]; + if ((c & 0xC0) != 0x080) { + _reportInvalidOther(c & 0xFF, _inputPtr); + } + if (_inputPtr >= _inputEnd) { + loadMoreGuaranteed(); + } + c = (int) _inputBuffer[_inputPtr++]; + if ((c & 0xC0) != 0x080) { + _reportInvalidOther(c & 0xFF, _inputPtr); + } + } + + private final void _skipUtf8_4(int c) + throws IOException, JsonParseException + { + if (_inputPtr >= _inputEnd) { + loadMoreGuaranteed(); + } + int d = (int) _inputBuffer[_inputPtr++]; + if ((d & 0xC0) != 0x080) { + _reportInvalidOther(d & 0xFF, _inputPtr); + } + if (_inputPtr >= _inputEnd) { + loadMoreGuaranteed(); + } + d = (int) _inputBuffer[_inputPtr++]; + if ((d & 0xC0) != 0x080) { + _reportInvalidOther(d & 0xFF, _inputPtr); + } + if (_inputPtr >= _inputEnd) { + loadMoreGuaranteed(); + } + d = (int) _inputBuffer[_inputPtr++]; + if ((d & 0xC0) != 0x080) { + _reportInvalidOther(d & 0xFF, _inputPtr); + } + } + + /* + /********************************************************** + /* Internal methods, input loading + /********************************************************** + */ + + /** + * We actually need to check the character value here + * (to see if we have \n following \r). + */ + protected final void _skipCR() throws IOException + { + if (_inputPtr < _inputEnd || loadMore()) { + if (_inputBuffer[_inputPtr] == BYTE_LF) { + ++_inputPtr; + } + } + ++_currInputRow; + _currInputRowStart = _inputPtr; + } + + protected final void _skipLF() throws IOException + { + ++_currInputRow; + _currInputRowStart = _inputPtr; + } + + private int nextByte() + throws IOException, JsonParseException + { + if (_inputPtr >= _inputEnd) { + loadMoreGuaranteed(); + } + return _inputBuffer[_inputPtr++] & 0xFF; + } + + /* + /********************************************************** + /* Internal methods, error reporting + /********************************************************** + */ + + protected void _reportInvalidChar(int c) + throws JsonParseException + { + // Either invalid WS or illegal UTF-8 start char + if (c < INT_SPACE) { + _throwInvalidSpace(c); + } + _reportInvalidInitial(c); + } + + protected void _reportInvalidInitial(int mask) + throws JsonParseException + { + _reportError("Invalid UTF-8 start byte 0x"+Integer.toHexString(mask)); + } + + protected void _reportInvalidOther(int mask) + throws JsonParseException + { + _reportError("Invalid UTF-8 middle byte 0x"+Integer.toHexString(mask)); + } + + protected void _reportInvalidOther(int mask, int ptr) + throws JsonParseException + { + _inputPtr = ptr; + _reportInvalidOther(mask); + } + + public static int[] growArrayBy(int[] arr, int more) + { + if (arr == null) { + return new int[more]; + } + int[] old = arr; + int len = arr.length; + arr = new int[len + more]; + System.arraycopy(old, 0, arr, 0, len); + return arr; + } + + /* + /********************************************************** + /* Binary access + /********************************************************** + */ + + /** + * Efficient handling for incremental parsing of base64-encoded + * textual content. + */ + protected byte[] _decodeBase64(Base64Variant b64variant) + throws IOException, JsonParseException + { + ByteArrayBuilder builder = _getByteArrayBuilder(); + + //main_loop: + while (true) { + // first, we'll skip preceding white space, if any + int ch; + do { + if (_inputPtr >= _inputEnd) { + loadMoreGuaranteed(); + } + ch = (int) _inputBuffer[_inputPtr++] & 0xFF; + } while (ch <= INT_SPACE); + int bits = b64variant.decodeBase64Char(ch); + if (bits < 0) { // reached the end, fair and square? + if (ch == INT_QUOTE) { + return builder.toByteArray(); + } + bits = _decodeBase64Escape(b64variant, ch, 0); + if (bits < 0) { // white space to skip + continue; + } + } + int decodedData = bits; + + // then second base64 char; can't get padding yet, nor ws + + if (_inputPtr >= _inputEnd) { + loadMoreGuaranteed(); + } + ch = _inputBuffer[_inputPtr++] & 0xFF; + bits = b64variant.decodeBase64Char(ch); + if (bits < 0) { + bits = _decodeBase64Escape(b64variant, ch, 1); + } + decodedData = (decodedData << 6) | bits; + + // third base64 char; can be padding, but not ws + if (_inputPtr >= _inputEnd) { + loadMoreGuaranteed(); + } + ch = _inputBuffer[_inputPtr++] & 0xFF; + bits = b64variant.decodeBase64Char(ch); + + // First branch: can get padding (-> 1 byte) + if (bits < 0) { + if (bits != Base64Variant.BASE64_VALUE_PADDING) { + // as per [JACKSON-631], could also just be 'missing' padding + if (ch == '"' && !b64variant.usesPadding()) { + decodedData >>= 4; + builder.append(decodedData); + return builder.toByteArray(); + } + bits = _decodeBase64Escape(b64variant, ch, 2); + } + if (bits == Base64Variant.BASE64_VALUE_PADDING) { + // Ok, must get padding + if (_inputPtr >= _inputEnd) { + loadMoreGuaranteed(); + } + ch = _inputBuffer[_inputPtr++] & 0xFF; + if (!b64variant.usesPaddingChar(ch)) { + throw reportInvalidBase64Char(b64variant, ch, 3, "expected padding character '"+b64variant.getPaddingChar()+"'"); + } + // Got 12 bits, only need 8, need to shift + decodedData >>= 4; + builder.append(decodedData); + continue; + } + } + // Nope, 2 or 3 bytes + decodedData = (decodedData << 6) | bits; + // fourth and last base64 char; can be padding, but not ws + if (_inputPtr >= _inputEnd) { + loadMoreGuaranteed(); + } + ch = _inputBuffer[_inputPtr++] & 0xFF; + bits = b64variant.decodeBase64Char(ch); + if (bits < 0) { + if (bits != Base64Variant.BASE64_VALUE_PADDING) { + // as per [JACKSON-631], could also just be 'missing' padding + if (ch == '"' && !b64variant.usesPadding()) { + decodedData >>= 2; + builder.appendTwoBytes(decodedData); + return builder.toByteArray(); + } + bits = _decodeBase64Escape(b64variant, ch, 3); + } + if (bits == Base64Variant.BASE64_VALUE_PADDING) { + /* With padding we only get 2 bytes; but we have + * to shift it a bit so it is identical to triplet + * case with partial output. + * 3 chars gives 3x6 == 18 bits, of which 2 are + * dummies, need to discard: + */ + decodedData >>= 2; + builder.appendTwoBytes(decodedData); + continue; + } + } + // otherwise, our triplet is now complete + decodedData = (decodedData << 6) | bits; + builder.appendThreeBytes(decodedData); + } + } +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/impl/WriterBasedGenerator.java b/1.9.10/src/java/org/codehaus/jackson/impl/WriterBasedGenerator.java new file mode 100644 index 0000000..de26493 --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/impl/WriterBasedGenerator.java
@@ -0,0 +1,1815 @@ +package org.codehaus.jackson.impl; + +import java.io.*; +import java.math.BigDecimal; +import java.math.BigInteger; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.io.*; +import org.codehaus.jackson.util.CharTypes; + +/** + * {@link JsonGenerator} that outputs JSON content using a {@link java.io.Writer} + * which handles character encoding. + */ +public final class WriterBasedGenerator + extends JsonGeneratorBase +{ + final protected static int SHORT_WRITE = 32; + + final protected static char[] HEX_CHARS = CharTypes.copyHexChars(); + + /** + * This is the default set of escape codes, over 7-bit ASCII range + * (first 128 character codes), used for single-byte UTF-8 characters. + */ + protected final static int[] sOutputEscapes = CharTypes.get7BitOutputEscapes(); + + /* + /********************************************************** + /* Configuration + /********************************************************** + */ + + final protected IOContext _ioContext; + + final protected Writer _writer; + + /* + /********************************************************** + /* Configuration, output escaping + /********************************************************** + */ + + /** + * Currently active set of output escape code definitions (whether + * and how to escape or not) for 7-bit ASCII range (first 128 + * character codes). Defined separately to make potentially + * customizable + */ + protected int[] _outputEscapes = sOutputEscapes; + + /** + * Value between 128 (0x80) and 65535 (0xFFFF) that indicates highest + * Unicode code point that will not need escaping; or 0 to indicate + * that all characters can be represented without escaping. + * Typically used to force escaping of some portion of character set; + * for example to always escape non-ASCII characters (if value was 127). + *<p> + * NOTE: not all sub-classes make use of this setting. + */ + protected int _maximumNonEscapedChar; + + /** + * Definition of custom character escapes to use for generators created + * by this factory, if any. If null, standard data format specific + * escapes are used. + * + * @since 1.8 + */ + protected CharacterEscapes _characterEscapes; + + /** + * When custom escapes are used, this member variable can be used to + * store escape to use + * + * @since 1.8 + */ + protected SerializableString _currentEscape; + + /* + /********************************************************** + /* Output buffering + /********************************************************** + */ + + /** + * Intermediate buffer in which contents are buffered before + * being written using {@link #_writer}. + */ + protected char[] _outputBuffer; + + /** + * Pointer to the first buffered character to output + */ + protected int _outputHead = 0; + + /** + * Pointer to the position right beyond the last character to output + * (end marker; may point to position right beyond the end of the buffer) + */ + protected int _outputTail = 0; + + /** + * End marker of the output buffer; one past the last valid position + * within the buffer. + */ + protected int _outputEnd; + + /** + * Short (14 char) temporary buffer allocated if needed, for constructing + * escape sequences + */ + protected char[] _entityBuffer; + + /* + /********************************************************** + /* Life-cycle + /********************************************************** + */ + + public WriterBasedGenerator(IOContext ctxt, int features, ObjectCodec codec, + Writer w) + { + super(features, codec); + _ioContext = ctxt; + _writer = w; + _outputBuffer = ctxt.allocConcatBuffer(); + _outputEnd = _outputBuffer.length; + + if (isEnabled(Feature.ESCAPE_NON_ASCII)) { + setHighestNonEscapedChar(127); + } + } + + /* + /********************************************************** + /* Overridden configuration methods + /********************************************************** + */ + + @Override + public JsonGenerator setHighestNonEscapedChar(int charCode) { + _maximumNonEscapedChar = (charCode < 0) ? 0 : charCode; + return this; + } + + @Override + public int getHighestEscapedChar() { + return _maximumNonEscapedChar; + } + + @Override + public JsonGenerator setCharacterEscapes(CharacterEscapes esc) + { + _characterEscapes = esc; + if (esc == null) { // revert to standard escapes + _outputEscapes = sOutputEscapes; + } else { + _outputEscapes = esc.getEscapeCodesForAscii(); + } + return this; + } + + /** + * Method for accessing custom escapes factory uses for {@link JsonGenerator}s + * it creates. + * + * @since 1.8 + */ + @Override + public CharacterEscapes getCharacterEscapes() { + return _characterEscapes; + } + + @Override + public Object getOutputTarget() { + return _writer; + } + + /* + /********************************************************** + /* Overridden methods + /********************************************************** + */ + + /* Most overrides in this section are just to make methods final, + * to allow better inlining... + */ + + @Override + public final void writeFieldName(String name) throws IOException, JsonGenerationException + { + int status = _writeContext.writeFieldName(name); + if (status == JsonWriteContext.STATUS_EXPECT_VALUE) { + _reportError("Can not write a field name, expecting a value"); + } + _writeFieldName(name, (status == JsonWriteContext.STATUS_OK_AFTER_COMMA)); + } + + @Override + public final void writeStringField(String fieldName, String value) + throws IOException, JsonGenerationException + { + writeFieldName(fieldName); + writeString(value); + } + + @Override + public final void writeFieldName(SerializedString name) + throws IOException, JsonGenerationException + { + // Object is a value, need to verify it's allowed + int status = _writeContext.writeFieldName(name.getValue()); + if (status == JsonWriteContext.STATUS_EXPECT_VALUE) { + _reportError("Can not write a field name, expecting a value"); + } + _writeFieldName(name, (status == JsonWriteContext.STATUS_OK_AFTER_COMMA)); + } + + @Override + public final void writeFieldName(SerializableString name) + throws IOException, JsonGenerationException + { + // Object is a value, need to verify it's allowed + int status = _writeContext.writeFieldName(name.getValue()); + if (status == JsonWriteContext.STATUS_EXPECT_VALUE) { + _reportError("Can not write a field name, expecting a value"); + } + _writeFieldName(name, (status == JsonWriteContext.STATUS_OK_AFTER_COMMA)); + } + + /* + /********************************************************** + /* Output method implementations, structural + /********************************************************** + */ + + @Override + public final void writeStartArray() throws IOException, JsonGenerationException + { + _verifyValueWrite("start an array"); + _writeContext = _writeContext.createChildArrayContext(); + if (_cfgPrettyPrinter != null) { + _cfgPrettyPrinter.writeStartArray(this); + } else { + if (_outputTail >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = '['; + } + } + + @Override + public final void writeEndArray() throws IOException, JsonGenerationException + { + if (!_writeContext.inArray()) { + _reportError("Current context not an ARRAY but "+_writeContext.getTypeDesc()); + } + if (_cfgPrettyPrinter != null) { + _cfgPrettyPrinter.writeEndArray(this, _writeContext.getEntryCount()); + } else { + if (_outputTail >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = ']'; + } + _writeContext = _writeContext.getParent(); + } + + @Override + public final void writeStartObject() throws IOException, JsonGenerationException + { + _verifyValueWrite("start an object"); + _writeContext = _writeContext.createChildObjectContext(); + if (_cfgPrettyPrinter != null) { + _cfgPrettyPrinter.writeStartObject(this); + } else { + if (_outputTail >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = '{'; + } + } + + @Override + public final void writeEndObject() throws IOException, JsonGenerationException + { + if (!_writeContext.inObject()) { + _reportError("Current context not an object but "+_writeContext.getTypeDesc()); + } + if (_cfgPrettyPrinter != null) { + _cfgPrettyPrinter.writeEndObject(this, _writeContext.getEntryCount()); + } else { + if (_outputTail >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = '}'; + } + _writeContext = _writeContext.getParent(); + } + + protected void _writeFieldName(String name, boolean commaBefore) + throws IOException, JsonGenerationException + { + if (_cfgPrettyPrinter != null) { + _writePPFieldName(name, commaBefore); + return; + } + // for fast+std case, need to output up to 2 chars, comma, dquote + if ((_outputTail + 1) >= _outputEnd) { + _flushBuffer(); + } + if (commaBefore) { + _outputBuffer[_outputTail++] = ','; + } + + /* To support [JACKSON-46], we'll do this: + * (Question: should quoting of spaces (etc) still be enabled?) + */ + if (!isEnabled(Feature.QUOTE_FIELD_NAMES)) { + _writeString(name); + return; + } + + // we know there's room for at least one more char + _outputBuffer[_outputTail++] = '"'; + // The beef: + _writeString(name); + // and closing quotes; need room for one more char: + if (_outputTail >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = '"'; + } + + public void _writeFieldName(SerializableString name, boolean commaBefore) + throws IOException, JsonGenerationException + { + if (_cfgPrettyPrinter != null) { + _writePPFieldName(name, commaBefore); + return; + } + // for fast+std case, need to output up to 2 chars, comma, dquote + if ((_outputTail + 1) >= _outputEnd) { + _flushBuffer(); + } + if (commaBefore) { + _outputBuffer[_outputTail++] = ','; + } + /* To support [JACKSON-46], we'll do this: + * (Question: should quoting of spaces (etc) still be enabled?) + */ + final char[] quoted = name.asQuotedChars(); + if (!isEnabled(Feature.QUOTE_FIELD_NAMES)) { + writeRaw(quoted, 0, quoted.length); + return; + } + // we know there's room for at least one more char + _outputBuffer[_outputTail++] = '"'; + // The beef: + final int qlen = quoted.length; + if ((_outputTail + qlen + 1) >= _outputEnd) { + writeRaw(quoted, 0, qlen); + // and closing quotes; need room for one more char: + if (_outputTail >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = '"'; + } else { + System.arraycopy(quoted, 0, _outputBuffer, _outputTail, qlen); + _outputTail += qlen; + _outputBuffer[_outputTail++] = '"'; + } + } + + /** + * Specialized version of <code>_writeFieldName</code>, off-lined + * to keep the "fast path" as simple (and hopefully fast) as possible. + */ + protected final void _writePPFieldName(String name, boolean commaBefore) + throws IOException, JsonGenerationException + { + if (commaBefore) { + _cfgPrettyPrinter.writeObjectEntrySeparator(this); + } else { + _cfgPrettyPrinter.beforeObjectEntries(this); + } + + if (isEnabled(Feature.QUOTE_FIELD_NAMES)) { // standard + if (_outputTail >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = '"'; + _writeString(name); + if (_outputTail >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = '"'; + } else { // non-standard, omit quotes + _writeString(name); + } + } + + protected final void _writePPFieldName(SerializableString name, boolean commaBefore) + throws IOException, JsonGenerationException + { + if (commaBefore) { + _cfgPrettyPrinter.writeObjectEntrySeparator(this); + } else { + _cfgPrettyPrinter.beforeObjectEntries(this); + } + + final char[] quoted = name.asQuotedChars(); + if (isEnabled(Feature.QUOTE_FIELD_NAMES)) { // standard + if (_outputTail >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = '"'; + writeRaw(quoted, 0, quoted.length); + if (_outputTail >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = '"'; + } else { // non-standard, omit quotes + writeRaw(quoted, 0, quoted.length); + } + } + + /* + /********************************************************** + /* Output method implementations, textual + /********************************************************** + */ + + @Override + public void writeString(String text) + throws IOException, JsonGenerationException + { + _verifyValueWrite("write text value"); + if (text == null) { + _writeNull(); + return; + } + if (_outputTail >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = '"'; + _writeString(text); + // And finally, closing quotes + if (_outputTail >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = '"'; + } + + @Override + public void writeString(char[] text, int offset, int len) + throws IOException, JsonGenerationException + { + _verifyValueWrite("write text value"); + if (_outputTail >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = '"'; + _writeString(text, offset, len); + // And finally, closing quotes + if (_outputTail >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = '"'; + } + + @Override + public final void writeString(SerializableString sstr) + throws IOException, JsonGenerationException + { + _verifyValueWrite("write text value"); + if (_outputTail >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = '"'; + // Note: copied from writeRaw: + char[] text = sstr.asQuotedChars(); + final int len = text.length; + // Only worth buffering if it's a short write? + if (len < SHORT_WRITE) { + int room = _outputEnd - _outputTail; + if (len > room) { + _flushBuffer(); + } + System.arraycopy(text, 0, _outputBuffer, _outputTail, len); + _outputTail += len; + } else { + // Otherwise, better just pass through: + _flushBuffer(); + _writer.write(text, 0, len); + } + if (_outputTail >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = '"'; + } + + @Override + public void writeRawUTF8String(byte[] text, int offset, int length) + throws IOException, JsonGenerationException + { + // could add support for buffering if we really want it... + _reportUnsupportedOperation(); + } + + @Override + public void writeUTF8String(byte[] text, int offset, int length) + throws IOException, JsonGenerationException + { + // could add support for buffering if we really want it... + _reportUnsupportedOperation(); + } + + /* + /********************************************************** + /* Output method implementations, unprocessed ("raw") + /********************************************************** + */ + + @Override + public void writeRaw(String text) + throws IOException, JsonGenerationException + { + // Nothing to check, can just output as is + int len = text.length(); + int room = _outputEnd - _outputTail; + + if (room == 0) { + _flushBuffer(); + room = _outputEnd - _outputTail; + } + // But would it nicely fit in? If yes, it's easy + if (room >= len) { + text.getChars(0, len, _outputBuffer, _outputTail); + _outputTail += len; + } else { + writeRawLong(text); + } + } + + @Override + public void writeRaw(String text, int start, int len) + throws IOException, JsonGenerationException + { + // Nothing to check, can just output as is + int room = _outputEnd - _outputTail; + + if (room < len) { + _flushBuffer(); + room = _outputEnd - _outputTail; + } + // But would it nicely fit in? If yes, it's easy + if (room >= len) { + text.getChars(start, start+len, _outputBuffer, _outputTail); + _outputTail += len; + } else { + writeRawLong(text.substring(start, start+len)); + } + } + + @Override + public void writeRaw(char[] text, int offset, int len) + throws IOException, JsonGenerationException + { + // Only worth buffering if it's a short write? + if (len < SHORT_WRITE) { + int room = _outputEnd - _outputTail; + if (len > room) { + _flushBuffer(); + } + System.arraycopy(text, offset, _outputBuffer, _outputTail, len); + _outputTail += len; + return; + } + // Otherwise, better just pass through: + _flushBuffer(); + _writer.write(text, offset, len); + } + + @Override + public void writeRaw(char c) + throws IOException, JsonGenerationException + { + if (_outputTail >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = c; + } + + private void writeRawLong(String text) + throws IOException, JsonGenerationException + { + int room = _outputEnd - _outputTail; + // If not, need to do it by looping + text.getChars(0, room, _outputBuffer, _outputTail); + _outputTail += room; + _flushBuffer(); + int offset = room; + int len = text.length() - room; + + while (len > _outputEnd) { + int amount = _outputEnd; + text.getChars(offset, offset+amount, _outputBuffer, 0); + _outputHead = 0; + _outputTail = amount; + _flushBuffer(); + offset += amount; + len -= amount; + } + // And last piece (at most length of buffer) + text.getChars(offset, offset+len, _outputBuffer, 0); + _outputHead = 0; + _outputTail = len; + } + + /* + /********************************************************** + /* Output method implementations, base64-encoded binary + /********************************************************** + */ + + @Override + public void writeBinary(Base64Variant b64variant, byte[] data, int offset, int len) + throws IOException, JsonGenerationException + { + _verifyValueWrite("write binary value"); + // Starting quotes + if (_outputTail >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = '"'; + _writeBinary(b64variant, data, offset, offset+len); + // and closing quotes + if (_outputTail >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = '"'; + } + + /* + /********************************************************** + /* Output method implementations, primitive + /********************************************************** + */ + + @Override + public void writeNumber(int i) + throws IOException, JsonGenerationException + { + _verifyValueWrite("write number"); + if (_cfgNumbersAsStrings) { + _writeQuotedInt(i); + return; + } + // up to 10 digits and possible minus sign + if ((_outputTail + 11) >= _outputEnd) { + _flushBuffer(); + } + _outputTail = NumberOutput.outputInt(i, _outputBuffer, _outputTail); + } + + private final void _writeQuotedInt(int i) throws IOException { + if ((_outputTail + 13) >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = '"'; + _outputTail = NumberOutput.outputInt(i, _outputBuffer, _outputTail); + _outputBuffer[_outputTail++] = '"'; + } + + @Override + public void writeNumber(long l) + throws IOException, JsonGenerationException + { + _verifyValueWrite("write number"); + if (_cfgNumbersAsStrings) { + _writeQuotedLong(l); + return; + } + if ((_outputTail + 21) >= _outputEnd) { + // up to 20 digits, minus sign + _flushBuffer(); + } + _outputTail = NumberOutput.outputLong(l, _outputBuffer, _outputTail); + } + + private final void _writeQuotedLong(long l) throws IOException { + if ((_outputTail + 23) >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = '"'; + _outputTail = NumberOutput.outputLong(l, _outputBuffer, _outputTail); + _outputBuffer[_outputTail++] = '"'; + } + + // !!! 05-Aug-2008, tatus: Any ways to optimize these? + + @Override + public void writeNumber(BigInteger value) + throws IOException, JsonGenerationException + { + _verifyValueWrite("write number"); + if (value == null) { + _writeNull(); + } else if (_cfgNumbersAsStrings) { + _writeQuotedRaw(value); + } else { + writeRaw(value.toString()); + } + } + + + @Override + public void writeNumber(double d) + throws IOException, JsonGenerationException + { + if (_cfgNumbersAsStrings || + // [JACKSON-139] + (((Double.isNaN(d) || Double.isInfinite(d)) + && isEnabled(Feature.QUOTE_NON_NUMERIC_NUMBERS)))) { + writeString(String.valueOf(d)); + return; + } + // What is the max length for doubles? 40 chars? + _verifyValueWrite("write number"); + writeRaw(String.valueOf(d)); + } + + @Override + public void writeNumber(float f) + throws IOException, JsonGenerationException + { + if (_cfgNumbersAsStrings || + // [JACKSON-139] + (((Float.isNaN(f) || Float.isInfinite(f)) + && isEnabled(Feature.QUOTE_NON_NUMERIC_NUMBERS)))) { + writeString(String.valueOf(f)); + return; + } + // What is the max length for floats? + _verifyValueWrite("write number"); + writeRaw(String.valueOf(f)); + } + + @Override + public void writeNumber(BigDecimal value) + throws IOException, JsonGenerationException + { + // Don't really know max length for big decimal, no point checking + _verifyValueWrite("write number"); + if (value == null) { + _writeNull(); + } else if (_cfgNumbersAsStrings) { + _writeQuotedRaw(value); + } else { + writeRaw(value.toString()); + } + } + + @Override + public void writeNumber(String encodedValue) + throws IOException, JsonGenerationException + { + _verifyValueWrite("write number"); + if (_cfgNumbersAsStrings) { + _writeQuotedRaw(encodedValue); + } else { + writeRaw(encodedValue); + } + } + + private final void _writeQuotedRaw(Object value) throws IOException + { + if (_outputTail >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = '"'; + writeRaw(value.toString()); + if (_outputTail >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = '"'; + } + + @Override + public void writeBoolean(boolean state) + throws IOException, JsonGenerationException + { + _verifyValueWrite("write boolean value"); + if ((_outputTail + 5) >= _outputEnd) { + _flushBuffer(); + } + int ptr = _outputTail; + char[] buf = _outputBuffer; + if (state) { + buf[ptr] = 't'; + buf[++ptr] = 'r'; + buf[++ptr] = 'u'; + buf[++ptr] = 'e'; + } else { + buf[ptr] = 'f'; + buf[++ptr] = 'a'; + buf[++ptr] = 'l'; + buf[++ptr] = 's'; + buf[++ptr] = 'e'; + } + _outputTail = ptr+1; + } + + @Override + public void writeNull() + throws IOException, JsonGenerationException + { + _verifyValueWrite("write null value"); + _writeNull(); + } + + /* + /********************************************************** + /* Implementations for other methods + /********************************************************** + */ + + @Override + protected final void _verifyValueWrite(String typeMsg) + throws IOException, JsonGenerationException + { + int status = _writeContext.writeValue(); + if (status == JsonWriteContext.STATUS_EXPECT_NAME) { + _reportError("Can not "+typeMsg+", expecting field name"); + } + if (_cfgPrettyPrinter == null) { + char c; + switch (status) { + case JsonWriteContext.STATUS_OK_AFTER_COMMA: + c = ','; + break; + case JsonWriteContext.STATUS_OK_AFTER_COLON: + c = ':'; + break; + case JsonWriteContext.STATUS_OK_AFTER_SPACE: + c = ' '; + break; + case JsonWriteContext.STATUS_OK_AS_IS: + default: + return; + } + if (_outputTail >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail] = c; + ++_outputTail; + return; + } + // Otherwise, pretty printer knows what to do... + _verifyPrettyValueWrite(typeMsg, status); + } + + protected final void _verifyPrettyValueWrite(String typeMsg, int status) + throws IOException, JsonGenerationException + { + // If we have a pretty printer, it knows what to do: + switch (status) { + case JsonWriteContext.STATUS_OK_AFTER_COMMA: // array + _cfgPrettyPrinter.writeArrayValueSeparator(this); + break; + case JsonWriteContext.STATUS_OK_AFTER_COLON: + _cfgPrettyPrinter.writeObjectFieldValueSeparator(this); + break; + case JsonWriteContext.STATUS_OK_AFTER_SPACE: + _cfgPrettyPrinter.writeRootValueSeparator(this); + break; + case JsonWriteContext.STATUS_OK_AS_IS: + // First entry, but of which context? + if (_writeContext.inArray()) { + _cfgPrettyPrinter.beforeArrayValues(this); + } else if (_writeContext.inObject()) { + _cfgPrettyPrinter.beforeObjectEntries(this); + } + break; + default: + _cantHappen(); + break; + } + } + + /* + /********************************************************** + /* Low-level output handling + /********************************************************** + */ + + @Override + public final void flush() + throws IOException + { + _flushBuffer(); + if (_writer != null) { + if (isEnabled(Feature.FLUSH_PASSED_TO_STREAM)) { + _writer.flush(); + } + } + } + + @Override + public void close() + throws IOException + { + super.close(); + + /* 05-Dec-2008, tatu: To add [JACKSON-27], need to close open + * scopes. + */ + // First: let's see that we still have buffers... + if (_outputBuffer != null + && isEnabled(Feature.AUTO_CLOSE_JSON_CONTENT)) { + while (true) { + JsonStreamContext ctxt = getOutputContext(); + if (ctxt.inArray()) { + writeEndArray(); + } else if (ctxt.inObject()) { + writeEndObject(); + } else { + break; + } + } + } + _flushBuffer(); + + /* 25-Nov-2008, tatus: As per [JACKSON-16] we are not to call close() + * on the underlying Reader, unless we "own" it, or auto-closing + * feature is enabled. + * One downside: when using UTF8Writer, underlying buffer(s) + * may not be properly recycled if we don't close the writer. + */ + if (_writer != null) { + if (_ioContext.isResourceManaged() || isEnabled(Feature.AUTO_CLOSE_TARGET)) { + _writer.close(); + } else if (isEnabled(Feature.FLUSH_PASSED_TO_STREAM)) { + // If we can't close it, we should at least flush + _writer.flush(); + } + } + // Internal buffer(s) generator has can now be released as well + _releaseBuffers(); + } + + @Override + protected void _releaseBuffers() + { + char[] buf = _outputBuffer; + if (buf != null) { + _outputBuffer = null; + _ioContext.releaseConcatBuffer(buf); + } + } + + /* + /********************************************************** + /* Internal methods, low-level writing; text, default + /********************************************************** + */ + + private void _writeString(String text) + throws IOException, JsonGenerationException + { + /* One check first: if String won't fit in the buffer, let's + * segment writes. No point in extending buffer to huge sizes + * (like if someone wants to include multi-megabyte base64 + * encoded stuff or such) + */ + final int len = text.length(); + if (len > _outputEnd) { // Let's reserve space for entity at begin/end + _writeLongString(text); + return; + } + + // Ok: we know String will fit in buffer ok + // But do we need to flush first? + if ((_outputTail + len) > _outputEnd) { + _flushBuffer(); + } + text.getChars(0, len, _outputBuffer, _outputTail); + + if (_characterEscapes != null) { + _writeStringCustom(len); + } else if (_maximumNonEscapedChar != 0) { + _writeStringASCII(len, _maximumNonEscapedChar); + } else { + _writeString2(len); + } + } + + private void _writeString2(final int len) + throws IOException, JsonGenerationException + { + // And then we'll need to verify need for escaping etc: + int end = _outputTail + len; + final int[] escCodes = _outputEscapes; + final int escLen = escCodes.length; + + output_loop: + while (_outputTail < end) { + // Fast loop for chars not needing escaping + escape_loop: + while (true) { + char c = _outputBuffer[_outputTail]; + if (c < escLen && escCodes[c] != 0) { + break escape_loop; + } + if (++_outputTail >= end) { + break output_loop; + } + } + + // Ok, bumped into something that needs escaping. + /* First things first: need to flush the buffer. + * Inlined, as we don't want to lose tail pointer + */ + int flushLen = (_outputTail - _outputHead); + if (flushLen > 0) { + _writer.write(_outputBuffer, _outputHead, flushLen); + } + /* In any case, tail will be the new start, so hopefully + * we have room now. + */ + char c = _outputBuffer[_outputTail++]; + _prependOrWriteCharacterEscape(c, escCodes[c]); + } + } + + /** + * Method called to write "long strings", strings whose length exceeds + * output buffer length. + */ + private void _writeLongString(String text) + throws IOException, JsonGenerationException + { + // First things first: let's flush the buffer to get some more room + _flushBuffer(); + + // Then we can write + final int textLen = text.length(); + int offset = 0; + do { + int max = _outputEnd; + int segmentLen = ((offset + max) > textLen) + ? (textLen - offset) : max; + text.getChars(offset, offset+segmentLen, _outputBuffer, 0); + if (_characterEscapes != null) { + _writeSegmentCustom(segmentLen); + } else if (_maximumNonEscapedChar != 0) { + _writeSegmentASCII(segmentLen, _maximumNonEscapedChar); + } else { + _writeSegment(segmentLen); + } + offset += segmentLen; + } while (offset < textLen); + } + + /** + * Method called to output textual context which has been copied + * to the output buffer prior to call. If any escaping is needed, + * it will also be handled by the method. + *<p> + * Note: when called, textual content to write is within output + * buffer, right after buffered content (if any). That's why only + * length of that text is passed, as buffer and offset are implied. + */ + private final void _writeSegment(int end) + throws IOException, JsonGenerationException + { + final int[] escCodes = _outputEscapes; + final int escLen = escCodes.length; + + int ptr = 0; + int start = ptr; + + output_loop: + while (ptr < end) { + // Fast loop for chars not needing escaping + char c; + while (true) { + c = _outputBuffer[ptr]; + if (c < escLen && escCodes[c] != 0) { + break; + } + if (++ptr >= end) { + break; + } + } + + // Ok, bumped into something that needs escaping. + /* First things first: need to flush the buffer. + * Inlined, as we don't want to lose tail pointer + */ + int flushLen = (ptr - start); + if (flushLen > 0) { + _writer.write(_outputBuffer, start, flushLen); + if (ptr >= end) { + break output_loop; + } + } + ++ptr; + // So; either try to prepend (most likely), or write directly: + start = _prependOrWriteCharacterEscape(_outputBuffer, ptr, end, c, escCodes[c]); + } + } + + /** + * This method called when the string content is already in + * a char buffer, and need not be copied for processing. + */ + private final void _writeString(char[] text, int offset, int len) + throws IOException, JsonGenerationException + { + if (_characterEscapes != null) { + _writeStringCustom(text, offset, len); + return; + } + if (_maximumNonEscapedChar != 0) { + _writeStringASCII(text, offset, len, _maximumNonEscapedChar); + return; + } + + /* Let's just find longest spans of non-escapable + * content, and for each see if it makes sense + * to copy them, or write through + */ + len += offset; // -> len marks the end from now on + final int[] escCodes = _outputEscapes; + final int escLen = escCodes.length; + while (offset < len) { + int start = offset; + + while (true) { + char c = text[offset]; + if (c < escLen && escCodes[c] != 0) { + break; + } + if (++offset >= len) { + break; + } + } + + // Short span? Better just copy it to buffer first: + int newAmount = offset - start; + if (newAmount < SHORT_WRITE) { + // Note: let's reserve room for escaped char (up to 6 chars) + if ((_outputTail + newAmount) > _outputEnd) { + _flushBuffer(); + } + if (newAmount > 0) { + System.arraycopy(text, start, _outputBuffer, _outputTail, newAmount); + _outputTail += newAmount; + } + } else { // Nope: better just write through + _flushBuffer(); + _writer.write(text, start, newAmount); + } + // Was this the end? + if (offset >= len) { // yup + break; + } + // Nope, need to escape the char. + char c = text[offset++]; + _appendCharacterEscape(c, escCodes[c]); + } + } + + /* + /********************************************************** + /* Internal methods, low-level writing, text segment + /* with additional escaping (ASCII or such) + /* (since 1.8; see [JACKSON-102]) + /********************************************************** + */ + + /* Same as "_writeString2()", except needs additional escaping + * for subset of characters + */ + private void _writeStringASCII(final int len, final int maxNonEscaped) + throws IOException, JsonGenerationException + { + // And then we'll need to verify need for escaping etc: + int end = _outputTail + len; + final int[] escCodes = _outputEscapes; + final int escLimit = Math.min(escCodes.length, maxNonEscaped+1); + int escCode = 0; + + output_loop: + while (_outputTail < end) { + char c; + // Fast loop for chars not needing escaping + escape_loop: + while (true) { + c = _outputBuffer[_outputTail]; + if (c < escLimit) { + escCode = escCodes[c]; + if (escCode != 0) { + break escape_loop; + } + } else if (c > maxNonEscaped) { + escCode = CharacterEscapes.ESCAPE_STANDARD; + break escape_loop; + } + if (++_outputTail >= end) { + break output_loop; + } + } + int flushLen = (_outputTail - _outputHead); + if (flushLen > 0) { + _writer.write(_outputBuffer, _outputHead, flushLen); + } + ++_outputTail; + _prependOrWriteCharacterEscape(c, escCode); + } + } + + private final void _writeSegmentASCII(int end, final int maxNonEscaped) + throws IOException, JsonGenerationException + { + final int[] escCodes = _outputEscapes; + final int escLimit = Math.min(escCodes.length, maxNonEscaped+1); + + int ptr = 0; + int escCode = 0; + int start = ptr; + + output_loop: + while (ptr < end) { + // Fast loop for chars not needing escaping + char c; + while (true) { + c = _outputBuffer[ptr]; + if (c < escLimit) { + escCode = escCodes[c]; + if (escCode != 0) { + break; + } + } else if (c > maxNonEscaped) { + escCode = CharacterEscapes.ESCAPE_STANDARD; + break; + } + if (++ptr >= end) { + break; + } + } + int flushLen = (ptr - start); + if (flushLen > 0) { + _writer.write(_outputBuffer, start, flushLen); + if (ptr >= end) { + break output_loop; + } + } + ++ptr; + start = _prependOrWriteCharacterEscape(_outputBuffer, ptr, end, c, escCode); + } + } + + private final void _writeStringASCII(char[] text, int offset, int len, + final int maxNonEscaped) + throws IOException, JsonGenerationException + { + len += offset; // -> len marks the end from now on + final int[] escCodes = _outputEscapes; + final int escLimit = Math.min(escCodes.length, maxNonEscaped+1); + + int escCode = 0; + + while (offset < len) { + int start = offset; + char c; + + while (true) { + c = text[offset]; + if (c < escLimit) { + escCode = escCodes[c]; + if (escCode != 0) { + break; + } + } else if (c > maxNonEscaped) { + escCode = CharacterEscapes.ESCAPE_STANDARD; + break; + } + if (++offset >= len) { + break; + } + } + + // Short span? Better just copy it to buffer first: + int newAmount = offset - start; + if (newAmount < SHORT_WRITE) { + // Note: let's reserve room for escaped char (up to 6 chars) + if ((_outputTail + newAmount) > _outputEnd) { + _flushBuffer(); + } + if (newAmount > 0) { + System.arraycopy(text, start, _outputBuffer, _outputTail, newAmount); + _outputTail += newAmount; + } + } else { // Nope: better just write through + _flushBuffer(); + _writer.write(text, start, newAmount); + } + // Was this the end? + if (offset >= len) { // yup + break; + } + // Nope, need to escape the char. + ++offset; + _appendCharacterEscape(c, escCode); + } + } + + /* + /********************************************************** + /* Internal methods, low-level writing, text segment + /* with custom escaping (possibly coupling with ASCII limits) + /* (since 1.8; see [JACKSON-106]) + /********************************************************** + */ + + /* Same as "_writeString2()", except needs additional escaping + * for subset of characters + */ + private void _writeStringCustom(final int len) + throws IOException, JsonGenerationException + { + // And then we'll need to verify need for escaping etc: + int end = _outputTail + len; + final int[] escCodes = _outputEscapes; + final int maxNonEscaped = (_maximumNonEscapedChar < 1) ? 0xFFFF : _maximumNonEscapedChar; + final int escLimit = Math.min(escCodes.length, maxNonEscaped+1); + int escCode = 0; + final CharacterEscapes customEscapes = _characterEscapes; + + output_loop: + while (_outputTail < end) { + char c; + // Fast loop for chars not needing escaping + escape_loop: + while (true) { + c = _outputBuffer[_outputTail]; + if (c < escLimit) { + escCode = escCodes[c]; + if (escCode != 0) { + break escape_loop; + } + } else if (c > maxNonEscaped) { + escCode = CharacterEscapes.ESCAPE_STANDARD; + break escape_loop; + } else { + if ((_currentEscape = customEscapes.getEscapeSequence(c)) != null) { + escCode = CharacterEscapes.ESCAPE_CUSTOM; + break escape_loop; + } + } + if (++_outputTail >= end) { + break output_loop; + } + } + int flushLen = (_outputTail - _outputHead); + if (flushLen > 0) { + _writer.write(_outputBuffer, _outputHead, flushLen); + } + ++_outputTail; + _prependOrWriteCharacterEscape(c, escCode); + } + } + + private final void _writeSegmentCustom(int end) + throws IOException, JsonGenerationException + { + final int[] escCodes = _outputEscapes; + final int maxNonEscaped = (_maximumNonEscapedChar < 1) ? 0xFFFF : _maximumNonEscapedChar; + final int escLimit = Math.min(escCodes.length, maxNonEscaped+1); + final CharacterEscapes customEscapes = _characterEscapes; + + int ptr = 0; + int escCode = 0; + int start = ptr; + + output_loop: + while (ptr < end) { + // Fast loop for chars not needing escaping + char c; + while (true) { + c = _outputBuffer[ptr]; + if (c < escLimit) { + escCode = escCodes[c]; + if (escCode != 0) { + break; + } + } else if (c > maxNonEscaped) { + escCode = CharacterEscapes.ESCAPE_STANDARD; + break; + } else { + if ((_currentEscape = customEscapes.getEscapeSequence(c)) != null) { + escCode = CharacterEscapes.ESCAPE_CUSTOM; + break; + } + } + if (++ptr >= end) { + break; + } + } + int flushLen = (ptr - start); + if (flushLen > 0) { + _writer.write(_outputBuffer, start, flushLen); + if (ptr >= end) { + break output_loop; + } + } + ++ptr; + start = _prependOrWriteCharacterEscape(_outputBuffer, ptr, end, c, escCode); + } + } + + private final void _writeStringCustom(char[] text, int offset, int len) + throws IOException, JsonGenerationException + { + len += offset; // -> len marks the end from now on + final int[] escCodes = _outputEscapes; + final int maxNonEscaped = (_maximumNonEscapedChar < 1) ? 0xFFFF : _maximumNonEscapedChar; + final int escLimit = Math.min(escCodes.length, maxNonEscaped+1); + final CharacterEscapes customEscapes = _characterEscapes; + + int escCode = 0; + + while (offset < len) { + int start = offset; + char c; + + while (true) { + c = text[offset]; + if (c < escLimit) { + escCode = escCodes[c]; + if (escCode != 0) { + break; + } + } else if (c > maxNonEscaped) { + escCode = CharacterEscapes.ESCAPE_STANDARD; + break; + } else { + if ((_currentEscape = customEscapes.getEscapeSequence(c)) != null) { + escCode = CharacterEscapes.ESCAPE_CUSTOM; + break; + } + } + if (++offset >= len) { + break; + } + } + + // Short span? Better just copy it to buffer first: + int newAmount = offset - start; + if (newAmount < SHORT_WRITE) { + // Note: let's reserve room for escaped char (up to 6 chars) + if ((_outputTail + newAmount) > _outputEnd) { + _flushBuffer(); + } + if (newAmount > 0) { + System.arraycopy(text, start, _outputBuffer, _outputTail, newAmount); + _outputTail += newAmount; + } + } else { // Nope: better just write through + _flushBuffer(); + _writer.write(text, start, newAmount); + } + // Was this the end? + if (offset >= len) { // yup + break; + } + // Nope, need to escape the char. + ++offset; + _appendCharacterEscape(c, escCode); + } + } + + /* + /********************************************************** + /* Internal methods, low-level writing; binary + /********************************************************** + */ + + protected void _writeBinary(Base64Variant b64variant, byte[] input, int inputPtr, final int inputEnd) + throws IOException, JsonGenerationException + { + // Encoding is by chunks of 3 input, 4 output chars, so: + int safeInputEnd = inputEnd - 3; + // Let's also reserve room for possible (and quoted) lf char each round + int safeOutputEnd = _outputEnd - 6; + int chunksBeforeLF = b64variant.getMaxLineLength() >> 2; + + // Ok, first we loop through all full triplets of data: + while (inputPtr <= safeInputEnd) { + if (_outputTail > safeOutputEnd) { // need to flush + _flushBuffer(); + } + // First, mash 3 bytes into lsb of 32-bit int + int b24 = ((int) input[inputPtr++]) << 8; + b24 |= ((int) input[inputPtr++]) & 0xFF; + b24 = (b24 << 8) | (((int) input[inputPtr++]) & 0xFF); + _outputTail = b64variant.encodeBase64Chunk(b24, _outputBuffer, _outputTail); + if (--chunksBeforeLF <= 0) { + // note: must quote in JSON value + _outputBuffer[_outputTail++] = '\\'; + _outputBuffer[_outputTail++] = 'n'; + chunksBeforeLF = b64variant.getMaxLineLength() >> 2; + } + } + + // And then we may have 1 or 2 leftover bytes to encode + int inputLeft = inputEnd - inputPtr; // 0, 1 or 2 + if (inputLeft > 0) { // yes, but do we have room for output? + if (_outputTail > safeOutputEnd) { // don't really need 6 bytes but... + _flushBuffer(); + } + int b24 = ((int) input[inputPtr++]) << 16; + if (inputLeft == 2) { + b24 |= (((int) input[inputPtr++]) & 0xFF) << 8; + } + _outputTail = b64variant.encodeBase64Partial(b24, inputLeft, _outputBuffer, _outputTail); + } + } + + /* + /********************************************************** + /* Internal methods, low-level writing, other + /********************************************************** + */ + + private final void _writeNull() throws IOException + { + if ((_outputTail + 4) >= _outputEnd) { + _flushBuffer(); + } + int ptr = _outputTail; + char[] buf = _outputBuffer; + buf[ptr] = 'n'; + buf[++ptr] = 'u'; + buf[++ptr] = 'l'; + buf[++ptr] = 'l'; + _outputTail = ptr+1; + } + + /* + /********************************************************** + /* Internal methods, low-level writing, escapes + /********************************************************** + */ + + /** + * Method called to try to either prepend character escape at front of + * given buffer; or if not possible, to write it out directly. + * Uses head and tail pointers (and updates as necessary) + */ + private final void _prependOrWriteCharacterEscape(char ch, int escCode) + throws IOException, JsonGenerationException + { + if (escCode >= 0) { // \\N (2 char) + if (_outputTail >= 2) { // fits, just prepend + int ptr = _outputTail - 2; + _outputHead = ptr; + _outputBuffer[ptr++] = '\\'; + _outputBuffer[ptr] = (char) escCode; + return; + } + // won't fit, write + char[] buf = _entityBuffer; + if (buf == null) { + buf = _allocateEntityBuffer(); + } + _outputHead = _outputTail; + buf[1] = (char) escCode; + _writer.write(buf, 0, 2); + return; + } + if (escCode != CharacterEscapes.ESCAPE_CUSTOM) { // std, \\uXXXX + if (_outputTail >= 6) { // fits, prepend to buffer + char[] buf = _outputBuffer; + int ptr = _outputTail - 6; + _outputHead = ptr; + buf[ptr] = '\\'; + buf[++ptr] = 'u'; + // We know it's a control char, so only the last 2 chars are non-0 + if (ch > 0xFF) { // beyond 8 bytes + int hi = (ch >> 8) & 0xFF; + buf[++ptr] = HEX_CHARS[hi >> 4]; + buf[++ptr] = HEX_CHARS[hi & 0xF]; + ch &= 0xFF; + } else { + buf[++ptr] = '0'; + buf[++ptr] = '0'; + } + buf[++ptr] = HEX_CHARS[ch >> 4]; + buf[++ptr] = HEX_CHARS[ch & 0xF]; + return; + } + // won't fit, flush and write + char[] buf = _entityBuffer; + if (buf == null) { + buf = _allocateEntityBuffer(); + } + _outputHead = _outputTail; + if (ch > 0xFF) { // beyond 8 bytes + int hi = (ch >> 8) & 0xFF; + int lo = ch & 0xFF; + buf[10] = HEX_CHARS[hi >> 4]; + buf[11] = HEX_CHARS[hi & 0xF]; + buf[12] = HEX_CHARS[lo >> 4]; + buf[13] = HEX_CHARS[lo & 0xF]; + _writer.write(buf, 8, 6); + } else { // We know it's a control char, so only the last 2 chars are non-0 + buf[6] = HEX_CHARS[ch >> 4]; + buf[7] = HEX_CHARS[ch & 0xF]; + _writer.write(buf, 2, 6); + } + return; + } + String escape; + + if (_currentEscape == null) { + escape = _characterEscapes.getEscapeSequence(ch).getValue(); + } else { + escape = _currentEscape.getValue(); + _currentEscape = null; + } + int len = escape.length(); + if (_outputTail >= len) { // fits in, prepend + int ptr = _outputTail - len; + _outputHead = ptr; + escape.getChars(0, len, _outputBuffer, ptr); + return; + } + // won't fit, write separately + _outputHead = _outputTail; + _writer.write(escape); + } + + /** + * Method called to try to either prepend character escape at front of + * given buffer; or if not possible, to write it out directly. + * + * @return Pointer to start of prepended entity (if prepended); or 'ptr' + * if not. + */ + private final int _prependOrWriteCharacterEscape(char[] buffer, int ptr, int end, + char ch, int escCode) + throws IOException, JsonGenerationException + { + if (escCode >= 0) { // \\N (2 char) + if (ptr > 1 && ptr < end) { // fits, just prepend + ptr -= 2; + buffer[ptr] = '\\'; + buffer[ptr+1] = (char) escCode; + } else { // won't fit, write + char[] ent = _entityBuffer; + if (ent == null) { + ent = _allocateEntityBuffer(); + } + ent[1] = (char) escCode; + _writer.write(ent, 0, 2); + } + return ptr; + } + if (escCode != CharacterEscapes.ESCAPE_CUSTOM) { // std, \\uXXXX + if (ptr > 5 && ptr < end) { // fits, prepend to buffer + ptr -= 6; + buffer[ptr++] = '\\'; + buffer[ptr++] = 'u'; + // We know it's a control char, so only the last 2 chars are non-0 + if (ch > 0xFF) { // beyond 8 bytes + int hi = (ch >> 8) & 0xFF; + buffer[ptr++] = HEX_CHARS[hi >> 4]; + buffer[ptr++] = HEX_CHARS[hi & 0xF]; + ch &= 0xFF; + } else { + buffer[ptr++] = '0'; + buffer[ptr++] = '0'; + } + buffer[ptr++] = HEX_CHARS[ch >> 4]; + buffer[ptr] = HEX_CHARS[ch & 0xF]; + ptr -= 5; + } else { + // won't fit, flush and write + char[] ent = _entityBuffer; + if (ent == null) { + ent = _allocateEntityBuffer(); + } + _outputHead = _outputTail; + if (ch > 0xFF) { // beyond 8 bytes + int hi = (ch >> 8) & 0xFF; + int lo = ch & 0xFF; + ent[10] = HEX_CHARS[hi >> 4]; + ent[11] = HEX_CHARS[hi & 0xF]; + ent[12] = HEX_CHARS[lo >> 4]; + ent[13] = HEX_CHARS[lo & 0xF]; + _writer.write(ent, 8, 6); + } else { // We know it's a control char, so only the last 2 chars are non-0 + ent[6] = HEX_CHARS[ch >> 4]; + ent[7] = HEX_CHARS[ch & 0xF]; + _writer.write(ent, 2, 6); + } + } + return ptr; + } + String escape; + if (_currentEscape == null) { + escape = _characterEscapes.getEscapeSequence(ch).getValue(); + } else { + escape = _currentEscape.getValue(); + _currentEscape = null; + } + int len = escape.length(); + if (ptr >= len && ptr < end) { // fits in, prepend + ptr -= len; + escape.getChars(0, len, buffer, ptr); + } else { // won't fit, write separately + _writer.write(escape); + } + return ptr; + } + + /** + * Method called to append escape sequence for given character, at the + * end of standard output buffer; or if not possible, write out directly. + */ + private final void _appendCharacterEscape(char ch, int escCode) + throws IOException, JsonGenerationException + { + if (escCode >= 0) { // \\N (2 char) + if ((_outputTail + 2) > _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = '\\'; + _outputBuffer[_outputTail++] = (char) escCode; + return; + } + if (escCode != CharacterEscapes.ESCAPE_CUSTOM) { // std, \\uXXXX + if ((_outputTail + 2) > _outputEnd) { + _flushBuffer(); + } + int ptr = _outputTail; + char[] buf = _outputBuffer; + buf[ptr++] = '\\'; + buf[ptr++] = 'u'; + // We know it's a control char, so only the last 2 chars are non-0 + if (ch > 0xFF) { // beyond 8 bytes + int hi = (ch >> 8) & 0xFF; + buf[ptr++] = HEX_CHARS[hi >> 4]; + buf[ptr++] = HEX_CHARS[hi & 0xF]; + ch &= 0xFF; + } else { + buf[ptr++] = '0'; + buf[ptr++] = '0'; + } + buf[ptr++] = HEX_CHARS[ch >> 4]; + buf[ptr] = HEX_CHARS[ch & 0xF]; + _outputTail = ptr; + return; + } + String escape; + if (_currentEscape == null) { + escape = _characterEscapes.getEscapeSequence(ch).getValue(); + } else { + escape = _currentEscape.getValue(); + _currentEscape = null; + } + int len = escape.length(); + if ((_outputTail + len) > _outputEnd) { + _flushBuffer(); + if (len > _outputEnd) { // very very long escape; unlikely but theoretically possible + _writer.write(escape); + return; + } + } + escape.getChars(0, len, _outputBuffer, _outputTail); + _outputTail += len; + } + + private char[] _allocateEntityBuffer() + { + char[] buf = new char[14]; + // first 2 chars, non-numeric escapes (like \n) + buf[0] = '\\'; + // next 6; 8-bit escapes (control chars mostly) + buf[2] = '\\'; + buf[3] = 'u'; + buf[4] = '0'; + buf[5] = '0'; + // last 6, beyond 8 bits + buf[8] = '\\'; + buf[9] = 'u'; + _entityBuffer = buf; + return buf; + } + + protected final void _flushBuffer() throws IOException + { + int len = _outputTail - _outputHead; + if (len > 0) { + int offset = _outputHead; + _outputTail = _outputHead = 0; + _writer.write(_outputBuffer, offset, len); + } + } +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/impl/package-info.java b/1.9.10/src/java/org/codehaus/jackson/impl/package-info.java new file mode 100644 index 0000000..3856ae8 --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/impl/package-info.java
@@ -0,0 +1,6 @@ +/** + * Parser and generator implementation classes that Jackson + * defines and uses. + * Application code should not (need to) use contents of this package. + */ +package org.codehaus.jackson.impl;
diff --git a/1.9.10/src/java/org/codehaus/jackson/io/BaseReader.java b/1.9.10/src/java/org/codehaus/jackson/io/BaseReader.java new file mode 100644 index 0000000..0d87c03 --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/io/BaseReader.java
@@ -0,0 +1,117 @@ + +package org.codehaus.jackson.io; + +import java.io.*; + + +/** + * Simple basic class for optimized readers in this package; implements + * "cookie-cutter" methods that are used by all actual implementations. + */ +abstract class BaseReader + extends Reader +{ + /** + * JSON actually limits available Unicode range in the high end + * to the same as xml (to basically limit UTF-8 max byte sequence + * length to 4) + */ + final protected static int LAST_VALID_UNICODE_CHAR = 0x10FFFF; + + final protected static char NULL_CHAR = (char) 0; + final protected static char NULL_BYTE = (byte) 0; + + final protected IOContext _context; + + protected InputStream _in; + + protected byte[] _buffer; + + protected int _ptr; + protected int _length; + + /* + /********************************************************** + /* Life-cycle + /********************************************************** + */ + + protected BaseReader(IOContext context, + InputStream in, byte[] buf, int ptr, int len) + { + _context = context; + _in = in; + _buffer = buf; + _ptr = ptr; + _length = len; + } + + /* + /********************************************************** + /* Reader API + /********************************************************** + */ + + @Override + public void close() throws IOException + { + InputStream in = _in; + + if (in != null) { + _in = null; + freeBuffers(); + in.close(); + } + } + + protected char[] _tmpBuf = null; + + /** + * Although this method is implemented by the base class, AND it should + * never be called by main code, let's still implement it bit more + * efficiently just in case + */ + @Override + public int read() throws IOException + { + if (_tmpBuf == null) { + _tmpBuf = new char[1]; + } + if (read(_tmpBuf, 0, 1) < 1) { + return -1; + } + return _tmpBuf[0]; + } + + /* + /********************************************************** + /* Internal/package methods: + /********************************************************** + */ + + /** + * This method should be called along with (or instead of) normal + * close. After calling this method, no further reads should be tried. + * Method will try to recycle read buffers (if any). + */ + public final void freeBuffers() + { + byte[] buf = _buffer; + if (buf != null) { + _buffer = null; + _context.releaseReadIOBuffer(buf); + } + } + + protected void reportBounds(char[] cbuf, int start, int len) + throws IOException + { + throw new ArrayIndexOutOfBoundsException("read(buf,"+start+","+len+"), cbuf["+cbuf.length+"]"); + } + + protected void reportStrangeStream() + throws IOException + { + throw new IOException("Strange I/O stream, returned 0 bytes on read"); + } +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/io/CharacterEscapes.java b/1.9.10/src/java/org/codehaus/jackson/io/CharacterEscapes.java new file mode 100644 index 0000000..ae87a1e --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/io/CharacterEscapes.java
@@ -0,0 +1,73 @@ +package org.codehaus.jackson.io; + +import org.codehaus.jackson.SerializableString; +import org.codehaus.jackson.util.CharTypes; + +/** + * Abstract base class that defines interface for customizing character + * escaping aspects for String values, for formats that use escaping. + * For JSON this applies to both property names and String values. + * + * @since 1.8 + */ +public abstract class CharacterEscapes +{ + /** + * Value used for lookup tables to indicate that matching characters + * do not need to be escaped. + */ + public final static int ESCAPE_NONE = 0; + + /** + * Value used for lookup tables to indicate that matching characters + * are to be escaped using standard escaping; for JSON this means + * (for example) using "backslash - u" escape method. + */ + public final static int ESCAPE_STANDARD = -1; + + /** + * Value used for lookup tables to indicate that matching characters + * will need custom escapes; and that another call + * to {@link #getEscapeSequence} is needed to figure out exact escape + * sequence to output. + */ + public final static int ESCAPE_CUSTOM = -2; + + /** + * Method generators can call to get lookup table for determining + * escape handling for first 128 characters of Unicode (ASCII + * characters. Caller is not to modify contents of this array, since + * this is expected to be a shared copy. + * + * @return Array with size of at least 128, where first 128 entries + * have either one of <code>ESCAPE_xxx</code> constants, or non-zero positive + * integer (meaning of which is data format specific; for JSON it means + * that combination of backslash and character with that value is to be used) + * to indicate that specific escape sequence is to be used. + */ + public abstract int[] getEscapeCodesForAscii(); + + /** + * Method generators can call to get lookup table for determining + * exact escape sequence to use for given character. + * It can be called for any character, but typically is called for + * either for ASCII characters for which custom escape + * sequence is needed; or for any non-ASCII character. + */ + public abstract SerializableString getEscapeSequence(int ch); + + /** + * Helper method that can be used to get a copy of standard JSON + * escape definitions; this is useful when just wanting to slightly + * customize definitions. Caller can modify this array as it sees + * fit and usually returns modified instance via {@link #getEscapeCodesForAscii} + */ + public static int[] standardAsciiEscapesForJSON() + { + int[] esc = CharTypes.get7BitOutputEscapes(); + int len = esc.length; + int[] result = new int[len]; + System.arraycopy(esc, 0, result, 0, esc.length); + return result; + } +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/io/IOContext.java b/1.9.10/src/java/org/codehaus/jackson/io/IOContext.java new file mode 100644 index 0000000..c9df984 --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/io/IOContext.java
@@ -0,0 +1,239 @@ +package org.codehaus.jackson.io; + +import org.codehaus.jackson.JsonEncoding; +import org.codehaus.jackson.util.BufferRecycler; +import org.codehaus.jackson.util.TextBuffer; + +/** + * To limit number of configuration and state objects to pass, all + * contextual objects that need to be passed by the factory to + * readers and writers are combined under this object. One instance + * is created for each reader and writer. + */ +public final class IOContext +{ + /* + /********************************************************** + /* Configuration + /********************************************************** + */ + + /** + * Reference to the source object, which can be used for displaying + * location information + */ + protected final Object _sourceRef; + + /** + * Encoding used by the underlying stream, if known. + */ + protected JsonEncoding _encoding; + + /** + * Flag that indicates whether underlying input/output source/target + * object is fully managed by the owner of this context (parser or + * generator). If true, it is, and is to be closed by parser/generator; + * if false, calling application has to do closing (unless auto-closing + * feature is enabled for the parser/generator in question; in which + * case it acts like the owner). + */ + protected final boolean _managedResource; + + /* + /********************************************************** + /* Buffer handling, recycling + /********************************************************** + */ + + /** + * Recycler used for actual allocation/deallocation/reuse + */ + protected final BufferRecycler _bufferRecycler; + + /** + * Reference to the allocated I/O buffer for low-level input reading, + * if any allocated. + */ + protected byte[] _readIOBuffer = null; + + /** + * Reference to the allocated I/O buffer used for low-level + * encoding-related buffering. + */ + protected byte[] _writeEncodingBuffer = null; + + /** + * Reference to the buffer allocated for tokenization purposes, + * in which character input is read, and from which it can be + * further returned. + */ + protected char[] _tokenCBuffer = null; + + /** + * Reference to the buffer allocated for buffering it for + * output, before being encoded: generally this means concatenating + * output, then encoding when buffer fills up. + */ + protected char[] _concatCBuffer = null; + + /** + * Reference temporary buffer Parser instances need if calling + * app decides it wants to access name via 'getTextCharacters' method. + * Regular text buffer can not be used as it may contain textual + * representation of the value token. + */ + protected char[] _nameCopyBuffer = null; + + /* + /********************************************************** + /* Life-cycle + /********************************************************** + */ + + public IOContext(BufferRecycler br, Object sourceRef, boolean managedResource) + { + _bufferRecycler = br; + _sourceRef = sourceRef; + _managedResource = managedResource; + } + + public void setEncoding(JsonEncoding enc) + { + _encoding = enc; + } + + /* + /********************************************************** + /* Public API, accessors + /********************************************************** + */ + + public final Object getSourceReference() { return _sourceRef; } + public final JsonEncoding getEncoding() { return _encoding; } + public final boolean isResourceManaged() { return _managedResource; } + + /* + /********************************************************** + /* Public API, buffer management + /********************************************************** + */ + + public final TextBuffer constructTextBuffer() { + return new TextBuffer(_bufferRecycler); + } + + /** + *<p> + * Note: the method can only be called once during its life cycle. + * This is to protect against accidental sharing. + */ + public final byte[] allocReadIOBuffer() + { + if (_readIOBuffer != null) { + throw new IllegalStateException("Trying to call allocReadIOBuffer() second time"); + } + _readIOBuffer = _bufferRecycler.allocByteBuffer(BufferRecycler.ByteBufferType.READ_IO_BUFFER); + return _readIOBuffer; + } + + public final byte[] allocWriteEncodingBuffer() + { + if (_writeEncodingBuffer != null) { + throw new IllegalStateException("Trying to call allocWriteEncodingBuffer() second time"); + } + _writeEncodingBuffer = _bufferRecycler.allocByteBuffer(BufferRecycler.ByteBufferType.WRITE_ENCODING_BUFFER); + return _writeEncodingBuffer; + } + + public final char[] allocTokenBuffer() + { + if (_tokenCBuffer != null) { + throw new IllegalStateException("Trying to call allocTokenBuffer() second time"); + } + _tokenCBuffer = _bufferRecycler.allocCharBuffer(BufferRecycler.CharBufferType.TOKEN_BUFFER); + return _tokenCBuffer; + } + + public final char[] allocConcatBuffer() + { + if (_concatCBuffer != null) { + throw new IllegalStateException("Trying to call allocConcatBuffer() second time"); + } + _concatCBuffer = _bufferRecycler.allocCharBuffer(BufferRecycler.CharBufferType.CONCAT_BUFFER); + return _concatCBuffer; + } + + public final char[] allocNameCopyBuffer(int minSize) + { + if (_nameCopyBuffer != null) { + throw new IllegalStateException("Trying to call allocNameCopyBuffer() second time"); + } + _nameCopyBuffer = _bufferRecycler.allocCharBuffer(BufferRecycler.CharBufferType.NAME_COPY_BUFFER, minSize); + return _nameCopyBuffer; + } + + /** + * Method to call when all the processing buffers can be safely + * recycled. + */ + public final void releaseReadIOBuffer(byte[] buf) + { + if (buf != null) { + /* Let's do sanity checks to ensure once-and-only-once release, + * as well as avoiding trying to release buffers not owned + */ + if (buf != _readIOBuffer) { + throw new IllegalArgumentException("Trying to release buffer not owned by the context"); + } + _readIOBuffer = null; + _bufferRecycler.releaseByteBuffer(BufferRecycler.ByteBufferType.READ_IO_BUFFER, buf); + } + } + + public final void releaseWriteEncodingBuffer(byte[] buf) + { + if (buf != null) { + /* Let's do sanity checks to ensure once-and-only-once release, + * as well as avoiding trying to release buffers not owned + */ + if (buf != _writeEncodingBuffer) { + throw new IllegalArgumentException("Trying to release buffer not owned by the context"); + } + _writeEncodingBuffer = null; + _bufferRecycler.releaseByteBuffer(BufferRecycler.ByteBufferType.WRITE_ENCODING_BUFFER, buf); + } + } + + public final void releaseTokenBuffer(char[] buf) + { + if (buf != null) { + if (buf != _tokenCBuffer) { + throw new IllegalArgumentException("Trying to release buffer not owned by the context"); + } + _tokenCBuffer = null; + _bufferRecycler.releaseCharBuffer(BufferRecycler.CharBufferType.TOKEN_BUFFER, buf); + } + } + + public final void releaseConcatBuffer(char[] buf) + { + if (buf != null) { + if (buf != _concatCBuffer) { + throw new IllegalArgumentException("Trying to release buffer not owned by the context"); + } + _concatCBuffer = null; + _bufferRecycler.releaseCharBuffer(BufferRecycler.CharBufferType.CONCAT_BUFFER, buf); + } + } + + public final void releaseNameCopyBuffer(char[] buf) + { + if (buf != null) { + if (buf != _nameCopyBuffer) { + throw new IllegalArgumentException("Trying to release buffer not owned by the context"); + } + _nameCopyBuffer = null; + _bufferRecycler.releaseCharBuffer(BufferRecycler.CharBufferType.NAME_COPY_BUFFER, buf); + } + } +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/io/InputDecorator.java b/1.9.10/src/java/org/codehaus/jackson/io/InputDecorator.java new file mode 100644 index 0000000..0084db7 --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/io/InputDecorator.java
@@ -0,0 +1,67 @@ +package org.codehaus.jackson.io; + +import java.io.*; + +/** + * Handler class that can be used to decorate input sources. + * Typical use is to use a filter abstraction (filtered stream, + * reader) around original input source, and apply additional + * processing during read operations. + * + * @since 1.8 + */ +public abstract class InputDecorator +{ + /** + * Method called by {@link org.codehaus.jackson.JsonFactory} instance when + * creating parser given an {@link InputStream}, when this decorator + * has been registered. + * + * @param ctxt IO context in use (provides access to declared encoding). + * NOTE: at this point context may not have all information initialized; + * specifically auto-detected encoding is only available once parsing starts, + * which may occur only after this method is called. + * @param in Original input source + * + * @return InputStream to use; either passed in argument, or something that + * calls it + */ + public abstract InputStream decorate(IOContext ctxt, InputStream in) + throws IOException; + + /** + * Method called by {@link org.codehaus.jackson.JsonFactory} instance when + * creating parser on given "raw" byte source. + * Method can either construct a {@link InputStream} for reading; or return + * null to indicate that no wrapping should occur. + * + * @param ctxt IO context in use (provides access to declared encoding) + * NOTE: at this point context may not have all information initialized; + * specifically auto-detected encoding is only available once parsing starts, + * which may occur only after this method is called. + * @param src Input buffer that contains contents to parse + * @param offset Offset of the first available byte in the input buffer + * @param length Number of bytes available in the input buffer + * + * @return Either {@link InputStream} to use as input source; or null to indicate + * that contents are to be processed as-is by caller + */ + public abstract InputStream decorate(IOContext ctxt, byte[] src, int offset, int length) + throws IOException; + + /** + * Method called by {@link org.codehaus.jackson.JsonFactory} instance when + * creating parser given an {@link Reader}, when this decorator + * has been registered. + * + * @param ctxt IO context in use (provides access to declared encoding) + * NOTE: at this point context may not have all information initialized; + * specifically auto-detected encoding is only available once parsing starts, + * which may occur only after this method is called. + * @param src Original input source + * + * @return Reader to use; either passed in argument, or something that + * calls it (for example, a {@link FilterReader}) + */ + public abstract Reader decorate(IOContext ctxt, Reader src) throws IOException; +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/io/JsonStringEncoder.java b/1.9.10/src/java/org/codehaus/jackson/io/JsonStringEncoder.java new file mode 100644 index 0000000..b0ed0f0 --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/io/JsonStringEncoder.java
@@ -0,0 +1,408 @@ +package org.codehaus.jackson.io; + +import java.lang.ref.SoftReference; + +import org.codehaus.jackson.util.BufferRecycler; +import org.codehaus.jackson.util.ByteArrayBuilder; +import org.codehaus.jackson.util.CharTypes; +import org.codehaus.jackson.util.TextBuffer; + +/** + * Helper class used for efficient encoding of JSON String values (including + * JSON field names) into Strings or UTF-8 byte arrays. + *<p> + * Note that methods in here are somewhat optimized, but not ridiculously so. + * Reason is that conversion method results are expected to be cached so that + * these methods will not be hot spots during normal operation. + * + * @since 1.6 + */ +public final class JsonStringEncoder +{ + private final static char[] HEX_CHARS = CharTypes.copyHexChars(); + + private final static byte[] HEX_BYTES = CharTypes.copyHexBytes(); + + private final static int SURR1_FIRST = 0xD800; + private final static int SURR1_LAST = 0xDBFF; + private final static int SURR2_FIRST = 0xDC00; + private final static int SURR2_LAST = 0xDFFF; + + private final static int INT_BACKSLASH = '\\'; + private final static int INT_U = 'u'; + private final static int INT_0 = '0'; + + /** + * This <code>ThreadLocal</code> contains a {@link java.lang.ref.SoftRerefence} + * to a {@link BufferRecycler} used to provide a low-cost + * buffer recycling between reader and writer instances. + */ + final protected static ThreadLocal<SoftReference<JsonStringEncoder>> _threadEncoder + = new ThreadLocal<SoftReference<JsonStringEncoder>>(); + + /** + * Lazily constructed text buffer used to produce JSON encoded Strings + * as characters (without UTF-8 encoding) + */ + protected TextBuffer _textBuffer; + + /** + * Lazily-constructed builder used for UTF-8 encoding of text values + * (quoted and unquoted) + */ + protected ByteArrayBuilder _byteBuilder; + + /** + * Temporary buffer used for composing quote/escape sequences + */ + protected final char[] _quoteBuffer; + + /* + /********************************************************** + /* Construction, instance access + /********************************************************** + */ + + public JsonStringEncoder() + { + _quoteBuffer = new char[6]; + _quoteBuffer[0] = '\\'; + _quoteBuffer[2] = '0'; + _quoteBuffer[3] = '0'; + } + + /** + * Factory method for getting an instance; this is either recycled per-thread instance, + * or a newly constructed one. + */ + public static JsonStringEncoder getInstance() + { + SoftReference<JsonStringEncoder> ref = _threadEncoder.get(); + JsonStringEncoder enc = (ref == null) ? null : ref.get(); + + if (enc == null) { + enc = new JsonStringEncoder(); + _threadEncoder.set(new SoftReference<JsonStringEncoder>(enc)); + } + return enc; + } + + /* + /********************************************************** + /* Public API + /********************************************************** + */ + + /** + * Method that will quote text contents using JSON standard quoting, + * and return results as a character array + */ + public char[] quoteAsString(String input) + { + TextBuffer textBuffer = _textBuffer; + if (textBuffer == null) { + // no allocator; can add if we must, shouldn't need to + _textBuffer = textBuffer = new TextBuffer(null); + } + char[] outputBuffer = textBuffer.emptyAndGetCurrentSegment(); + final int[] escCodes = CharTypes.get7BitOutputEscapes(); + final int escCodeCount = escCodes.length; + int inPtr = 0; + final int inputLen = input.length(); + int outPtr = 0; + + outer_loop: + while (inPtr < inputLen) { + tight_loop: + while (true) { + char c = input.charAt(inPtr); + if (c < escCodeCount && escCodes[c] != 0) { + break tight_loop; + } + if (outPtr >= outputBuffer.length) { + outputBuffer = textBuffer.finishCurrentSegment(); + outPtr = 0; + } + outputBuffer[outPtr++] = c; + if (++inPtr >= inputLen) { + break outer_loop; + } + } + // something to escape; 2 or 6-char variant? + int escCode = escCodes[input.charAt(inPtr++)]; + int length = _appendSingleEscape(escCode, _quoteBuffer); + if ((outPtr + length) > outputBuffer.length) { + int first = outputBuffer.length - outPtr; + if (first > 0) { + System.arraycopy(_quoteBuffer, 0, outputBuffer, outPtr, first); + } + outputBuffer = textBuffer.finishCurrentSegment(); + int second = length - first; + System.arraycopy(_quoteBuffer, first, outputBuffer, 0, second); + outPtr = second; + } else { + System.arraycopy(_quoteBuffer, 0, outputBuffer, outPtr, length); + outPtr += length; + } + + } + textBuffer.setCurrentLength(outPtr); + return textBuffer.contentsAsArray(); + } + + /** + * Will quote given JSON String value using standard quoting, encode + * results as UTF-8, and return result as a byte array. + */ + public byte[] quoteAsUTF8(String text) + { + ByteArrayBuilder byteBuilder = _byteBuilder; + if (byteBuilder == null) { + // no allocator; can add if we must, shouldn't need to + _byteBuilder = byteBuilder = new ByteArrayBuilder(null); + } + int inputPtr = 0; + int inputEnd = text.length(); + int outputPtr = 0; + byte[] outputBuffer = byteBuilder.resetAndGetFirstSegment(); + + main_loop: + while (inputPtr < inputEnd) { + final int[] escCodes = CharTypes.get7BitOutputEscapes(); + + inner_loop: // ascii and escapes + while (true) { + int ch = text.charAt(inputPtr); + if (ch > 0x7F || escCodes[ch] != 0) { + break inner_loop; + } + if (outputPtr >= outputBuffer.length) { + outputBuffer = byteBuilder.finishCurrentSegment(); + outputPtr = 0; + } + outputBuffer[outputPtr++] = (byte) ch; + if (++inputPtr >= inputEnd) { + break main_loop; + } + } + if (outputPtr >= outputBuffer.length) { + outputBuffer = byteBuilder.finishCurrentSegment(); + outputPtr = 0; + } + // Ok, so what did we hit? + int ch = (int) text.charAt(inputPtr++); + if (ch <= 0x7F) { // needs quoting + int escape = escCodes[ch]; + // ctrl-char, 6-byte escape... + outputPtr = _appendByteEscape(ch, escape, byteBuilder, outputPtr); + outputBuffer = byteBuilder.getCurrentSegment(); + continue main_loop; + } else if (ch <= 0x7FF) { // fine, just needs 2 byte output + outputBuffer[outputPtr++] = (byte) (0xc0 | (ch >> 6)); + ch = (0x80 | (ch & 0x3f)); + } else { // 3 or 4 bytes + // Surrogates? + if (ch < SURR1_FIRST || ch > SURR2_LAST) { // nope + outputBuffer[outputPtr++] = (byte) (0xe0 | (ch >> 12)); + if (outputPtr >= outputBuffer.length) { + outputBuffer = byteBuilder.finishCurrentSegment(); + outputPtr = 0; + } + outputBuffer[outputPtr++] = (byte) (0x80 | ((ch >> 6) & 0x3f)); + ch = (0x80 | (ch & 0x3f)); + } else { // yes, surrogate pair + if (ch > SURR1_LAST) { // must be from first range + _throwIllegalSurrogate(ch); + } + // and if so, followed by another from next range + if (inputPtr >= inputEnd) { + _throwIllegalSurrogate(ch); + } + ch = _convertSurrogate(ch, text.charAt(inputPtr++)); + if (ch > 0x10FFFF) { // illegal, as per RFC 4627 + _throwIllegalSurrogate(ch); + } + outputBuffer[outputPtr++] = (byte) (0xf0 | (ch >> 18)); + if (outputPtr >= outputBuffer.length) { + outputBuffer = byteBuilder.finishCurrentSegment(); + outputPtr = 0; + } + outputBuffer[outputPtr++] = (byte) (0x80 | ((ch >> 12) & 0x3f)); + if (outputPtr >= outputBuffer.length) { + outputBuffer = byteBuilder.finishCurrentSegment(); + outputPtr = 0; + } + outputBuffer[outputPtr++] = (byte) (0x80 | ((ch >> 6) & 0x3f)); + ch = (0x80 | (ch & 0x3f)); + } + } + if (outputPtr >= outputBuffer.length) { + outputBuffer = byteBuilder.finishCurrentSegment(); + outputPtr = 0; + } + outputBuffer[outputPtr++] = (byte) ch; + } + return _byteBuilder.completeAndCoalesce(outputPtr); + } + + /** + * Will encode given String as UTF-8 (without any quoting), return + * resulting byte array. + */ + public byte[] encodeAsUTF8(String text) + { + ByteArrayBuilder byteBuilder = _byteBuilder; + if (byteBuilder == null) { + // no allocator; can add if we must, shouldn't need to + _byteBuilder = byteBuilder = new ByteArrayBuilder(null); + } + int inputPtr = 0; + int inputEnd = text.length(); + int outputPtr = 0; + byte[] outputBuffer = byteBuilder.resetAndGetFirstSegment(); + int outputEnd = outputBuffer.length; + + main_loop: + while (inputPtr < inputEnd) { + int c = text.charAt(inputPtr++); + + // first tight loop for ascii + while (c <= 0x7F) { + if (outputPtr >= outputEnd) { + outputBuffer = byteBuilder.finishCurrentSegment(); + outputEnd = outputBuffer.length; + outputPtr = 0; + } + outputBuffer[outputPtr++] = (byte) c; + if (inputPtr >= inputEnd) { + break main_loop; + } + c = text.charAt(inputPtr++); + } + + // then multi-byte... + if (outputPtr >= outputEnd) { + outputBuffer = byteBuilder.finishCurrentSegment(); + outputEnd = outputBuffer.length; + outputPtr = 0; + } + if (c < 0x800) { // 2-byte + outputBuffer[outputPtr++] = (byte) (0xc0 | (c >> 6)); + } else { // 3 or 4 bytes + // Surrogates? + if (c < SURR1_FIRST || c > SURR2_LAST) { // nope + outputBuffer[outputPtr++] = (byte) (0xe0 | (c >> 12)); + if (outputPtr >= outputEnd) { + outputBuffer = byteBuilder.finishCurrentSegment(); + outputEnd = outputBuffer.length; + outputPtr = 0; + } + outputBuffer[outputPtr++] = (byte) (0x80 | ((c >> 6) & 0x3f)); + } else { // yes, surrogate pair + if (c > SURR1_LAST) { // must be from first range + _throwIllegalSurrogate(c); + } + // and if so, followed by another from next range + if (inputPtr >= inputEnd) { + _throwIllegalSurrogate(c); + } + c = _convertSurrogate(c, text.charAt(inputPtr++)); + if (c > 0x10FFFF) { // illegal, as per RFC 4627 + _throwIllegalSurrogate(c); + } + outputBuffer[outputPtr++] = (byte) (0xf0 | (c >> 18)); + if (outputPtr >= outputEnd) { + outputBuffer = byteBuilder.finishCurrentSegment(); + outputEnd = outputBuffer.length; + outputPtr = 0; + } + outputBuffer[outputPtr++] = (byte) (0x80 | ((c >> 12) & 0x3f)); + if (outputPtr >= outputEnd) { + outputBuffer = byteBuilder.finishCurrentSegment(); + outputEnd = outputBuffer.length; + outputPtr = 0; + } + outputBuffer[outputPtr++] = (byte) (0x80 | ((c >> 6) & 0x3f)); + } + } + if (outputPtr >= outputEnd) { + outputBuffer = byteBuilder.finishCurrentSegment(); + outputEnd = outputBuffer.length; + outputPtr = 0; + } + outputBuffer[outputPtr++] = (byte) (0x80 | (c & 0x3f)); + } + return _byteBuilder.completeAndCoalesce(outputPtr); + } + + /* + /********************************************************** + /* Internal methods + /********************************************************** + */ + + private int _appendSingleEscape(int escCode, char[] quoteBuffer) + { + if (escCode < 0) { // control char, value -(char + 1) + int value = -(escCode + 1); + quoteBuffer[1] = 'u'; + // We know it's a control char, so only the last 2 chars are non-0 + quoteBuffer[4] = HEX_CHARS[value >> 4]; + quoteBuffer[5] = HEX_CHARS[value & 0xF]; + return 6; + } + quoteBuffer[1] = (char) escCode; + return 2; + } + + private int _appendByteEscape(int ch, int escCode, ByteArrayBuilder byteBuilder, int ptr) + { + byteBuilder.setCurrentSegmentLength(ptr); + byteBuilder.append(INT_BACKSLASH); + if (escCode < 0) { // standard escape + byteBuilder.append(INT_U); + if (ch > 0xFF) { + int hi = (ch >> 8); + byteBuilder.append(HEX_BYTES[hi >> 4]); + byteBuilder.append(HEX_BYTES[hi & 0xF]); + ch &= 0xFF; + } else { + byteBuilder.append(INT_0); + byteBuilder.append(INT_0); + } + byteBuilder.append(HEX_BYTES[ch >> 4]); + byteBuilder.append(HEX_BYTES[ch & 0xF]); + } else { // 2-char simple escape + byteBuilder.append((byte) escCode); + } + return byteBuilder.getCurrentSegmentLength(); + } + + /** + * Method called to calculate UTF code point, from a surrogate pair. + */ + private int _convertSurrogate(int firstPart, int secondPart) + { + // Ok, then, is the second part valid? + if (secondPart < SURR2_FIRST || secondPart > SURR2_LAST) { + throw new IllegalArgumentException("Broken surrogate pair: first char 0x"+Integer.toHexString(firstPart)+", second 0x"+Integer.toHexString(secondPart)+"; illegal combination"); + } + return 0x10000 + ((firstPart - SURR1_FIRST) << 10) + (secondPart - SURR2_FIRST); + } + + private void _throwIllegalSurrogate(int code) + { + if (code > 0x10FFFF) { // over max? + throw new IllegalArgumentException("Illegal character point (0x"+Integer.toHexString(code)+") to output; max is 0x10FFFF as per RFC 4627"); + } + if (code >= SURR1_FIRST) { + if (code <= SURR1_LAST) { // Unmatched first part (closing without second part?) + throw new IllegalArgumentException("Unmatched first part of surrogate pair (0x"+Integer.toHexString(code)+")"); + } + throw new IllegalArgumentException("Unmatched second part of surrogate pair (0x"+Integer.toHexString(code)+")"); + } + // should we ever get this? + throw new IllegalArgumentException("Illegal character point (0x"+Integer.toHexString(code)+") to output"); + } + +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/io/MergedStream.java b/1.9.10/src/java/org/codehaus/jackson/io/MergedStream.java new file mode 100644 index 0000000..788ebce --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/io/MergedStream.java
@@ -0,0 +1,145 @@ +package org.codehaus.jackson.io; + +import java.io.*; + +/** + * Simple {@link InputStream} implementation that is used to "unwind" some + * data previously read from an input stream; so that as long as some of + * that data remains, it's returned; but as long as it's read, we'll + * just use data from the underlying original stream. + * This is similar to {@link java.io.PushbackInputStream}, but here there's + * only one implicit pushback, when instance is constructed. + */ +public final class MergedStream + extends InputStream +{ + final protected IOContext _context; + + final InputStream _in; + + byte[] _buffer; + + int _ptr; + + final int _end; + + public MergedStream(IOContext context, + InputStream in, byte[] buf, int start, int end) + { + _context = context; + _in = in; + _buffer = buf; + _ptr = start; + _end = end; + } + + @Override + public int available() throws IOException + { + if (_buffer != null) { + return _end - _ptr; + } + return _in.available(); + } + + @Override + public void close() throws IOException + { + freeMergedBuffer(); + _in.close(); + } + + @Override + public void mark(int readlimit) + { + if (_buffer == null) { + _in.mark(readlimit); + } + } + + @Override + public boolean markSupported() + { + // Only supports marks past the initial rewindable section... + return (_buffer == null) && _in.markSupported(); + } + + @Override + public int read() throws IOException + { + if (_buffer != null) { + int c = _buffer[_ptr++] & 0xFF; + if (_ptr >= _end) { + freeMergedBuffer(); + } + return c; + } + return _in.read(); + } + + @Override + public int read(byte[] b) throws IOException + { + return read(b, 0, b.length); + } + + @Override + public int read(byte[] b, int off, int len) throws IOException + { + if (_buffer != null) { + int avail = _end - _ptr; + if (len > avail) { + len = avail; + } + System.arraycopy(_buffer, _ptr, b, off, len); + _ptr += len; + if (_ptr >= _end) { + freeMergedBuffer(); + } + return len; + } + return _in.read(b, off, len); + } + + @Override + public void reset() throws IOException + { + if (_buffer == null) { + _in.reset(); + } + } + + @Override + public long skip(long n) throws IOException + { + long count = 0L; + + if (_buffer != null) { + int amount = _end - _ptr; + + if (amount > n) { // all in pushed back segment? + _ptr += (int) n; + return n; + } + freeMergedBuffer(); + count += amount; + n -= amount; + } + + if (n > 0) { + count += _in.skip(n); + } + return count; + } + + private void freeMergedBuffer() + { + byte[] buf = _buffer; + if (buf != null) { + _buffer = null; + if (_context != null) { + _context.releaseReadIOBuffer(buf); + } + } + } +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/io/NumberInput.java b/1.9.10/src/java/org/codehaus/jackson/io/NumberInput.java new file mode 100644 index 0000000..56d3362 --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/io/NumberInput.java
@@ -0,0 +1,303 @@ +package org.codehaus.jackson.io; + +public final class NumberInput +{ + /** + * Textual representation of a double constant that can cause nasty problems + * with JDK (see http://www.exploringbinary.com/java-hangs-when-converting-2-2250738585072012e-308). + */ + public final static String NASTY_SMALL_DOUBLE = "2.2250738585072012e-308"; + + /** + * Constants needed for parsing longs from basic int parsing methods + */ + final static long L_BILLION = 1000000000; + + final static String MIN_LONG_STR_NO_SIGN = String.valueOf(Long.MIN_VALUE).substring(1); + final static String MAX_LONG_STR = String.valueOf(Long.MAX_VALUE); + + /** + * Fast method for parsing integers that are known to fit into + * regular 32-bit signed int type. This means that length is + * between 1 and 9 digits (inclusive) + *<p> + * Note: public to let unit tests call it + */ + public final static int parseInt(char[] digitChars, int offset, int len) + { + int num = digitChars[offset] - '0'; + len += offset; + // This looks ugly, but appears the fastest way (as per measurements) + if (++offset < len) { + num = (num * 10) + (digitChars[offset] - '0'); + if (++offset < len) { + num = (num * 10) + (digitChars[offset] - '0'); + if (++offset < len) { + num = (num * 10) + (digitChars[offset] - '0'); + if (++offset < len) { + num = (num * 10) + (digitChars[offset] - '0'); + if (++offset < len) { + num = (num * 10) + (digitChars[offset] - '0'); + if (++offset < len) { + num = (num * 10) + (digitChars[offset] - '0'); + if (++offset < len) { + num = (num * 10) + (digitChars[offset] - '0'); + if (++offset < len) { + num = (num * 10) + (digitChars[offset] - '0'); + } + } + } + } + } + } + } + } + return num; + } + + /** + * Helper method to (more) efficiently parse integer numbers from + * String values. + * + * @since 1.7 + */ + public final static int parseInt(String str) + { + /* Ok: let's keep strategy simple: ignoring optional minus sign, + * we'll accept 1 - 9 digits and parse things efficiently; + * otherwise just defer to JDK parse functionality. + */ + char c = str.charAt(0); + int length = str.length(); + boolean negative = (c == '-'); + int offset = 1; + // must have 1 - 9 digits after optional sign: + // negative? + if (negative) { + if (length == 1 || length > 10) { + return Integer.parseInt(str); + } + c = str.charAt(offset++); + } else { + if (length > 9) { + return Integer.parseInt(str); + } + } + if (c > '9' || c < '0') { + return Integer.parseInt(str); + } + int num = c - '0'; + if (offset < length) { + c = str.charAt(offset++); + if (c > '9' || c < '0') { + return Integer.parseInt(str); + } + num = (num * 10) + (c - '0'); + if (offset < length) { + c = str.charAt(offset++); + if (c > '9' || c < '0') { + return Integer.parseInt(str); + } + num = (num * 10) + (c - '0'); + // Let's just loop if we have more than 3 digits: + if (offset < length) { + do { + c = str.charAt(offset++); + if (c > '9' || c < '0') { + return Integer.parseInt(str); + } + num = (num * 10) + (c - '0'); + } while (offset < length); + } + } + } + return negative ? -num : num; + } + + public final static long parseLong(char[] digitChars, int offset, int len) + { + // Note: caller must ensure length is [10, 18] + int len1 = len-9; + long val = parseInt(digitChars, offset, len1) * L_BILLION; + return val + (long) parseInt(digitChars, offset+len1, 9); + } + + public final static long parseLong(String str) + { + /* Ok, now; as the very first thing, let's just optimize case of "fake longs"; + * that is, if we know they must be ints, call int parsing + */ + int length = str.length(); + if (length <= 9) { + return (long) parseInt(str); + } + // !!! TODO: implement efficient 2-int parsing... + return Long.parseLong(str); + } + + /** + * Helper method for determining if given String representation of + * an integral number would fit in 64-bit Java long or not. + * Note that input String must NOT contain leading minus sign (even + * if 'negative' is set to true). + * + * @param negative Whether original number had a minus sign (which is + * NOT passed to this method) or not + */ + public final static boolean inLongRange(char[] digitChars, int offset, int len, + boolean negative) + { + String cmpStr = negative ? MIN_LONG_STR_NO_SIGN : MAX_LONG_STR; + int cmpLen = cmpStr.length(); + if (len < cmpLen) return true; + if (len > cmpLen) return false; + + for (int i = 0; i < cmpLen; ++i) { + int diff = digitChars[offset+i] - cmpStr.charAt(i); + if (diff != 0) { + return (diff < 0); + } + } + return true; + } + + /** + * Similar to {@link #inLongRange(char[],int,int,boolean)}, but + * with String argument + * + * @param negative Whether original number had a minus sign (which is + * NOT passed to this method) or not + * + * @since 1.5.0 + */ + public final static boolean inLongRange(String numberStr, boolean negative) + { + String cmpStr = negative ? MIN_LONG_STR_NO_SIGN : MAX_LONG_STR; + int cmpLen = cmpStr.length(); + int actualLen = numberStr.length(); + if (actualLen < cmpLen) return true; + if (actualLen > cmpLen) return false; + + // could perhaps just use String.compareTo()? + for (int i = 0; i < cmpLen; ++i) { + int diff = numberStr.charAt(i) - cmpStr.charAt(i); + if (diff != 0) { + return (diff < 0); + } + } + return true; + } + + /** + * @since 1.6 + */ + public static int parseAsInt(String input, int defaultValue) + { + if (input == null) { + return defaultValue; + } + input = input.trim(); + int len = input.length(); + if (len == 0) { + return defaultValue; + } + // One more thing: use integer parsing for 'simple' + int i = 0; + if (i < len) { // skip leading sign: + char c = input.charAt(0); + if (c == '+') { // for plus, actually physically remove + input = input.substring(1); + len = input.length(); + } else if (c == '-') { // minus, just skip for checks, must retain + ++i; + } + } + for (; i < len; ++i) { + char c = input.charAt(i); + // if other symbols, parse as Double, coerce + if (c > '9' || c < '0') { + try { + return (int) parseDouble(input); + } catch (NumberFormatException e) { + return defaultValue; + } + } + } + try { + return Integer.parseInt(input); + } catch (NumberFormatException e) { } + return defaultValue; + } + + /** + * @since 1.6 + */ + public static long parseAsLong(String input, long defaultValue) + { + if (input == null) { + return defaultValue; + } + input = input.trim(); + int len = input.length(); + if (len == 0) { + return defaultValue; + } + // One more thing: use long parsing for 'simple' + int i = 0; + if (i < len) { // skip leading sign: + char c = input.charAt(0); + if (c == '+') { // for plus, actually physically remove + input = input.substring(1); + len = input.length(); + } else if (c == '-') { // minus, just skip for checks, must retain + ++i; + } + } + for (; i < len; ++i) { + char c = input.charAt(i); + // if other symbols, parse as Double, coerce + if (c > '9' || c < '0') { + try { + return (long) parseDouble(input); + } catch (NumberFormatException e) { + return defaultValue; + } + } + } + try { + return Long.parseLong(input); + } catch (NumberFormatException e) { } + return defaultValue; + } + + /** + * @since 1.6 + */ + public static double parseAsDouble(String input, double defaultValue) + { + if (input == null) { + return defaultValue; + } + input = input.trim(); + int len = input.length(); + if (len == 0) { + return defaultValue; + } + try { + return parseDouble(input); + } catch (NumberFormatException e) { } + return defaultValue; + } + + /** + * @since 1.8 + */ + public final static double parseDouble(String numStr) throws NumberFormatException + { + // [JACKSON-486]: avoid some nasty float representations... but should it be MIN_NORMAL or MIN_VALUE? + if (NASTY_SMALL_DOUBLE.equals(numStr)) { + return Double.MIN_NORMAL; + } + return Double.parseDouble(numStr); + } +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/io/NumberOutput.java b/1.9.10/src/java/org/codehaus/jackson/io/NumberOutput.java new file mode 100644 index 0000000..9ab9d49 --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/io/NumberOutput.java
@@ -0,0 +1,398 @@ +package org.codehaus.jackson.io; + +public final class NumberOutput +{ + private final static char NULL_CHAR = (char) 0; + + private static int MILLION = 1000000; + private static int BILLION = 1000000000; + private static long TEN_BILLION_L = 10000000000L; + private static long THOUSAND_L = 1000L; + + private static long MIN_INT_AS_LONG = (long) Integer.MIN_VALUE; + private static long MAX_INT_AS_LONG = (long) Integer.MAX_VALUE; + + final static String SMALLEST_LONG = String.valueOf(Long.MIN_VALUE); + + final static char[] LEADING_TRIPLETS = new char[4000]; + final static char[] FULL_TRIPLETS = new char[4000]; + static { + /* Let's fill it with NULLs for ignorable leading digits, + * and digit chars for others + */ + int ix = 0; + for (int i1 = 0; i1 < 10; ++i1) { + char f1 = (char) ('0' + i1); + char l1 = (i1 == 0) ? NULL_CHAR : f1; + for (int i2 = 0; i2 < 10; ++i2) { + char f2 = (char) ('0' + i2); + char l2 = (i1 == 0 && i2 == 0) ? NULL_CHAR : f2; + for (int i3 = 0; i3 < 10; ++i3) { + // Last is never to be empty + char f3 = (char) ('0' + i3); + LEADING_TRIPLETS[ix] = l1; + LEADING_TRIPLETS[ix+1] = l2; + LEADING_TRIPLETS[ix+2] = f3; + FULL_TRIPLETS[ix] = f1; + FULL_TRIPLETS[ix+1] = f2; + FULL_TRIPLETS[ix+2] = f3; + ix += 4; + } + } + } + } + + final static byte[] FULL_TRIPLETS_B = new byte[4000]; + static { + for (int i = 0; i < 4000; ++i) { + FULL_TRIPLETS_B[i] = (byte) FULL_TRIPLETS[i]; + } + } + + final static String[] sSmallIntStrs = new String[] { + "0","1","2","3","4","5","6","7","8","9","10" + }; + final static String[] sSmallIntStrs2 = new String[] { + "-1","-2","-3","-4","-5","-6","-7","-8","-9","-10" + }; + + /* + /********************************************************** + /* Efficient serialization methods using raw buffers + /********************************************************** + */ + + /** + * @return Offset within buffer after outputting int + */ + public static int outputInt(int value, char[] buffer, int offset) + { + if (value < 0) { + if (value == Integer.MIN_VALUE) { + /* Special case: no matching positive value within range; + * let's then "upgrade" to long and output as such. + */ + return outputLong((long) value, buffer, offset); + } + buffer[offset++] = '-'; + value = -value; + } + + if (value < MILLION) { // at most 2 triplets... + if (value < 1000) { + if (value < 10) { + buffer[offset++] = (char) ('0' + value); + } else { + offset = outputLeadingTriplet(value, buffer, offset); + } + } else { + int thousands = value / 1000; + value -= (thousands * 1000); // == value % 1000 + offset = outputLeadingTriplet(thousands, buffer, offset); + offset = outputFullTriplet(value, buffer, offset); + } + return offset; + } + + // ok, all 3 triplets included + /* Let's first hand possible billions separately before + * handling 3 triplets. This is possible since we know we + * can have at most '2' as billion count. + */ + boolean hasBillions = (value >= BILLION); + if (hasBillions) { + value -= BILLION; + if (value >= BILLION) { + value -= BILLION; + buffer[offset++] = '2'; + } else { + buffer[offset++] = '1'; + } + } + int newValue = value / 1000; + int ones = (value - (newValue * 1000)); // == value % 1000 + value = newValue; + newValue /= 1000; + int thousands = (value - (newValue * 1000)); + + // value now has millions, which have 1, 2 or 3 digits + if (hasBillions) { + offset = outputFullTriplet(newValue, buffer, offset); + } else { + offset = outputLeadingTriplet(newValue, buffer, offset); + } + offset = outputFullTriplet(thousands, buffer, offset); + offset = outputFullTriplet(ones, buffer, offset); + return offset; + } + + public static int outputInt(int value, byte[] buffer, int offset) + { + if (value < 0) { + if (value == Integer.MIN_VALUE) { + return outputLong((long) value, buffer, offset); + } + buffer[offset++] = '-'; + value = -value; + } + + if (value < MILLION) { // at most 2 triplets... + if (value < 1000) { + if (value < 10) { + buffer[offset++] = (byte) ('0' + value); + } else { + offset = outputLeadingTriplet(value, buffer, offset); + } + } else { + int thousands = value / 1000; + value -= (thousands * 1000); // == value % 1000 + offset = outputLeadingTriplet(thousands, buffer, offset); + offset = outputFullTriplet(value, buffer, offset); + } + return offset; + } + boolean hasBillions = (value >= BILLION); + if (hasBillions) { + value -= BILLION; + if (value >= BILLION) { + value -= BILLION; + buffer[offset++] = '2'; + } else { + buffer[offset++] = '1'; + } + } + int newValue = value / 1000; + int ones = (value - (newValue * 1000)); // == value % 1000 + value = newValue; + newValue /= 1000; + int thousands = (value - (newValue * 1000)); + + if (hasBillions) { + offset = outputFullTriplet(newValue, buffer, offset); + } else { + offset = outputLeadingTriplet(newValue, buffer, offset); + } + offset = outputFullTriplet(thousands, buffer, offset); + offset = outputFullTriplet(ones, buffer, offset); + return offset; + } + + /** + * @return Offset within buffer after outputting int + */ + public static int outputLong(long value, char[] buffer, int offset) + { + // First: does it actually fit in an int? + if (value < 0L) { + /* MIN_INT is actually printed as long, just because its + * negation is not an int but long + */ + if (value > MIN_INT_AS_LONG) { + return outputInt((int) value, buffer, offset); + } + if (value == Long.MIN_VALUE) { + // Special case: no matching positive value within range + int len = SMALLEST_LONG.length(); + SMALLEST_LONG.getChars(0, len, buffer, offset); + return (offset + len); + } + buffer[offset++] = '-'; + value = -value; + } else { + if (value <= MAX_INT_AS_LONG) { + return outputInt((int) value, buffer, offset); + } + } + + /* Ok: real long print. Need to first figure out length + * in characters, and then print in from end to beginning + */ + int origOffset = offset; + offset += calcLongStrLength(value); + int ptr = offset; + + // First, with long arithmetics: + while (value > MAX_INT_AS_LONG) { // full triplet + ptr -= 3; + long newValue = value / THOUSAND_L; + int triplet = (int) (value - newValue * THOUSAND_L); + outputFullTriplet(triplet, buffer, ptr); + value = newValue; + } + // Then with int arithmetics: + int ivalue = (int) value; + while (ivalue >= 1000) { // still full triplet + ptr -= 3; + int newValue = ivalue / 1000; + int triplet = ivalue - (newValue * 1000); + outputFullTriplet(triplet, buffer, ptr); + ivalue = newValue; + } + // And finally, if anything remains, partial triplet + outputLeadingTriplet(ivalue, buffer, origOffset); + + return offset; + } + + public static int outputLong(long value, byte[] buffer, int offset) + { + if (value < 0L) { + if (value > MIN_INT_AS_LONG) { + return outputInt((int) value, buffer, offset); + } + if (value == Long.MIN_VALUE) { + // Special case: no matching positive value within range + int len = SMALLEST_LONG.length(); + for (int i = 0; i < len; ++i) { + buffer[offset++] = (byte) SMALLEST_LONG.charAt(i); + } + return offset; + } + buffer[offset++] = '-'; + value = -value; + } else { + if (value <= MAX_INT_AS_LONG) { + return outputInt((int) value, buffer, offset); + } + } + int origOffset = offset; + offset += calcLongStrLength(value); + int ptr = offset; + + // First, with long arithmetics: + while (value > MAX_INT_AS_LONG) { // full triplet + ptr -= 3; + long newValue = value / THOUSAND_L; + int triplet = (int) (value - newValue * THOUSAND_L); + outputFullTriplet(triplet, buffer, ptr); + value = newValue; + } + // Then with int arithmetics: + int ivalue = (int) value; + while (ivalue >= 1000) { // still full triplet + ptr -= 3; + int newValue = ivalue / 1000; + int triplet = ivalue - (newValue * 1000); + outputFullTriplet(triplet, buffer, ptr); + ivalue = newValue; + } + outputLeadingTriplet(ivalue, buffer, origOffset); + return offset; + } + + /* + /********************************************************** + /* Secondary convenience serialization methods + /********************************************************** + */ + + /* !!! 05-Aug-2008, tatus: Any ways to further optimize + * these? (or need: only called by diagnostics methods?) + */ + + public static String toString(int value) + { + // Lookup table for small values + if (value < sSmallIntStrs.length) { + if (value >= 0) { + return sSmallIntStrs[value]; + } + int v2 = -value - 1; + if (v2 < sSmallIntStrs2.length) { + return sSmallIntStrs2[v2]; + } + } + return Integer.toString(value); + } + + public static String toString(long value) + { + if (value <= Integer.MAX_VALUE && + value >= Integer.MIN_VALUE) { + return toString((int) value); + } + return Long.toString(value); + } + + public static String toString(double value) + { + return Double.toString(value); + } + + /* + /********************************************************** + /* Internal methods + /********************************************************** + */ + + private static int outputLeadingTriplet(int triplet, char[] buffer, int offset) + { + int digitOffset = (triplet << 2); + char c = LEADING_TRIPLETS[digitOffset++]; + if (c != NULL_CHAR) { + buffer[offset++] = c; + } + c = LEADING_TRIPLETS[digitOffset++]; + if (c != NULL_CHAR) { + buffer[offset++] = c; + } + // Last is required to be non-empty + buffer[offset++] = LEADING_TRIPLETS[digitOffset]; + return offset; + } + + private static int outputLeadingTriplet(int triplet, byte[] buffer, int offset) + { + int digitOffset = (triplet << 2); + char c = LEADING_TRIPLETS[digitOffset++]; + if (c != NULL_CHAR) { + buffer[offset++] = (byte) c; + } + c = LEADING_TRIPLETS[digitOffset++]; + if (c != NULL_CHAR) { + buffer[offset++] = (byte) c; + } + // Last is required to be non-empty + buffer[offset++] = (byte) LEADING_TRIPLETS[digitOffset]; + return offset; + } + + private static int outputFullTriplet(int triplet, char[] buffer, int offset) + { + int digitOffset = (triplet << 2); + buffer[offset++] = FULL_TRIPLETS[digitOffset++]; + buffer[offset++] = FULL_TRIPLETS[digitOffset++]; + buffer[offset++] = FULL_TRIPLETS[digitOffset]; + return offset; + } + + private static int outputFullTriplet(int triplet, byte[] buffer, int offset) + { + int digitOffset = (triplet << 2); + buffer[offset++] = FULL_TRIPLETS_B[digitOffset++]; + buffer[offset++] = FULL_TRIPLETS_B[digitOffset++]; + buffer[offset++] = FULL_TRIPLETS_B[digitOffset]; + return offset; + } + + /** + *<p> + * Pre-conditions: posValue is positive, and larger than + * Integer.MAX_VALUE (about 2 billions). + */ + private static int calcLongStrLength(long posValue) + { + int len = 10; + long comp = TEN_BILLION_L; + + // 19 is longest, need to worry about overflow + while (posValue >= comp) { + if (len == 19) { + break; + } + ++len; + comp = (comp << 3) + (comp << 1); // 10x + } + return len; + } +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/io/OutputDecorator.java b/1.9.10/src/java/org/codehaus/jackson/io/OutputDecorator.java new file mode 100644 index 0000000..3ec4442 --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/io/OutputDecorator.java
@@ -0,0 +1,40 @@ +package org.codehaus.jackson.io; + +import java.io.*; + +/** + * Handler class that can be used to decorate output destinations. + * Typical use is to use a filter abstraction (filtered output stream, + * writer) around original output destination, and apply additional + * processing during write operations. + * + * @since 1.8 + */ +public abstract class OutputDecorator +{ + /** + * Method called by {@link org.codehaus.jackson.JsonFactory} instance when + * creating generator for given {@link OutputStream}, when this decorator + * has been registered. + * + * @param ctxt IO context in use (provides access to declared encoding) + * @param out Original output destination + * + * @return OutputStream to use; either passed in argument, or something that + * calls it + */ + public abstract OutputStream decorate(IOContext ctxt, OutputStream out) + throws IOException; + + /** + * Method called by {@link org.codehaus.jackson.JsonFactory} instance when + * creating generator for given {@link Writer}, when this decorator + * has been registered. + * + * @param ctxt IO context in use (provides access to declared encoding) + * @param w Original output writer + * + * @return Writer to use; either passed in argument, or something that calls it + */ + public abstract Writer decorate(IOContext ctxt, Writer w) throws IOException; +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/io/SegmentedStringWriter.java b/1.9.10/src/java/org/codehaus/jackson/io/SegmentedStringWriter.java new file mode 100644 index 0000000..715b1d1 --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/io/SegmentedStringWriter.java
@@ -0,0 +1,104 @@ +package org.codehaus.jackson.io; + +import java.io.*; + +import org.codehaus.jackson.util.BufferRecycler; +import org.codehaus.jackson.util.TextBuffer; + +/** + * Efficient alternative to {@link StringWriter}, based on using segmented + * internal buffer. Initial input buffer is also recyclable. + *<p> + * This class is most useful when serializing JSON content as a String: + * if so, instance of this class can be given as the writer to + * <code>JsonGenerator</code>. + * + * @since 1.3 + */ +public final class SegmentedStringWriter + extends Writer +{ + final protected TextBuffer _buffer; + + public SegmentedStringWriter(BufferRecycler br) + { + super(); + _buffer = new TextBuffer(br); + } + + /* + /********************************************************** + /* java.io.Writer implementation + /********************************************************** + */ + + @Override + public Writer append(char c) + { + write(c); + return this; + } + + @Override + public Writer append(CharSequence csq) + { + String str = csq.toString(); + _buffer.append(str, 0, str.length()); + return this; + } + + @Override + public Writer append(CharSequence csq, int start, int end) + { + String str = csq.subSequence(start, end).toString(); + _buffer.append(str, 0, str.length()); + return this; + } + + @Override public void close() { } // NOP + + @Override public void flush() { } // NOP + + @Override + public void write(char[] cbuf) { + _buffer.append(cbuf, 0, cbuf.length); + } + + @Override + public void write(char[] cbuf, int off, int len) { + _buffer.append(cbuf, off, len); + } + + @Override + public void write(int c) { + _buffer.append((char) c); + } + + @Override + public void write(String str) { _buffer.append(str, 0, str.length()); } + + @Override + public void write(String str, int off, int len) { + _buffer.append(str, off, len); + } + + /* + /********************************************************** + /* Extended API + /********************************************************** + */ + + /** + * Main access method that will construct a String that contains + * all the contents, release all internal buffers we may have, + * and return result String. + * Note that the method is not idempotent -- if called second time, + * will just return an empty String. + */ + public String getAndClear() + { + String result = _buffer.contentsAsString(); + _buffer.releaseBuffers(); + return result; + } +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/io/SerializedString.java b/1.9.10/src/java/org/codehaus/jackson/io/SerializedString.java new file mode 100644 index 0000000..50ca637 --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/io/SerializedString.java
@@ -0,0 +1,114 @@ +package org.codehaus.jackson.io; + +import org.codehaus.jackson.SerializableString; + +/** + * String token that can lazily serialize String contained and then reuse that + * serialization later on. This is similar to JDBC prepared statements, for example, + * in that instances should only be created when they are used more than use; + * prime candidates are various serializers. + *<p> + * Class is final for performance reasons and since this is not designed to + * be extensible or customizable (customizations would occur in calling code) + * + * @since 1.6 + */ +public class SerializedString implements SerializableString +{ + protected final String _value; + + /* 13-Dec-2010, tatu: Whether use volatile or not is actually an important + * decision for multi-core use cases. Cost of volatility can be non-trivial + * for heavy use cases, and serialized-string instances are accessed often. + * Given that all code paths with common Jackson usage patterns go through + * a few memory barriers (mostly with cache/reuse pool access) it seems safe + * enough to omit volatiles here, given how simple lazy initialization is. + * This can be compared to how {@link String#intern} works; lazily and + * without synchronization or use of volatile keyword. + */ + + protected /*volatile*/ byte[] _quotedUTF8Ref; + + protected /*volatile*/ byte[] _unquotedUTF8Ref; + + protected /*volatile*/ char[] _quotedChars; + + public SerializedString(String v) { _value = v; } + + /* + /********************************************************** + /* API + /********************************************************** + */ + + @Override + public final String getValue() { return _value; } + + /** + * Returns length of the String as characters + */ + @Override + public final int charLength() { return _value.length(); } + + @Override + public final char[] asQuotedChars() + { + char[] result = _quotedChars; + if (result == null) { + result = JsonStringEncoder.getInstance().quoteAsString(_value); + _quotedChars = result; + } + return result; + } + + /** + * Accessor for accessing value that has been quoted using JSON + * quoting rules, and encoded using UTF-8 encoding. + */ + @Override + public final byte[] asUnquotedUTF8() + { + byte[] result = _unquotedUTF8Ref; + if (result == null) { + result = JsonStringEncoder.getInstance().encodeAsUTF8(_value); + _unquotedUTF8Ref = result; + } + return result; + } + + /** + * Accessor for accessing value as is (without JSON quoting) + * encoded using UTF-8 encoding. + */ + @Override + public final byte[] asQuotedUTF8() + { + byte[] result = _quotedUTF8Ref; + if (result == null) { + result = JsonStringEncoder.getInstance().quoteAsUTF8(_value); + _quotedUTF8Ref = result; + } + return result; + } + + /* + /********************************************************** + /* Standard method overrides + /********************************************************** + */ + + @Override + public final String toString() { return _value; } + + @Override + public final int hashCode() { return _value.hashCode(); } + + @Override + public final boolean equals(Object o) + { + if (o == this) return true; + if (o == null || o.getClass() != getClass()) return false; + SerializedString other = (SerializedString) o; + return _value.equals(other._value); + } +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/io/UTF32Reader.java b/1.9.10/src/java/org/codehaus/jackson/io/UTF32Reader.java new file mode 100644 index 0000000..35dc712 --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/io/UTF32Reader.java
@@ -0,0 +1,214 @@ +package org.codehaus.jackson.io; + +import java.io.*; + + +/** + * Since JDK does not come with UTF-32/UCS-4, let's implement a simple + * decoder to use. + */ +public final class UTF32Reader + extends BaseReader +{ + final boolean mBigEndian; + + /** + * Although input is fine with full Unicode set, Java still uses + * 16-bit chars, so we may have to split high-order chars into + * surrogate pairs. + */ + char mSurrogate = NULL_CHAR; + + /** + * Total read character count; used for error reporting purposes + */ + int mCharCount = 0; + + /** + * Total read byte count; used for error reporting purposes + */ + int mByteCount = 0; + + /* + //////////////////////////////////////// + // Life-cycle + //////////////////////////////////////// + */ + + public UTF32Reader(IOContext ctxt, + InputStream in, byte[] buf, int ptr, int len, + boolean isBigEndian) + { + super(ctxt, in, buf, ptr, len); + mBigEndian = isBigEndian; + } + + /* + //////////////////////////////////////// + // Public API + //////////////////////////////////////// + */ + + @Override + public int read(char[] cbuf, int start, int len) + throws IOException + { + // Already EOF? + if (_buffer == null) { + return -1; + } + if (len < 1) { + return len; + } + // Let's then ensure there's enough room... + if (start < 0 || (start+len) > cbuf.length) { + reportBounds(cbuf, start, len); + } + + len += start; + int outPtr = start; + + // Ok, first; do we have a surrogate from last round? + if (mSurrogate != NULL_CHAR) { + cbuf[outPtr++] = mSurrogate; + mSurrogate = NULL_CHAR; + // No need to load more, already got one char + } else { + /* Note: we'll try to avoid blocking as much as possible. As a + * result, we only need to get 4 bytes for a full char. + */ + int left = (_length - _ptr); + if (left < 4) { + if (!loadMore(left)) { // (legal) EOF? + return -1; + } + } + } + + main_loop: + while (outPtr < len) { + int ptr = _ptr; + int ch; + + if (mBigEndian) { + ch = (_buffer[ptr] << 24) | ((_buffer[ptr+1] & 0xFF) << 16) + | ((_buffer[ptr+2] & 0xFF) << 8) | (_buffer[ptr+3] & 0xFF); + } else { + ch = (_buffer[ptr] & 0xFF) | ((_buffer[ptr+1] & 0xFF) << 8) + | ((_buffer[ptr+2] & 0xFF) << 16) | (_buffer[ptr+3] << 24); + } + _ptr += 4; + + // Does it need to be split to surrogates? + // (also, we can and need to verify illegal chars) + if (ch > 0xFFFF) { // need to split into surrogates? + if (ch > LAST_VALID_UNICODE_CHAR) { + reportInvalid(ch, outPtr-start, + "(above "+Integer.toHexString(LAST_VALID_UNICODE_CHAR)+") "); + } + ch -= 0x10000; // to normalize it starting with 0x0 + cbuf[outPtr++] = (char) (0xD800 + (ch >> 10)); + // hmmh. can this ever be 0? (not legal, at least?) + ch = (0xDC00 | (ch & 0x03FF)); + // Room for second part? + if (outPtr >= len) { // nope + mSurrogate = (char) ch; + break main_loop; + } + } + cbuf[outPtr++] = (char) ch; + if (_ptr >= _length) { + break main_loop; + } + } + + len = outPtr - start; + mCharCount += len; + return len; + } + + /* + //////////////////////////////////////// + // Internal methods + //////////////////////////////////////// + */ + + private void reportUnexpectedEOF(int gotBytes, int needed) + throws IOException + { + int bytePos = mByteCount + gotBytes; + int charPos = mCharCount; + + throw new CharConversionException("Unexpected EOF in the middle of a 4-byte UTF-32 char: got " + +gotBytes+", needed "+needed + +", at char #"+charPos+", byte #"+bytePos+")"); + } + + private void reportInvalid(int value, int offset, String msg) + throws IOException + { + int bytePos = mByteCount + _ptr - 1; + int charPos = mCharCount + offset; + + throw new CharConversionException("Invalid UTF-32 character 0x" + +Integer.toHexString(value) + +msg+" at char #"+charPos+", byte #"+bytePos+")"); + } + + /** + * @param available Number of "unused" bytes in the input buffer + * + * @return True, if enough bytes were read to allow decoding of at least + * one full character; false if EOF was encountered instead. + */ + private boolean loadMore(int available) + throws IOException + { + mByteCount += (_length - available); + + // Bytes that need to be moved to the beginning of buffer? + if (available > 0) { + if (_ptr > 0) { + for (int i = 0; i < available; ++i) { + _buffer[i] = _buffer[_ptr+i]; + } + _ptr = 0; + } + _length = available; + } else { + /* Ok; here we can actually reasonably expect an EOF, + * so let's do a separate read right away: + */ + _ptr = 0; + int count = _in.read(_buffer); + if (count < 1) { + _length = 0; + if (count < 0) { // -1 + freeBuffers(); // to help GC? + return false; + } + // 0 count is no good; let's err out + reportStrangeStream(); + } + _length = count; + } + + /* Need at least 4 bytes; if we don't get that many, it's an + * error. + */ + while (_length < 4) { + int count = _in.read(_buffer, _length, _buffer.length - _length); + if (count < 1) { + if (count < 0) { // -1, EOF... no good! + freeBuffers(); // to help GC? + reportUnexpectedEOF(_length, 4); + } + // 0 count is no good; let's err out + reportStrangeStream(); + } + _length += count; + } + return true; + } +} +
diff --git a/1.9.10/src/java/org/codehaus/jackson/io/UTF8Writer.java b/1.9.10/src/java/org/codehaus/jackson/io/UTF8Writer.java new file mode 100644 index 0000000..3f19778 --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/io/UTF8Writer.java
@@ -0,0 +1,387 @@ +package org.codehaus.jackson.io; + +import java.io.*; + + +public final class UTF8Writer + extends Writer +{ + final static int SURR1_FIRST = 0xD800; + final static int SURR1_LAST = 0xDBFF; + final static int SURR2_FIRST = 0xDC00; + final static int SURR2_LAST = 0xDFFF; + + final protected IOContext _context; + + OutputStream _out; + + byte[] _outBuffer; + + final int _outBufferEnd; + + int _outPtr; + + /** + * When outputting chars from BMP, surrogate pairs need to be coalesced. + * To do this, both pairs must be known first; and since it is possible + * pairs may be split, we need temporary storage for the first half + */ + int _surrogate = 0; + + public UTF8Writer(IOContext ctxt, OutputStream out) + { + _context = ctxt; + _out = out; + + _outBuffer = ctxt.allocWriteEncodingBuffer(); + /* Max. expansion for a single char (in unmodified UTF-8) is + * 4 bytes (or 3 depending on how you view it -- 4 when recombining + * surrogate pairs) + */ + _outBufferEnd = _outBuffer.length - 4; + _outPtr = 0; + } + + @Override + public Writer append(char c) + throws IOException + { + write(c); + return this; + } + + @Override + public void close() + throws IOException + { + if (_out != null) { + if (_outPtr > 0) { + _out.write(_outBuffer, 0, _outPtr); + _outPtr = 0; + } + OutputStream out = _out; + _out = null; + + byte[] buf = _outBuffer; + if (buf != null) { + _outBuffer = null; + _context.releaseWriteEncodingBuffer(buf); + } + + out.close(); + + /* Let's 'flush' orphan surrogate, no matter what; but only + * after cleanly closing everything else. + */ + int code = _surrogate; + _surrogate = 0; + if (code > 0) { + throwIllegal(code); + } + } + } + + @Override + public void flush() + throws IOException + { + if (_out != null) { + if (_outPtr > 0) { + _out.write(_outBuffer, 0, _outPtr); + _outPtr = 0; + } + _out.flush(); + } + } + + @Override + public void write(char[] cbuf) + throws IOException + { + write(cbuf, 0, cbuf.length); + } + + @Override + public void write(char[] cbuf, int off, int len) + throws IOException + { + if (len < 2) { + if (len == 1) { + write(cbuf[off]); + } + return; + } + + // First: do we have a leftover surrogate to deal with? + if (_surrogate > 0) { + char second = cbuf[off++]; + --len; + write(convertSurrogate(second)); + // will have at least one more char + } + + int outPtr = _outPtr; + byte[] outBuf = _outBuffer; + int outBufLast = _outBufferEnd; // has 4 'spare' bytes + + // All right; can just loop it nice and easy now: + len += off; // len will now be the end of input buffer + + output_loop: + for (; off < len; ) { + /* First, let's ensure we can output at least 4 bytes + * (longest UTF-8 encoded codepoint): + */ + if (outPtr >= outBufLast) { + _out.write(outBuf, 0, outPtr); + outPtr = 0; + } + + int c = cbuf[off++]; + // And then see if we have an Ascii char: + if (c < 0x80) { // If so, can do a tight inner loop: + outBuf[outPtr++] = (byte)c; + // Let's calc how many ascii chars we can copy at most: + int maxInCount = (len - off); + int maxOutCount = (outBufLast - outPtr); + + if (maxInCount > maxOutCount) { + maxInCount = maxOutCount; + } + maxInCount += off; + ascii_loop: + while (true) { + if (off >= maxInCount) { // done with max. ascii seq + continue output_loop; + } + c = cbuf[off++]; + if (c >= 0x80) { + break ascii_loop; + } + outBuf[outPtr++] = (byte) c; + } + } + + // Nope, multi-byte: + if (c < 0x800) { // 2-byte + outBuf[outPtr++] = (byte) (0xc0 | (c >> 6)); + outBuf[outPtr++] = (byte) (0x80 | (c & 0x3f)); + } else { // 3 or 4 bytes + // Surrogates? + if (c < SURR1_FIRST || c > SURR2_LAST) { + outBuf[outPtr++] = (byte) (0xe0 | (c >> 12)); + outBuf[outPtr++] = (byte) (0x80 | ((c >> 6) & 0x3f)); + outBuf[outPtr++] = (byte) (0x80 | (c & 0x3f)); + continue; + } + // Yup, a surrogate: + if (c > SURR1_LAST) { // must be from first range + _outPtr = outPtr; + throwIllegal(c); + } + _surrogate = c; + // and if so, followed by another from next range + if (off >= len) { // unless we hit the end? + break; + } + c = convertSurrogate(cbuf[off++]); + if (c > 0x10FFFF) { // illegal in JSON as well as in XML + _outPtr = outPtr; + throwIllegal(c); + } + outBuf[outPtr++] = (byte) (0xf0 | (c >> 18)); + outBuf[outPtr++] = (byte) (0x80 | ((c >> 12) & 0x3f)); + outBuf[outPtr++] = (byte) (0x80 | ((c >> 6) & 0x3f)); + outBuf[outPtr++] = (byte) (0x80 | (c & 0x3f)); + } + } + _outPtr = outPtr; + } + + @Override + public void write(int c) throws IOException + { + // First; do we have a left over surrogate? + if (_surrogate > 0) { + c = convertSurrogate(c); + // If not, do we start with a surrogate? + } else if (c >= SURR1_FIRST && c <= SURR2_LAST) { + // Illegal to get second part without first: + if (c > SURR1_LAST) { + throwIllegal(c); + } + // First part just needs to be held for now + _surrogate = c; + return; + } + + if (_outPtr >= _outBufferEnd) { // let's require enough room, first + _out.write(_outBuffer, 0, _outPtr); + _outPtr = 0; + } + + if (c < 0x80) { // ascii + _outBuffer[_outPtr++] = (byte) c; + } else { + int ptr = _outPtr; + if (c < 0x800) { // 2-byte + _outBuffer[ptr++] = (byte) (0xc0 | (c >> 6)); + _outBuffer[ptr++] = (byte) (0x80 | (c & 0x3f)); + } else if (c <= 0xFFFF) { // 3 bytes + _outBuffer[ptr++] = (byte) (0xe0 | (c >> 12)); + _outBuffer[ptr++] = (byte) (0x80 | ((c >> 6) & 0x3f)); + _outBuffer[ptr++] = (byte) (0x80 | (c & 0x3f)); + } else { // 4 bytes + if (c > 0x10FFFF) { // illegal + throwIllegal(c); + } + _outBuffer[ptr++] = (byte) (0xf0 | (c >> 18)); + _outBuffer[ptr++] = (byte) (0x80 | ((c >> 12) & 0x3f)); + _outBuffer[ptr++] = (byte) (0x80 | ((c >> 6) & 0x3f)); + _outBuffer[ptr++] = (byte) (0x80 | (c & 0x3f)); + } + _outPtr = ptr; + } + } + + @Override + public void write(String str) throws IOException + { + write(str, 0, str.length()); + } + + @Override + public void write(String str, int off, int len) throws IOException + { + if (len < 2) { + if (len == 1) { + write(str.charAt(off)); + } + return; + } + + // First: do we have a leftover surrogate to deal with? + if (_surrogate > 0) { + char second = str.charAt(off++); + --len; + write(convertSurrogate(second)); + // will have at least one more char (case of 1 char was checked earlier on) + } + + int outPtr = _outPtr; + byte[] outBuf = _outBuffer; + int outBufLast = _outBufferEnd; // has 4 'spare' bytes + + // All right; can just loop it nice and easy now: + len += off; // len will now be the end of input buffer + + output_loop: + for (; off < len; ) { + /* First, let's ensure we can output at least 4 bytes + * (longest UTF-8 encoded codepoint): + */ + if (outPtr >= outBufLast) { + _out.write(outBuf, 0, outPtr); + outPtr = 0; + } + + int c = str.charAt(off++); + // And then see if we have an Ascii char: + if (c < 0x80) { // If so, can do a tight inner loop: + outBuf[outPtr++] = (byte)c; + // Let's calc how many ascii chars we can copy at most: + int maxInCount = (len - off); + int maxOutCount = (outBufLast - outPtr); + + if (maxInCount > maxOutCount) { + maxInCount = maxOutCount; + } + maxInCount += off; + ascii_loop: + while (true) { + if (off >= maxInCount) { // done with max. ascii seq + continue output_loop; + } + c = str.charAt(off++); + if (c >= 0x80) { + break ascii_loop; + } + outBuf[outPtr++] = (byte) c; + } + } + + // Nope, multi-byte: + if (c < 0x800) { // 2-byte + outBuf[outPtr++] = (byte) (0xc0 | (c >> 6)); + outBuf[outPtr++] = (byte) (0x80 | (c & 0x3f)); + } else { // 3 or 4 bytes + // Surrogates? + if (c < SURR1_FIRST || c > SURR2_LAST) { + outBuf[outPtr++] = (byte) (0xe0 | (c >> 12)); + outBuf[outPtr++] = (byte) (0x80 | ((c >> 6) & 0x3f)); + outBuf[outPtr++] = (byte) (0x80 | (c & 0x3f)); + continue; + } + // Yup, a surrogate: + if (c > SURR1_LAST) { // must be from first range + _outPtr = outPtr; + throwIllegal(c); + } + _surrogate = c; + // and if so, followed by another from next range + if (off >= len) { // unless we hit the end? + break; + } + c = convertSurrogate(str.charAt(off++)); + if (c > 0x10FFFF) { // illegal, as per RFC 4627 + _outPtr = outPtr; + throwIllegal(c); + } + outBuf[outPtr++] = (byte) (0xf0 | (c >> 18)); + outBuf[outPtr++] = (byte) (0x80 | ((c >> 12) & 0x3f)); + outBuf[outPtr++] = (byte) (0x80 | ((c >> 6) & 0x3f)); + outBuf[outPtr++] = (byte) (0x80 | (c & 0x3f)); + } + } + _outPtr = outPtr; + } + + /* + /********************************************************** + /* Internal methods + /********************************************************** + */ + + /** + * Method called to calculate UTF codepoint, from a surrogate pair. + */ + private int convertSurrogate(int secondPart) + throws IOException + { + int firstPart = _surrogate; + _surrogate = 0; + + // Ok, then, is the second part valid? + if (secondPart < SURR2_FIRST || secondPart > SURR2_LAST) { + throw new IOException("Broken surrogate pair: first char 0x"+Integer.toHexString(firstPart)+", second 0x"+Integer.toHexString(secondPart)+"; illegal combination"); + } + return 0x10000 + ((firstPart - SURR1_FIRST) << 10) + (secondPart - SURR2_FIRST); + } + + private void throwIllegal(int code) + throws IOException + { + if (code > 0x10FFFF) { // over max? + throw new IOException("Illegal character point (0x"+Integer.toHexString(code)+") to output; max is 0x10FFFF as per RFC 4627"); + } + if (code >= SURR1_FIRST) { + if (code <= SURR1_LAST) { // Unmatched first part (closing without second part?) + throw new IOException("Unmatched first part of surrogate pair (0x"+Integer.toHexString(code)+")"); + } + throw new IOException("Unmatched second part of surrogate pair (0x"+Integer.toHexString(code)+")"); + } + + // should we ever get this? + throw new IOException("Illegal character point (0x"+Integer.toHexString(code)+") to output"); + } +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/io/package.html b/1.9.10/src/java/org/codehaus/jackson/io/package.html new file mode 100644 index 0000000..e1e662d --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/io/package.html
@@ -0,0 +1,4 @@ +<body> +This package contains I/O helper classes Jackson itself uses, but that +are not exposed for external reuse. +</body>
diff --git a/1.9.10/src/java/org/codehaus/jackson/package-info.java b/1.9.10/src/java/org/codehaus/jackson/package-info.java new file mode 100644 index 0000000..5783ce7 --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/package-info.java
@@ -0,0 +1,30 @@ +/** + * Main public API classes of the core streaming JSON + * processor: most importantly {@link org.codehaus.jackson.JsonFactory} + * used for constructing + * JSON parser ({@link org.codehaus.jackson.JsonParser}) + * and generator + * ({@link org.codehaus.jackson.JsonParser}) + * instances. + * <p> + * Public API of the higher-level mapping interfaces ("Mapping API") + * is found from + * under {@link org.codehaus.jackson.map} and not included here, + * except for following base interfaces: + * <ul> + *<li>{@link org.codehaus.jackson.JsonNode} is included + *within Streaming API to support integration of the Tree Model + *(which is based on <code>JsonNode</code>) with the basic + *parsers and generators (iff using mapping-supporting factory: which + *is part of Mapping API, not core) + * </li> + *<li>{@link org.codehaus.jackson.ObjectCodec} is included so that + * reference to the object capable of serializing/deserializing + * Objects to/from JSON (usually, {@link org.codehaus.jackson.map.ObjectMapper}) + * can be exposed, without adding direct dependency to implementation. + * </li> + *</ul> + * </ul> + */ + +package org.codehaus.jackson;
diff --git a/1.9.10/src/java/org/codehaus/jackson/sym/BytesToNameCanonicalizer.java b/1.9.10/src/java/org/codehaus/jackson/sym/BytesToNameCanonicalizer.java new file mode 100644 index 0000000..ea4a6c3 --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/sym/BytesToNameCanonicalizer.java
@@ -0,0 +1,1208 @@ +package org.codehaus.jackson.sym; + +import java.util.Arrays; +import java.util.concurrent.atomic.AtomicReference; + +import org.codehaus.jackson.util.InternCache; + +/** + * A caching symbol table implementation used for canonicalizing JSON field + * names (as {@link Name}s which are constructed directly from a byte-based + * input source). + * Complications arise from trying to do efficient reuse and merging of + * symbol tables, to be able to make use of usually shared vocabulary + * of subsequent parsing runs. + * + * @author Tatu Saloranta + */ +public final class BytesToNameCanonicalizer +{ + protected static final int DEFAULT_TABLE_SIZE = 64; + + /** + * Let's not expand symbol tables past some maximum size; + * this should protected against OOMEs caused by large documents + * with unique (~= random) names. + */ + protected static final int MAX_TABLE_SIZE = 0x10000; // 64k entries == 256k mem + + /** + * Let's only share reasonably sized symbol tables. Max size set to 3/4 of 16k; + * this corresponds to 64k main hash index. This should allow for enough distinct + * names for almost any case. + */ + final static int MAX_ENTRIES_FOR_REUSE = 6000; + + /** + * Also: to thwart attacks based on hash collisions (which may or may not + * be cheap to calculate), we will need to detect "too long" + * collision chains. Let's start with static value of 255 entries + * for the longest legal chain. + *<p> + * Note: longest chain we have been able to produce without malicious + * intent has been 60 (with "com.fasterxml.jackson.core.main.TestWithTonsaSymbols"); + * our setting should be reasonable here. + * + * @since 1.9.9 + */ + final static int MAX_COLL_CHAIN_LENGTH = 255; + + /** + * And to support reduce likelihood of accidental collisions causing + * exceptions, let's prevent reuse of tables with long collision + * overflow lists as well. + * + * @since 1.9.9 + */ + final static int MAX_COLL_CHAIN_FOR_REUSE = 63; + + /** + * No point in trying to construct tiny tables, just need to resize + * soon. + */ + final static int MIN_HASH_SIZE = 16; + + /** + * We will also need to defin + */ + final static int INITIAL_COLLISION_LEN = 32; + + /** + * Bucket index is 8 bits, and value 0 is reserved to represent + * 'empty' status. + */ + final static int LAST_VALID_BUCKET = 0xFE; + + /* + /********************************************************** + /* Linkage, needed for merging symbol tables + /********************************************************** + */ + + /** + * Reference to the root symbol table, for child tables, so + * that they can merge table information back as necessary. + */ + final protected BytesToNameCanonicalizer _parent; + + /** + * Member that is only used by the root table instance: root + * passes immutable state into child instances, and children + * may return new state if they add entries to the table. + * Child tables do NOT use the reference. + */ + final protected AtomicReference<TableInfo> _tableInfo; + + /** + * Seed value we use as the base to make hash codes non-static between + * different runs, but still stable for lifetime of a single symbol table + * instance. + * This is done for security reasons, to avoid potential DoS attack via + * hash collisions. + * + * @since 1.9.9 + */ + final private int _hashSeed; + + /* + /********************************************************** + /* Main table state + /********************************************************** + */ + + /** + * Whether canonical symbol Strings are to be intern()ed before added + * to the table or not + */ + protected final boolean _intern; + + // // // First, global information + + /** + * Total number of Names in the symbol table; + * only used for child tables. + */ + protected int _count; + + /** + * We need to keep track of the longest collision list; this is needed + * both to indicate problems with attacks and to allow flushing for + * other cases. + * + * @since 1.9.9 + */ + protected int _longestCollisionList; + + // // // Then information regarding primary hash array and its + // // // matching Name array + + /** + * Mask used to truncate 32-bit hash value to current hash array + * size; essentially, hash array size - 1 (since hash array sizes + * are 2^N). + */ + protected int _mainHashMask; + + /** + * Array of 2^N size, which contains combination + * of 24-bits of hash (0 to indicate 'empty' slot), + * and 8-bit collision bucket index (0 to indicate empty + * collision bucket chain; otherwise subtract one from index) + */ + protected int[] _mainHash; + + /** + * Array that contains <code>Name</code> instances matching + * entries in <code>_mainHash</code>. Contains nulls for unused + * entries. + */ + protected Name[] _mainNames; + + // // // Then the collision/spill-over area info + + /** + * Array of heads of collision bucket chains; size dynamically + */ + protected Bucket[] _collList; + + /** + * Total number of Names in collision buckets (included in + * <code>_count</code> along with primary entries) + */ + protected int _collCount; + + /** + * Index of the first unused collision bucket entry (== size of + * the used portion of collision list): less than + * or equal to 0xFF (255), since max number of entries is 255 + * (8-bit, minus 0 used as 'empty' marker) + */ + protected int _collEnd; + + // // // Info regarding pending rehashing... + + /** + * This flag is set if, after adding a new entry, it is deemed + * that a rehash is warranted if any more entries are to be added. + */ + private transient boolean _needRehash; + + /* + /********************************************************** + /* Sharing, versioning + /********************************************************** + */ + + // // // Which of the buffers may be shared (and are copy-on-write)? + + /** + * Flag that indicates whether underlying data structures for + * the main hash area are shared or not. If they are, then they + * need to be handled in copy-on-write way, i.e. if they need + * to be modified, a copy needs to be made first; at this point + * it will not be shared any more, and can be modified. + *<p> + * This flag needs to be checked both when adding new main entries, + * and when adding new collision list queues (i.e. creating a new + * collision list head entry) + */ + private boolean _mainHashShared; + + private boolean _mainNamesShared; + + /** + * Flag that indicates whether underlying data structures for + * the collision list are shared or not. If they are, then they + * need to be handled in copy-on-write way, i.e. if they need + * to be modified, a copy needs to be made first; at this point + * it will not be shared any more, and can be modified. + *<p> + * This flag needs to be checked when adding new collision entries. + */ + private boolean _collListShared; + + /* + /********************************************************** + /* Life-cycle: constructors + /********************************************************** + */ + + /** + * Constructor used for creating per-<code>JsonFactory</code> "root" + * symbol tables: ones used for merging and sharing common symbols + * + * @param hashSize Initial hash area size + * @param intern Whether Strings contained should be {@link String#intern}ed + * @param seed Random seed valued used to make it more difficult to cause + * collisions (used for collision-based DoS attacks). + */ + private BytesToNameCanonicalizer(int hashSize, boolean intern, int seed) + { + _parent = null; + _hashSeed = seed; + _intern = intern; + // Sanity check: let's now allow hash sizes below certain minimum value + if (hashSize < MIN_HASH_SIZE) { + hashSize = MIN_HASH_SIZE; + } else { + /* Also; size must be 2^N; otherwise hash algorithm won't + * work... so let's just pad it up, if so + */ + if ((hashSize & (hashSize - 1)) != 0) { // only true if it's 2^N + int curr = MIN_HASH_SIZE; + while (curr < hashSize) { + curr += curr; + } + hashSize = curr; + } + } + _tableInfo = new AtomicReference<TableInfo>(initTableInfo(hashSize)); + } + + /** + * Constructor used when creating a child instance + */ + private BytesToNameCanonicalizer(BytesToNameCanonicalizer parent, boolean intern, int seed, + TableInfo state) + { + _parent = parent; + _hashSeed = seed; + _intern = intern; + _tableInfo = null; // not used by child tables + + // Then copy shared state + _count = state.count; + _mainHashMask = state.mainHashMask; + _mainHash = state.mainHash; + _mainNames = state.mainNames; + _collList = state.collList; + _collCount = state.collCount; + _collEnd = state.collEnd; + _longestCollisionList = state.longestCollisionList; + + // and then set other state to reflect sharing status + _needRehash = false; + _mainHashShared = true; + _mainNamesShared = true; + _collListShared = true; + } + + /* + public TableInfo(int count, int mainHashMask, int[] mainHash, Name[] mainNames, + Bucket[] collList, int collCount, int collEnd, int longestCollisionList) + */ + private TableInfo initTableInfo(int hashSize) + { + return new TableInfo(0, // count + hashSize - 1, // mainHashMask + new int[hashSize], // mainHash + new Name[hashSize], // mainNames + null, // collList + 0, // collCount, + 0, // collEnd + 0 // longestCollisionList + ); + } + + /* + /********************************************************** + /* Life-cycle: factory methods, merging + /********************************************************** + */ + + /** + * Factory method to call to create a symbol table instance with a + * randomized seed value. + */ + public static BytesToNameCanonicalizer createRoot() + { + /* [Issue-21]: Need to use a variable seed, to thwart hash-collision + * based attacks. + */ + long now = System.currentTimeMillis(); + // ensure it's not 0; and might as well require to be odd so: + int seed = (((int) now) + ((int) now >>> 32)) | 1; + return createRoot(seed); + } + + /** + * Factory method that should only be called from unit tests, where seed + * value should remain the same. + */ + protected static BytesToNameCanonicalizer createRoot(int hashSeed) { + return new BytesToNameCanonicalizer(DEFAULT_TABLE_SIZE, true, hashSeed); + } + + /** + * Factory method used to create actual symbol table instance to + * use for parsing. + * + * @param intern Whether canonical symbol Strings should be interned + * or not + */ + public BytesToNameCanonicalizer makeChild(boolean canonicalize, + boolean intern) + { + return new BytesToNameCanonicalizer(this, intern, _hashSeed, _tableInfo.get()); + } + + /** + * Method called by the using code to indicate it is done + * with this instance. This lets instance merge accumulated + * changes into parent (if need be), safely and efficiently, + * and without calling code having to know about parent + * information + */ + public void release() + { + // we will try to merge if child table has new entries + if (_parent != null && maybeDirty()) { + _parent.mergeChild(new TableInfo(this)); + /* Let's also mark this instance as dirty, so that just in + * case release was too early, there's no corruption of possibly shared data. + */ + _mainHashShared = true; + _mainNamesShared = true; + _collListShared = true; + } + } + + private void mergeChild(TableInfo childState) + { + final int childCount = childState.count; + TableInfo currState = _tableInfo.get(); + + // Only makes sense if child actually has more entries + if (childCount <= currState.count) { + return; + } + + /* One caveat: let's try to avoid problems with + * degenerate cases of documents with generated "random" + * names: for these, symbol tables would bloat indefinitely. + * One way to do this is to just purge tables if they grow + * too large, and that's what we'll do here. + */ + if (childCount > MAX_ENTRIES_FOR_REUSE + || childState.longestCollisionList > MAX_COLL_CHAIN_FOR_REUSE) { + /* Should there be a way to get notified about this + * event, to log it or such? (as it's somewhat abnormal + * thing to happen) + */ + // At any rate, need to clean up the tables + childState = initTableInfo(DEFAULT_TABLE_SIZE); + } + _tableInfo.compareAndSet(currState, childState); + } + + /* + /********************************************************** + /* API, accessors + /********************************************************** + */ + + public int size() + { + if (_tableInfo != null) { // root table + return _tableInfo.get().count; + } + // nope, child table + return _count; + } + + /** + * @since 1.9.9 + */ + public int bucketCount() { return _mainHash.length; } + + /** + * Method called to check to quickly see if a child symbol table + * may have gotten additional entries. Used for checking to see + * if a child table should be merged into shared table. + */ + public boolean maybeDirty() { + return !_mainHashShared; + } + + /** + * @since 1.9.9 + */ + public int hashSeed() { return _hashSeed; } + + /** + * Method mostly needed by unit tests; calculates number of + * entries that are in collision list. Value can be at most + * ({@link #size} - 1), but should usually be much lower, ideally 0. + * + * @since 1.9.9 + */ + public int collisionCount() { + return _collCount; + } + + /** + * Method mostly needed by unit tests; calculates length of the + * longest collision chain. This should typically be a low number, + * but may be up to {@link #size} - 1 in the pathological case + * + * @since 1.9.9 + */ + public int maxCollisionLength() { + return _longestCollisionList; + } + + /* + /********************************************************** + /* Public API, accessing symbols: + /********************************************************** + */ + + public static Name getEmptyName() + { + return Name1.getEmptyName(); + } + + /** + * Finds and returns name matching the specified symbol, if such + * name already exists in the table. + * If not, will return null. + *<p> + * Note: separate methods to optimize common case of + * short element/attribute names (4 or less ascii characters) + * + * @param firstQuad int32 containing first 4 bytes of the name; + * if the whole name less than 4 bytes, padded with zero bytes + * in front (zero MSBs, ie. right aligned) + * + * @return Name matching the symbol passed (or constructed for + * it) + */ + public Name findName(int firstQuad) + { + int hash = calcHash(firstQuad); + int ix = (hash & _mainHashMask); + int val = _mainHash[ix]; + + /* High 24 bits of the value are low 24 bits of hash (low 8 bits + * are bucket index)... match? + */ + if ((((val >> 8) ^ hash) << 8) == 0) { // match + // Ok, but do we have an actual match? + Name name = _mainNames[ix]; + if (name == null) { // main slot empty; can't find + return null; + } + if (name.equals(firstQuad)) { + return name; + } + } else if (val == 0) { // empty slot? no match + return null; + } + // Maybe a spill-over? + val &= 0xFF; + if (val > 0) { // 0 means 'empty' + val -= 1; // to convert from 1-based to 0... + Bucket bucket = _collList[val]; + if (bucket != null) { + return bucket.find(hash, firstQuad, 0); + } + } + // Nope, no match whatsoever + return null; + } + + /** + * Finds and returns name matching the specified symbol, if such + * name already exists in the table. + * If not, will return null. + *<p> + * Note: separate methods to optimize common case of relatively + * short element/attribute names (8 or less ascii characters) + * + * @param firstQuad int32 containing first 4 bytes of the name. + * @param secondQuad int32 containing bytes 5 through 8 of the + * name; if less than 8 bytes, padded with up to 3 zero bytes + * in front (zero MSBs, ie. right aligned) + * + * @return Name matching the symbol passed (or constructed for it) + */ + public Name findName(int firstQuad, int secondQuad) + { + int hash = (secondQuad == 0) ? calcHash(firstQuad) : calcHash(firstQuad, secondQuad); + int ix = (hash & _mainHashMask); + int val = _mainHash[ix]; + + /* High 24 bits of the value are low 24 bits of hash (low 8 bits + * are bucket index)... match? + */ + if ((((val >> 8) ^ hash) << 8) == 0) { // match + // Ok, but do we have an actual match? + Name name = _mainNames[ix]; + if (name == null) { // main slot empty; can't find + return null; + } + if (name.equals(firstQuad, secondQuad)) { + return name; + } + } else if (val == 0) { // empty slot? no match + return null; + } + // Maybe a spill-over? + val &= 0xFF; + if (val > 0) { // 0 means 'empty' + val -= 1; // to convert from 1-based to 0... + Bucket bucket = _collList[val]; + if (bucket != null) { + return bucket.find(hash, firstQuad, secondQuad); + } + } + // Nope, no match whatsoever + return null; + } + + /** + * Finds and returns name matching the specified symbol, if such + * name already exists in the table; or if not, creates name object, + * adds to the table, and returns it. + *<p> + * Note: this is the general purpose method that can be called for + * names of any length. However, if name is less than 9 bytes long, + * it is preferable to call the version optimized for short + * names. + * + * @param quads Array of int32s, each of which contain 4 bytes of + * encoded name + * @param qlen Number of int32s, starting from index 0, in quads + * parameter + * + * @return Name matching the symbol passed (or constructed for it) + */ + public Name findName(int[] quads, int qlen) + { + if (qlen < 3) { // another sanity check + return findName(quads[0], (qlen < 2) ? 0 : quads[1]); + } + int hash = calcHash(quads, qlen); + // (for rest of comments regarding logic, see method above) + int ix = (hash & _mainHashMask); + int val = _mainHash[ix]; + if ((((val >> 8) ^ hash) << 8) == 0) { + Name name = _mainNames[ix]; + if (name == null // main slot empty; no collision list then either + || name.equals(quads, qlen)) { // should be match, let's verify + return name; + } + } else if (val == 0) { // empty slot? no match + return null; + } + val &= 0xFF; + if (val > 0) { // 0 means 'empty' + val -= 1; // to convert from 1-based to 0... + Bucket bucket = _collList[val]; + if (bucket != null) { + return bucket.find(hash, quads, qlen); + } + } + return null; + } + + /* + /********************************************************** + /* API, mutators + /********************************************************** + */ + + public Name addName(String symbolStr, int q1, int q2) + { + if (_intern) { + symbolStr = InternCache.instance.intern(symbolStr); + } + int hash = (q2 == 0) ? calcHash(q1) : calcHash(q1, q2); + Name symbol = constructName(hash, symbolStr, q1, q2); + _addSymbol(hash, symbol); + return symbol; + } + + public Name addName(String symbolStr, int[] quads, int qlen) + { + if (_intern) { + symbolStr = InternCache.instance.intern(symbolStr); + } + int hash; + if (qlen < 3) { + hash = (qlen == 1) ? calcHash(quads[0]) : calcHash(quads[0], quads[1]); + } else { + hash = calcHash(quads, qlen); + } + Name symbol = constructName(hash, symbolStr, quads, qlen); + _addSymbol(hash, symbol); + return symbol; + } + + /* + /********************************************************** + /* Helper methods + /********************************************************** + */ + + /* Note on hash calculation: we try to make it more difficult to + * generate collisions automatically; part of this is to avoid + * simple "multiply-add" algorithm (like JDK String.hashCode()), + * and add bit of shifting. And other part is to make this + * non-linear, at least for shorter symbols. + */ + + // JDK uses 31; other fine choices are 33 and 65599, let's use 33 + // as it seems to give fewest collisions for us + // (see [http://www.cse.yorku.ca/~oz/hash.html] for details) + private final static int MULT = 33; + private final static int MULT2 = 65599; + private final static int MULT3 = 31; + + public final int calcHash(int firstQuad) + { + int hash = firstQuad ^ _hashSeed; + hash += (hash >>> 15); // to xor hi- and low- 16-bits + hash ^= (hash >>> 9); // as well as lowest 2 bytes + return hash; + } + + public final int calcHash(int firstQuad, int secondQuad) + { + /* For two quads, let's change algorithm a bit, to spice + * things up (can do bit more processing anyway) + */ + int hash = firstQuad; + hash ^= (hash >>> 15); // try mixing first and second byte pairs first + hash += (secondQuad * MULT); // then add second quad + hash ^= _hashSeed; + hash += (hash >>> 7); // and shuffle some more + return hash; + } + + public final int calcHash(int[] quads, int qlen) + { + // Note: may be called for qlen < 3; but has at least one int + if (qlen < 3) { + throw new IllegalArgumentException(); + } + + /* And then change handling again for "multi-quad" case; mostly + * to make calculation of collisions less fun. For example, + * add seed bit later in the game, and switch plus/xor around, + * use different shift lengths. + */ + int hash = quads[0] ^ _hashSeed; + hash += (hash >>> 9); + hash *= MULT; + hash += quads[1]; + hash *= MULT2; + hash += (hash >>> 15); + hash ^= quads[2]; + hash += (hash >>> 17); + + for (int i = 3; i < qlen; ++i) { + hash = (hash * MULT3) ^ quads[i]; + // for longer entries, mess a bit in-between too + hash += (hash >>> 3); + hash ^= (hash << 7); + } + // and finally shuffle some more once done + hash += (hash >>> 15); // to get high-order bits to mix more + hash ^= (hash << 9); // as well as lowest 2 bytes + return hash; + } + + // Method only used by unit tests + protected static int[] calcQuads(byte[] wordBytes) + { + int blen = wordBytes.length; + int[] result = new int[(blen + 3) / 4]; + for (int i = 0; i < blen; ++i) { + int x = wordBytes[i] & 0xFF; + + if (++i < blen) { + x = (x << 8) | (wordBytes[i] & 0xFF); + if (++i < blen) { + x = (x << 8) | (wordBytes[i] & 0xFF); + if (++i < blen) { + x = (x << 8) | (wordBytes[i] & 0xFF); + } + } + } + result[i >> 2] = x; + } + return result; + } + + /* + /********************************************************** + /* Standard methods + /********************************************************** + */ + + /* + @Override + public String toString() + { + StringBuilder sb = new StringBuilder(); + sb.append("[BytesToNameCanonicalizer, size: "); + sb.append(_count); + sb.append('/'); + sb.append(_mainHash.length); + sb.append(", "); + sb.append(_collCount); + sb.append(" coll; avg length: "); + + // Average length: minimum of 1 for all (1 == primary hit); + // and then 1 per each traversal for collisions/buckets + //int maxDist = 1; + int pathCount = _count; + for (int i = 0; i < _collEnd; ++i) { + int spillLen = _collList[i].length(); + for (int j = 1; j <= spillLen; ++j) { + pathCount += j; + } + } + double avgLength; + + if (_count == 0) { + avgLength = 0.0; + } else { + avgLength = (double) pathCount / (double) _count; + } + // let's round up a bit (two 2 decimal places) + //avgLength -= (avgLength % 0.01); + + sb.append(avgLength); + sb.append(']'); + return sb.toString(); + } + */ + + /* + /********************************************************** + /* Internal methods + /********************************************************** + */ + + private void _addSymbol(int hash, Name symbol) + { + if (_mainHashShared) { // always have to modify main entry + unshareMain(); + } + // First, do we need to rehash? + if (_needRehash) { + rehash(); + } + + ++_count; + + /* Ok, enough about set up: now we need to find the slot to add + * symbol in: + */ + int ix = (hash & _mainHashMask); + if (_mainNames[ix] == null) { // primary empty? + _mainHash[ix] = (hash << 8); + if (_mainNamesShared) { + unshareNames(); + } + _mainNames[ix] = symbol; + } else { // nope, it's a collision, need to spill over + /* How about spill-over area... do we already know the bucket + * (is the case if it's not the first collision) + */ + if (_collListShared) { + unshareCollision(); // also allocates if list was null + } + ++_collCount; + int entryValue = _mainHash[ix]; + int bucket = entryValue & 0xFF; + if (bucket == 0) { // first spill over? + if (_collEnd <= LAST_VALID_BUCKET) { // yup, still unshared bucket + bucket = _collEnd; + ++_collEnd; + // need to expand? + if (bucket >= _collList.length) { + expandCollision(); + } + } else { // nope, have to share... let's find shortest? + bucket = findBestBucket(); + } + // Need to mark the entry... and the spill index is 1-based + _mainHash[ix] = (entryValue & ~0xFF) | (bucket + 1); + } else { + --bucket; // 1-based index in value + } + + // And then just need to link the new bucket entry in + Bucket newB = new Bucket(symbol, _collList[bucket]); + _collList[bucket] = newB; + // but, be careful wrt attacks + _longestCollisionList = Math.max(newB.length(), _longestCollisionList); + if (_longestCollisionList > MAX_COLL_CHAIN_LENGTH) { + reportTooManyCollisions(MAX_COLL_CHAIN_LENGTH); + } + } + + /* Ok. Now, do we need a rehash next time? Need to have at least + * 50% fill rate no matter what: + */ + { + int hashSize = _mainHash.length; + if (_count > (hashSize >> 1)) { + int hashQuarter = (hashSize >> 2); + /* And either strictly above 75% (the usual) or + * just 50%, and collision count >= 25% of total hash size + */ + if (_count > (hashSize - hashQuarter)) { + _needRehash = true; + } else if (_collCount >= hashQuarter) { + _needRehash = true; + } + } + } + } + + private void rehash() + { + _needRehash = false; + // Note: since we'll make copies, no need to unshare, can just mark as such: + _mainNamesShared = false; + + /* And then we can first deal with the main hash area. Since we + * are expanding linearly (double up), we know there'll be no + * collisions during this phase. + */ + int[] oldMainHash = _mainHash; + int len = oldMainHash.length; + int newLen = len+len; + + /* 13-Mar-2010, tatu: Let's guard against OOME that could be caused by + * large documents with unique (or mostly so) names + */ + if (newLen > MAX_TABLE_SIZE) { + nukeSymbols(); + return; + } + + _mainHash = new int[newLen]; + _mainHashMask = (newLen - 1); + Name[] oldNames = _mainNames; + _mainNames = new Name[newLen]; + int symbolsSeen = 0; // let's do a sanity check + for (int i = 0; i < len; ++i) { + Name symbol = oldNames[i]; + if (symbol != null) { + ++symbolsSeen; + int hash = symbol.hashCode(); + int ix = (hash & _mainHashMask); + _mainNames[ix] = symbol; + _mainHash[ix] = hash << 8; // will clear spill index + } + } + + /* And then the spill area. This may cause collisions, although + * not necessarily as many as there were earlier. Let's allocate + * same amount of space, however + */ + int oldEnd = _collEnd; + if (oldEnd == 0) { // no prior collisions... + _longestCollisionList = 0; + return; + } + + _collCount = 0; + _collEnd = 0; + _collListShared = false; + + int maxColl = 0; + + Bucket[] oldBuckets = _collList; + _collList = new Bucket[oldBuckets.length]; + for (int i = 0; i < oldEnd; ++i) { + for (Bucket curr = oldBuckets[i]; curr != null; curr = curr._next) { + ++symbolsSeen; + Name symbol = curr._name; + int hash = symbol.hashCode(); + int ix = (hash & _mainHashMask); + int val = _mainHash[ix]; + if (_mainNames[ix] == null) { // no primary entry? + _mainHash[ix] = (hash << 8); + _mainNames[ix] = symbol; + } else { // nope, it's a collision, need to spill over + ++_collCount; + int bucket = val & 0xFF; + if (bucket == 0) { // first spill over? + if (_collEnd <= LAST_VALID_BUCKET) { // yup, still unshared bucket + bucket = _collEnd; + ++_collEnd; + // need to expand? + if (bucket >= _collList.length) { + expandCollision(); + } + } else { // nope, have to share... let's find shortest? + bucket = findBestBucket(); + } + // Need to mark the entry... and the spill index is 1-based + _mainHash[ix] = (val & ~0xFF) | (bucket + 1); + } else { + --bucket; // 1-based index in value + } + // And then just need to link the new bucket entry in + Bucket newB = new Bucket(symbol, _collList[bucket]); + _collList[bucket] = newB; + maxColl = Math.max(maxColl, newB.length()); + } + } // for (... buckets in the chain ...) + } // for (... list of bucket heads ... ) + + _longestCollisionList = maxColl; + + if (symbolsSeen != _count) { // sanity check + throw new RuntimeException("Internal error: count after rehash "+symbolsSeen+"; should be "+_count); + } + } + + /** + * Helper method called to empty all shared symbols, but to leave + * arrays allocated + */ + private void nukeSymbols() + { + _count = 0; + _longestCollisionList = 0; + Arrays.fill(_mainHash, 0); + Arrays.fill(_mainNames, null); + Arrays.fill(_collList, null); + _collCount = 0; + _collEnd = 0; + } + + /** + * Method called to find the best bucket to spill a Name over to: + * usually the first bucket that has only one entry, but in general + * first one of the buckets with least number of entries + */ + private int findBestBucket() + { + Bucket[] buckets = _collList; + int bestCount = Integer.MAX_VALUE; + int bestIx = -1; + + for (int i = 0, len = _collEnd; i < len; ++i) { + int count = buckets[i].length(); + if (count < bestCount) { + if (count == 1) { // best possible + return i; + } + bestCount = count; + bestIx = i; + } + } + return bestIx; + } + + /** + * Method that needs to be called, if the main hash structure + * is (may be) shared. This happens every time something is added, + * even if addition is to the collision list (since collision list + * index comes from lowest 8 bits of the primary hash entry) + */ + private void unshareMain() + { + int[] old = _mainHash; + int len = _mainHash.length; + + _mainHash = new int[len]; + System.arraycopy(old, 0, _mainHash, 0, len); + _mainHashShared = false; + } + + private void unshareCollision() + { + Bucket[] old = _collList; + if (old == null) { + _collList = new Bucket[INITIAL_COLLISION_LEN]; + } else { + int len = old.length; + _collList = new Bucket[len]; + System.arraycopy(old, 0, _collList, 0, len); + } + _collListShared = false; + } + + private void unshareNames() + { + Name[] old = _mainNames; + int len = old.length; + _mainNames = new Name[len]; + System.arraycopy(old, 0, _mainNames, 0, len); + _mainNamesShared = false; + } + + private void expandCollision() + { + Bucket[] old = _collList; + int len = old.length; + _collList = new Bucket[len+len]; + System.arraycopy(old, 0, _collList, 0, len); + } + + + /* + /********************************************************** + /* Constructing name objects + /********************************************************** + */ + + private static Name constructName(int hash, String name, int q1, int q2) + { + if (q2 == 0) { // one quad only? + return new Name1(name, hash, q1); + } + return new Name2(name, hash, q1, q2); + } + + private static Name constructName(int hash, String name, int[] quads, int qlen) + { + if (qlen < 4) { // Need to check for 3 quad one, can do others too + switch (qlen) { + case 1: + return new Name1(name, hash, quads[0]); + case 2: + return new Name2(name, hash, quads[0], quads[1]); + case 3: + return new Name3(name, hash, quads[0], quads[1], quads[2]); + default: + } + } + // Otherwise, need to copy the incoming buffer + int[] buf = new int[qlen]; + for (int i = 0; i < qlen; ++i) { + buf[i] = quads[i]; + } + return new NameN(name, hash, buf, qlen); + } + + /* + /********************************************************** + /* Other helper methods + /********************************************************** + */ + + /** + * @since 1.9.9 + */ + protected void reportTooManyCollisions(int maxLen) + { + throw new IllegalStateException("Longest collision chain in symbol table (of size "+_count + +") now exceeds maximum, "+maxLen+" -- suspect a DoS attack based on hash collisions"); + } + + /* + /********************************************************** + /* Helper classes + /********************************************************** + */ + + /** + * Immutable value class used for sharing information as efficiently + * as possible, by only require synchronization of reference manipulation + * but not access to contents. + * + * @since 1.9.9 + */ + private final static class TableInfo + { + public final int count; + public final int mainHashMask; + public final int[] mainHash; + public final Name[] mainNames; + public final Bucket[] collList; + public final int collCount; + public final int collEnd; + public final int longestCollisionList; + + public TableInfo(int count, int mainHashMask, int[] mainHash, Name[] mainNames, + Bucket[] collList, int collCount, int collEnd, int longestCollisionList) + { + this.count = count; + this.mainHashMask = mainHashMask; + this.mainHash = mainHash; + this.mainNames = mainNames; + this.collList = collList; + this.collCount = collCount; + this.collEnd = collEnd; + this.longestCollisionList = longestCollisionList; + } + + public TableInfo(BytesToNameCanonicalizer src) + { + count = src._count; + mainHashMask = src._mainHashMask; + mainHash = src._mainHash; + mainNames = src._mainNames; + collList = src._collList; + collCount = src._collCount; + collEnd = src._collEnd; + longestCollisionList = src._longestCollisionList; + } + + } + + /** + * + */ + final static class Bucket + { + protected final Name _name; + protected final Bucket _next; + private final int _length; + + Bucket(Name name, Bucket next) + { + _name = name; + _next = next; + _length = (next == null) ? 1 : next._length+1; + } + + public int length() { return _length; } + + public Name find(int hash, int firstQuad, int secondQuad) + { + if (_name.hashCode() == hash) { + if (_name.equals(firstQuad, secondQuad)) { + return _name; + } + } + for (Bucket curr = _next; curr != null; curr = curr._next) { + Name currName = curr._name; + if (currName.hashCode() == hash) { + if (currName.equals(firstQuad, secondQuad)) { + return currName; + } + } + } + return null; + } + + public Name find(int hash, int[] quads, int qlen) + { + if (_name.hashCode() == hash) { + if (_name.equals(quads, qlen)) { + return _name; + } + } + for (Bucket curr = _next; curr != null; curr = curr._next) { + Name currName = curr._name; + if (currName.hashCode() == hash) { + if (currName.equals(quads, qlen)) { + return currName; + } + } + } + return null; + } + } +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/sym/CharsToNameCanonicalizer.java b/1.9.10/src/java/org/codehaus/jackson/sym/CharsToNameCanonicalizer.java new file mode 100644 index 0000000..e20e691 --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/sym/CharsToNameCanonicalizer.java
@@ -0,0 +1,730 @@ +package org.codehaus.jackson.sym; + +import java.util.Arrays; + +import org.codehaus.jackson.util.InternCache; + +/** + * This class is a kind of specialized type-safe Map, from char array to + * String value. Specialization means that in addition to type-safety + * and specific access patterns (key char array, Value optionally interned + * String; values added on access if necessary), and that instances are + * meant to be used concurrently, but by using well-defined mechanisms + * to obtain such concurrently usable instances. Main use for the class + * is to store symbol table information for things like compilers and + * parsers; especially when number of symbols (keywords) is limited. + *<p> + * For optimal performance, usage pattern should be one where matches + * should be very common (especially after "warm-up"), and as with most hash-based + * maps/sets, that hash codes are uniformly distributed. Also, collisions + * are slightly more expensive than with HashMap or HashSet, since hash codes + * are not used in resolving collisions; that is, equals() comparison is + * done with all symbols in same bucket index.<br /> + * Finally, rehashing is also more expensive, as hash codes are not + * stored; rehashing requires all entries' hash codes to be recalculated. + * Reason for not storing hash codes is reduced memory usage, hoping + * for better memory locality. + *<p> + * Usual usage pattern is to create a single "master" instance, and either + * use that instance in sequential fashion, or to create derived "child" + * instances, which after use, are asked to return possible symbol additions + * to master instance. In either case benefit is that symbol table gets + * initialized so that further uses are more efficient, as eventually all + * symbols needed will already be in symbol table. At that point no more + * Symbol String allocations are needed, nor changes to symbol table itself. + *<p> + * Note that while individual SymbolTable instances are NOT thread-safe + * (much like generic collection classes), concurrently used "child" + * instances can be freely used without synchronization. However, using + * master table concurrently with child instances can only be done if + * access to master instance is read-only (i.e. no modifications done). + */ +public final class CharsToNameCanonicalizer +{ + /* If we use "multiply-add" based hash algorithm, this is the multiplier + * we use. + */ + public final static int HASH_MULT = 33; + + /** + * Default initial table size. Shouldn't be miniscule (as there's + * cost to both array realloc and rehashing), but let's keep + * it reasonably small nonetheless. For systems that properly + * reuse factories it doesn't matter either way; but when + * recreating factories often, initial overhead may dominate. + */ + protected static final int DEFAULT_TABLE_SIZE = 64; + + /** + * Let's not expand symbol tables past some maximum size; + * this should protected against OOMEs caused by large documents + * with uniquer (~= random) names. + */ + protected static final int MAX_TABLE_SIZE = 0x10000; // 64k entries == 256k mem + + /** + * Let's only share reasonably sized symbol tables. Max size set to 3/4 of 16k; + * this corresponds to 64k main hash index. This should allow for enough distinct + * names for almost any case. + */ + final static int MAX_ENTRIES_FOR_REUSE = 12000; + + /** + * Also: to thwart attacks based on hash collisions (which may or may not + * be cheap to calculate), we will need to detect "too long" + * collision chains. Let's start with static value of 255 entries + * for the longest legal chain. + *<p> + * Note: longest chain we have been able to produce without malicious + * intent has been 38 (with "com.fasterxml.jackson.core.main.TestWithTonsaSymbols"); + * our setting should be reasonable here. + * + * @since 1.9.9 + */ + final static int MAX_COLL_CHAIN_LENGTH = 255; + + /** + * And to support reduce likelihood of accidental collisons causing + * exceptions, let's prevent reuse of tables with long collision + * overflow lists as well. + * + * @since 1.9.9 + */ + final static int MAX_COLL_CHAIN_FOR_REUSE = 63; + + final static CharsToNameCanonicalizer sBootstrapSymbolTable; + static { + sBootstrapSymbolTable = new CharsToNameCanonicalizer(); + } + + /* + /********************************************************** + /* Configuration + /********************************************************** + */ + + /** + * Sharing of learnt symbols is done by optional linking of symbol + * table instances with their parents. When parent linkage is + * defined, and child instance is released (call to <code>release</code>), + * parent's shared tables may be updated from the child instance. + */ + protected CharsToNameCanonicalizer _parent; + + /** + * Seed value we use as the base to make hash codes non-static between + * different runs, but still stable for lifetime of a single symbol table + * instance. + * This is done for security reasons, to avoid potential DoS attack via + * hash collisions. + * + * @since 1.9.9 + */ + final private int _hashSeed; + + /** + * Whether canonical symbol Strings are to be intern()ed before added + * to the table or not + */ + final protected boolean _intern; + + /** + * Whether any canonicalization should be attempted (whether using + * intern or not) + */ + final protected boolean _canonicalize; + + /* + /********************************************************** + /* Actual symbol table data + /********************************************************** + */ + + /** + * Primary matching symbols; it's expected most match occur from + * here. + */ + protected String[] _symbols; + + /** + * Overflow buckets; if primary doesn't match, lookup is done + * from here. + *<p> + * Note: Number of buckets is half of number of symbol entries, on + * assumption there's less need for buckets. + */ + protected Bucket[] _buckets; + + /** + * Current size (number of entries); needed to know if and when + * rehash. + */ + protected int _size; + + /** + * Limit that indicates maximum size this instance can hold before + * it needs to be expanded and rehashed. Calculated using fill + * factor passed in to constructor. + */ + protected int _sizeThreshold; + + /** + * Mask used to get index from hash values; equal to + * <code>_buckets.length - 1</code>, when _buckets.length is + * a power of two. + */ + protected int _indexMask; + + /** + * We need to keep track of the longest collision list; this is needed + * both to indicate problems with attacks and to allow flushing for + * other cases. + * + * @since 1.9.9 + */ + protected int _longestCollisionList; + + /* + /********************************************************** + /* State regarding shared arrays + /********************************************************** + */ + + /** + * Flag that indicates if any changes have been made to the data; + * used to both determine if bucket array needs to be copied when + * (first) change is made, and potentially if updated bucket list + * is to be resync'ed back to master instance. + */ + protected boolean _dirty; + + /* + /********************************************************** + /* Life-cycle + /********************************************************** + */ + + /** + * Method called to create root canonicalizer for a {@link org.codehaus.jackson.JsonFactory} + * instance. Root instance is never used directly; its main use is for + * storing and sharing underlying symbol arrays as needed. + */ + public static CharsToNameCanonicalizer createRoot() + { + /* [Issue-21]: Need to use a variable seed, to thwart hash-collision + * based attacks. + */ + long now = System.currentTimeMillis(); + // ensure it's not 0; and might as well require to be odd so: + int seed = (((int) now) + ((int) now >>> 32)) | 1; + return createRoot(seed); + } + + protected static CharsToNameCanonicalizer createRoot(int hashSeed) { + return sBootstrapSymbolTable.makeOrphan(hashSeed); + } + + /** + * Main method for constructing a master symbol table instance. + * + * @param initialSize Minimum initial size for bucket array; internally + * will always use a power of two equal to or bigger than this value. + */ + private CharsToNameCanonicalizer() + { + // these settings don't really matter for the bootstrap instance + _canonicalize = true; + _intern = true; + // And we'll also set flags so no copying of buckets is needed: + _dirty = true; + _hashSeed = 0; + _longestCollisionList = 0; + initTables(DEFAULT_TABLE_SIZE); + } + + private void initTables(int initialSize) + { + _symbols = new String[initialSize]; + _buckets = new Bucket[initialSize >> 1]; + // Mask is easy to calc for powers of two. + _indexMask = initialSize - 1; + _size = 0; + _longestCollisionList = 0; + // Hard-coded fill factor is 75% + _sizeThreshold = _thresholdSize(initialSize); + } + + private final static int _thresholdSize(int hashAreaSize) { + return hashAreaSize - (hashAreaSize >> 2); + } + + /** + * Internal constructor used when creating child instances. + */ + private CharsToNameCanonicalizer(CharsToNameCanonicalizer parent, + boolean canonicalize, boolean intern, + String[] symbols, Bucket[] buckets, int size, + int hashSeed, int longestColl) + { + _parent = parent; + _canonicalize = canonicalize; + _intern = intern; + + _symbols = symbols; + _buckets = buckets; + _size = size; + _hashSeed = hashSeed; + // Hard-coded fill factor, 75% + int arrayLen = (symbols.length); + _sizeThreshold = _thresholdSize(arrayLen); + _indexMask = (arrayLen - 1); + _longestCollisionList = longestColl; + + // Need to make copies of arrays, if/when adding new entries + _dirty = false; + } + + /** + * "Factory" method; will create a new child instance of this symbol + * table. It will be a copy-on-write instance, ie. it will only use + * read-only copy of parent's data, but when changes are needed, a + * copy will be created. + *<p> + * Note: while this method is synchronized, it is generally not + * safe to both use makeChild/mergeChild, AND to use instance + * actively. Instead, a separate 'root' instance should be used + * on which only makeChild/mergeChild are called, but instance itself + * is not used as a symbol table. + */ + public synchronized CharsToNameCanonicalizer makeChild(final boolean canonicalize, + final boolean intern) + { + /* 24-Jul-2012, tatu: Trying to reduce scope of synchronization, assuming + * that synchronizing construction is the (potentially) expensive part, + * and not so much short copy-the-variables thing. + */ + final String[] symbols; + final Bucket[] buckets; + final int size; + final int hashSeed; + final int longestCollisionList; + + synchronized (this) { + symbols = _symbols; + buckets = _buckets; + size = _size; + hashSeed = _hashSeed; + longestCollisionList = _longestCollisionList; + } + + return new CharsToNameCanonicalizer(this, canonicalize, intern, + symbols, buckets, size, hashSeed, longestCollisionList); + } + + private CharsToNameCanonicalizer makeOrphan(int seed) + { + return new CharsToNameCanonicalizer(null, true, true, + _symbols, _buckets, _size, seed, _longestCollisionList); + } + + /** + * Method that allows contents of child table to potentially be + * "merged in" with contents of this symbol table. + *<p> + * Note that caller has to make sure symbol table passed in is + * really a child or sibling of this symbol table. + */ + private void mergeChild(CharsToNameCanonicalizer child) + { + /* One caveat: let's try to avoid problems with + * degenerate cases of documents with generated "random" + * names: for these, symbol tables would bloat indefinitely. + * One way to do this is to just purge tables if they grow + * too large, and that's what we'll do here. + */ + if (child.size() > MAX_ENTRIES_FOR_REUSE + || child._longestCollisionList > MAX_COLL_CHAIN_FOR_REUSE) { + // Should there be a way to get notified about this event, to log it or such? + // (as it's somewhat abnormal thing to happen) + // At any rate, need to clean up the tables, then: + synchronized (this) { + initTables(DEFAULT_TABLE_SIZE); + // Dirty flag... well, let's just clear it. Shouldn't really matter for master tables + // (which this is, given something is merged to it) + _dirty = false; + } + } else { + // Otherwise, we'll merge changed stuff in, if there are more entries (which + // may not be the case if one of siblings has added symbols first or such) + if (child.size() <= size()) { // nothing to add + return; + } + // Okie dokie, let's get the data in! + synchronized (this) { + _symbols = child._symbols; + _buckets = child._buckets; + _size = child._size; + _sizeThreshold = child._sizeThreshold; + _indexMask = child._indexMask; + _longestCollisionList = child._longestCollisionList; + // Dirty flag... well, let's just clear it. Shouldn't really matter for master tables + // (which this is, given something is merged to it) + _dirty = false; + } + } + } + + public void release() + { + // If nothing has been added, nothing to do + if (!maybeDirty()) { + return; + } + if (_parent != null) { + _parent.mergeChild(this); + /* Let's also mark this instance as dirty, so that just in + * case release was too early, there's no corruption + * of possibly shared data. + */ + _dirty = false; + } + } + + /* + /********************************************************** + /* Public API, generic accessors: + /********************************************************** + */ + + public int size() { return _size; } + + /** + * Method for checking number of primary hash buckets this symbol + * table uses. + * + * @since 1.9.9 + */ + public int bucketCount() { + return _symbols.length; } + + public boolean maybeDirty() { return _dirty; } + + public int hashSeed() { return _hashSeed; } + + /** + * Method mostly needed by unit tests; calculates number of + * entries that are in collision list. Value can be at most + * ({@link #size} - 1), but should usually be much lower, ideally 0. + * + * @since 1.9.9 + */ + public int collisionCount() + { + int count = 0; + + for (Bucket bucket : _buckets) { + if (bucket != null) { + count += bucket.length(); + } + } + return count; + } + + /** + * Method mostly needed by unit tests; calculates length of the + * longest collision chain. This should typically be a low number, + * but may be up to {@link #size} - 1 in the pathological case + * + * @since 1.9.9 + */ + public int maxCollisionLength() + { + return _longestCollisionList; + } + + /* + /********************************************************** + /* Public API, accessing symbols: + /********************************************************** + */ + + public String findSymbol(char[] buffer, int start, int len, int h) + { + if (len < 1) { // empty Strings are simplest to handle up front + return ""; + } + if (!_canonicalize) { // [JACKSON-259] + return new String(buffer, start, len); + } + + /* Related to problems with sub-standard hashing (somewhat + * relevant for collision attacks too), let's try little + * bit of shuffling to improve hash codes. + * (note, however, that this can't help with full collisions) + */ + int index = _hashToIndex(h); + String sym = _symbols[index]; + + // Optimal case; checking existing primary symbol for hash index: + if (sym != null) { + // Let's inline primary String equality checking: + if (sym.length() == len) { + int i = 0; + do { + if (sym.charAt(i) != buffer[start+i]) { + break; + } + } while (++i < len); + // Optimal case; primary match found + if (i == len) { + return sym; + } + } + // How about collision bucket? + Bucket b = _buckets[index >> 1]; + if (b != null) { + sym = b.find(buffer, start, len); + if (sym != null) { + return sym; + } + } + } + + if (!_dirty) { //need to do copy-on-write? + copyArrays(); + _dirty = true; + } else if (_size >= _sizeThreshold) { // Need to expand? + rehash(); + /* Need to recalc hash; rare occurence (index mask has been + * recalculated as part of rehash) + */ + index = _hashToIndex(calcHash(buffer, start, len)); + } + + String newSymbol = new String(buffer, start, len); + if (_intern) { + newSymbol = InternCache.instance.intern(newSymbol); + } + ++_size; + // Ok; do we need to add primary entry, or a bucket? + if (_symbols[index] == null) { + _symbols[index] = newSymbol; + } else { + int bix = (index >> 1); + Bucket newB = new Bucket(newSymbol, _buckets[bix]); + _buckets[bix] = newB; + _longestCollisionList = Math.max(newB.length(), _longestCollisionList); + if (_longestCollisionList > MAX_COLL_CHAIN_LENGTH) { + reportTooManyCollisions(MAX_COLL_CHAIN_LENGTH); + } + } + + return newSymbol; + } + + /** + * Helper method that takes in a "raw" hash value, shuffles it as necessary, + * and truncates to be used as the index. + */ + public final int _hashToIndex(int rawHash) + { + rawHash += (rawHash >>> 15); // this seems to help quite a bit, at least for our tests + return (rawHash & _indexMask); + } + + /** + * Implementation of a hashing method for variable length + * Strings. Most of the time intention is that this calculation + * is done by caller during parsing, not here; however, sometimes + * it needs to be done for parsed "String" too. + * + * @param len Length of String; has to be at least 1 (caller guarantees + * this pre-condition) + */ + public int calcHash(char[] buffer, int start, int len) + { + int hash = _hashSeed; + for (int i = 0; i < len; ++i) { + hash = (hash * HASH_MULT) + (int) buffer[i]; + } + // NOTE: shuffling, if any, is done in 'findSymbol()', not here: + return (hash == 0) ? 1 : hash; + } + + public int calcHash(String key) + { + final int len = key.length(); + + int hash = _hashSeed; + for (int i = 0; i < len; ++i) { + hash = (hash * HASH_MULT) + (int) key.charAt(i); + } + // NOTE: shuffling, if any, is done in 'findSymbol()', not here: + return (hash == 0) ? 1 : hash; + } + + /* + /********************************************************** + /* Internal methods + /********************************************************** + */ + + /** + * Method called when copy-on-write is needed; generally when first + * change is made to a derived symbol table. + */ + private void copyArrays() { + String[] oldSyms = _symbols; + int size = oldSyms.length; + _symbols = new String[size]; + System.arraycopy(oldSyms, 0, _symbols, 0, size); + Bucket[] oldBuckets = _buckets; + size = oldBuckets.length; + _buckets = new Bucket[size]; + System.arraycopy(oldBuckets, 0, _buckets, 0, size); + } + + /** + * Method called when size (number of entries) of symbol table grows + * so big that load factor is exceeded. Since size has to remain + * power of two, arrays will then always be doubled. Main work + * is really redistributing old entries into new String/Bucket + * entries. + */ + private void rehash() + { + int size = _symbols.length; + int newSize = size + size; + + /* 12-Mar-2010, tatu: Let's actually limit maximum size we are + * prepared to use, to guard against OOME in case of unbounded + * name sets (unique [non-repeating] names) + */ + if (newSize > MAX_TABLE_SIZE) { + /* If this happens, there's no point in either growing or + * shrinking hash areas. Rather, it's better to just clean + * them up for reuse. + */ + _size = 0; + Arrays.fill(_symbols, null); + Arrays.fill(_buckets, null); + _dirty = true; + return; + } + + String[] oldSyms = _symbols; + Bucket[] oldBuckets = _buckets; + _symbols = new String[newSize]; + _buckets = new Bucket[newSize >> 1]; + // Let's update index mask, threshold, now (needed for rehashing) + _indexMask = newSize - 1; + _sizeThreshold = _thresholdSize(newSize); + + int count = 0; // let's do sanity check + + /* Need to do two loops, unfortunately, since spill-over area is + * only half the size: + */ + int maxColl = 0; + for (int i = 0; i < size; ++i) { + String symbol = oldSyms[i]; + if (symbol != null) { + ++count; + int index = _hashToIndex(calcHash(symbol)); + if (_symbols[index] == null) { + _symbols[index] = symbol; + } else { + int bix = (index >> 1); + Bucket newB = new Bucket(symbol, _buckets[bix]); + _buckets[bix] = newB; + maxColl = Math.max(maxColl, newB.length()); + } + } + } + + size >>= 1; + for (int i = 0; i < size; ++i) { + Bucket b = oldBuckets[i]; + while (b != null) { + ++count; + String symbol = b.getSymbol(); + int index = _hashToIndex(calcHash(symbol)); + if (_symbols[index] == null) { + _symbols[index] = symbol; + } else { + int bix = (index >> 1); + Bucket newB = new Bucket(symbol, _buckets[bix]); + _buckets[bix] = newB; + maxColl = Math.max(maxColl, newB.length()); + } + b = b.getNext(); + } + } + _longestCollisionList = maxColl; + + if (count != _size) { + throw new Error("Internal error on SymbolTable.rehash(): had "+_size+" entries; now have "+count+"."); + } + } + + /** + * @since 1.9.9 + */ + protected void reportTooManyCollisions(int maxLen) + { + throw new IllegalStateException("Longest collision chain in symbol table (of size "+_size + +") now exceeds maximum, "+maxLen+" -- suspect a DoS attack based on hash collisions"); + } + + /* + /********************************************************** + /* Bucket class + /********************************************************** + */ + + /** + * This class is a symbol table entry. Each entry acts as a node + * in a linked list. + */ + static final class Bucket + { + private final String _symbol; + private final Bucket _next; + private final int _length; + + public Bucket(String symbol, Bucket next) { + _symbol = symbol; + _next = next; + _length = (next == null) ? 1 : next._length+1; + } + + public String getSymbol() { return _symbol; } + public Bucket getNext() { return _next; } + public int length() { return _length; } + + public String find(char[] buf, int start, int len) { + String sym = _symbol; + Bucket b = _next; + + while (true) { // Inlined equality comparison: + if (sym.length() == len) { + int i = 0; + do { + if (sym.charAt(i) != buf[start+i]) { + break; + } + } while (++i < len); + if (i == len) { + return sym; + } + } + if (b == null) { + break; + } + sym = b.getSymbol(); + b = b.getNext(); + } + return null; + } + } +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/sym/Name.java b/1.9.10/src/java/org/codehaus/jackson/sym/Name.java new file mode 100644 index 0000000..29a50f8 --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/sym/Name.java
@@ -0,0 +1,50 @@ +package org.codehaus.jackson.sym; + +/** + * Base class for tokenized names (key strings in objects) that have + * been tokenized from byte-based input sources (like + * {@link java.io.InputStream}. + * + * @author Tatu Saloranta + */ +public abstract class Name +{ + protected final String _name; + + protected final int _hashCode; + + protected Name(String name, int hashCode) { + _name = name; + _hashCode = hashCode; + } + + public String getName() { return _name; } + + /* + /********************************************************** + /* Methods for package/core parser + /********************************************************** + */ + + public abstract boolean equals(int quad1); + + public abstract boolean equals(int quad1, int quad2); + + public abstract boolean equals(int[] quads, int qlen); + + /* + /********************************************************** + /* Overridden standard methods + /********************************************************** + */ + + @Override public String toString() { return _name; } + + @Override public final int hashCode() { return _hashCode; } + + @Override public boolean equals(Object o) + { + // Canonical instances, can usually just do identity comparison + return (o == this); + } +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/sym/Name1.java b/1.9.10/src/java/org/codehaus/jackson/sym/Name1.java new file mode 100644 index 0000000..1ee5976 --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/sym/Name1.java
@@ -0,0 +1,44 @@ +package org.codehaus.jackson.sym; + +/** + * Specialized implementation of PName: can be used for short Strings + * that consists of at most 4 bytes. Usually this means short + * ascii-only names. + *<p> + * The reason for such specialized classes is mostly space efficiency; + * and to a lesser degree performance. Both are achieved for short + * Strings by avoiding another level of indirection (via quad arrays) + */ +public final class Name1 + extends Name +{ + final static Name1 sEmptyName = new Name1("", 0, 0); + + final int mQuad; + + Name1(String name, int hash, int quad) + { + super(name, hash); + mQuad = quad; + } + + final static Name1 getEmptyName() { return sEmptyName; } + + @Override + public boolean equals(int quad) + { + return (quad == mQuad); + } + + @Override + public boolean equals(int quad1, int quad2) + { + return (quad1 == mQuad) && (quad2 == 0); + } + + @Override + public boolean equals(int[] quads, int qlen) + { + return (qlen == 1 && quads[0] == mQuad); + } +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/sym/Name2.java b/1.9.10/src/java/org/codehaus/jackson/sym/Name2.java new file mode 100644 index 0000000..933db2a --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/sym/Name2.java
@@ -0,0 +1,40 @@ +package org.codehaus.jackson.sym; + +/** + * Specialized implementation of PName: can be used for short Strings + * that consists of 5 to 8 bytes. Usually this means relatively short + * ascii-only names. + *<p> + * The reason for such specialized classes is mostly space efficiency; + * and to a lesser degree performance. Both are achieved for short + * Strings by avoiding another level of indirection (via quad arrays) + */ +public final class Name2 + extends Name +{ + final int mQuad1; + + final int mQuad2; + + Name2(String name, int hash, int quad1, int quad2) + { + super(name, hash); + mQuad1 = quad1; + mQuad2 = quad2; + } + + @Override + public boolean equals(int quad) { return false; } + + @Override + public boolean equals(int quad1, int quad2) + { + return (quad1 == mQuad1) && (quad2 == mQuad2); + } + + @Override + public boolean equals(int[] quads, int qlen) + { + return (qlen == 2 && quads[0] == mQuad1 && quads[1] == mQuad2); + } +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/sym/Name3.java b/1.9.10/src/java/org/codehaus/jackson/sym/Name3.java new file mode 100644 index 0000000..0b10404 --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/sym/Name3.java
@@ -0,0 +1,39 @@ +package org.codehaus.jackson.sym; + +/** + * Specialized implementation of PName: can be used for short Strings + * that consists of 9 to 12 bytes. It's the longest special purpose + * implementaion; longer ones are expressed using {@link NameN}. + */ +public final class Name3 + extends Name +{ + final int mQuad1; + final int mQuad2; + final int mQuad3; + + Name3(String name, int hash, int q1, int q2, int q3) + { + super(name, hash); + mQuad1 = q1; + mQuad2 = q2; + mQuad3 = q3; + } + + // Implies quad length == 1, never matches + @Override + public boolean equals(int quad) { return false; } + + // Implies quad length == 2, never matches + @Override + public boolean equals(int quad1, int quad2) { return false; } + + @Override + public boolean equals(int[] quads, int qlen) + { + return (qlen == 3) + && (quads[0] == mQuad1) + && (quads[1] == mQuad2) + && (quads[2] == mQuad3); + } +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/sym/NameN.java b/1.9.10/src/java/org/codehaus/jackson/sym/NameN.java new file mode 100644 index 0000000..b5236f2 --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/sym/NameN.java
@@ -0,0 +1,68 @@ +package org.codehaus.jackson.sym; + +/** + * Generic implementation of PName used for "long" names, where long + * means that its byte (UTF-8) representation is 13 bytes or more. + */ +public final class NameN + extends Name +{ + final int[] mQuads; + final int mQuadLen; + + NameN(String name, int hash, int[] quads, int quadLen) + { + super(name, hash); + /* We have specialized implementations for shorter + * names, so let's not allow runt instances here + */ + if (quadLen < 3) { + throw new IllegalArgumentException("Qlen must >= 3"); + } + mQuads = quads; + mQuadLen = quadLen; + } + + // Implies quad length == 1, never matches + @Override + public boolean equals(int quad) { return false; } + + // Implies quad length == 2, never matches + @Override + public boolean equals(int quad1, int quad2) { return false; } + + @Override + public boolean equals(int[] quads, int qlen) + { + if (qlen != mQuadLen) { + return false; + } + + /* 26-Nov-2008, tatus: Strange, but it does look like + * unrolling here is counter-productive, reducing + * speed. Perhaps it prevents inlining by HotSpot or + * something... + */ + // Will always have >= 3 quads, can unroll + /* + if (quads[0] == mQuads[0] + && quads[1] == mQuads[1] + && quads[2] == mQuads[2]) { + for (int i = 3; i < qlen; ++i) { + if (quads[i] != mQuads[i]) { + return false; + } + } + return true; + } + */ + + // or simpler way without unrolling: + for (int i = 0; i < qlen; ++i) { + if (quads[i] != mQuads[i]) { + return false; + } + } + return true; + } +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/sym/package-info.java b/1.9.10/src/java/org/codehaus/jackson/sym/package-info.java new file mode 100644 index 0000000..8b84959 --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/sym/package-info.java
@@ -0,0 +1,5 @@ +/** + * Internal implementation classes for efficient handling of + * of symbols in JSON (field names in Objects) + */ +package org.codehaus.jackson.sym;
diff --git a/1.9.10/src/java/org/codehaus/jackson/type/JavaType.java b/1.9.10/src/java/org/codehaus/jackson/type/JavaType.java new file mode 100644 index 0000000..3b21649 --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/type/JavaType.java
@@ -0,0 +1,503 @@ +package org.codehaus.jackson.type; + +import java.lang.reflect.Modifier; + +/** + * Base class for type token classes used both to contain information + * and as keys for deserializers. + *<p> + * Instances can (only) be constructed by + * {@link org.codehaus.jackson.map.type.TypeFactory}. + */ +public abstract class JavaType +{ + /** + * This is the nominal type-erased Class that would be close to the + * type represented (but not exactly type, due to type erasure: type + * instance may have more information on this). + * May be an interface or abstract class, so instantiation + * may not be possible. + */ + protected final Class<?> _class; + + protected final int _hashCode; + + /** + * Optional handler (codec) that can be attached to indicate + * what to use for handling (serializing, deserializing) values of + * this specific type. + *<p> + * Note: untyped (i.e. caller has to cast) because it is used for + * different kinds of handlers, with unrelated types. + *<p> + * TODO: make final and possible promote to sub-classes + * + * @since 1.3 + */ + protected /*final*/ Object _valueHandler; + + /** + * Optional handler that can be attached to indicate how to handle + * additional type metadata associated with this type. + *<p> + * Note: untyped (i.e. caller has to cast) because it is used for + * different kinds of handlers, with unrelated types. + *<p> + * TODO: make final and possible promote to sub-classes + * + * @since 1.5 + */ + protected /*final*/ Object _typeHandler; + + /* + /********************************************************** + /* Life-cycle + /********************************************************** + */ + + /** + * @param raw "Raw" (type-erased) class for this type + * @param additionalHash Additional hash code to use, in addition + * to hash code of the class name + */ + protected JavaType(Class<?> raw, int additionalHash) + { + _class = raw; + _hashCode = raw.getName().hashCode() + additionalHash; + _valueHandler = null; + _typeHandler = null; + } + + /** + * "Copy method" that will construct a new instance that is identical to + * this instance, except that it will have specified type handler assigned. + * + * @return Newly created type instance + * + * @since 1.7 + */ + public abstract JavaType withTypeHandler(Object h); + + /** + * "Copy method" that will construct a new instance that is identical to + * this instance, except that its content type will have specified + * type handler assigned. + * + * @return Newly created type instance + * + * @since 1.7 + */ + public abstract JavaType withContentTypeHandler(Object h); + + // !!! TODO: in 2.0, change to be abstract method + //public abstract JavaType withValueHandler(Object h); + /** + * @since 1.9 + */ + public JavaType withValueHandler(Object h) { + /* 16-Aug-2011, tatu: This is not entirely correct, as we can not + * create new immutable instances. However, sub-classes can, + * so if mapper is version 1.9, things work as expected. + * Otherwise, in 2.0 we can make this method abstract. + */ + setValueHandler(h); + return this; + } + + // !!! TODO: in 2.0, change to be abstract method + //public abstract JavaType withContentValueHandler(Object h); + /** + * @since 1.9 + */ + public JavaType withContentValueHandler(Object h) { + /* 16-Aug-2011, tatu: This is not entirely correct, as we can not + * create new immutable instances. However, sub-classes can, + * so if mapper is version 1.9, things work as expected. + * Otherwise, in 2.0 we can make this method abstract. + */ + getContentType().setValueHandler(h); + return this; + } + + /** + * Method for assigning handler to associate with this type; or + * if null passed, to remove such assignment + * + * @since 1.3 + * + * @deprecated Since 1.9, should not be used; instead, use + * <code>withContentTypeHandler</code> and + * <code>withContentValueHandler</code> methods. + */ + @Deprecated + public void setValueHandler(Object h) { + // sanity check, should be assigned just once + if (h != null && _valueHandler != null) { + throw new IllegalStateException("Trying to reset value handler for type ["+toString() + +"]; old handler of type "+_valueHandler.getClass().getName()+", new handler of type "+h.getClass().getName()); + } + _valueHandler = h; + } + + /* + /********************************************************** + /* Type coercion fluent factory methods + /********************************************************** + */ + + /** + * Method that can be called to do a "narrowing" conversions; that is, + * to return a type with a raw class that is assignable to the raw + * class of this type. If this is not possible, an + * {@link IllegalArgumentException} is thrown. + * If class is same as the current raw class, instance itself is + * returned. + */ + public JavaType narrowBy(Class<?> subclass) + { + // First: if same raw class, just return this instance + if (subclass == _class) { + return this; + } + // Otherwise, ensure compatibility + _assertSubclass(subclass, _class); + JavaType result = _narrow(subclass); + + // TODO: these checks should NOT actually be needed; above should suffice: + if (_valueHandler != result.getValueHandler()) { + result = result.withValueHandler(_valueHandler); + } + if (_typeHandler != result.getTypeHandler()) { + result = result.withTypeHandler(_typeHandler); + } + return result; + } + + /** + * More efficient version of {@link #narrowBy}, called by + * internal framework in cases where compatibility checks + * are to be skipped. + * + * @since 1.5 + */ + public JavaType forcedNarrowBy(Class<?> subclass) + { + if (subclass == _class) { // can still optimize for simple case + return this; + } + JavaType result = _narrow(subclass); + // TODO: these checks should NOT actually be needed; above should suffice: + if (_valueHandler != result.getValueHandler()) { + result = result.withValueHandler(_valueHandler); + } + if (_typeHandler != result.getTypeHandler()) { + result = result.withTypeHandler(_typeHandler); + } + return result; + } + + /** + * Method that can be called to do a "widening" conversions; that is, + * to return a type with a raw class that could be assigned from this + * type. + * If such conversion is not possible, an + * {@link IllegalArgumentException} is thrown. + * If class is same as the current raw class, instance itself is + * returned. + */ + public JavaType widenBy(Class<?> superclass) + { + // First: if same raw class, just return this instance + if (superclass == _class) { + return this; + } + // Otherwise, ensure compatibility + _assertSubclass(_class, superclass); + return _widen(superclass); + } + + protected abstract JavaType _narrow(Class<?> subclass); + + /** + *<p> + * Default implementation is just to call {@link #_narrow}, since + * underlying type construction is usually identical + */ + protected JavaType _widen(Class<?> superclass) { + return _narrow(superclass); + } + + public abstract JavaType narrowContentsBy(Class<?> contentClass); + + /** + * @since 1.8 + */ + public abstract JavaType widenContentsBy(Class<?> contentClass); + + /* + /********************************************************** + /* Public API, simple accessors + /********************************************************** + */ + + public final Class<?> getRawClass() { return _class; } + + /** + * Method that can be used to check whether this type has + * specified Class as its type erasure. Put another way, returns + * true if instantiation of this Type is given (type-erased) Class. + */ + public final boolean hasRawClass(Class<?> clz) { + return _class == clz; + } + + public boolean isAbstract() { + return Modifier.isAbstract(_class.getModifiers()); + } + + /** + * @since 1.3 + */ + public boolean isConcrete() { + int mod = _class.getModifiers(); + if ((mod & (Modifier.INTERFACE | Modifier.ABSTRACT)) == 0) { + return true; + } + /* 19-Feb-2010, tatus: Holy mackarel; primitive types + * have 'abstract' flag set... + */ + if (_class.isPrimitive()) { + return true; + } + return false; + } + + public boolean isThrowable() { + return Throwable.class.isAssignableFrom(_class); + } + + public boolean isArrayType() { return false; } + + public final boolean isEnumType() { return _class.isEnum(); } + + public final boolean isInterface() { return _class.isInterface(); } + + public final boolean isPrimitive() { return _class.isPrimitive(); } + + public final boolean isFinal() { return Modifier.isFinal(_class.getModifiers()); } + + /** + * @return True if type represented is a container type; this includes + * array, Map and Collection types. + */ + public abstract boolean isContainerType(); + + /** + * @return True if type is either true {@link java.util.Collection} type, + * or something similar (meaning it has at least one type parameter, + * which describes type of contents) + * + * @since 1.8 + */ + public boolean isCollectionLikeType() { return false; } + + /** + * @return True if type is either true {@link java.util.Map} type, + * or something similar (meaning it has at least two type parameter; + * first one describing key type, second value type) + * + * @since 1.8 + */ + public boolean isMapLikeType() { return false; } + + /* + /********************************************************** + /* Public API, type parameter access + /********************************************************** + */ + + /** + * Method that can be used to find out if the type directly declares generic + * parameters (for its direct super-class and/or super-interfaces). + * + * @since 1.6 + */ + public boolean hasGenericTypes() + { + return containedTypeCount() > 0; + } + + /** + * Method for accessing key type for this type, assuming type + * has such a concept (only Map types do) + */ + public JavaType getKeyType() { return null; } + + /** + * Method for accessing content type of this type, if type has + * such a thing: simple types do not, structured types do + * (like arrays, Collections and Maps) + */ + public JavaType getContentType() { return null; } + + /** + * Method for checking how many contained types this type + * has. Contained types are usually generic types, so that + * generic Maps have 2 contained types. + * + * @since 1.5 + */ + public int containedTypeCount() { return 0; } + + /** + * Method for accessing definitions of contained ("child") + * types. + * + * @param index Index of contained type to return + * + * @return Contained type at index, or null if no such type + * exists (no exception thrown) + * + * @since 1.5 + */ + public JavaType containedType(int index) { return null; } + + /** + * Method for accessing name of type variable in indicated + * position. If no name is bound, will use placeholders (derived + * from 0-based index); if no type variable or argument exists + * with given index, null is returned. + * + * @param index Index of contained type to return + * + * @return Contained type at index, or null if no such type + * exists (no exception thrown) + * + * @since 1.5 + */ + public String containedTypeName(int index) { return null; } + + /* + /********************************************************** + /* Semi-public API, accessing handlers + /********************************************************** + */ + + /** + * Method for accessing value handler associated with this type, if any + * + * @since 1.3 + */ + @SuppressWarnings("unchecked") + public <T> T getValueHandler() { return (T) _valueHandler; } + + /** + * Method for accessing type handler associated with this type, if any + * + * @since 1.5 + */ + @SuppressWarnings("unchecked") + public <T> T getTypeHandler() { return (T) _typeHandler; } + + /* + /********************************************************** + /* Support for producing signatures (1.6+) + /********************************************************** + */ + + /** + * Method that can be used to serialize type into form from which + * it can be fully deserialized from at a later point (using + * <code>TypeFactory</code> from mapper package). + * For simple types this is same as calling + * {@link Class#getName}, but for structured types it may additionally + * contain type information about contents. + * + * @since 1.5 + */ + public abstract String toCanonical(); + + /** + * Method for accessing signature that contains generic + * type information, in form compatible with JVM 1.5 + * as per JLS. It is a superset of {@link #getErasedSignature}, + * in that generic information can be automatically removed + * if necessary (just remove outermost + * angle brackets along with content inside) + * + * @since 1.6 + */ + public String getGenericSignature() { + StringBuilder sb = new StringBuilder(40); + getGenericSignature(sb); + return sb.toString(); + } + + /** + * + * @param sb StringBuilder to append signature to + * + * @return StringBuilder that was passed in; returned to allow + * call chaining + * + * @since 1.6 + */ + public abstract StringBuilder getGenericSignature(StringBuilder sb); + + /** + * Method for accessing signature without generic + * type information, in form compatible with all versions + * of JVM, and specifically used for type descriptions + * when generating byte code. + * + * @since 1.6 + */ + public String getErasedSignature() { + StringBuilder sb = new StringBuilder(40); + getErasedSignature(sb); + return sb.toString(); + } + + /** + * Method for accessing signature without generic + * type information, in form compatible with all versions + * of JVM, and specifically used for type descriptions + * when generating byte code. + * + * @param sb StringBuilder to append signature to + * + * @return StringBuilder that was passed in; returned to allow + * call chaining + * + * @since 1.6 + */ + public abstract StringBuilder getErasedSignature(StringBuilder sb); + + /* + /********************************************************** + /* Helper methods + /********************************************************** + */ + + protected void _assertSubclass(Class<?> subclass, Class<?> superClass) + { + if (!_class.isAssignableFrom(subclass)) { + throw new IllegalArgumentException("Class "+subclass.getName()+" is not assignable to "+_class.getName()); + } + } + + /* + /********************************************************** + /* Standard methods; let's make them abstract to force override + /********************************************************** + */ + + @Override + public abstract String toString(); + + @Override + public abstract boolean equals(Object o); + + @Override + public final int hashCode() { return _hashCode; } +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/type/TypeReference.java b/1.9.10/src/java/org/codehaus/jackson/type/TypeReference.java new file mode 100644 index 0000000..65e0f93 --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/type/TypeReference.java
@@ -0,0 +1,60 @@ +package org.codehaus.jackson.type; + +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; + +/** + * This class is used to pass full generics type information, and + * avoid problems with type erasure (that basically removes most + * usable type references from runtime Class objects). + * It is based on ideas from + * <a href="http://gafter.blogspot.com/2006/12/super-type-tokens.html" + * >http://gafter.blogspot.com/2006/12/super-type-tokens.html</a>, + * Additional idea (from a suggestion made in comments of the article) + * is to require bogus implementation of <code>Comparable</code> + * (any such generic interface would do, as long as it forces a method + * with generic type to be implemented). + * to ensure that a Type argument is indeed given. + *<p> + * Usage is by sub-classing: here is one way to instantiate reference + * to generic type <code>List<Integer></code>: + *<pre> + * TypeReference ref = new TypeReference<List<Integer>>() { }; + *</pre> + * which can be passed to methods that accept TypeReference. + */ +public abstract class TypeReference<T> + implements Comparable<TypeReference<T>> +{ + final Type _type; + + protected TypeReference() + { + Type superClass = getClass().getGenericSuperclass(); + if (superClass instanceof Class<?>) { // sanity check, should never happen + throw new IllegalArgumentException("Internal error: TypeReference constructed without actual type information"); + } + /* 22-Dec-2008, tatu: Not sure if this case is safe -- I suspect + * it is possible to make it fail? + * But let's deal with specifc + * case when we know an actual use case, and thereby suitable + * work arounds for valid case(s) and/or error to throw + * on invalid one(s). + */ + _type = ((ParameterizedType) superClass).getActualTypeArguments()[0]; + } + + public Type getType() { return _type; } + + /** + * The only reason we define this method (and require implementation + * of <code>Comparable</code>) is to prevent constructing a + * reference without type information. + */ + @Override + public int compareTo(TypeReference<T> o) { + // just need an implementation, not a good one... hence: + return 0; + } +} +
diff --git a/1.9.10/src/java/org/codehaus/jackson/type/package-info.java b/1.9.10/src/java/org/codehaus/jackson/type/package-info.java new file mode 100644 index 0000000..79f8499 --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/type/package-info.java
@@ -0,0 +1,8 @@ +/** + * Contains classes needed for type introspection, mostly used by data binding + * functionality. Most of this functionality is needed to properly handled + * generic types, and to simplify and unify processing of things Jackson needs + * to determine how contained types (of {@link java.util.Collection} and + * {@link java.util.Map} classes) are to be handled. + */ +package org.codehaus.jackson.type;
diff --git a/1.9.10/src/java/org/codehaus/jackson/util/BufferRecycler.java b/1.9.10/src/java/org/codehaus/jackson/util/BufferRecycler.java new file mode 100644 index 0000000..6128de2 --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/util/BufferRecycler.java
@@ -0,0 +1,109 @@ +package org.codehaus.jackson.util; + +/** + * This is a small utility class, whose main functionality is to allow + * simple reuse of raw byte/char buffers. It is usually used through + * <code>ThreadLocal</code> member of the owning class pointing to + * instance of this class through a <code>SoftReference</code>. The + * end result is a low-overhead GC-cleanable recycling: hopefully + * ideal for use by stream readers. + */ +public class BufferRecycler +{ + public final static int DEFAULT_WRITE_CONCAT_BUFFER_LEN = 2000; + + public enum ByteBufferType { + READ_IO_BUFFER(4000) + /** + * Buffer used for temporarily storing encoded content; used + * for example by UTF-8 encoding writer + */ + ,WRITE_ENCODING_BUFFER(4000) + + /** + * Buffer used for temporarily concatenating output; used for + * example when requesting output as byte array. + */ + ,WRITE_CONCAT_BUFFER(2000) + ; + + private final int size; + + ByteBufferType(int size) { this.size = size; } + } + + public enum CharBufferType { + TOKEN_BUFFER(2000) // Tokenizable input + ,CONCAT_BUFFER(2000) // concatenated output + ,TEXT_BUFFER(200) // Text content from input + ,NAME_COPY_BUFFER(200) // Temporary buffer for getting name characters + ; + + private final int size; + + CharBufferType(int size) { this.size = size; } + } + + final protected byte[][] _byteBuffers = new byte[ByteBufferType.values().length][]; + final protected char[][] _charBuffers = new char[CharBufferType.values().length][]; + + public BufferRecycler() { } + + public final byte[] allocByteBuffer(ByteBufferType type) + { + int ix = type.ordinal(); + byte[] buffer = _byteBuffers[ix]; + if (buffer == null) { + buffer = balloc(type.size); + } else { + _byteBuffers[ix] = null; + } + return buffer; + } + + public final void releaseByteBuffer(ByteBufferType type, byte[] buffer) + { + _byteBuffers[type.ordinal()] = buffer; + } + + public final char[] allocCharBuffer(CharBufferType type) + { + return allocCharBuffer(type, 0); + } + + public final char[] allocCharBuffer(CharBufferType type, int minSize) + { + if (type.size > minSize) { + minSize = type.size; + } + int ix = type.ordinal(); + char[] buffer = _charBuffers[ix]; + if (buffer == null || buffer.length < minSize) { + buffer = calloc(minSize); + } else { + _charBuffers[ix] = null; + } + return buffer; + } + + public final void releaseCharBuffer(CharBufferType type, char[] buffer) + { + _charBuffers[type.ordinal()] = buffer; + } + + /* + /********************************************************** + /* Actual allocations separated for easier debugging/profiling + /********************************************************** + */ + + private final byte[] balloc(int size) + { + return new byte[size]; + } + + private final char[] calloc(int size) + { + return new char[size]; + } +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/util/ByteArrayBuilder.java b/1.9.10/src/java/org/codehaus/jackson/util/ByteArrayBuilder.java new file mode 100644 index 0000000..5953f6f --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/util/ByteArrayBuilder.java
@@ -0,0 +1,294 @@ +/* Jackson JSON-processor. + * + * Copyright (c) 2007- Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in file LICENSE, included with + * the source code and binary code bundles. + * You may not use this file except in compliance with the License. + * + * 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.codehaus.jackson.util; + +import java.io.OutputStream; +import java.util.*; + +/** + * Helper class that is similar to {@link java.io.ByteArrayOutputStream} + * in usage, but more geared to Jackson use cases internally. + * Specific changes include segment storage (no need to have linear + * backing buffer, can avoid reallocs, copying), as well API + * not based on {@link java.io.OutputStream}. In short, a very much + * specialized builder object. + *<p> + * Since version 1.5, also implements {@link OutputStream} to allow + * efficient aggregation of output content as a byte array, similar + * to how {@link java.io.ByteArrayOutputStream} works, but somewhat more + * efficiently for many use cases. + */ +public final class ByteArrayBuilder + extends OutputStream +{ + private final static byte[] NO_BYTES = new byte[0]; + + /** + * Size of the first block we will allocate. + */ + private final static int INITIAL_BLOCK_SIZE = 500; + + /** + * Maximum block size we will use for individual non-aggregated + * blocks. Let's limit to using 256k chunks. + */ + private final static int MAX_BLOCK_SIZE = (1 << 18); + + final static int DEFAULT_BLOCK_ARRAY_SIZE = 40; + + /** + * Optional buffer recycler instance that we can use for allocating + * the first block. + * + * @since 1.5 + */ + private final BufferRecycler _bufferRecycler; + + private final LinkedList<byte[]> _pastBlocks = new LinkedList<byte[]>(); + + /** + * Number of bytes within byte arrays in {@link _pastBlocks}. + */ + private int _pastLen; + + private byte[] _currBlock; + + private int _currBlockPtr; + + public ByteArrayBuilder() { this(null); } + + public ByteArrayBuilder(BufferRecycler br) { this(br, INITIAL_BLOCK_SIZE); } + + public ByteArrayBuilder(int firstBlockSize) { this(null, firstBlockSize); } + + public ByteArrayBuilder(BufferRecycler br, int firstBlockSize) + { + _bufferRecycler = br; + if (br == null) { + _currBlock = new byte[firstBlockSize]; + } else { + _currBlock = br.allocByteBuffer(BufferRecycler.ByteBufferType.WRITE_CONCAT_BUFFER); + } + } + + public void reset() + { + _pastLen = 0; + _currBlockPtr = 0; + + if (!_pastBlocks.isEmpty()) { + _pastBlocks.clear(); + } + } + + /** + * Clean up method to call to release all buffers this object may be + * using. After calling the method, no other accessors can be used (and + * attempt to do so may result in an exception) + */ + public void release() { + reset(); + if (_bufferRecycler != null && _currBlock != null) { + _bufferRecycler.releaseByteBuffer(BufferRecycler.ByteBufferType.WRITE_CONCAT_BUFFER, _currBlock); + _currBlock = null; + } + } + + public void append(int i) + { + if (_currBlockPtr >= _currBlock.length) { + _allocMore(); + } + _currBlock[_currBlockPtr++] = (byte) i; + } + + public void appendTwoBytes(int b16) + { + if ((_currBlockPtr + 1) < _currBlock.length) { + _currBlock[_currBlockPtr++] = (byte) (b16 >> 8); + _currBlock[_currBlockPtr++] = (byte) b16; + } else { + append(b16 >> 8); + append(b16); + } + } + + public void appendThreeBytes(int b24) + { + if ((_currBlockPtr + 2) < _currBlock.length) { + _currBlock[_currBlockPtr++] = (byte) (b24 >> 16); + _currBlock[_currBlockPtr++] = (byte) (b24 >> 8); + _currBlock[_currBlockPtr++] = (byte) b24; + } else { + append(b24 >> 16); + append(b24 >> 8); + append(b24); + } + } + + /** + * Method called when results are finalized and we can get the + * full aggregated result buffer to return to the caller + */ + public byte[] toByteArray() + { + int totalLen = _pastLen + _currBlockPtr; + + if (totalLen == 0) { // quick check: nothing aggregated? + return NO_BYTES; + } + + byte[] result = new byte[totalLen]; + int offset = 0; + + for (byte[] block : _pastBlocks) { + int len = block.length; + System.arraycopy(block, 0, result, offset, len); + offset += len; + } + System.arraycopy(_currBlock, 0, result, offset, _currBlockPtr); + offset += _currBlockPtr; + if (offset != totalLen) { // just a sanity check + throw new RuntimeException("Internal error: total len assumed to be "+totalLen+", copied "+offset+" bytes"); + } + // Let's only reset if there's sizable use, otherwise will get reset later on + if (!_pastBlocks.isEmpty()) { + reset(); + } + return result; + } + + /* + /********************************************************** + /* Non-stream API (similar to TextBuffer), since 1.6 + /********************************************************** + */ + + /** + * Method called when starting "manual" output: will clear out + * current state and return the first segment buffer to fill + * + * @since 1.6 + */ + public byte[] resetAndGetFirstSegment() { + reset(); + return _currBlock; + } + + /** + * Method called when the current segment buffer is full; will + * append to current contents, allocate a new segment buffer + * and return it + * + * @since 1.6 + */ + public byte[] finishCurrentSegment() { + _allocMore(); + return _currBlock; + } + + /** + * Method that will complete "manual" output process, coalesce + * content (if necessary) and return results as a contiguous buffer. + * + * @param lastBlockLength Amount of content in the current segment + * buffer. + * + * @return Coalesced contents + */ + public byte[] completeAndCoalesce(int lastBlockLength) + { + _currBlockPtr = lastBlockLength; + return toByteArray(); + } + + public byte[] getCurrentSegment() { + return _currBlock; + } + + public void setCurrentSegmentLength(int len) { + _currBlockPtr = len; + } + + public int getCurrentSegmentLength() { + return _currBlockPtr; + } + + /* + /********************************************************** + /* OutputStream implementation + /********************************************************** + */ + + @Override + public void write(byte[] b) { + write(b, 0, b.length); + } + + @Override + public void write(byte[] b, int off, int len) + { + while (true) { + int max = _currBlock.length - _currBlockPtr; + int toCopy = Math.min(max, len); + if (toCopy > 0) { + System.arraycopy(b, off, _currBlock, _currBlockPtr, toCopy); + off += toCopy; + _currBlockPtr += toCopy; + len -= toCopy; + } + if (len <= 0) break; + _allocMore(); + } + } + + @Override + public void write(int b) { + append(b); + } + + @Override public void close() { /* NOP */ } + + @Override public void flush() { /* NOP */ } + + /* + /********************************************************** + /* Internal methods + /********************************************************** + */ + + private void _allocMore() + { + _pastLen += _currBlock.length; + + /* Let's allocate block that's half the total size, except + * never smaller than twice the initial block size. + * The idea is just to grow with reasonable rate, to optimize + * between minimal number of chunks and minimal amount of + * wasted space. + */ + int newSize = Math.max((_pastLen >> 1), (INITIAL_BLOCK_SIZE + INITIAL_BLOCK_SIZE)); + // plus not to exceed max we define... + if (newSize > MAX_BLOCK_SIZE) { + newSize = MAX_BLOCK_SIZE; + } + _pastBlocks.add(_currBlock); + _currBlock = new byte[newSize]; + _currBlockPtr = 0; + } + +} +
diff --git a/1.9.10/src/java/org/codehaus/jackson/util/CharTypes.java b/1.9.10/src/java/org/codehaus/jackson/util/CharTypes.java new file mode 100644 index 0000000..4f7a986 --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/util/CharTypes.java
@@ -0,0 +1,237 @@ +package org.codehaus.jackson.util; + +import java.util.Arrays; + +import org.codehaus.jackson.io.CharacterEscapes; + +public final class CharTypes +{ + private final static char[] HEX_CHARS = "0123456789ABCDEF".toCharArray(); + private final static byte[] HEX_BYTES; + static { + int len = HEX_CHARS.length; + HEX_BYTES = new byte[len]; + for (int i = 0; i < len; ++i) { + HEX_BYTES[i] = (byte) HEX_CHARS[i]; + } + } + + + /** + * Lookup table used for determining which input characters + * need special handling when contained in text segment. + */ + final static int[] sInputCodes; + static { + /* 96 would do for most cases (backslash is ascii 94) + * but if we want to do lookups by raw bytes it's better + * to have full table + */ + int[] table = new int[256]; + // Control chars and non-space white space are not allowed unquoted + for (int i = 0; i < 32; ++i) { + table[i] = -1; + } + // And then string end and quote markers are special too + table['"'] = 1; + table['\\'] = 1; + sInputCodes = table; + } + + /** + * Additionally we can combine UTF-8 decoding info into similar + * data table. + */ + final static int[] sInputCodesUtf8; + static { + int[] table = new int[sInputCodes.length]; + System.arraycopy(sInputCodes, 0, table, 0, sInputCodes.length); + for (int c = 128; c < 256; ++c) { + int code; + + // We'll add number of bytes needed for decoding + if ((c & 0xE0) == 0xC0) { // 2 bytes (0x0080 - 0x07FF) + code = 2; + } else if ((c & 0xF0) == 0xE0) { // 3 bytes (0x0800 - 0xFFFF) + code = 3; + } else if ((c & 0xF8) == 0xF0) { + // 4 bytes; double-char with surrogates and all... + code = 4; + } else { + // And -1 seems like a good "universal" error marker... + code = -1; + } + table[c] = code; + } + sInputCodesUtf8 = table; + } + + /** + * To support non-default (and -standard) unquoted field names mode, + * need to have alternate checking. + * Basically this is list of 8-bit ASCII characters that are legal + * as part of Javascript identifier + * + * @since 1.2 + */ + final static int[] sInputCodesJsNames; + static { + int[] table = new int[256]; + // Default is "not a name char", mark ones that are + Arrays.fill(table, -1); + // Assume rules with JS same as Java (change if/as needed) + for (int i = 33; i < 256; ++i) { + if (Character.isJavaIdentifierPart((char) i)) { + table[i] = 0; + } + } + /* As per [JACKSON-267], '@', '#' and '*' are also to be accepted as well. + * And '-' (for hyphenated names); and '+' for sake of symmetricity... + */ + table['@'] = 0; + table['#'] = 0; + table['*'] = 0; + table['-'] = 0; + table['+'] = 0; + sInputCodesJsNames = table; + } + + /** + * This table is similar to Latin-1, except that it marks all "high-bit" + * code as ok. They will be validated at a later point, when decoding + * name + */ + final static int[] sInputCodesUtf8JsNames; + static { + int[] table = new int[256]; + // start with 8-bit JS names + System.arraycopy(sInputCodesJsNames, 0, table, 0, sInputCodesJsNames.length); + Arrays.fill(table, 128, 128, 0); + sInputCodesUtf8JsNames = table; + } + + /** + * Decoding table used to quickly determine characters that are + * relevant within comment content + */ + final static int[] sInputCodesComment = new int[256]; + static { + // but first: let's start with UTF-8 multi-byte markers: + System.arraycopy(sInputCodesUtf8, 128, sInputCodesComment, 128, 128); + + // default (0) means "ok" (skip); -1 invalid, others marked by char itself + Arrays.fill(sInputCodesComment, 0, 32, -1); // invalid white space + sInputCodesComment['\t'] = 0; // tab is still fine + sInputCodesComment['\n'] = '\n'; // lf/cr need to be observed, ends cpp comment + sInputCodesComment['\r'] = '\r'; + sInputCodesComment['*'] = '*'; // end marker for c-style comments + } + + /** + * Lookup table used for determining which output characters in + * 7-bit ASCII range need to be quoted. + */ + final static int[] sOutputEscapes128; + static { + int[] table = new int[128]; + // Control chars need generic escape sequence + for (int i = 0; i < 32; ++i) { + // 04-Mar-2011, tatu: Used to use "-(i + 1)", replaced with constants + table[i] = CharacterEscapes.ESCAPE_STANDARD; + } + /* Others (and some within that range too) have explicit shorter + * sequences + */ + table['"'] = '"'; + table['\\'] = '\\'; + // Escaping of slash is optional, so let's not add it + table[0x08] = 'b'; + table[0x09] = 't'; + table[0x0C] = 'f'; + table[0x0A] = 'n'; + table[0x0D] = 'r'; + sOutputEscapes128 = table; + } + + /** + * Lookup table for the first 128 Unicode characters (7-bit ASCII) + * range. For actual hex digits, contains corresponding value; + * for others -1. + */ + final static int[] sHexValues = new int[128]; + static { + Arrays.fill(sHexValues, -1); + for (int i = 0; i < 10; ++i) { + sHexValues['0' + i] = i; + } + for (int i = 0; i < 6; ++i) { + sHexValues['a' + i] = 10 + i; + sHexValues['A' + i] = 10 + i; + } + } + + public final static int[] getInputCodeLatin1() { return sInputCodes; } + public final static int[] getInputCodeUtf8() { return sInputCodesUtf8; } + + public final static int[] getInputCodeLatin1JsNames() { return sInputCodesJsNames; } + public final static int[] getInputCodeUtf8JsNames() { return sInputCodesUtf8JsNames; } + + public final static int[] getInputCodeComment() { return sInputCodesComment; } + + /** + * Accessor for getting a read-only encoding table for first 128 Unicode + * code points (single-byte UTF-8 characters). + * Value of 0 means "no escaping"; other positive values that value is character + * to use after backslash; and negative values that generic (backslash - u) + * escaping is to be used. + */ + public final static int[] get7BitOutputEscapes() { return sOutputEscapes128; } + + public static int charToHex(int ch) + { + return (ch > 127) ? -1 : sHexValues[ch]; + } + + public static void appendQuoted(StringBuilder sb, String content) + { + final int[] escCodes = sOutputEscapes128; + int escLen = escCodes.length; + for (int i = 0, len = content.length(); i < len; ++i) { + char c = content.charAt(i); + if (c >= escLen || escCodes[c] == 0) { + sb.append(c); + continue; + } + sb.append('\\'); + int escCode = escCodes[c]; + if (escCode < 0) { // generic quoting (hex value) + // We know that it has to fit in just 2 hex chars + sb.append('u'); + sb.append('0'); + sb.append('0'); + int value = -(escCode + 1); + sb.append(HEX_CHARS[value >> 4]); + sb.append(HEX_CHARS[value & 0xF]); + } else { // "named", i.e. prepend with slash + sb.append((char) escCode); + } + } + } + + /** + * @since 1.6 + */ + public static char[] copyHexChars() + { + return (char[]) HEX_CHARS.clone(); + } + + /** + * @since 1.6 + */ + public static byte[] copyHexBytes() + { + return (byte[]) HEX_BYTES.clone(); + } +} +
diff --git a/1.9.10/src/java/org/codehaus/jackson/util/DefaultPrettyPrinter.java b/1.9.10/src/java/org/codehaus/jackson/util/DefaultPrettyPrinter.java new file mode 100644 index 0000000..ef8a6df --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/util/DefaultPrettyPrinter.java
@@ -0,0 +1,282 @@ +package org.codehaus.jackson.util; + +import java.io.*; +import java.util.Arrays; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.impl.Indenter; + +/** + * Default {@link PrettyPrinter} implementation that uses 2-space + * indentation with platform-default linefeeds. + * Usually this class is not instantiated directly, but instead + * method {@link JsonGenerator#useDefaultPrettyPrinter} is + * used, which will use an instance of this class for operation. + */ +public class DefaultPrettyPrinter + implements PrettyPrinter +{ + // // // Config, indentation + + /** + * By default, let's use only spaces to separate array values. + */ + protected Indenter _arrayIndenter = new FixedSpaceIndenter(); + + /** + * By default, let's use linefeed-adding indenter for separate + * object entries. We'll further configure indenter to use + * system-specific linefeeds, and 2 spaces per level (as opposed to, + * say, single tabs) + */ + protected Indenter _objectIndenter = new Lf2SpacesIndenter(); + + // // // Config, other white space configuration + + /** + * By default we will add spaces around colons used to + * separate object fields and values. + * If disabled, will not use spaces around colon. + */ + protected boolean _spacesInObjectEntries = true; + + // // // State: + + /** + * Number of open levels of nesting. Used to determine amount of + * indentation to use. + */ + protected int _nesting = 0; + + /* + /********************************************************** + /* Life-cycle (construct, configure) + /********************************************************** + */ + + public DefaultPrettyPrinter() { } + + public void indentArraysWith(Indenter i) + { + _arrayIndenter = (i == null) ? new NopIndenter() : i; + } + + public void indentObjectsWith(Indenter i) + { + _objectIndenter = (i == null) ? new NopIndenter() : i; + } + + public void spacesInObjectEntries(boolean b) { _spacesInObjectEntries = b; } + + /* + /********************************************************** + /* PrettyPrinter impl + /********************************************************** + */ + + @Override + public void writeRootValueSeparator(JsonGenerator jg) + throws IOException, JsonGenerationException + { + jg.writeRaw(' '); + } + + @Override + public void writeStartObject(JsonGenerator jg) + throws IOException, JsonGenerationException + { + jg.writeRaw('{'); + if (!_objectIndenter.isInline()) { + ++_nesting; + } + } + + @Override + public void beforeObjectEntries(JsonGenerator jg) + throws IOException, JsonGenerationException + { + _objectIndenter.writeIndentation(jg, _nesting); + } + + /** + * Method called after an object field has been output, but + * before the value is output. + *<p> + * Default handling (without pretty-printing) will output a single + * colon to separate the two. Pretty-printer is + * to output a colon as well, but can surround that with other + * (white-space) decoration. + */ + @Override + public void writeObjectFieldValueSeparator(JsonGenerator jg) + throws IOException, JsonGenerationException + { + if (_spacesInObjectEntries) { + jg.writeRaw(" : "); + } else { + jg.writeRaw(':'); + } + } + + /** + * Method called after an object entry (field:value) has been completely + * output, and before another value is to be output. + *<p> + * Default handling (without pretty-printing) will output a single + * comma to separate the two. Pretty-printer is + * to output a comma as well, but can surround that with other + * (white-space) decoration. + */ + @Override + public void writeObjectEntrySeparator(JsonGenerator jg) + throws IOException, JsonGenerationException + { + jg.writeRaw(','); + _objectIndenter.writeIndentation(jg, _nesting); + } + + @Override + public void writeEndObject(JsonGenerator jg, int nrOfEntries) + throws IOException, JsonGenerationException + { + if (!_objectIndenter.isInline()) { + --_nesting; + } + if (nrOfEntries > 0) { + _objectIndenter.writeIndentation(jg, _nesting); + } else { + jg.writeRaw(' '); + } + jg.writeRaw('}'); + } + + @Override + public void writeStartArray(JsonGenerator jg) + throws IOException, JsonGenerationException + { + if (!_arrayIndenter.isInline()) { + ++_nesting; + } + jg.writeRaw('['); + } + + @Override + public void beforeArrayValues(JsonGenerator jg) + throws IOException, JsonGenerationException + { + _arrayIndenter.writeIndentation(jg, _nesting); + } + + /** + * Method called after an array value has been completely + * output, and before another value is to be output. + *<p> + * Default handling (without pretty-printing) will output a single + * comma to separate the two. Pretty-printer is + * to output a comma as well, but can surround that with other + * (white-space) decoration. + */ + @Override + public void writeArrayValueSeparator(JsonGenerator jg) + throws IOException, JsonGenerationException + { + jg.writeRaw(','); + _arrayIndenter.writeIndentation(jg, _nesting); + } + + @Override + public void writeEndArray(JsonGenerator jg, int nrOfValues) + throws IOException, JsonGenerationException + { + if (!_arrayIndenter.isInline()) { + --_nesting; + } + if (nrOfValues > 0) { + _arrayIndenter.writeIndentation(jg, _nesting); + } else { + jg.writeRaw(' '); + } + jg.writeRaw(']'); + } + + /* + /********************************************************** + /* Helper classes + /********************************************************** + */ + + /** + * Dummy implementation that adds no indentation whatsoever + */ + public static class NopIndenter + implements Indenter + { + public NopIndenter() { } + @Override + public void writeIndentation(JsonGenerator jg, int level) { } + @Override + public boolean isInline() { return true; } + } + + /** + * This is a very simple indenter that only every adds a + * single space for indentation. It is used as the default + * indenter for array values. + */ + public static class FixedSpaceIndenter + implements Indenter + { + public FixedSpaceIndenter() { } + + @Override + public void writeIndentation(JsonGenerator jg, int level) + throws IOException, JsonGenerationException + { + jg.writeRaw(' '); + } + + @Override + public boolean isInline() { return true; } + } + + /** + * Default linefeed-based indenter uses system-specific linefeeds and + * 2 spaces for indentation per level. + */ + public static class Lf2SpacesIndenter + implements Indenter + { + final static String SYSTEM_LINE_SEPARATOR; + static { + String lf = null; + try { + lf = System.getProperty("line.separator"); + } catch (Throwable t) { } // access exception? + SYSTEM_LINE_SEPARATOR = (lf == null) ? "\n" : lf; + } + + final static int SPACE_COUNT = 64; + final static char[] SPACES = new char[SPACE_COUNT]; + static { + Arrays.fill(SPACES, ' '); + } + + public Lf2SpacesIndenter() { } + + @Override + public boolean isInline() { return false; } + + @Override + public void writeIndentation(JsonGenerator jg, int level) + throws IOException, JsonGenerationException + { + jg.writeRaw(SYSTEM_LINE_SEPARATOR); + level += level; // 2 spaces per level + while (level > SPACE_COUNT) { // should never happen but... + jg.writeRaw(SPACES, 0, SPACE_COUNT); + level -= SPACES.length; + } + jg.writeRaw(SPACES, 0, level); + } + } +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/util/InternCache.java b/1.9.10/src/java/org/codehaus/jackson/util/InternCache.java new file mode 100644 index 0000000..7fdae9f --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/util/InternCache.java
@@ -0,0 +1,49 @@ +package org.codehaus.jackson.util; + +import java.util.Map; +import java.util.LinkedHashMap; + +/** + * Singleton class that adds a simple first-level cache in front of + * regular String.intern() functionality. This is done as a minor + * performance optimization, to avoid calling native intern() method + * in cases where same String is being interned multiple times. + *<p> + * Note: that this class extends {@link LinkedHashMap} is an implementation + * detail -- no code should ever directly call Map methods. + */ +@SuppressWarnings("serial") +public final class InternCache + extends LinkedHashMap<String,String> +{ + /** + * Size to use is somewhat arbitrary, so let's choose something that's + * neither too small (low hit ratio) nor too large (waste of memory) + */ + private final static int MAX_ENTRIES = 192; + + public final static InternCache instance = new InternCache(); + + private InternCache() { + super(MAX_ENTRIES, 0.8f, true); + } + + @Override + protected boolean removeEldestEntry(Map.Entry<String,String> eldest) + { + return size() > MAX_ENTRIES; + } + + public synchronized String intern(String input) + { + String result = get(input); + if (result == null) { + result = input.intern(); + put(result, result); + } + return result; + } + + +} +
diff --git a/1.9.10/src/java/org/codehaus/jackson/util/JsonGeneratorDelegate.java b/1.9.10/src/java/org/codehaus/jackson/util/JsonGeneratorDelegate.java new file mode 100644 index 0000000..1dc681c --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/util/JsonGeneratorDelegate.java
@@ -0,0 +1,273 @@ +package org.codehaus.jackson.util; + +import java.io.IOException; +import java.math.BigDecimal; +import java.math.BigInteger; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.io.SerializedString; + +public class JsonGeneratorDelegate extends JsonGenerator +{ + /** + * Delegate object that method calls are delegated to. + */ + protected JsonGenerator delegate; + + public JsonGeneratorDelegate(JsonGenerator d) { + delegate = d; + } + + @Override + public void close() throws IOException { + delegate.close(); + } + + @Override + public void copyCurrentEvent(JsonParser jp) throws IOException, JsonProcessingException { + delegate.copyCurrentEvent(jp); + } + + @Override + public void copyCurrentStructure(JsonParser jp) throws IOException, JsonProcessingException { + delegate.copyCurrentStructure(jp); + } + + @Override + public JsonGenerator disable(Feature f) { + return delegate.disable(f); + } + + @Override + public JsonGenerator enable(Feature f) { + return delegate.enable(f); + } + + @Override + public void flush() throws IOException { + delegate.flush(); + } + + @Override + public ObjectCodec getCodec() { + return delegate.getCodec(); + } + + @Override + public JsonStreamContext getOutputContext() { + return delegate.getOutputContext(); + } + + @Override + public void setSchema(FormatSchema schema) { + delegate.setSchema(schema); + } + + @Override + public boolean canUseSchema(FormatSchema schema) { + return delegate.canUseSchema(schema); + } + + @Override + public Version version() { + return delegate.version(); + } + + @Override + public Object getOutputTarget() { + return delegate.getOutputTarget(); + } + + @Override + public boolean isClosed() { + return delegate.isClosed(); + } + + @Override + public boolean isEnabled(Feature f) { + return delegate.isEnabled(f); + } + + @Override + public JsonGenerator setCodec(ObjectCodec oc) { + delegate.setCodec(oc); + return this; + } + + @Override + public JsonGenerator useDefaultPrettyPrinter() { + delegate.useDefaultPrettyPrinter(); + return this; + } + + @Override + public void writeBinary(Base64Variant b64variant, byte[] data, int offset, int len) + throws IOException, JsonGenerationException + { + delegate.writeBinary(b64variant, data, offset, len); + } + + @Override + public void writeBoolean(boolean state) throws IOException, JsonGenerationException { + delegate.writeBoolean(state); + } + + @Override + public void writeEndArray() throws IOException, JsonGenerationException { + delegate.writeEndArray(); + } + + @Override + public void writeEndObject() throws IOException, JsonGenerationException { + delegate.writeEndObject(); + } + + @Override + public void writeFieldName(String name) + throws IOException, JsonGenerationException + { + delegate.writeFieldName(name); + } + + @Override + public void writeFieldName(SerializedString name) + throws IOException, JsonGenerationException + { + delegate.writeFieldName(name); + } + + @Override + public void writeFieldName(SerializableString name) + throws IOException, JsonGenerationException + { + delegate.writeFieldName(name); + } + + @Override + public void writeNull() throws IOException, JsonGenerationException { + delegate.writeNull(); + } + + @Override + public void writeNumber(int v) throws IOException, JsonGenerationException { + delegate.writeNumber(v); + } + + @Override + public void writeNumber(long v) throws IOException, JsonGenerationException { + delegate.writeNumber(v); + } + + @Override + public void writeNumber(BigInteger v) throws IOException, + JsonGenerationException { + delegate.writeNumber(v); + } + + @Override + public void writeNumber(double v) throws IOException, + JsonGenerationException { + delegate.writeNumber(v); + } + + @Override + public void writeNumber(float v) throws IOException, + JsonGenerationException { + delegate.writeNumber(v); + } + + @Override + public void writeNumber(BigDecimal v) throws IOException, + JsonGenerationException { + delegate.writeNumber(v); + } + + @Override + public void writeNumber(String encodedValue) throws IOException, JsonGenerationException, UnsupportedOperationException { + delegate.writeNumber(encodedValue); + } + + @Override + public void writeObject(Object pojo) throws IOException,JsonProcessingException { + delegate.writeObject(pojo); + } + + @Override + public void writeRaw(String text) throws IOException, JsonGenerationException { + delegate.writeRaw(text); + } + + @Override + public void writeRaw(String text, int offset, int len) throws IOException, JsonGenerationException { + delegate.writeRaw(text, offset, len); + } + + @Override + public void writeRaw(char[] text, int offset, int len) throws IOException, JsonGenerationException { + delegate.writeRaw(text, offset, len); + } + + @Override + public void writeRaw(char c) throws IOException, JsonGenerationException { + delegate.writeRaw(c); + } + + @Override + public void writeRawValue(String text) throws IOException, JsonGenerationException { + delegate.writeRawValue(text); + } + + @Override + public void writeRawValue(String text, int offset, int len) throws IOException, JsonGenerationException { + delegate.writeRawValue(text, offset, len); + } + + @Override + public void writeRawValue(char[] text, int offset, int len) throws IOException, JsonGenerationException { + delegate.writeRawValue(text, offset, len); + } + + @Override + public void writeStartArray() throws IOException, JsonGenerationException { + delegate.writeStartArray(); + } + + @Override + public void writeStartObject() throws IOException, JsonGenerationException { + delegate.writeStartObject(); + } + + @Override + public void writeString(String text) throws IOException,JsonGenerationException { + delegate.writeString(text); + } + + @Override + public void writeString(char[] text, int offset, int len) throws IOException, JsonGenerationException { + delegate.writeString(text, offset, len); + } + + @Override + public void writeString(SerializableString text) throws IOException, JsonGenerationException { + delegate.writeString(text); + } + + @Override + public void writeRawUTF8String(byte[] text, int offset, int length) + throws IOException, JsonGenerationException + { + delegate.writeRawUTF8String(text, offset, length); + } + + @Override + public void writeUTF8String(byte[] text, int offset, int length) + throws IOException, JsonGenerationException + { + delegate.writeUTF8String(text, offset, length); + } + + @Override + public void writeTree(JsonNode rootNode) throws IOException, JsonProcessingException { + delegate.writeTree(rootNode); + } +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/util/JsonParserDelegate.java b/1.9.10/src/java/org/codehaus/jackson/util/JsonParserDelegate.java new file mode 100644 index 0000000..b038efb --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/util/JsonParserDelegate.java
@@ -0,0 +1,251 @@ +package org.codehaus.jackson.util; + +import java.io.IOException; +import java.math.BigDecimal; +import java.math.BigInteger; + +import org.codehaus.jackson.*; + +/** + * Helper class that implements + * <a href="http://en.wikipedia.org/wiki/Delegation_pattern">delegation pattern</a> for {@link JsonParser}, + * to allow for simple overridability of basic parsing functionality. + * The idea is that any functionality to be modified can be simply + * overridden; and anything else will be delegated by default. + * + * @since 1.4 + */ +public class JsonParserDelegate extends JsonParser +{ + /** + * Delegate object that method calls are delegated to. + */ + protected JsonParser delegate; + + public JsonParserDelegate(JsonParser d) { + delegate = d; + } + + /* + /********************************************************** + /* Public API, configuration + /********************************************************** + */ + + @Override + public void setCodec(ObjectCodec c) { + delegate.setCodec(c); + } + + @Override + public ObjectCodec getCodec() { + return delegate.getCodec(); + } + + @Override + public JsonParser enable(Feature f) { + delegate.enable(f); + return this; + } + + @Override + public JsonParser disable(Feature f) { + delegate.disable(f); + return this; + } + + @Override + public boolean isEnabled(Feature f) { + return delegate.isEnabled(f); + } + + @Override + public void setSchema(FormatSchema schema) { + delegate.setSchema(schema); + } + + @Override + public boolean canUseSchema(FormatSchema schema) { + return delegate.canUseSchema(schema); + } + + @Override + public Version version() { + return delegate.version(); + } + + @Override + public Object getInputSource() { + return delegate.getInputSource(); + } + + /* + /********************************************************** + /* Closeable impl + /********************************************************** + */ + + @Override + public void close() throws IOException { + delegate.close(); + } + + @Override + public boolean isClosed() { + return delegate.isClosed(); + } + + /* + /********************************************************** + /* Public API, token accessors + /********************************************************** + */ + + @Override + public JsonToken getCurrentToken() { + return delegate.getCurrentToken(); + } + + @Override + public boolean hasCurrentToken() { + return delegate.hasCurrentToken(); + } + + @Override + public void clearCurrentToken() { + delegate.clearCurrentToken(); + } + + @Override + public String getCurrentName() throws IOException, JsonParseException { + return delegate.getCurrentName(); + } + + @Override + public JsonLocation getCurrentLocation() { + return delegate.getCurrentLocation(); + } + + @Override + public JsonToken getLastClearedToken() { + return delegate.getLastClearedToken(); + } + + @Override + public JsonStreamContext getParsingContext() { + return delegate.getParsingContext(); + } + + /* + /********************************************************** + /* Public API, access to token information, text + /********************************************************** + */ + + @Override + public String getText() throws IOException, JsonParseException { + return delegate.getText(); + } + + @Override + public char[] getTextCharacters() throws IOException, JsonParseException { + return delegate.getTextCharacters(); + } + + @Override + public int getTextLength() throws IOException, JsonParseException { + return delegate.getTextLength(); + } + + @Override + public int getTextOffset() throws IOException, JsonParseException { + return delegate.getTextOffset(); + } + + /* + /********************************************************** + /* Public API, access to token information, numeric + /********************************************************** + */ + + public boolean getBooleanValue() throws IOException, JsonParseException { + return delegate.getBooleanValue(); + } + + @Override + public BigInteger getBigIntegerValue() throws IOException,JsonParseException { + return delegate.getBigIntegerValue(); + } + + @Override + public byte getByteValue() throws IOException, JsonParseException { + return delegate.getByteValue(); + } + + @Override + public short getShortValue() throws IOException, JsonParseException { + return delegate.getShortValue(); + } + + @Override + public BigDecimal getDecimalValue() throws IOException, JsonParseException { + return delegate.getDecimalValue(); + } + + @Override + public double getDoubleValue() throws IOException, JsonParseException { + return delegate.getDoubleValue(); + } + + @Override + public float getFloatValue() throws IOException, JsonParseException { + return delegate.getFloatValue(); + } + + @Override + public int getIntValue() throws IOException, JsonParseException { + return delegate.getIntValue(); + } + + @Override + public long getLongValue() throws IOException, JsonParseException { + return delegate.getLongValue(); + } + + @Override + public NumberType getNumberType() throws IOException, JsonParseException { + return delegate.getNumberType(); + } + + @Override + public Number getNumberValue() throws IOException, JsonParseException { + return delegate.getNumberValue(); + } + + @Override + public byte[] getBinaryValue(Base64Variant b64variant) throws IOException, JsonParseException { + return delegate.getBinaryValue(b64variant); + } + + @Override + public Object getEmbeddedObject() throws IOException, JsonParseException { + return delegate.getEmbeddedObject(); + } + + @Override + public JsonLocation getTokenLocation() { + return delegate.getTokenLocation(); + } + + @Override + public JsonToken nextToken() throws IOException, JsonParseException { + return delegate.nextToken(); + } + + @Override + public JsonParser skipChildren() throws IOException, JsonParseException { + delegate.skipChildren(); + // NOTE: must NOT delegate this method to delegate, needs to be self-reference for chaining + return this; + } +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/util/JsonParserSequence.java b/1.9.10/src/java/org/codehaus/jackson/util/JsonParserSequence.java new file mode 100644 index 0000000..4d49d00 --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/util/JsonParserSequence.java
@@ -0,0 +1,150 @@ +package org.codehaus.jackson.util; + +import java.io.IOException; +import java.util.*; + +import org.codehaus.jackson.*; + +/** + * Helper class that can be used to sequence multiple physical + * {@link JsonParser}s to create a single logical sequence of + * tokens, as a single {@link JsonParser}. + *<p> + * Fairly simple use of {@link JsonParserDelegate}: only need + * to override {@link #nextToken} to handle transition + * + * @author tatu + * @since 1.5 + */ +public class JsonParserSequence extends JsonParserDelegate +{ + /** + * Parsers other than the first one (which is initially assigned + * as delegate) + */ + protected final JsonParser[] _parsers; + + /** + * Index of the next parser in {@link #_parsers}. + */ + protected int _nextParser; + + /* + ******************************************************* + * Construction + ******************************************************* + */ + + protected JsonParserSequence(JsonParser[] parsers) + { + super(parsers[0]); + _parsers = parsers; + _nextParser = 1; + } + + /** + * Method that will construct a parser (possibly a sequence) that + * contains all given sub-parsers. + * All parsers given are checked to see if they are sequences: and + * if so, they will be "flattened", that is, contained parsers are + * directly added in a new sequence instead of adding sequences + * within sequences. This is done to minimize delegation depth, + * ideally only having just a single level of delegation. + */ + public static JsonParserSequence createFlattened(JsonParser first, JsonParser second) + { + if (!(first instanceof JsonParserSequence || second instanceof JsonParserSequence)) { + // simple: + return new JsonParserSequence(new JsonParser[] { first, second }); + } + ArrayList<JsonParser> p = new ArrayList<JsonParser>(); + if (first instanceof JsonParserSequence) { + ((JsonParserSequence) first).addFlattenedActiveParsers(p); + } else { + p.add(first); + } + if (second instanceof JsonParserSequence) { + ((JsonParserSequence) second).addFlattenedActiveParsers(p); + } else { + p.add(second); + } + return new JsonParserSequence(p.toArray(new JsonParser[p.size()])); + } + + protected void addFlattenedActiveParsers(List<JsonParser> result) + { + for (int i = _nextParser-1, len = _parsers.length; i < len; ++i) { + JsonParser p = _parsers[i]; + if (p instanceof JsonParserSequence) { + ((JsonParserSequence) p).addFlattenedActiveParsers(result); + } else { + result.add(p); + } + } + } + + /* + ******************************************************* + * Overridden methods, needed: cases where default + * delegation does not work + ******************************************************* + */ + + @Override + public void close() throws IOException + { + do { + delegate.close(); + } while (switchToNext()); + } + + @Override + public JsonToken nextToken() throws IOException, JsonParseException + { + JsonToken t = delegate.nextToken(); + if (t != null) return t; + while (switchToNext()) { + t = delegate.nextToken(); + if (t != null) return t; + } + return null; + } + + /* + /******************************************************* + /* Additional extended API + /******************************************************* + */ + + /** + * Method that is most useful for debugging or testing; + * returns actual number of underlying parsers sequence + * was constructed with (nor just ones remaining active) + */ + public int containedParsersCount() { + return _parsers.length; + } + + /* + /******************************************************* + /* Helper methods + /******************************************************* + */ + + /** + * Method that will switch active parser from the current one + * to next parser in sequence, if there is another parser left, + * making this the new delegate. Old delegate is returned if + * switch succeeds. + * + * @return True if switch succeeded; false otherwise + */ + protected boolean switchToNext() + { + if (_nextParser >= _parsers.length) { + return false; + } + delegate = _parsers[_nextParser++]; + return true; + } +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/util/MinimalPrettyPrinter.java b/1.9.10/src/java/org/codehaus/jackson/util/MinimalPrettyPrinter.java new file mode 100644 index 0000000..cdd6a6b --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/util/MinimalPrettyPrinter.java
@@ -0,0 +1,152 @@ +package org.codehaus.jackson.util; + +import java.io.IOException; + +import org.codehaus.jackson.JsonGenerationException; +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.PrettyPrinter; + +/** + * {@link PrettyPrinter} implementation that adds no indentation, + * just implements everything necessary for value output to work + * as expected, and provide simpler extension points to allow + * for creating simple custom implementations that add specific + * decoration or overrides. Since behavior then is very similar + * to using no pretty printer at all, usually sub-classes are used. + *<p> + * Beyond purely minimal implementation, there is limited amount of + * configurability which may be useful for actual use: for example, + * it is possible to redefine separator used between root-level + * values (default is single space; can be changed to line-feed). + * + * @since 1.6 + */ +public class MinimalPrettyPrinter + implements PrettyPrinter +{ + /** + * Default String used for separating root values is single space. + */ + public final static String DEFAULT_ROOT_VALUE_SEPARATOR = " "; + + protected String _rootValueSeparator = DEFAULT_ROOT_VALUE_SEPARATOR; + + /* + /********************************************************** + /* Life-cycle, construction, configuration + /********************************************************** + */ + + public MinimalPrettyPrinter() { + this(DEFAULT_ROOT_VALUE_SEPARATOR); + } + + /** + * @since 1.9 + */ + public MinimalPrettyPrinter(String rootValueSeparator) { + _rootValueSeparator = rootValueSeparator; + } + + public void setRootValueSeparator(String sep) { + _rootValueSeparator = sep; + } + + /* + /********************************************************** + /* PrettyPrinter impl + /********************************************************** + */ + + @Override + public void writeRootValueSeparator(JsonGenerator jg) throws IOException, JsonGenerationException + { + if (_rootValueSeparator != null) { + jg.writeRaw(_rootValueSeparator); + } + } + + @Override + public void writeStartObject(JsonGenerator jg) + throws IOException, JsonGenerationException + { + jg.writeRaw('{'); + } + + @Override + public void beforeObjectEntries(JsonGenerator jg) + throws IOException, JsonGenerationException + { + // nothing special, since no indentation is added + } + + /** + * Method called after an object field has been output, but + * before the value is output. + *<p> + * Default handling will just output a single + * colon to separate the two, without additional spaces. + */ + @Override + public void writeObjectFieldValueSeparator(JsonGenerator jg) + throws IOException, JsonGenerationException + { + jg.writeRaw(':'); + } + + /** + * Method called after an object entry (field:value) has been completely + * output, and before another value is to be output. + *<p> + * Default handling (without pretty-printing) will output a single + * comma to separate the two. + */ + @Override + public void writeObjectEntrySeparator(JsonGenerator jg) + throws IOException, JsonGenerationException + { + jg.writeRaw(','); + } + + @Override + public void writeEndObject(JsonGenerator jg, int nrOfEntries) + throws IOException, JsonGenerationException + { + jg.writeRaw('}'); + } + + @Override + public void writeStartArray(JsonGenerator jg) + throws IOException, JsonGenerationException + { + jg.writeRaw('['); + } + + @Override + public void beforeArrayValues(JsonGenerator jg) + throws IOException, JsonGenerationException + { + // nothing special, since no indentation is added + } + + /** + * Method called after an array value has been completely + * output, and before another value is to be output. + *<p> + * Default handling (without pretty-printing) will output a single + * comma to separate values. + */ + @Override + public void writeArrayValueSeparator(JsonGenerator jg) + throws IOException, JsonGenerationException + { + jg.writeRaw(','); + } + + @Override + public void writeEndArray(JsonGenerator jg, int nrOfValues) + throws IOException, JsonGenerationException + { + jg.writeRaw(']'); + } +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/util/TextBuffer.java b/1.9.10/src/java/org/codehaus/jackson/util/TextBuffer.java new file mode 100644 index 0000000..8f1eff1 --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/util/TextBuffer.java
@@ -0,0 +1,720 @@ +package org.codehaus.jackson.util; + +import java.math.BigDecimal; +import java.util.ArrayList; + +import org.codehaus.jackson.io.NumberInput; + +/** + * TextBuffer is a class similar to {@link StringBuffer}, with + * following differences: + *<ul> + * <li>TextBuffer uses segments character arrays, to avoid having + * to do additional array copies when array is not big enough. + * This means that only reallocating that is necessary is done only once: + * if and when caller + * wants to access contents in a linear array (char[], String). + * </li> +* <li>TextBuffer can also be initialized in "shared mode", in which +* it will just act as a wrapper to a single char array managed +* by another object (like parser that owns it) + * </li> + * <li>TextBuffer is not synchronized. + * </li> + * </ul> + */ +public final class TextBuffer +{ + final static char[] NO_CHARS = new char[0]; + + /** + * Let's start with sizable but not huge buffer, will grow as necessary + */ + final static int MIN_SEGMENT_LEN = 1000; + + /** + * Let's limit maximum segment length to something sensible + * like 256k + */ + final static int MAX_SEGMENT_LEN = 0x40000; + + /* + /********************************************************** + /* Configuration: + /********************************************************** + */ + + private final BufferRecycler _allocator; + + /* + /********************************************************** + /* Shared input buffers + /********************************************************** + */ + + /** + * Shared input buffer; stored here in case some input can be returned + * as is, without being copied to collector's own buffers. Note that + * this is read-only for this Object. + */ + private char[] _inputBuffer; + + /** + * Character offset of first char in input buffer; -1 to indicate + * that input buffer currently does not contain any useful char data + */ + private int _inputStart; + + private int _inputLen; + + /* + /********************************************************** + /* Aggregation segments (when not using input buf) + /********************************************************** + */ + + /** + * List of segments prior to currently active segment. + */ + private ArrayList<char[]> _segments; + + /** + * Flag that indicates whether _seqments is non-empty + */ + private boolean _hasSegments = false; + + // // // Currently used segment; not (yet) contained in _seqments + + /** + * Amount of characters in segments in {@link _segments} + */ + private int _segmentSize; + + private char[] _currentSegment; + + /** + * Number of characters in currently active (last) segment + */ + private int _currentSize; + + /* + /********************************************************** + /* Caching of results + /********************************************************** + */ + + /** + * String that will be constructed when the whole contents are + * needed; will be temporarily stored in case asked for again. + */ + private String _resultString; + + private char[] _resultArray; + + /* + /********************************************************** + /* Life-cycle + /********************************************************** + */ + + public TextBuffer(BufferRecycler allocator) + { + _allocator = allocator; + } + + /** + * Method called to indicate that the underlying buffers should now + * be recycled if they haven't yet been recycled. Although caller + * can still use this text buffer, it is not advisable to call this + * method if that is likely, since next time a buffer is needed, + * buffers need to reallocated. + * Note: calling this method automatically also clears contents + * of the buffer. + */ + public void releaseBuffers() + { + if (_allocator == null) { + resetWithEmpty(); + } else { + if (_currentSegment != null) { + // First, let's get rid of all but the largest char array + resetWithEmpty(); + // And then return that array + char[] buf = _currentSegment; + _currentSegment = null; + _allocator.releaseCharBuffer(BufferRecycler.CharBufferType.TEXT_BUFFER, buf); + } + } + } + + /** + * Method called to clear out any content text buffer may have, and + * initializes buffer to use non-shared data. + */ + public void resetWithEmpty() + { + _inputStart = -1; // indicates shared buffer not used + _currentSize = 0; + _inputLen = 0; + + _inputBuffer = null; + _resultString = null; + _resultArray = null; + + // And then reset internal input buffers, if necessary: + if (_hasSegments) { + clearSegments(); + } + } + + /** + * Method called to initialize the buffer with a shared copy of data; + * this means that buffer will just have pointers to actual data. It + * also means that if anything is to be appended to the buffer, it + * will first have to unshare it (make a local copy). + */ + public void resetWithShared(char[] buf, int start, int len) + { + // First, let's clear intermediate values, if any: + _resultString = null; + _resultArray = null; + + // Then let's mark things we need about input buffer + _inputBuffer = buf; + _inputStart = start; + _inputLen = len; + + // And then reset internal input buffers, if necessary: + if (_hasSegments) { + clearSegments(); + } + } + + public void resetWithCopy(char[] buf, int start, int len) + { + _inputBuffer = null; + _inputStart = -1; // indicates shared buffer not used + _inputLen = 0; + + _resultString = null; + _resultArray = null; + + // And then reset internal input buffers, if necessary: + if (_hasSegments) { + clearSegments(); + } else if (_currentSegment == null) { + _currentSegment = findBuffer(len); + } + _currentSize = _segmentSize = 0; + append(buf, start, len); + } + + public void resetWithString(String value) + { + _inputBuffer = null; + _inputStart = -1; + _inputLen = 0; + + _resultString = value; + _resultArray = null; + + if (_hasSegments) { + clearSegments(); + } + _currentSize = 0; + + } + + /** + * Helper method used to find a buffer to use, ideally one + * recycled earlier. + */ + private final char[] findBuffer(int needed) + { + if (_allocator != null) { + return _allocator.allocCharBuffer(BufferRecycler.CharBufferType.TEXT_BUFFER, needed); + } + return new char[Math.max(needed, MIN_SEGMENT_LEN)]; + } + + private final void clearSegments() + { + _hasSegments = false; + /* Let's start using _last_ segment from list; for one, it's + * the biggest one, and it's also most likely to be cached + */ + /* 28-Aug-2009, tatu: Actually, the current segment should + * be the biggest one, already + */ + //_currentSegment = _segments.get(_segments.size() - 1); + _segments.clear(); + _currentSize = _segmentSize = 0; + } + + /* + /********************************************************** + /* Accessors for implementing public interface + /********************************************************** + */ + + /** + * @return Number of characters currently stored by this collector + */ + public int size() { + if (_inputStart >= 0) { // shared copy from input buf + return _inputLen; + } + if (_resultArray != null) { + return _resultArray.length; + } + if (_resultString != null) { + return _resultString.length(); + } + // local segmented buffers + return _segmentSize + _currentSize; + } + + public int getTextOffset() + { + /* Only shared input buffer can have non-zero offset; buffer + * segments start at 0, and if we have to create a combo buffer, + * that too will start from beginning of the buffer + */ + return (_inputStart >= 0) ? _inputStart : 0; + } + + /** + * Method that can be used to check whether textual contents can + * be efficiently accessed using {@link #getTextBuffer}. + * + * @since 1.9 + */ + public boolean hasTextAsCharacters() + { + // if we have array in some form, sure + if (_inputStart >= 0 || _resultArray != null) { + return true; + } + // not if we have String as value + if (_resultString != null) { + return false; + } + return true; + } + + public char[] getTextBuffer() + { + // Are we just using shared input buffer? + if (_inputStart >= 0) { + return _inputBuffer; + } + if (_resultArray != null) { + return _resultArray; + } + if (_resultString != null) { + return (_resultArray = _resultString.toCharArray()); + } + // Nope; but does it fit in just one segment? + if (!_hasSegments) { + return _currentSegment; + } + // Nope, need to have/create a non-segmented array and return it + return contentsAsArray(); + } + + /* + /********************************************************** + /* Other accessors: + /********************************************************** + */ + + public String contentsAsString() + { + if (_resultString == null) { + // Has array been requested? Can make a shortcut, if so: + if (_resultArray != null) { + _resultString = new String(_resultArray); + } else { + // Do we use shared array? + if (_inputStart >= 0) { + if (_inputLen < 1) { + return (_resultString = ""); + } + _resultString = new String(_inputBuffer, _inputStart, _inputLen); + } else { // nope... need to copy + // But first, let's see if we have just one buffer + int segLen = _segmentSize; + int currLen = _currentSize; + + if (segLen == 0) { // yup + _resultString = (currLen == 0) ? "" : new String(_currentSegment, 0, currLen); + } else { // no, need to combine + StringBuilder sb = new StringBuilder(segLen + currLen); + // First stored segments + if (_segments != null) { + for (int i = 0, len = _segments.size(); i < len; ++i) { + char[] curr = _segments.get(i); + sb.append(curr, 0, curr.length); + } + } + // And finally, current segment: + sb.append(_currentSegment, 0, _currentSize); + _resultString = sb.toString(); + } + } + } + } + return _resultString; + } + + public char[] contentsAsArray() + { + char[] result = _resultArray; + if (result == null) { + _resultArray = result = buildResultArray(); + } + return result; + } + + /** + * Convenience method for converting contents of the buffer + * into a {@link BigDecimal}. + */ + public BigDecimal contentsAsDecimal() + throws NumberFormatException + { + // Already got a pre-cut array? + if (_resultArray != null) { + return new BigDecimal(_resultArray); + } + // Or a shared buffer? + if (_inputStart >= 0) { + return new BigDecimal(_inputBuffer, _inputStart, _inputLen); + } + // Or if not, just a single buffer (the usual case) + if (_segmentSize == 0) { + return new BigDecimal(_currentSegment, 0, _currentSize); + } + // If not, let's just get it aggregated... + return new BigDecimal(contentsAsArray()); + } + + /** + * Convenience method for converting contents of the buffer + * into a Double value. + */ + public double contentsAsDouble() + throws NumberFormatException + { + return NumberInput.parseDouble(contentsAsString()); + } + + /* + /********************************************************** + /* Public mutators: + /********************************************************** + */ + + /** + * Method called to make sure that buffer is not using shared input + * buffer; if it is, it will copy such contents to private buffer. + */ + public void ensureNotShared() { + if (_inputStart >= 0) { + unshare(16); + } + } + + public void append(char c) { + // Using shared buffer so far? + if (_inputStart >= 0) { + unshare(16); + } + _resultString = null; + _resultArray = null; + // Room in current segment? + char[] curr = _currentSegment; + if (_currentSize >= curr.length) { + expand(1); + curr = _currentSegment; + } + curr[_currentSize++] = c; + } + + public void append(char[] c, int start, int len) + { + // Can't append to shared buf (sanity check) + if (_inputStart >= 0) { + unshare(len); + } + _resultString = null; + _resultArray = null; + + // Room in current segment? + char[] curr = _currentSegment; + int max = curr.length - _currentSize; + + if (max >= len) { + System.arraycopy(c, start, curr, _currentSize, len); + _currentSize += len; + return; + } + // No room for all, need to copy part(s): + if (max > 0) { + System.arraycopy(c, start, curr, _currentSize, max); + start += max; + len -= max; + } + /* And then allocate new segment; we are guaranteed to now + * have enough room in segment. + */ + // Except, as per [Issue-24], not for HUGE appends... so: + do { + expand(len); + int amount = Math.min(_currentSegment.length, len); + System.arraycopy(c, start, _currentSegment, 0, amount); + _currentSize += amount; + start += amount; + len -= amount; + } while (len > 0); + } + + public void append(String str, int offset, int len) + { + // Can't append to shared buf (sanity check) + if (_inputStart >= 0) { + unshare(len); + } + _resultString = null; + _resultArray = null; + + // Room in current segment? + char[] curr = _currentSegment; + int max = curr.length - _currentSize; + if (max >= len) { + str.getChars(offset, offset+len, curr, _currentSize); + _currentSize += len; + return; + } + // No room for all, need to copy part(s): + if (max > 0) { + str.getChars(offset, offset+max, curr, _currentSize); + len -= max; + offset += max; + } + /* And then allocate new segment; we are guaranteed to now + * have enough room in segment. + */ + // Except, as per [Issue-24], not for HUGE appends... so: + do { + expand(len); + int amount = Math.min(_currentSegment.length, len); + str.getChars(offset, offset+amount, _currentSegment, 0); + _currentSize += amount; + offset += amount; + len -= amount; + } while (len > 0); + } + + /* + /********************************************************** + /* Raw access, for high-performance use: + /********************************************************** + */ + + public char[] getCurrentSegment() + { + /* Since the intention of the caller is to directly add stuff into + * buffers, we should NOT have anything in shared buffer... ie. may + * need to unshare contents. + */ + if (_inputStart >= 0) { + unshare(1); + } else { + char[] curr = _currentSegment; + if (curr == null) { + _currentSegment = findBuffer(0); + } else if (_currentSize >= curr.length) { + // Plus, we better have room for at least one more char + expand(1); + } + } + return _currentSegment; + } + + public final char[] emptyAndGetCurrentSegment() + { + // inlined 'resetWithEmpty()' + _inputStart = -1; // indicates shared buffer not used + _currentSize = 0; + _inputLen = 0; + + _inputBuffer = null; + _resultString = null; + _resultArray = null; + + // And then reset internal input buffers, if necessary: + if (_hasSegments) { + clearSegments(); + } + char[] curr = _currentSegment; + if (curr == null) { + _currentSegment = curr = findBuffer(0); + } + return curr; + } + + public int getCurrentSegmentSize() { + return _currentSize; + } + + public void setCurrentLength(int len) { + _currentSize = len; + } + + public char[] finishCurrentSegment() + { + if (_segments == null) { + _segments = new ArrayList<char[]>(); + } + _hasSegments = true; + _segments.add(_currentSegment); + int oldLen = _currentSegment.length; + _segmentSize += oldLen; + // Let's grow segments by 50% + int newLen = Math.min(oldLen + (oldLen >> 1), MAX_SEGMENT_LEN); + char[] curr = _charArray(newLen); + _currentSize = 0; + _currentSegment = curr; + return curr; + } + + /** + * Method called to expand size of the current segment, to + * accomodate for more contiguous content. Usually only + * used when parsing tokens like names. + */ + public char[] expandCurrentSegment() + { + char[] curr = _currentSegment; + // Let's grow by 50% + int len = curr.length; + // Must grow by at least 1 char, no matter what + int newLen = (len == MAX_SEGMENT_LEN) ? + (MAX_SEGMENT_LEN + 1) : Math.min(MAX_SEGMENT_LEN, len + (len >> 1)); + _currentSegment = _charArray(newLen); + System.arraycopy(curr, 0, _currentSegment, 0, len); + return _currentSegment; + } + + /* + /********************************************************** + /* Standard methods: + /********************************************************** + */ + + /** + * Note: calling this method may not be as efficient as calling + * {@link #contentsAsString}, since it's not guaranteed that resulting + * String is cached. + */ + @Override + public String toString() { + return contentsAsString(); + } + + /* + /********************************************************** + /* Internal methods: + /********************************************************** + */ + + /** + * Method called if/when we need to append content when we have been + * initialized to use shared buffer. + */ + private void unshare(int needExtra) + { + int sharedLen = _inputLen; + _inputLen = 0; + char[] inputBuf = _inputBuffer; + _inputBuffer = null; + int start = _inputStart; + _inputStart = -1; + + // Is buffer big enough, or do we need to reallocate? + int needed = sharedLen+needExtra; + if (_currentSegment == null || needed > _currentSegment.length) { + _currentSegment = findBuffer(needed); + } + if (sharedLen > 0) { + System.arraycopy(inputBuf, start, _currentSegment, 0, sharedLen); + } + _segmentSize = 0; + _currentSize = sharedLen; + } + + /** + * Method called when current segment is full, to allocate new + * segment. + */ + private void expand(int minNewSegmentSize) + { + // First, let's move current segment to segment list: + if (_segments == null) { + _segments = new ArrayList<char[]>(); + } + char[] curr = _currentSegment; + _hasSegments = true; + _segments.add(curr); + _segmentSize += curr.length; + int oldLen = curr.length; + // Let's grow segments by 50% minimum + int sizeAddition = oldLen >> 1; + if (sizeAddition < minNewSegmentSize) { + sizeAddition = minNewSegmentSize; + } + curr = _charArray(Math.min(MAX_SEGMENT_LEN, oldLen + sizeAddition)); + _currentSize = 0; + _currentSegment = curr; + } + + private char[] buildResultArray() + { + if (_resultString != null) { // Can take a shortcut... + return _resultString.toCharArray(); + } + char[] result; + + // Do we use shared array? + if (_inputStart >= 0) { + if (_inputLen < 1) { + return NO_CHARS; + } + result = _charArray(_inputLen); + System.arraycopy(_inputBuffer, _inputStart, result, 0, + _inputLen); + } else { // nope + int size = size(); + if (size < 1) { + return NO_CHARS; + } + int offset = 0; + result = _charArray(size); + if (_segments != null) { + for (int i = 0, len = _segments.size(); i < len; ++i) { + char[] curr = (char[]) _segments.get(i); + int currLen = curr.length; + System.arraycopy(curr, 0, result, offset, currLen); + offset += currLen; + } + } + System.arraycopy(_currentSegment, 0, result, offset, _currentSize); + } + return result; + } + + private final char[] _charArray(int len) { + return new char[len]; + } +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/util/TokenBuffer.java b/1.9.10/src/java/org/codehaus/jackson/util/TokenBuffer.java new file mode 100644 index 0000000..6aa2356 --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/util/TokenBuffer.java
@@ -0,0 +1,1221 @@ +package org.codehaus.jackson.util; + +import java.io.IOException; +import java.math.BigDecimal; +import java.math.BigInteger; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.impl.JsonParserMinimalBase; +import org.codehaus.jackson.impl.JsonReadContext; +import org.codehaus.jackson.impl.JsonWriteContext; +import org.codehaus.jackson.io.SerializedString; + +/** + * Utility class used for efficient storage of {@link JsonToken} + * sequences, needed for temporary buffering. + * Space efficient for different sequence lengths (especially so for smaller + * ones; but not significantly less efficient for larger), highly efficient + * for linear iteration and appending. Implemented as segmented/chunked + * linked list of tokens; only modifications are via appends. + * + * @since 1.5 + */ +public class TokenBuffer +/* Won't use JsonGeneratorBase, to minimize overhead for validity + * checking + */ + extends JsonGenerator +{ + protected final static int DEFAULT_PARSER_FEATURES = JsonParser.Feature.collectDefaults(); + + /* + /********************************************************** + /* Configuration + /********************************************************** + */ + + /** + * Object codec to use for stream-based object + * conversion through parser/generator interfaces. If null, + * such methods can not be used. + */ + protected ObjectCodec _objectCodec; + + /** + * Bit flag composed of bits that indicate which + * {@link org.codehaus.jackson.JsonGenerator.Feature}s + * are enabled. + *<p> + * NOTE: most features have no effect on this class + */ + protected int _generatorFeatures; + + protected boolean _closed; + + /* + /********************************************************** + /* Token buffering state + /********************************************************** + */ + + /** + * First segment, for contents this buffer has + */ + protected Segment _first; + + /** + * Last segment of this buffer, one that is used + * for appending more tokens + */ + protected Segment _last; + + /** + * Offset within last segment, + */ + protected int _appendOffset; + + /* + /********************************************************** + /* Output state + /********************************************************** + */ + + protected JsonWriteContext _writeContext; + + /* + /********************************************************** + /* Life-cycle + /********************************************************** + */ + + /** + * @param codec Object codec to use for stream-based object + * conversion through parser/generator interfaces. If null, + * such methods can not be used. + */ + public TokenBuffer(ObjectCodec codec) + { + _objectCodec = codec; + _generatorFeatures = DEFAULT_PARSER_FEATURES; + _writeContext = JsonWriteContext.createRootContext(); + // at first we have just one segment + _first = _last = new Segment(); + _appendOffset = 0; + } + + /** + * Method used to create a {@link JsonParser} that can read contents + * stored in this buffer. Will use default <code>_objectCodec</code> for + * object conversions. + *<p> + * Note: instances are not synchronized, that is, they are not thread-safe + * if there are concurrent appends to the underlying buffer. + * + * @return Parser that can be used for reading contents stored in this buffer + */ + public JsonParser asParser() + { + return asParser(_objectCodec); + } + + /** + * Method used to create a {@link JsonParser} that can read contents + * stored in this buffer. + *<p> + * Note: instances are not synchronized, that is, they are not thread-safe + * if there are concurrent appends to the underlying buffer. + * + * @param codec Object codec to use for stream-based object + * conversion through parser/generator interfaces. If null, + * such methods can not be used. + * + * @return Parser that can be used for reading contents stored in this buffer + */ + public JsonParser asParser(ObjectCodec codec) + { + return new Parser(_first, codec); + } + + /** + * @param src Parser to use for accessing source information + * like location, configured codec + */ + public JsonParser asParser(JsonParser src) + { + Parser p = new Parser(_first, src.getCodec()); + p.setLocation(src.getTokenLocation()); + return p; + } + + /* + /********************************************************** + /* Other custom methods not needed for implementing interfaces + /********************************************************** + */ + + /** + * Helper method that will write all contents of this buffer + * using given {@link JsonGenerator}. + *<p> + * Note: this method would be enough to implement + * <code>JsonSerializer</code> for <code>TokenBuffer</code> type; + * but we can not have upwards + * references (from core to mapper package); and as such we also + * can not take second argument. + */ + public void serialize(JsonGenerator jgen) + throws IOException, JsonGenerationException + { + Segment segment = _first; + int ptr = -1; + + while (true) { + if (++ptr >= Segment.TOKENS_PER_SEGMENT) { + ptr = 0; + segment = segment.next(); + if (segment == null) break; + } + JsonToken t = segment.type(ptr); + if (t == null) break; + + // Note: copied from 'copyCurrentEvent'... + switch (t) { + case START_OBJECT: + jgen.writeStartObject(); + break; + case END_OBJECT: + jgen.writeEndObject(); + break; + case START_ARRAY: + jgen.writeStartArray(); + break; + case END_ARRAY: + jgen.writeEndArray(); + break; + case FIELD_NAME: + { + // 13-Dec-2010, tatu: Maybe we should start using different type tokens to reduce casting? + Object ob = segment.get(ptr); + if (ob instanceof SerializableString) { + jgen.writeFieldName((SerializableString) ob); + } else { + jgen.writeFieldName((String) ob); + } + } + break; + case VALUE_STRING: + { + Object ob = segment.get(ptr); + if (ob instanceof SerializableString) { + jgen.writeString((SerializableString) ob); + } else { + jgen.writeString((String) ob); + } + } + break; + case VALUE_NUMBER_INT: + { + Number n = (Number) segment.get(ptr); + if (n instanceof BigInteger) { + jgen.writeNumber((BigInteger) n); + } else if (n instanceof Long) { + jgen.writeNumber(n.longValue()); + } else { + jgen.writeNumber(n.intValue()); + } + } + break; + case VALUE_NUMBER_FLOAT: + { + Object n = segment.get(ptr); + if (n instanceof BigDecimal) { + jgen.writeNumber((BigDecimal) n); + } else if (n instanceof Float) { + jgen.writeNumber(((Float) n).floatValue()); + } else if (n instanceof Double) { + jgen.writeNumber(((Double) n).doubleValue()); + } else if (n == null) { + jgen.writeNull(); + } else if (n instanceof String) { + jgen.writeNumber((String) n); + } else { + throw new JsonGenerationException("Unrecognized value type for VALUE_NUMBER_FLOAT: "+n.getClass().getName()+", can not serialize"); + } + } + break; + case VALUE_TRUE: + jgen.writeBoolean(true); + break; + case VALUE_FALSE: + jgen.writeBoolean(false); + break; + case VALUE_NULL: + jgen.writeNull(); + break; + case VALUE_EMBEDDED_OBJECT: + jgen.writeObject(segment.get(ptr)); + break; + default: + throw new RuntimeException("Internal error: should never end up through this code path"); + } + } + } + + @Override + public String toString() + { + // Let's print up to 100 first tokens... + final int MAX_COUNT = 100; + + StringBuilder sb = new StringBuilder(); + sb.append("[TokenBuffer: "); + JsonParser jp = asParser(); + int count = 0; + + while (true) { + JsonToken t; + try { + t = jp.nextToken(); + } catch (IOException ioe) { // should never occur + throw new IllegalStateException(ioe); + } + if (t == null) break; + if (count < MAX_COUNT) { + if (count > 0) { + sb.append(", "); + } + sb.append(t.toString()); + } + ++count; + } + + if (count >= MAX_COUNT) { + sb.append(" ... (truncated ").append(count-MAX_COUNT).append(" entries)"); + } + sb.append(']'); + return sb.toString(); + } + + /* + /********************************************************** + /* JsonGenerator implementation: configuration + /********************************************************** + */ + + @Override + public JsonGenerator enable(Feature f) { + _generatorFeatures |= f.getMask(); + return this; + } + + @Override + public JsonGenerator disable(Feature f) { + _generatorFeatures &= ~f.getMask(); + return this; + } + + //public JsonGenerator configure(Feature f, boolean state) { } + + @Override + public boolean isEnabled(Feature f) { + return (_generatorFeatures & f.getMask()) != 0; + } + + @Override + public JsonGenerator useDefaultPrettyPrinter() { + // No-op: we don't indent + return this; + } + + @Override + public JsonGenerator setCodec(ObjectCodec oc) { + _objectCodec = oc; + return this; + } + + @Override + public ObjectCodec getCodec() { return _objectCodec; } + + @Override + public final JsonWriteContext getOutputContext() { return _writeContext; } + + /* + /********************************************************** + /* JsonGenerator implementation: low-level output handling + /********************************************************** + */ + + @Override + public void flush() throws IOException { /* NOP */ } + + @Override + public void close() throws IOException { + _closed = true; + } + + @Override + public boolean isClosed() { return _closed; } + + /* + /********************************************************** + /* JsonGenerator implementation: write methods, structural + /********************************************************** + */ + + @Override + public final void writeStartArray() + throws IOException, JsonGenerationException + { + _append(JsonToken.START_ARRAY); + _writeContext = _writeContext.createChildArrayContext(); + } + + @Override + public final void writeEndArray() + throws IOException, JsonGenerationException + { + _append(JsonToken.END_ARRAY); + // Let's allow unbalanced tho... i.e. not run out of root level, ever + JsonWriteContext c = _writeContext.getParent(); + if (c != null) { + _writeContext = c; + } + } + + @Override + public final void writeStartObject() + throws IOException, JsonGenerationException + { + _append(JsonToken.START_OBJECT); + _writeContext = _writeContext.createChildObjectContext(); + } + + @Override + public final void writeEndObject() + throws IOException, JsonGenerationException + { + _append(JsonToken.END_OBJECT); + // Let's allow unbalanced tho... i.e. not run out of root level, ever + JsonWriteContext c = _writeContext.getParent(); + if (c != null) { + _writeContext = c; + } + } + + @Override + public final void writeFieldName(String name) + throws IOException, JsonGenerationException + { + _append(JsonToken.FIELD_NAME, name); + _writeContext.writeFieldName(name); + } + + @Override + public void writeFieldName(SerializableString name) + throws IOException, JsonGenerationException + { + _append(JsonToken.FIELD_NAME, name); + _writeContext.writeFieldName(name.getValue()); + } + + @Override + public void writeFieldName(SerializedString name) + throws IOException, JsonGenerationException + { + _append(JsonToken.FIELD_NAME, name); + _writeContext.writeFieldName(name.getValue()); + } + + /* + /********************************************************** + /* JsonGenerator implementation: write methods, textual + /********************************************************** + */ + + @Override + public void writeString(String text) throws IOException,JsonGenerationException { + if (text == null) { + writeNull(); + } else { + _append(JsonToken.VALUE_STRING, text); + } + } + + @Override + public void writeString(char[] text, int offset, int len) throws IOException, JsonGenerationException { + writeString(new String(text, offset, len)); + } + + @Override + public void writeString(SerializableString text) throws IOException, JsonGenerationException { + if (text == null) { + writeNull(); + } else { + _append(JsonToken.VALUE_STRING, text); + } + } + + @Override + public void writeRawUTF8String(byte[] text, int offset, int length) + throws IOException, JsonGenerationException + { + // could add support for buffering if we really want it... + _reportUnsupportedOperation(); + } + + @Override + public void writeUTF8String(byte[] text, int offset, int length) + throws IOException, JsonGenerationException + { + // could add support for buffering if we really want it... + _reportUnsupportedOperation(); + } + + @Override + public void writeRaw(String text) throws IOException, JsonGenerationException { + _reportUnsupportedOperation(); + } + + @Override + public void writeRaw(String text, int offset, int len) throws IOException, JsonGenerationException { + _reportUnsupportedOperation(); + } + + @Override + public void writeRaw(char[] text, int offset, int len) throws IOException, JsonGenerationException { + _reportUnsupportedOperation(); + } + + @Override + public void writeRaw(char c) throws IOException, JsonGenerationException { + _reportUnsupportedOperation(); + } + + @Override + public void writeRawValue(String text) throws IOException, JsonGenerationException { + _reportUnsupportedOperation(); + } + + @Override + public void writeRawValue(String text, int offset, int len) throws IOException, JsonGenerationException { + _reportUnsupportedOperation(); + } + + @Override + public void writeRawValue(char[] text, int offset, int len) throws IOException, JsonGenerationException { + _reportUnsupportedOperation(); + } + + /* + /********************************************************** + /* JsonGenerator implementation: write methods, primitive types + /********************************************************** + */ + + @Override + public void writeNumber(int i) throws IOException, JsonGenerationException { + _append(JsonToken.VALUE_NUMBER_INT, Integer.valueOf(i)); + } + + @Override + public void writeNumber(long l) throws IOException, JsonGenerationException { + _append(JsonToken.VALUE_NUMBER_INT, Long.valueOf(l)); + } + + @Override + public void writeNumber(double d) throws IOException,JsonGenerationException { + _append(JsonToken.VALUE_NUMBER_FLOAT, Double.valueOf(d)); + } + + @Override + public void writeNumber(float f) throws IOException, JsonGenerationException { + _append(JsonToken.VALUE_NUMBER_FLOAT, Float.valueOf(f)); + } + + @Override + public void writeNumber(BigDecimal dec) throws IOException,JsonGenerationException { + if (dec == null) { + writeNull(); + } else { + _append(JsonToken.VALUE_NUMBER_FLOAT, dec); + } + } + + @Override + public void writeNumber(BigInteger v) throws IOException, JsonGenerationException { + if (v == null) { + writeNull(); + } else { + _append(JsonToken.VALUE_NUMBER_INT, v); + } + } + + @Override + public void writeNumber(String encodedValue) throws IOException, JsonGenerationException { + /* 03-Dec-2010, tatu: related to [JACKSON-423], should try to keep as numeric + * identity as long as possible + */ + _append(JsonToken.VALUE_NUMBER_FLOAT, encodedValue); + } + + @Override + public void writeBoolean(boolean state) throws IOException,JsonGenerationException { + _append(state ? JsonToken.VALUE_TRUE : JsonToken.VALUE_FALSE); + } + + @Override + public void writeNull() throws IOException, JsonGenerationException { + _append(JsonToken.VALUE_NULL); + } + + /* + /*********************************************************** + /* JsonGenerator implementation: write methods for POJOs/trees + /*********************************************************** + */ + + @Override + public void writeObject(Object value) + throws IOException, JsonProcessingException + { + // embedded means that no conversions should be done... + _append(JsonToken.VALUE_EMBEDDED_OBJECT, value); + } + + @Override + public void writeTree(JsonNode rootNode) + throws IOException, JsonProcessingException + { + /* 31-Dec-2009, tatu: no need to convert trees either is there? + * (note: may need to re-evaluate at some point) + */ + _append(JsonToken.VALUE_EMBEDDED_OBJECT, rootNode); + } + + /* + /*********************************************************** + /* JsonGenerator implementation; binary + /*********************************************************** + */ + + @Override + public void writeBinary(Base64Variant b64variant, byte[] data, int offset, int len) + throws IOException, JsonGenerationException + { + /* 31-Dec-2009, tatu: can do this using multiple alternatives; but for + * now, let's try to limit number of conversions. + * The only (?) tricky thing is that of whether to preserve variant, + * seems pointless, so let's not worry about it unless there's some + * compelling reason to. + */ + byte[] copy = new byte[len]; + System.arraycopy(data, offset, copy, 0, len); + writeObject(copy); + } + + /* + /********************************************************** + /* JsonGenerator implementation; pass-through copy + /********************************************************** + */ + + @Override + public void copyCurrentEvent(JsonParser jp) throws IOException, JsonProcessingException + { + switch (jp.getCurrentToken()) { + case START_OBJECT: + writeStartObject(); + break; + case END_OBJECT: + writeEndObject(); + break; + case START_ARRAY: + writeStartArray(); + break; + case END_ARRAY: + writeEndArray(); + break; + case FIELD_NAME: + writeFieldName(jp.getCurrentName()); + break; + case VALUE_STRING: + if (jp.hasTextCharacters()) { + writeString(jp.getTextCharacters(), jp.getTextOffset(), jp.getTextLength()); + } else { + writeString(jp.getText()); + } + break; + case VALUE_NUMBER_INT: + switch (jp.getNumberType()) { + case INT: + writeNumber(jp.getIntValue()); + break; + case BIG_INTEGER: + writeNumber(jp.getBigIntegerValue()); + break; + default: + writeNumber(jp.getLongValue()); + } + break; + case VALUE_NUMBER_FLOAT: + switch (jp.getNumberType()) { + case BIG_DECIMAL: + writeNumber(jp.getDecimalValue()); + break; + case FLOAT: + writeNumber(jp.getFloatValue()); + break; + default: + writeNumber(jp.getDoubleValue()); + } + break; + case VALUE_TRUE: + writeBoolean(true); + break; + case VALUE_FALSE: + writeBoolean(false); + break; + case VALUE_NULL: + writeNull(); + break; + case VALUE_EMBEDDED_OBJECT: + writeObject(jp.getEmbeddedObject()); + break; + default: + throw new RuntimeException("Internal error: should never end up through this code path"); + } + } + + @Override + public void copyCurrentStructure(JsonParser jp) throws IOException, JsonProcessingException { + JsonToken t = jp.getCurrentToken(); + + // Let's handle field-name separately first + if (t == JsonToken.FIELD_NAME) { + writeFieldName(jp.getCurrentName()); + t = jp.nextToken(); + // fall-through to copy the associated value + } + + switch (t) { + case START_ARRAY: + writeStartArray(); + while (jp.nextToken() != JsonToken.END_ARRAY) { + copyCurrentStructure(jp); + } + writeEndArray(); + break; + case START_OBJECT: + writeStartObject(); + while (jp.nextToken() != JsonToken.END_OBJECT) { + copyCurrentStructure(jp); + } + writeEndObject(); + break; + default: // others are simple: + copyCurrentEvent(jp); + } + } + + /* + /********************************************************** + /* Internal methods + /********************************************************** + */ + protected final void _append(JsonToken type) { + Segment next = _last.append(_appendOffset, type); + if (next == null) { + ++_appendOffset; + } else { + _last = next; + _appendOffset = 1; // since we added first at 0 + } + } + + protected final void _append(JsonToken type, Object value) { + Segment next = _last.append(_appendOffset, type, value); + if (next == null) { + ++_appendOffset; + } else { + _last = next; + _appendOffset = 1; + } + } + + protected void _reportUnsupportedOperation() { + throw new UnsupportedOperationException("Called operation not supported for TokenBuffer"); + } + + /* + /********************************************************** + /* Supporting classes + /********************************************************** + */ + + protected final static class Parser + extends JsonParserMinimalBase + { + protected ObjectCodec _codec; + + /* + /********************************************************** + /* Parsing state + /********************************************************** + */ + + /** + * Currently active segment + */ + protected Segment _segment; + + /** + * Pointer to current token within current segment + */ + protected int _segmentPtr; + + /** + * Information about parser context, context in which + * the next token is to be parsed (root, array, object). + */ + protected JsonReadContext _parsingContext; + + protected boolean _closed; + + protected transient ByteArrayBuilder _byteBuilder; + + protected JsonLocation _location = null; + + /* + /********************************************************** + /* Construction, init + /********************************************************** + */ + + public Parser(Segment firstSeg, ObjectCodec codec) + { + super(0); + _segment = firstSeg; + _segmentPtr = -1; // not yet read + _codec = codec; + _parsingContext = JsonReadContext.createRootContext(-1, -1); + } + + public void setLocation(JsonLocation l) { + _location = l; + } + + @Override + public ObjectCodec getCodec() { return _codec; } + + @Override + public void setCodec(ObjectCodec c) { _codec = c; } + + /* + /********************************************************** + /* Extended API beyond JsonParser + /********************************************************** + */ + + public JsonToken peekNextToken() + throws IOException, JsonParseException + { + // closed? nothing more to peek, either + if (_closed) return null; + Segment seg = _segment; + int ptr = _segmentPtr+1; + if (ptr >= Segment.TOKENS_PER_SEGMENT) { + ptr = 0; + seg = (seg == null) ? null : seg.next(); + } + return (seg == null) ? null : seg.type(ptr); + } + + /* + /********************************************************** + /* Closeable implementation + /********************************************************** + */ + + @Override + public void close() throws IOException { + if (!_closed) { + _closed = true; + } + } + + /* + /********************************************************** + /* Public API, traversal + /********************************************************** + */ + + @Override + public JsonToken nextToken() throws IOException, JsonParseException + { + // If we are closed, nothing more to do + if (_closed || (_segment == null)) return null; + + // Ok, then: any more tokens? + if (++_segmentPtr >= Segment.TOKENS_PER_SEGMENT) { + _segmentPtr = 0; + _segment = _segment.next(); + if (_segment == null) { + return null; + } + } + _currToken = _segment.type(_segmentPtr); + // Field name? Need to update context + if (_currToken == JsonToken.FIELD_NAME) { + Object ob = _currentObject(); + String name = (ob instanceof String) ? ((String) ob) : ob.toString(); + _parsingContext.setCurrentName(name); + } else if (_currToken == JsonToken.START_OBJECT) { + _parsingContext = _parsingContext.createChildObjectContext(-1, -1); + } else if (_currToken == JsonToken.START_ARRAY) { + _parsingContext = _parsingContext.createChildArrayContext(-1, -1); + } else if (_currToken == JsonToken.END_OBJECT + || _currToken == JsonToken.END_ARRAY) { + // Closing JSON Object/Array? Close matching context + _parsingContext = _parsingContext.getParent(); + // but allow unbalanced cases too (more close markers) + if (_parsingContext == null) { + _parsingContext = JsonReadContext.createRootContext(-1, -1); + } + } + return _currToken; + } + + @Override + public boolean isClosed() { return _closed; } + + /* + /********************************************************** + /* Public API, token accessors + /********************************************************** + */ + + @Override + public JsonStreamContext getParsingContext() { return _parsingContext; } + + @Override + public JsonLocation getTokenLocation() { return getCurrentLocation(); } + + @Override + public JsonLocation getCurrentLocation() { + return (_location == null) ? JsonLocation.NA : _location; + } + + @Override + public String getCurrentName() { return _parsingContext.getCurrentName(); } + + /* + /********************************************************** + /* Public API, access to token information, text + /********************************************************** + */ + + @Override + public String getText() + { + // common cases first: + if (_currToken == JsonToken.VALUE_STRING + || _currToken == JsonToken.FIELD_NAME) { + Object ob = _currentObject(); + if (ob instanceof String) { + return (String) ob; + } + return (ob == null) ? null : ob.toString(); + } + if (_currToken == null) { + return null; + } + switch (_currToken) { + case VALUE_NUMBER_INT: + case VALUE_NUMBER_FLOAT: + Object ob = _currentObject(); + return (ob == null) ? null : ob.toString(); + } + return _currToken.asString(); + } + + @Override + public char[] getTextCharacters() { + String str = getText(); + return (str == null) ? null : str.toCharArray(); + } + + @Override + public int getTextLength() { + String str = getText(); + return (str == null) ? 0 : str.length(); + } + + @Override + public int getTextOffset() { return 0; } + + @Override + public boolean hasTextCharacters() { + // We never have raw buffer available, so: + return false; + } + + /* + /********************************************************** + /* Public API, access to token information, numeric + /********************************************************** + */ + + @Override + public BigInteger getBigIntegerValue() throws IOException, JsonParseException + { + Number n = getNumberValue(); + if (n instanceof BigInteger) { + return (BigInteger) n; + } + switch (getNumberType()) { + case BIG_DECIMAL: + return ((BigDecimal) n).toBigInteger(); + } + // int/long is simple, but let's also just truncate float/double: + return BigInteger.valueOf(n.longValue()); + } + + @Override + public BigDecimal getDecimalValue() throws IOException, JsonParseException + { + Number n = getNumberValue(); + if (n instanceof BigDecimal) { + return (BigDecimal) n; + } + switch (getNumberType()) { + case INT: + case LONG: + return BigDecimal.valueOf(n.longValue()); + case BIG_INTEGER: + return new BigDecimal((BigInteger) n); + } + // float or double + return BigDecimal.valueOf(n.doubleValue()); + } + + @Override + public double getDoubleValue() throws IOException, JsonParseException { + return getNumberValue().doubleValue(); + } + + @Override + public float getFloatValue() throws IOException, JsonParseException { + return getNumberValue().floatValue(); + } + + @Override + public int getIntValue() throws IOException, JsonParseException + { + // optimize common case: + if (_currToken == JsonToken.VALUE_NUMBER_INT) { + return ((Number) _currentObject()).intValue(); + } + return getNumberValue().intValue(); + } + + @Override + public long getLongValue() throws IOException, JsonParseException { + return getNumberValue().longValue(); + } + + @Override + public NumberType getNumberType() throws IOException, JsonParseException + { + Number n = getNumberValue(); + if (n instanceof Integer) return NumberType.INT; + if (n instanceof Long) return NumberType.LONG; + if (n instanceof Double) return NumberType.DOUBLE; + if (n instanceof BigDecimal) return NumberType.BIG_DECIMAL; + if (n instanceof Float) return NumberType.FLOAT; + if (n instanceof BigInteger) return NumberType.BIG_INTEGER; + return null; + } + + @Override + public final Number getNumberValue() throws IOException, JsonParseException { + _checkIsNumber(); + return (Number) _currentObject(); + } + + /* + /********************************************************** + /* Public API, access to token information, other + /********************************************************** + */ + + @Override + public Object getEmbeddedObject() + { + if (_currToken == JsonToken.VALUE_EMBEDDED_OBJECT) { + return _currentObject(); + } + return null; + } + + @Override + public byte[] getBinaryValue(Base64Variant b64variant) throws IOException, JsonParseException + { + // First: maybe we some special types? + if (_currToken == JsonToken.VALUE_EMBEDDED_OBJECT) { + // Embedded byte array would work nicely... + Object ob = _currentObject(); + if (ob instanceof byte[]) { + return (byte[]) ob; + } + // fall through to error case + } + if (_currToken != JsonToken.VALUE_STRING) { + throw _constructError("Current token ("+_currToken+") not VALUE_STRING (or VALUE_EMBEDDED_OBJECT with byte[]), can not access as binary"); + } + final String str = getText(); + if (str == null) { + return null; + } + ByteArrayBuilder builder = _byteBuilder; + if (builder == null) { + _byteBuilder = builder = new ByteArrayBuilder(100); + } else { + _byteBuilder.reset(); + } + _decodeBase64(str, builder, b64variant); + return builder.toByteArray(); + } + + /* + /********************************************************** + /* Internal methods + /********************************************************** + */ + + protected final Object _currentObject() { + return _segment.get(_segmentPtr); + } + + protected final void _checkIsNumber() throws JsonParseException + { + if (_currToken == null || !_currToken.isNumeric()) { + throw _constructError("Current token ("+_currToken+") not numeric, can not use numeric value accessors"); + } + } + + @Override + protected void _handleEOF() throws JsonParseException { + _throwInternal(); + } + } + + /** + * Individual segment of TokenBuffer that can store up to 16 tokens + * (limited by 4 bits per token type marker requirement). + * Current implementation uses fixed length array; could alternatively + * use 16 distinct fields and switch statement (slightly more efficient + * storage, slightly slower access) + */ + protected final static class Segment + { + public final static int TOKENS_PER_SEGMENT = 16; + + /** + * Static array used for fast conversion between token markers and + * matching {@link JsonToken} instances + */ + private final static JsonToken[] TOKEN_TYPES_BY_INDEX; + static { + // ... here we know that there are <= 16 values in JsonToken enum + TOKEN_TYPES_BY_INDEX = new JsonToken[16]; + JsonToken[] t = JsonToken.values(); + System.arraycopy(t, 1, TOKEN_TYPES_BY_INDEX, 1, Math.min(15, t.length - 1)); + } + + // // // Linking + + protected Segment _next; + + // // // State + + /** + * Bit field used to store types of buffered tokens; 4 bits per token. + * Value 0 is reserved for "not in use" + */ + protected long _tokenTypes; + + + // Actual tokens + + protected final Object[] _tokens = new Object[TOKENS_PER_SEGMENT]; + + public Segment() { } + + // // // Accessors + + public JsonToken type(int index) + { + long l = _tokenTypes; + if (index > 0) { + l >>= (index << 2); + } + int ix = ((int) l) & 0xF; + return TOKEN_TYPES_BY_INDEX[ix]; + } + + public Object get(int index) { + return _tokens[index]; + } + + public Segment next() { return _next; } + + // // // Mutators + + public Segment append(int index, JsonToken tokenType) + { + if (index < TOKENS_PER_SEGMENT) { + set(index, tokenType); + return null; + } + _next = new Segment(); + _next.set(0, tokenType); + return _next; + } + + public Segment append(int index, JsonToken tokenType, Object value) + { + if (index < TOKENS_PER_SEGMENT) { + set(index, tokenType, value); + return null; + } + _next = new Segment(); + _next.set(0, tokenType, value); + return _next; + } + + public void set(int index, JsonToken tokenType) + { + long typeCode = tokenType.ordinal(); + /* Assumption here is that there are no overwrites, just appends; + * and so no masking is needed + */ + if (index > 0) { + typeCode <<= (index << 2); + } + _tokenTypes |= typeCode; + } + + public void set(int index, JsonToken tokenType, Object value) + { + _tokens[index] = value; + long typeCode = tokenType.ordinal(); + /* Assumption here is that there are no overwrites, just appends; + * and so no masking is needed + */ + if (index > 0) { + typeCode <<= (index << 2); + } + _tokenTypes |= typeCode; + } + } +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/util/VersionUtil.java b/1.9.10/src/java/org/codehaus/jackson/util/VersionUtil.java new file mode 100644 index 0000000..ec663eb --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/util/VersionUtil.java
@@ -0,0 +1,79 @@ +package org.codehaus.jackson.util; + +import java.io.*; +import java.util.regex.Pattern; + +import org.codehaus.jackson.Version; + +/** + * Functionality for supporting exposing of component {@link Version}s. + * + * @since 1.6 + */ +public class VersionUtil +{ + public final static String VERSION_FILE = "VERSION.txt"; + + private final static Pattern VERSION_SEPARATOR = Pattern.compile("[-_./;:]"); + + /** + * Helper method that will try to load version information for specified + * class. Implementation is simple: class loader that loaded specified + * class is asked to load resource with name "VERSION" from same + * location (package) as class itself had. + * If no version information is found, {@link Version#unknownVersion()} is + * returned. + */ + public static Version versionFor(Class<?> cls) + { + InputStream in; + Version version = null; + + try { + in = cls.getResourceAsStream(VERSION_FILE); + if (in != null) { + try { + BufferedReader br = new BufferedReader(new InputStreamReader(in, "UTF-8")); + version = parseVersion(br.readLine()); + } finally { + try { + in.close(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + } + } catch (IOException e) { } + return (version == null) ? Version.unknownVersion() : version; + } + + public static Version parseVersion(String versionStr) + { + if (versionStr == null) return null; + versionStr = versionStr.trim(); + if (versionStr.length() == 0) return null; + String[] parts = VERSION_SEPARATOR.split(versionStr); + // Let's not bother if there's no separate parts; otherwise use whatever we got + if (parts.length < 2) { + return null; + } + int major = parseVersionPart(parts[0]); + int minor = parseVersionPart(parts[1]); + int patch = (parts.length > 2) ? parseVersionPart(parts[2]) : 0; + String snapshot = (parts.length > 3) ? parts[3] : null; + return new Version(major, minor, patch, snapshot); + } + + protected static int parseVersionPart(String partStr) + { + partStr = partStr.toString(); + int len = partStr.length(); + int number = 0; + for (int i = 0; i < len; ++i) { + char c = partStr.charAt(i); + if (c > '9' || c < '0') break; + number = (number * 10) + (c - '0'); + } + return number; + } +}
diff --git a/1.9.10/src/java/org/codehaus/jackson/util/package-info.java b/1.9.10/src/java/org/codehaus/jackson/util/package-info.java new file mode 100644 index 0000000..d45d988 --- /dev/null +++ b/1.9.10/src/java/org/codehaus/jackson/util/package-info.java
@@ -0,0 +1,4 @@ +/** + * Utility classes used by Jackson Core functionality. + */ +package org.codehaus.jackson.util;
diff --git a/1.9.10/src/jaxrs/java/org/codehaus/jackson/jaxrs/Annotations.java b/1.9.10/src/jaxrs/java/org/codehaus/jackson/jaxrs/Annotations.java new file mode 100644 index 0000000..79b2517 --- /dev/null +++ b/1.9.10/src/jaxrs/java/org/codehaus/jackson/jaxrs/Annotations.java
@@ -0,0 +1,21 @@ +package org.codehaus.jackson.jaxrs; + +/** + * Enumeration that defines standard annotation sets available for configuring + * data binding aspects. + */ +public enum Annotations { + /** + * Standard Jackson annotations, defined in Jackson core and mapper + * packages + */ + JACKSON, + + /** + * Standard JAXB annotations, used in a way that approximates expected + * definitions (since JAXB defines XML aspects, not all features map + * well to JSON handling) + */ + JAXB + ; +}
diff --git a/1.9.10/src/jaxrs/java/org/codehaus/jackson/jaxrs/JacksonJaxbJsonProvider.java b/1.9.10/src/jaxrs/java/org/codehaus/jackson/jaxrs/JacksonJaxbJsonProvider.java new file mode 100644 index 0000000..d6c1258 --- /dev/null +++ b/1.9.10/src/jaxrs/java/org/codehaus/jackson/jaxrs/JacksonJaxbJsonProvider.java
@@ -0,0 +1,66 @@ +package org.codehaus.jackson.jaxrs; + +import javax.ws.rs.Consumes; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.ext.Provider; + +import org.codehaus.jackson.map.ObjectMapper; + +/** + * JSON content type provider automatically configured to use both Jackson + * and JAXB annotations (in that order of priority). Otherwise functionally + * same as {@link JacksonJsonProvider}. + *<p> + * Typical usage pattern is to just instantiate instance of this + * provider for JAX-RS and use as is: this will use both Jackson and + * JAXB annotations (with Jackson annotations having priority). + *<p> + * Note: class annotations are duplicated from super class, since it + * is not clear whether JAX-RS implementations are required to + * check settings of super-classes. It is important to keep annotations + * in sync if changed. + * + * @since 1.3 + */ +@Provider +@Consumes({MediaType.APPLICATION_JSON, "text/json"}) +@Produces({MediaType.APPLICATION_JSON, "text/json"}) +public class JacksonJaxbJsonProvider extends JacksonJsonProvider { + /** + * Default annotation sets to use, if not explicitly defined during + * construction: use Jackson annotations if found; if not, use + * JAXB annotations as fallback. + */ + public final static Annotations[] DEFAULT_ANNOTATIONS = { + Annotations.JACKSON, Annotations.JAXB + }; + + /** + * Default constructor, usually used when provider is automatically + * configured to be used with JAX-RS implementation. + */ + public JacksonJaxbJsonProvider() + { + this(null, DEFAULT_ANNOTATIONS); + } + + /** + * @param annotationsToUse Annotation set(s) to use for configuring + * data binding + */ + public JacksonJaxbJsonProvider(Annotations... annotationsToUse) + { + this(null, annotationsToUse); + } + + /** + * Constructor to use when a custom mapper (usually components + * like serializer/deserializer factories that have been configured) + * is to be used. + */ + public JacksonJaxbJsonProvider(ObjectMapper mapper, Annotations[] annotationsToUse) + { + super(mapper, annotationsToUse); + } +}
diff --git a/1.9.10/src/jaxrs/java/org/codehaus/jackson/jaxrs/JacksonJsonProvider.java b/1.9.10/src/jaxrs/java/org/codehaus/jackson/jaxrs/JacksonJsonProvider.java new file mode 100644 index 0000000..2393838 --- /dev/null +++ b/1.9.10/src/jaxrs/java/org/codehaus/jackson/jaxrs/JacksonJsonProvider.java
@@ -0,0 +1,703 @@ +package org.codehaus.jackson.jaxrs; + +import java.io.*; +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; +import java.util.*; + +import javax.ws.rs.*; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.StreamingOutput; +import javax.ws.rs.ext.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.DeserializationConfig; +import org.codehaus.jackson.map.JsonMappingException; +import org.codehaus.jackson.map.ObjectMapper; +import org.codehaus.jackson.map.ObjectWriter; +import org.codehaus.jackson.map.SerializationConfig; +import org.codehaus.jackson.map.annotate.JsonView; +import org.codehaus.jackson.map.type.ClassKey; +import org.codehaus.jackson.map.util.ClassUtil; +import org.codehaus.jackson.map.util.JSONPObject; +import org.codehaus.jackson.type.JavaType; +import org.codehaus.jackson.util.VersionUtil; + +/** + * Basic implementation of JAX-RS abstractions ({@link MessageBodyReader}, + * {@link MessageBodyWriter}) needed for binding + * JSON ("application/json") content to and from Java Objects ("POJO"s). + *<p> + * Actual data binding functionality is implemented by {@link ObjectMapper}: + * mapper to use can be configured in multiple ways: + * <ul> + * <li>By explicitly passing mapper to use in constructor + * <li>By explictly setting mapper to use by {@link #setMapper} + * <li>By defining JAX-RS <code>Provider</code> that returns {@link ObjectMapper}s. + * <li>By doing none of above, in which case a default mapper instance is + * constructed (and configured if configuration methods are called) + * </ul> + * The last method ("do nothing specific") is often good enough; explicit passing + * of Mapper is simple and explicit; and Provider-based method may make sense + * with Depedency Injection frameworks, or if Mapper has to be configured differently + * for different media types. + *<p> + * Note that the default mapper instance will be automatically created if + * one of explicit configuration methods (like {@link #configure}) + * is called: if so, Provider-based introspection is <b>NOT</b> used, but the + * resulting Mapper is used as configured. + *<p> + * Note: version 1.3 added a sub-class ({@link JacksonJaxbJsonProvider}) which + * is configured by default to use both Jackson and JAXB annotations for configuration + * (base class when used as-is defaults to using just Jackson annotations) + * + * @author Tatu Saloranta + */ +@Provider +@Consumes({MediaType.APPLICATION_JSON, "text/json"}) +@Produces({MediaType.APPLICATION_JSON, "text/json"}) +public class JacksonJsonProvider + implements + MessageBodyReader<Object>, + MessageBodyWriter<Object>, + Versioned // since 1.6 +{ + /** + * Default annotation sets to use, if not explicitly defined during + * construction: only Jackson annotations are used for the base + * class. Sub-classes can use other settings. + */ + public final static Annotations[] BASIC_ANNOTATIONS = { + Annotations.JACKSON + }; + + /** + * Looks like we need to worry about accidental + * data binding for types we shouldn't be handling. This is + * probably not a very good way to do it, but let's start by + * blacklisting things we are not to handle. + *<p> + * (why ClassKey? since plain old Class has no hashCode() defined, + * lookups are painfully slow) + */ + public final static HashSet<ClassKey> _untouchables = new HashSet<ClassKey>(); + static { + // First, I/O things (direct matches) + _untouchables.add(new ClassKey(java.io.InputStream.class)); + _untouchables.add(new ClassKey(java.io.Reader.class)); + _untouchables.add(new ClassKey(java.io.OutputStream.class)); + _untouchables.add(new ClassKey(java.io.Writer.class)); + + // then some primitive types + _untouchables.add(new ClassKey(byte[].class)); + _untouchables.add(new ClassKey(char[].class)); + // 24-Apr-2009, tatu: String is an edge case... let's leave it out + _untouchables.add(new ClassKey(String.class)); + + // Then core JAX-RS things + _untouchables.add(new ClassKey(StreamingOutput.class)); + _untouchables.add(new ClassKey(Response.class)); + } + + /** + * These are classes that we never use for reading + * (never try to deserialize instances of these types). + */ + public final static Class<?>[] _unreadableClasses = new Class<?>[] { + InputStream.class, Reader.class + }; + + /** + * These are classes that we never use for writing + * (never try to serialize instances of these types). + */ + public final static Class<?>[] _unwritableClasses = new Class<?>[] { + OutputStream.class, Writer.class, + StreamingOutput.class, Response.class + }; + + /** + * Helper object used for encapsulating configuration aspects + * of {@link ObjectMapper} + */ + protected final MapperConfigurator _mapperConfig; + + /** + * Set of types (classes) that provider should ignore for data binding + * + * @since 1.5 + */ + protected HashSet<ClassKey> _cfgCustomUntouchables; + + /** + * JSONP function name to use for automatic JSONP wrapping, if any; + * if null, no JSONP wrapping is done. + */ + protected String _jsonpFunctionName; + + /* + /********************************************************** + /* Context configuration + /********************************************************** + */ + + /** + * Injectable context object used to locate configured + * instance of {@link ObjectMapper} to use for actual + * serialization. + */ + @Context + protected Providers _providers; + + /* + /********************************************************** + /* Configuration + /********************************************************** + */ + + /** + * Whether we want to actually check that Jackson has + * a serializer for given type. Since this should generally + * be the case (due to auto-discovery) and since the call + * to check availability can be bit expensive, defaults to false. + */ + protected boolean _cfgCheckCanSerialize = false; + + /** + * Whether we want to actually check that Jackson has + * a deserializer for given type. Since this should generally + * be the case (due to auto-discovery) and since the call + * to check availability can be bit expensive, defaults to false. + */ + protected boolean _cfgCheckCanDeserialize = false; + + /* + /********************************************************** + /* Construction + /********************************************************** + */ + + /** + * Default constructor, usually used when provider is automatically + * configured to be used with JAX-RS implementation. + */ + public JacksonJsonProvider() + { + this(null, BASIC_ANNOTATIONS); + } + + /** + * @param annotationsToUse Annotation set(s) to use for configuring + * data binding + */ + public JacksonJsonProvider(Annotations... annotationsToUse) + { + this(null, annotationsToUse); + } + + public JacksonJsonProvider(ObjectMapper mapper) + { + this(mapper, BASIC_ANNOTATIONS); + } + + /** + * Constructor to use when a custom mapper (usually components + * like serializer/deserializer factories that have been configured) + * is to be used. + * + * @annotationsToUse Sets of annotations (Jackson, JAXB) that provider should + * support + */ + public JacksonJsonProvider(ObjectMapper mapper, Annotations[] annotationsToUse) + { + _mapperConfig = new MapperConfigurator(mapper, annotationsToUse); + } + + /** + * Method that will return version information stored in and read from jar + * that contains this class. + * + * @since 1.6 + */ + @Override + public Version version() { + return VersionUtil.versionFor(getClass()); + } + + /* + /********************************************************** + /* Configuring + /********************************************************** + */ + + /** + * Method for defining whether actual detection for existence of + * a deserializer for type should be done when {@link #isReadable} + * is called. + */ + public void checkCanDeserialize(boolean state) { _cfgCheckCanDeserialize = state; } + + /** + * Method for defining whether actual detection for existence of + * a serializer for type should be done when {@link #isWriteable} + * is called. + */ + public void checkCanSerialize(boolean state) { _cfgCheckCanSerialize = state; } + + /** + * Method for configuring which annotation sets to use (including none). + * Annotation sets are defined in order decreasing precedence; that is, + * first one has the priority over following ones. + * + * @param annotationsToUse Ordered list of annotation sets to use; if null, + * default + */ + public void setAnnotationsToUse(Annotations[] annotationsToUse) { + _mapperConfig.setAnnotationsToUse(annotationsToUse); + } + + /** + * Method that can be used to directly define {@link ObjectMapper} to use + * for serialization and deserialization; if null, will use the standard + * provider discovery from context instead. Default setting is null. + */ + public void setMapper(ObjectMapper m) { + _mapperConfig.setMapper(m); + } + + public JacksonJsonProvider configure(DeserializationConfig.Feature f, boolean state) { + _mapperConfig.configure(f, state); + return this; + } + + public JacksonJsonProvider configure(SerializationConfig.Feature f, boolean state) { + _mapperConfig.configure(f, state); + return this; + } + + public JacksonJsonProvider configure(JsonParser.Feature f, boolean state) { + _mapperConfig.configure(f, state); + return this; + } + + public JacksonJsonProvider configure(JsonGenerator.Feature f, boolean state) { + _mapperConfig.configure(f, state); + return this; + } + + public JacksonJsonProvider enable(DeserializationConfig.Feature f, boolean state) { + _mapperConfig.configure(f, true); + return this; + } + + public JacksonJsonProvider enable(SerializationConfig.Feature f, boolean state) { + _mapperConfig.configure(f, true); + return this; + } + + public JacksonJsonProvider enable(JsonParser.Feature f, boolean state) { + _mapperConfig.configure(f, true); + return this; + } + + public JacksonJsonProvider enable(JsonGenerator.Feature f, boolean state) { + _mapperConfig.configure(f, true); + return this; + } + + public JacksonJsonProvider disable(DeserializationConfig.Feature f, boolean state) { + _mapperConfig.configure(f, false); + return this; + } + + public JacksonJsonProvider disable(SerializationConfig.Feature f, boolean state) { + _mapperConfig.configure(f, false); + return this; + } + + public JacksonJsonProvider disable(JsonParser.Feature f, boolean state) { + _mapperConfig.configure(f, false); + return this; + } + + public JacksonJsonProvider disable(JsonGenerator.Feature f, boolean state) { + _mapperConfig.configure(f, false); + return this; + } + + /** + * Method for marking specified type as "untouchable", meaning that provider + * will not try to read or write values of this type (or its subtypes). + * + * @param type Type to consider untouchable; can be any kind of class, + * including abstract class or interface. No instance of this type + * (including subtypes, i.e. types assignable to this type) will + * be read or written by provider + * + * @since 1.5 + */ + public void addUntouchable(Class<?> type) + { + if (_cfgCustomUntouchables == null) { + _cfgCustomUntouchables = new HashSet<ClassKey>(); + } + _cfgCustomUntouchables.add(new ClassKey(type)); + } + + public void setJSONPFunctionName(String fname) { + this._jsonpFunctionName = fname; + } + + /* + /********************************************************** + /* MessageBodyReader impl + /********************************************************** + */ + + /** + * Method that JAX-RS container calls to try to check whether + * values of given type (and media type) can be deserialized by + * this provider. + * Implementation will first check that expected media type is + * a JSON type (via call to {@link #isJsonType}; then verify + * that type is not one of "untouchable" types (types we will never + * automatically handle), and finally that there is a deserializer + * for type (iff {@link #checkCanDeserialize} has been called with + * true argument -- otherwise assumption is there will be a handler) + */ + @Override + public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) + { + if (!isJsonType(mediaType)) { + return false; + } + + /* Ok: looks like we must weed out some core types here; ones that + * make no sense to try to bind from JSON: + */ + if (_untouchables.contains(new ClassKey(type))) { + return false; + } + // and there are some other abstract/interface types to exclude too: + for (Class<?> cls : _unreadableClasses) { + if (cls.isAssignableFrom(type)) { + return false; + } + } + // as well as possible custom exclusions + if (_containedIn(type, _cfgCustomUntouchables)) { + return false; + } + + // Finally: if we really want to verify that we can serialize, we'll check: + if (_cfgCheckCanSerialize) { + ObjectMapper mapper = locateMapper(type, mediaType); + if (!mapper.canDeserialize(mapper.constructType(type))) { + return false; + } + } + return true; + } + + /** + * Method that JAX-RS container calls to deserialize given + * value. + */ + @Override + public Object readFrom(Class<Object> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String,String> httpHeaders, InputStream entityStream) + throws IOException + { + ObjectMapper mapper = locateMapper(type, mediaType); + JsonParser jp = mapper.getJsonFactory().createJsonParser(entityStream); + /* Important: we are NOT to close the underlying stream after + * mapping, so we need to instruct parser: + */ + jp.disable(JsonParser.Feature.AUTO_CLOSE_SOURCE); + return mapper.readValue(jp, mapper.constructType(genericType)); + } + + /* + /********************************************************** + /* MessageBodyWriter impl + /********************************************************** + */ + + /** + * Method that JAX-RS container calls to try to figure out + * serialized length of given value. Since computation of + * this length is about as expensive as serialization itself, + * implementation will return -1 to denote "not known", so + * that container will determine length from actual serialized + * output (if needed). + */ + @Override + public long getSize(Object value, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) + { + /* In general figuring output size requires actual writing; usually not + * worth it to write everything twice. + */ + return -1; + } + + /** + * Method that JAX-RS container calls to try to check whether + * given value (of specified type) can be serialized by + * this provider. + * Implementation will first check that expected media type is + * a JSON type (via call to {@link #isJsonType}; then verify + * that type is not one of "untouchable" types (types we will never + * automatically handle), and finally that there is a serializer + * for type (iff {@link #checkCanSerialize} has been called with + * true argument -- otherwise assumption is there will be a handler) + */ + @Override + public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) + { + if (!isJsonType(mediaType)) { + return false; + } + + /* Ok: looks like we must weed out some core types here; ones that + * make no sense to try to bind from JSON: + */ + if (_untouchables.contains(new ClassKey(type))) { + return false; + } + // but some are interface/abstract classes, so + for (Class<?> cls : _unwritableClasses) { + if (cls.isAssignableFrom(type)) { + return false; + } + } + // and finally, may have additional custom types to exclude + if (_containedIn(type, _cfgCustomUntouchables)) { + return false; + } + + // Also: if we really want to verify that we can deserialize, we'll check: + if (_cfgCheckCanSerialize) { + if (!locateMapper(type, mediaType).canSerialize(type)) { + return false; + } + } + return true; + } + + /** + * Method that JAX-RS container calls to serialize given value. + */ + @Override + public void writeTo(Object value, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType, + MultivaluedMap<String,Object> httpHeaders, OutputStream entityStream) + throws IOException + { + /* 27-Feb-2009, tatu: Where can we find desired encoding? Within + * HTTP headers? + */ + ObjectMapper mapper = locateMapper(type, mediaType); + JsonEncoding enc = findEncoding(mediaType, httpHeaders); + JsonGenerator jg = mapper.getJsonFactory().createJsonGenerator(entityStream, enc); + jg.disable(JsonGenerator.Feature.AUTO_CLOSE_TARGET); + + // Want indentation? + if (mapper.getSerializationConfig().isEnabled(SerializationConfig.Feature.INDENT_OUTPUT)) { + jg.useDefaultPrettyPrinter(); + } + // 04-Mar-2010, tatu: How about type we were given? (if any) + JavaType rootType = null; + + if (genericType != null && value != null) { + /* 10-Jan-2011, tatu: as per [JACKSON-456], it's not safe to just force root + * type since it prevents polymorphic type serialization. Since we really + * just need this for generics, let's only use generic type if it's truly + * generic. + */ + if (genericType.getClass() != Class.class) { // generic types are other impls of 'java.lang.reflect.Type' + /* This is still not exactly right; should root type be further + * specialized with 'value.getClass()'? Let's see how well this works before + * trying to come up with more complete solution. + */ + rootType = mapper.getTypeFactory().constructType(genericType); + /* 26-Feb-2011, tatu: To help with [JACKSON-518], we better recognize cases where + * type degenerates back into "Object.class" (as is the case with plain TypeVariable, + * for example), and not use that. + */ + if (rootType.getRawClass() == Object.class) { + rootType = null; + } + } + } + // [JACKSON-578]: Allow use of @JsonView in resource methods. + Class<?> viewToUse = null; + if (annotations != null && annotations.length > 0) { + viewToUse = _findView(mapper, annotations); + } + if (viewToUse != null) { + // TODO: change to use 'writerWithType' for 2.0 (1.9 could use, but let's defer) + ObjectWriter viewWriter = mapper.viewWriter(viewToUse); + // [JACKSON-245] Allow automatic JSONP wrapping + if (_jsonpFunctionName != null) { + viewWriter.writeValue(jg, new JSONPObject(this._jsonpFunctionName, value, rootType)); + } else if (rootType != null) { + // TODO: change to use 'writerWithType' for 2.0 (1.9 could use, but let's defer) + mapper.typedWriter(rootType).withView(viewToUse).writeValue(jg, value); + } else { + viewWriter.writeValue(jg, value); + } + } else { + // [JACKSON-245] Allow automatic JSONP wrapping + if (_jsonpFunctionName != null) { + mapper.writeValue(jg, new JSONPObject(this._jsonpFunctionName, value, rootType)); + } else if (rootType != null) { + // TODO: change to use 'writerWithType' for 2.0 (1.9 could use, but let's defer) + mapper.typedWriter(rootType).writeValue(jg, value); + } else { + mapper.writeValue(jg, value); + } + } + } + + /** + * Helper method to use for determining desired output encoding. + * For now, will always just use UTF-8... + * + * @since 1.7.0 + */ + protected JsonEncoding findEncoding(MediaType mediaType, MultivaluedMap<String,Object> httpHeaders) + { + return JsonEncoding.UTF8; + } + + /* + /********************************************************** + /* Public helper methods + /********************************************************** + */ + + /** + * Helper method used to check whether given media type + * is JSON type or sub type. + * Current implementation essentially checks to see whether + * {@link MediaType#getSubtype} returns "json" or something + * ending with "+json". + */ + protected boolean isJsonType(MediaType mediaType) + { + /* As suggested by Stephen D, there are 2 ways to check: either + * being as inclusive as possible (if subtype is "json"), or + * exclusive (major type "application", minor type "json"). + * Let's start with inclusive one, hard to know which major + * types we should cover aside from "application". + */ + if (mediaType != null) { + // Ok: there are also "xxx+json" subtypes, which count as well + String subtype = mediaType.getSubtype(); + return "json".equalsIgnoreCase(subtype) || subtype.endsWith("+json"); + } + /* Not sure if this can happen; but it seems reasonable + * that we can at least produce json without media type? + */ + return true; + } + + /** + * Method called to locate {@link ObjectMapper} to use for serialization + * and deserialization. If an instance has been explicitly defined by + * {@link #setMapper} (or non-null instance passed in constructor), that + * will be used. + * If not, will try to locate it using standard JAX-RS + * {@link ContextResolver} mechanism, if it has been properly configured + * to access it (by JAX-RS runtime). + * Finally, if no mapper is found, will return a default unconfigured + * {@link ObjectMapper} instance (one constructed with default constructor + * and not modified in any way) + * + * @param type Class of object being serialized or deserialized; + * not checked at this point, since it is assumed that unprocessable + * classes have been already weeded out, + * but will be passed to {@link ContextResolver} as is. + * @param mediaType Declared media type for the instance to process: + * not used by this method, + * but will be passed to {@link ContextResolver} as is. + */ + public ObjectMapper locateMapper(Class<?> type, MediaType mediaType) + { + // First: were we configured with a specific instance? + ObjectMapper m = _mapperConfig.getConfiguredMapper(); + if (m == null) { + // If not, maybe we can get one configured via context? + if (_providers != null) { + ContextResolver<ObjectMapper> resolver = _providers.getContextResolver(ObjectMapper.class, mediaType); + /* Above should work as is, but due to this bug + * [https://jersey.dev.java.net/issues/show_bug.cgi?id=288] + * in Jersey, it doesn't. But this works until resolution of + * the issue: + */ + if (resolver == null) { + resolver = _providers.getContextResolver(ObjectMapper.class, null); + } + if (resolver != null) { + m = resolver.getContext(type); + } + } + if (m == null) { + // If not, let's get the fallback default instance + m = _mapperConfig.getDefaultMapper(); + } + } + return m; + } + + /* + /********************************************************** + /* Private/sub-class helper methods + /********************************************************** + */ + + protected static boolean _containedIn(Class<?> mainType, HashSet<ClassKey> set) + { + if (set != null) { + ClassKey key = new ClassKey(mainType); + // First: type itself? + if (set.contains(key)) return true; + // Then supertypes (note: will not contain Object.class) + for (Class<?> cls : ClassUtil.findSuperTypes(mainType, null)) { + key.reset(cls); + if (set.contains(key)) return true; + } + } + return false; + } + + protected Class<?> _findView(ObjectMapper mapper, Annotation[] annotations) + throws JsonMappingException + { + /* Ideally we would try to use AnnotationIntrospector here, but current + * API expects to get a method/field, not bunch of annotations, + * so we would need to change it a bit. + * Let's not bother, then, since this works well for now. + */ + for (Annotation annotation : annotations) { + if (annotation.annotationType().isAssignableFrom(JsonView.class)) { + JsonView jsonView = (JsonView) annotation; + Class<?>[] views = jsonView.value(); + if (views.length > 1) { + StringBuilder s = new StringBuilder("Multiple @JsonView's can not be used on a JAX-RS method. Got "); + s.append(views.length).append(" views: "); + for (int i = 0; i < views.length; i++) { + if (i > 0) { + s.append(", "); + } + s.append(views[i].getName()); + } + throw new JsonMappingException(s.toString()); + } + return views[0]; + } + } + return null; + } +}
diff --git a/1.9.10/src/jaxrs/java/org/codehaus/jackson/jaxrs/JsonMappingExceptionMapper.java b/1.9.10/src/jaxrs/java/org/codehaus/jackson/jaxrs/JsonMappingExceptionMapper.java new file mode 100644 index 0000000..e8015c1 --- /dev/null +++ b/1.9.10/src/jaxrs/java/org/codehaus/jackson/jaxrs/JsonMappingExceptionMapper.java
@@ -0,0 +1,19 @@ +package org.codehaus.jackson.jaxrs; + +import org.codehaus.jackson.map.JsonMappingException; + +import javax.ws.rs.core.Response; +import javax.ws.rs.ext.ExceptionMapper; +import javax.ws.rs.ext.Provider; + +/** + * Implementation if {@link ExceptionMapper} to send down a "400 Bad Request" + * response in the event that unmappable JSON is received. + */ +@Provider +public class JsonMappingExceptionMapper implements ExceptionMapper<JsonMappingException> { + @Override + public Response toResponse(JsonMappingException exception) { + return Response.status(Response.Status.BAD_REQUEST).entity(exception.getMessage()).type("text/plain").build(); + } +}
diff --git a/1.9.10/src/jaxrs/java/org/codehaus/jackson/jaxrs/JsonParseExceptionMapper.java b/1.9.10/src/jaxrs/java/org/codehaus/jackson/jaxrs/JsonParseExceptionMapper.java new file mode 100644 index 0000000..2388bb0 --- /dev/null +++ b/1.9.10/src/jaxrs/java/org/codehaus/jackson/jaxrs/JsonParseExceptionMapper.java
@@ -0,0 +1,19 @@ +package org.codehaus.jackson.jaxrs; + +import org.codehaus.jackson.JsonParseException; + +import javax.ws.rs.core.Response; +import javax.ws.rs.ext.ExceptionMapper; +import javax.ws.rs.ext.Provider; + +/** + * Implementation of {@link ExceptionMapper} to send down a "400 Bad Request" + * in the event unparsable JSON is received. + */ +@Provider +public class JsonParseExceptionMapper implements ExceptionMapper<JsonParseException> { + @Override + public Response toResponse(JsonParseException exception) { + return Response.status(Response.Status.BAD_REQUEST).entity(exception.getMessage()).type("text/plain").build(); + } +}
diff --git a/1.9.10/src/jaxrs/java/org/codehaus/jackson/jaxrs/MapperConfigurator.java b/1.9.10/src/jaxrs/java/org/codehaus/jackson/jaxrs/MapperConfigurator.java new file mode 100644 index 0000000..9606af7 --- /dev/null +++ b/1.9.10/src/jaxrs/java/org/codehaus/jackson/jaxrs/MapperConfigurator.java
@@ -0,0 +1,181 @@ +package org.codehaus.jackson.jaxrs; + +import java.util.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.introspect.JacksonAnnotationIntrospector; +import org.codehaus.jackson.xc.JaxbAnnotationIntrospector; + +/** + * Helper class used to encapsulate details of configuring an + * {@link ObjectMapper} instance to be used for data binding, as + * well as accessing it. + */ +public class MapperConfigurator +{ + /** + * Mapper provider was constructed with if any, or that was constructed + * due to a call to explicitly configure mapper. + * If defined (explicitly or implicitly) it will be used, instead + * of using provider-based lookup. + */ + protected ObjectMapper _mapper; + + /** + * If no mapper was specified when constructed, and no configuration + * calls are made, a default mapper is constructed. The difference + * between default mapper and regular one is that default mapper + * is only used if no mapper is found via provider lookup. + */ + protected ObjectMapper _defaultMapper; + + /** + * Annotations set to use by default; overridden by explicit call + * to {@link #setAnnotationsToUse} + */ + protected Annotations[] _defaultAnnotationsToUse; + + /** + * To support optional dependency to Jackson-XC module (needed if and + * when JAXB annotations are used for configuration) + */ + protected Class<? extends AnnotationIntrospector> _jaxbIntrospectorClass; + + /* + *********************************************************** + * Construction + *********************************************************** + */ + + public MapperConfigurator(ObjectMapper mapper, Annotations[] defAnnotations) + { + _mapper = mapper; + _defaultAnnotationsToUse = defAnnotations; + } + + /** + * Method that locates, configures and returns {@link ObjectMapper} to use + */ + public synchronized ObjectMapper getConfiguredMapper() { + /* important: should NOT call mapper(); needs to return null + * if no instance has been passed or constructed + */ + return _mapper; + } + + public synchronized ObjectMapper getDefaultMapper() { + if (_defaultMapper == null) { + _defaultMapper = new ObjectMapper(); + _setAnnotations(_defaultMapper, _defaultAnnotationsToUse); + } + return _defaultMapper; + } + + /* + *********************************************************** + * Configuration methods + *********************************************************** + */ + + public synchronized void setMapper(ObjectMapper m) { + _mapper = m; + } + + public synchronized void setAnnotationsToUse(Annotations[] annotationsToUse) { + _setAnnotations(mapper(), annotationsToUse); + } + + public synchronized void configure(DeserializationConfig.Feature f, boolean state) { + mapper().configure(f, state); + } + + public synchronized void configure(SerializationConfig.Feature f, boolean state) { + mapper().configure(f, state); + } + + public synchronized void configure(JsonParser.Feature f, boolean state) { + mapper().configure(f, state); + } + + public synchronized void configure(JsonGenerator.Feature f, boolean state) { + mapper().configure(f, state); + } + + /* + *********************************************************** + * Internal methods + *********************************************************** + */ + + /** + * Helper method that will ensure that there is a configurable non-default + * mapper (constructing an instance if one didn't yet exit), and return + * that mapper. + */ + protected ObjectMapper mapper() + { + if (_mapper == null) { + _mapper = new ObjectMapper(); + _setAnnotations(_mapper, _defaultAnnotationsToUse); + } + return _mapper; + } + + // since replacement methods were added in 1.8, let's not yet switch over to use them: + @SuppressWarnings("deprecation") + protected void _setAnnotations(ObjectMapper mapper, Annotations[] annotationsToUse) + { + AnnotationIntrospector intr; + if (annotationsToUse == null || annotationsToUse.length == 0) { + intr = AnnotationIntrospector.nopInstance(); + } else { + intr = _resolveIntrospectors(annotationsToUse); + } + mapper.getDeserializationConfig().setAnnotationIntrospector(intr); + mapper.getSerializationConfig().setAnnotationIntrospector(intr); + } + + + protected AnnotationIntrospector _resolveIntrospectors(Annotations[] annotationsToUse) + { + // Let's ensure there are no dups there first, filter out nulls + ArrayList<AnnotationIntrospector> intr = new ArrayList<AnnotationIntrospector>(); + for (Annotations a : annotationsToUse) { + if (a != null) { + intr.add(_resolveIntrospector(a)); + } + } + int count = intr.size(); + if (count == 0) { + return AnnotationIntrospector.nopInstance(); + } + AnnotationIntrospector curr = intr.get(0); + for (int i = 1, len = intr.size(); i < len; ++i) { + curr = AnnotationIntrospector.pair(curr, intr.get(i)); + } + return curr; + } + + protected AnnotationIntrospector _resolveIntrospector(Annotations ann) + { + switch (ann) { + case JACKSON: + return new JacksonAnnotationIntrospector(); + case JAXB: + /* For this, need to use indirection just so that error occurs + * when we get here, and not when this class is being loaded + */ + try { + if (_jaxbIntrospectorClass == null) { + _jaxbIntrospectorClass = JaxbAnnotationIntrospector.class; + } + return _jaxbIntrospectorClass.newInstance(); + } catch (Exception e) { + throw new IllegalStateException("Failed to instantiate JaxbAnnotationIntrospector: "+e.getMessage(), e); + } + default: + throw new IllegalStateException(); + } + } +}
diff --git a/1.9.10/src/jaxrs/java/org/codehaus/jackson/jaxrs/package-info.java b/1.9.10/src/jaxrs/java/org/codehaus/jackson/jaxrs/package-info.java new file mode 100644 index 0000000..f5fb57e --- /dev/null +++ b/1.9.10/src/jaxrs/java/org/codehaus/jackson/jaxrs/package-info.java
@@ -0,0 +1,10 @@ +/** + * Jackson-based JAX-RS provider that can automatically + * serialize and deserialize resources for + * JSON content type (MediaType). + *<p> + * Also continues supporting functionality, such as + * exception mappers that can simplify handling of + * error conditions. + */ +package org.codehaus.jackson.jaxrs;
diff --git a/1.9.10/src/jaxrs/resources/javax.ws.rs.ext.MessageBodyReader b/1.9.10/src/jaxrs/resources/javax.ws.rs.ext.MessageBodyReader new file mode 100644 index 0000000..b5e634f --- /dev/null +++ b/1.9.10/src/jaxrs/resources/javax.ws.rs.ext.MessageBodyReader
@@ -0,0 +1 @@ +org.codehaus.jackson.jaxrs.JacksonJsonProvider
diff --git a/1.9.10/src/jaxrs/resources/javax.ws.rs.ext.MessageBodyWriter b/1.9.10/src/jaxrs/resources/javax.ws.rs.ext.MessageBodyWriter new file mode 100644 index 0000000..b5e634f --- /dev/null +++ b/1.9.10/src/jaxrs/resources/javax.ws.rs.ext.MessageBodyWriter
@@ -0,0 +1 @@ +org.codehaus.jackson.jaxrs.JacksonJsonProvider
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/AbstractTypeResolver.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/AbstractTypeResolver.java new file mode 100644 index 0000000..08a5313 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/AbstractTypeResolver.java
@@ -0,0 +1,63 @@ +package org.codehaus.jackson.map; + +import org.codehaus.jackson.type.JavaType; + +/** + * Defines interface for resolvers that can resolve abstract types into concrete + * ones; either by using static mappings, or possibly by materializing + * implementations dynamically. + *<p> + * Note that this class was changed in 1.8, to separate two parts of operation + * (defaulting, which has higher precedence, and fallback, which has lowest + * precedence). Existing m + * + * @since 1.6 + */ +public abstract class AbstractTypeResolver +{ + /** + * Try to locate a subtype for given abstract type, to either resolve + * to a concrete type, or at least to a more-specific (and hopefully supported) + * abstract type, one which may have registered deserializers. + * Method is called before trying to locate registered deserializers + * (as well as standard abstract type defaulting that core Jackson does), + * so it is typically implemented to add custom mappings of common abstract + * types (like specify which concrete implementation to use for binding + * {@link java.util.List}s). + *<p> + * Note that this method does not necessarily have to do full resolution + * of bindings; that is, it is legal to return type that could be further + * resolved: caller is expected to keep calling this method on registered + * resolvers, until a concrete type is located. + * + * @param config Configuration in use; should always be of type + * <code>DeserializationConfig</code> + * + * @since 1.8 + */ + public JavaType findTypeMapping(DeserializationConfig config, JavaType type) { + return null; + } + + /** + * Method called to try to resolve an abstract type into + * concrete type (usually for purposes of deserializing), + * when no concrete implementation was found. + * It will be called after checking all other possibilities, + * including defaulting. + * + * @param config Configuration in use; should always be of type + * <code>DeserializationConfig</code> + * @param type Type for which materialization maybe needed + * + * @return Resolved concrete type (which should retain generic + * type parameters of input type, if any), if resolution succeeds; + * null if resolver does not know how to resolve type + * + * @since 1.6 + */ + public JavaType resolveAbstractType(DeserializationConfig config, + JavaType type) { + return null; + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/AnnotationIntrospector.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/AnnotationIntrospector.java new file mode 100644 index 0000000..9c146de --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/AnnotationIntrospector.java
@@ -0,0 +1,1476 @@ +package org.codehaus.jackson.map; + +import java.lang.annotation.Annotation; +import java.util.*; + +import org.codehaus.jackson.type.JavaType; +import org.codehaus.jackson.map.JsonDeserializer; +import org.codehaus.jackson.map.JsonSerializer; +import org.codehaus.jackson.map.annotate.JsonSerialize; +import org.codehaus.jackson.map.deser.ValueInstantiator; +import org.codehaus.jackson.map.introspect.*; +import org.codehaus.jackson.map.jsontype.NamedType; +import org.codehaus.jackson.map.jsontype.TypeResolverBuilder; + +/** + * Abstract class that defines API used for introspecting annotation-based + * configuration for serialization and deserialization. Separated + * so that different sets of annotations can be supported, and support + * plugged-in dynamically. + *<p> + * NOTE: due to rapid addition of new methods (and changes to existing methods), + * it is <b>strongly</b> recommended that custom implementations should not directly + * extend this class, but rather extend {@link NopAnnotationIntrospector}. + * This way added methods will not break backwards compatibility of custom annotation + * introspectors. + */ +public abstract class AnnotationIntrospector +{ + /* + /********************************************************** + /* Helper types + /********************************************************** + */ + + /** + * Value type used with managed and back references; contains type and + * logic name, used to link related references + * + * @since 1.6 + */ + public static class ReferenceProperty + { + public enum Type { + /** + * Reference property that Jackson manages and that is serialized normally (by serializing + * reference object), but is used for resolving back references during + * deserialization. + * Usually this can be defined by using + * {@link org.codehaus.jackson.annotate.JsonManagedReference} + */ + MANAGED_REFERENCE + + /** + * Reference property that Jackson manages by suppressing it during serialization, + * and reconstructing during deserialization. + * Usually this can be defined by using + * {@link org.codehaus.jackson.annotate.JsonBackReference} + */ + ,BACK_REFERENCE + ; + } + + private final Type _type; + private final String _name; + + public ReferenceProperty(Type t, String n) { + _type = t; + _name = n; + } + + public static ReferenceProperty managed(String name) { return new ReferenceProperty(Type.MANAGED_REFERENCE, name); } + public static ReferenceProperty back(String name) { return new ReferenceProperty(Type.BACK_REFERENCE, name); } + + public Type getType() { return _type; } + public String getName() { return _name; } + + public boolean isManagedReference() { return _type == Type.MANAGED_REFERENCE; } + public boolean isBackReference() { return _type == Type.BACK_REFERENCE; } + } + + /* + /********************************************************** + /* Factory methods + /********************************************************** + */ + + /** + * Factory method for accessing "no operation" implementation + * of introspector: instance that will never find any annotation-based + * configuration. + * + * @since 1.3 + */ + public static AnnotationIntrospector nopInstance() { + return NopAnnotationIntrospector.instance; + } + + public static AnnotationIntrospector pair(AnnotationIntrospector a1, AnnotationIntrospector a2) { + return new Pair(a1, a2); + } + + /* + /********************************************************** + /* Access to possibly chained introspectors (1.7) + /********************************************************** + */ + + /** + * Method that can be used to collect all "real" introspectors that + * this introspector contains, if any; or this introspector + * if it is not a container. Used to get access to all container + * introspectors in their priority order. + *<p> + * Default implementation returns a Singleton list with this introspector + * as contents. + * This usually works for sub-classes, except for proxy or delegating "container + * introspectors" which need to override implementation. + */ + public Collection<AnnotationIntrospector> allIntrospectors() { + return Collections.singletonList(this); + } + + /** + * Method that can be used to collect all "real" introspectors that + * this introspector contains, if any; or this introspector + * if it is not a container. Used to get access to all container + * introspectors in their priority order. + *<p> + * Default implementation adds this introspector in result; this usually + * works for sub-classes, except for proxy or delegating "container + * introspectors" which need to override implementation. + */ + public Collection<AnnotationIntrospector> allIntrospectors(Collection<AnnotationIntrospector> result) { + result.add(this); + return result; + } + + /* + /********************************************************** + /* Generic annotation properties, lookup + /********************************************************** + */ + + /** + * Method called by framework to determine whether given annotation + * is handled by this introspector. + */ + public abstract boolean isHandled(Annotation ann); + + /* + /********************************************************** + /* General class annotations + /********************************************************** + */ + + /** + * Method that checks whether specified class has annotations + * that indicate that it is (or is not) cachable. Exact + * semantics depend on type of class annotated and using + * class (factory or provider). + *<p> + * Currently only used + * with deserializers, to determine whether provider + * should cache instances, and if no annotations are found, + * assumes non-cachable instances. + * + * @return True, if class is considered cachable within context, + * False if not, and null if introspector does not care either + * way. + */ + public Boolean findCachability(AnnotatedClass ac) { + return null; + } + + /** + * Method for locating name used as "root name" (for use by + * some serializers when outputting root-level object -- mostly + * for XML compatibility purposes) for given class, if one + * is defined. Returns null if no declaration found; can return + * explicit empty String, which is usually ignored as well as null. + * + * @since 1.3 + */ + public abstract String findRootName(AnnotatedClass ac); + + /** + * Method for finding list of properties to ignore for given class + * (null is returned if not specified). + * List of property names is applied + * after other detection mechanisms, to filter out these specific + * properties from being serialized and deserialized. + * + * @since 1.4 + */ + public abstract String[] findPropertiesToIgnore(AnnotatedClass ac); + + /** + * Method for checking whether an annotation indicates that all unknown properties + * + * @since 1.4 + */ + public abstract Boolean findIgnoreUnknownProperties(AnnotatedClass ac); + + /** + * Method for checking whether properties that have specified type + * (class, not generics aware) should be completely ignored for + * serialization and deserialization purposes. + * + * @param ac Type to check + * + * @return Boolean.TRUE if properties of type should be ignored; + * Boolean.FALSE if they are not to be ignored, null for default + * handling (which is 'do not ignore') + * + * @since 1.7 + */ + public Boolean isIgnorableType(AnnotatedClass ac) { + return null; + } + + /** + * Method for finding if annotated class has associated filter; and if so, + * to return id that is used to locate filter. + * + * @return Id of the filter to use for filtering properties of annotated + * class, if any; or null if none found. + */ + public Object findFilterId(AnnotatedClass ac) { + return null; + } + + /* + /********************************************************** + /* Property auto-detection + /********************************************************** + */ + + /** + * Method for checking if annotations indicate changes to minimum visibility levels + * needed for auto-detecting property elements (fields, methods, constructors). + * A baseline checker is given, and introspector is to either return it as is (if + * no annotations are found), or build and return a derived instance (using checker's build + * methods). + * + * @since 1.5 + */ + public VisibilityChecker<?> findAutoDetectVisibility(AnnotatedClass ac, VisibilityChecker<?> checker) { + return checker; + } + + /* + /********************************************************** + /* Class annotations for Polymorphic type handling (1.5+) + /********************************************************** + */ + + /** + * Method for checking if given class has annotations that indicate + * that specific type resolver is to be used for handling instances. + * This includes not only + * instantiating resolver builder, but also configuring it based on + * relevant annotations (not including ones checked with a call to + * {@link #findSubtypes} + * + * @param config Configuration settings in effect (for serialization or deserialization) + * @param ac Annotated class to check for annotations + * @param baseType Base java type of value for which resolver is to be found + * + * @return Type resolver builder for given type, if one found; null if none + * + * @since 1.5 -- although changed in 1.8 to pass configuration object + */ + public TypeResolverBuilder<?> findTypeResolver(MapperConfig<?> config, + AnnotatedClass ac, JavaType baseType) { + return null; + } + + /** + * Method for checking if given property entity (field or method) has annotations + * that indicate that specific type resolver is to be used for handling instances. + * This includes not only + * instantiating resolver builder, but also configuring it based on + * relevant annotations (not including ones checked with a call to + * {@link #findSubtypes} + * + * @param config Configuration settings in effect (for serialization or deserialization) + * @param am Annotated member (field or method) to check for annotations + * @param baseType Base java type of property for which resolver is to be found + * + * @return Type resolver builder for properties of given entity, if one found; + * null if none + * + * @since 1.5 -- although changed in 1.8 to pass configuration object + */ + public TypeResolverBuilder<?> findPropertyTypeResolver(MapperConfig<?> config, + AnnotatedMember am, JavaType baseType) { + return null; + } + + /** + * Method for checking if given structured property entity (field or method that + * has nominal value of Map, Collection or array type) has annotations + * that indicate that specific type resolver is to be used for handling type + * information of contained values. + * This includes not only + * instantiating resolver builder, but also configuring it based on + * relevant annotations (not including ones checked with a call to + * {@link #findSubtypes} + * + * @param config Configuration settings in effect (for serialization or deserialization) + * @param am Annotated member (field or method) to check for annotations + * @param containerType Type of property for which resolver is to be found (must be a container type) + * + * @return Type resolver builder for values contained in properties of given entity, + * if one found; null if none + * + * @since 1.5 -- although changed in 1.8 to pass configuration object + */ + public TypeResolverBuilder<?> findPropertyContentTypeResolver(MapperConfig<?> config, + AnnotatedMember am, JavaType containerType) { + return null; + } + + /** + * Method for locating annotation-specified subtypes related to annotated + * entity (class, method, field). Note that this is only guaranteed to be + * a list of directly + * declared subtypes, no recursive processing is guarantees (i.e. caller + * has to do it if/as necessary) + * + * @param a Annotated entity (class, field/method) to check for annotations + * + * @since 1.5 + */ + public List<NamedType> findSubtypes(Annotated a) { + return null; + } + + /** + * Method for checking if specified type has explicit name. + * + * @param ac Class to check for type name annotations + * + * @since 1.5 + */ + public String findTypeName(AnnotatedClass ac) { + return null; + } + + /* + /********************************************************** + /* General member (field, method/constructor) annotations + /********************************************************** + */ + + /** + * Note: defined as non-abstract to reduce fragility between + * versions. + * + * @since 1.6 + */ + public ReferenceProperty findReferenceType(AnnotatedMember member) { + return null; + } + + /** + * Method called to check whether given property is marked to be "unwrapped" + * when being serialized (and appropriately handled in reverse direction, + * i.e. expect unwrapped representation during deserialization) + * + * @since 1.9 + */ + public Boolean shouldUnwrapProperty(AnnotatedMember member) { + return null; + } + + /** + * Method called to check whether given property is marked to + * be ignored; but NOT to determine if it should necessarily + * be ignored, since that may depend on other factors. + *<p> + * Default implementation calls existing 'isIgnored' methods + * such as {@link #isIgnorableField(AnnotatedField)} and + * {@link #isIgnorableMethod(AnnotatedMethod)}. + * + * @since 1.9 + */ + public boolean hasIgnoreMarker(AnnotatedMember m) + { + /* For maximum backwards compatibility, we better call + * existing methods. + */ + /* TODO: For 2.0, replace with simple 'return false;' + */ + if (m instanceof AnnotatedMethod) { + return isIgnorableMethod((AnnotatedMethod) m); + } + if (m instanceof AnnotatedField) { + return isIgnorableField((AnnotatedField) m); + } + if (m instanceof AnnotatedConstructor) { + return isIgnorableConstructor((AnnotatedConstructor) m); + } + return false; + } + + /** + * Method called to find out whether given member expectes a value + * to be injected, and if so, what is the identifier of the value + * to use during injection. + * Type if identifier needs to be compatible with provider of + * values (of type {@link InjectableValues}); often a simple String + * id is used. + * + * @param m Member to check + * + * @return Identifier of value to inject, if any; null if no injection + * indicator is found + */ + public Object findInjectableValueId(AnnotatedMember m) { + return null; + } + + /* + /********************************************************** + /* General method annotations + /********************************************************** + */ + + /** + * Method for checking whether there is an annotation that + * indicates that given method should be ignored for all + * operations (serialization, deserialization). + *<p> + * Note that this method should <b>ONLY</b> return true for such + * explicit ignoral cases; and not if method just happens not to + * be visible for annotation processor. + * + * @return True, if an annotation is found to indicate that the + * method should be ignored; false if not. + */ + public abstract boolean isIgnorableMethod(AnnotatedMethod m); + + /** + * @since 1.2 + */ + public abstract boolean isIgnorableConstructor(AnnotatedConstructor c); + + /* + /********************************************************** + /* General field annotations + /********************************************************** + */ + + /** + * Method for checking whether there is an annotation that + * indicates that given field should be ignored for all + * operations (serialization, deserialization). + * + * @return True, if an annotation is found to indicate that the + * field should be ignored; false if not. + */ + public abstract boolean isIgnorableField(AnnotatedField f); + + /* + /********************************************************** + /* Serialization: general annotations + /********************************************************** + */ + + /** + * Method for getting a serializer definition on specified method + * or field. Type of definition is either instance (of type + * {@link JsonSerializer}) or Class (of type + * <code>Class<JsonSerializer></code>); if value of different + * type is returned, a runtime exception may be thrown by caller. + *<p> + * Note: this variant was briefly deprecated for 1.7; should not be + */ + public abstract Object findSerializer(Annotated am); + + /** + * Method for getting a serializer definition for keys of associated <code>Map</code> property. + * Type of definition is either instance (of type + * {@link JsonSerializer}) or Class (of type + * <code>Class<JsonSerializer></code>); if value of different + * type is returned, a runtime exception may be thrown by caller. + * + * @since 1.8 + */ + public Class<? extends JsonSerializer<?>> findKeySerializer(Annotated am) { + return null; + } + + /** + * Method for getting a serializer definition for content (values) of + * associated <code>Collection</code>, <code>array</code> or <code>Map</code> property. + * Type of definition is either instance (of type + * {@link JsonSerializer}) or Class (of type + * <code>Class<JsonSerializer></code>); if value of different + * type is returned, a runtime exception may be thrown by caller. + * + * @since 1.8 + */ + public Class<? extends JsonSerializer<?>> findContentSerializer(Annotated am) { + return null; + } + + /** + * Method for checking whether given annotated entity (class, method, + * field) defines which Bean/Map properties are to be included in + * serialization. + * If no annotation is found, method should return given second + * argument; otherwise value indicated by the annotation + * + * @return Enumerated value indicating which properties to include + * in serialization + */ + public JsonSerialize.Inclusion findSerializationInclusion(Annotated a, JsonSerialize.Inclusion defValue) { + return defValue; + } + + /** + * Method for accessing annotated type definition that a + * method/field can have, to be used as the type for serialization + * instead of the runtime type. + * Type returned (if any) needs to be widening conversion (super-type). + * Declared return type of the method is also considered acceptable. + * + * @return Class to use instead of runtime type + */ + public abstract Class<?> findSerializationType(Annotated a); + + /** + * Method for finding possible widening type definition that a property + * value can have, to define less specific key type to use for serialization. + * It should be only be used with {@link java.util.Map} types. + * + * @return Class specifying more general type to use instead of + * declared type, if annotation found; null if not + */ + public Class<?> findSerializationKeyType(Annotated am, JavaType baseType) { + return null; + } + + /** + * Method for finding possible widening type definition that a property + * value can have, to define less specific key type to use for serialization. + * It should be only used with structured types (arrays, collections, maps). + * + * @return Class specifying more general type to use instead of + * declared type, if annotation found; null if not + */ + public Class<?> findSerializationContentType(Annotated am, JavaType baseType) { + return null; + } + + /** + * Method for accessing declared typing mode annotated (if any). + * This is used for type detection, unless more granular settings + * (such as actual exact type; or serializer to use which means + * no type information is needed) take precedence. + * + * @since 1.2 + * + * @return Typing mode to use, if annotation is found; null otherwise + */ + public abstract JsonSerialize.Typing findSerializationTyping(Annotated a); + + /** + * Method for checking if annotated serializable property (represented by + * field or getter method) has definitions for views it is to be included + * in. If null is returned, no view definitions exist and property is always + * included; otherwise it will only be included for views included in returned + * array. View matches are checked using class inheritance rules (sub-classes + * inherit inclusions of super-classes) + * + * @param a Annotated serializable property (field or getter method) + * @return Array of views (represented by classes) that the property is included in; + * if null, always included (same as returning array containing <code>Object.class</code>) + */ + public abstract Class<?>[] findSerializationViews(Annotated a); + + /* + /********************************************************** + /* Serialization: class annotations + /********************************************************** + */ + + /** + * Method for accessing defined property serialization order (which may be + * partial). May return null if no ordering is defined. + * + * @since 1.4 + */ + public abstract String[] findSerializationPropertyOrder(AnnotatedClass ac); + + /** + * Method for checking whether an annotation indicates that serialized properties + * for which no explicit is defined should be alphabetically (lexicograpically) + * ordered + * + * @since 1.4 + */ + public abstract Boolean findSerializationSortAlphabetically(AnnotatedClass ac); + + /* + /********************************************************** + /* Serialization: method annotations + /********************************************************** + */ + + /** + * Method for checking whether given method has an annotation + * that suggests property name associated with method that + * may be a "getter". Should return null if no annotation + * is found; otherwise a non-null String. + * If non-null value is returned, it is used as the property + * name, except for empty String ("") which is taken to mean + * "use standard bean name detection if applicable; + * method name if not". + */ + public abstract String findGettablePropertyName(AnnotatedMethod am); + + /** + * Method for checking whether given method has an annotation + * that suggests that the return value of annotated method + * should be used as "the value" of the object instance; usually + * serialized as a primitive value such as String or number. + * + * @return True if such annotation is found (and is not disabled); + * false if no enabled annotation is found + */ + public abstract boolean hasAsValueAnnotation(AnnotatedMethod am); + + /** + * Method for determining the String value to use for serializing + * given enumeration entry; used when serializing enumerations + * as Strings (the standard method). + * + * @return Serialized enum value. + */ + public abstract String findEnumValue(Enum<?> value); + + /* + /********************************************************** + /* Serialization: field annotations + /********************************************************** + */ + + /** + * Method for checking whether given member field represent + * a serializable logical property; and if so, returns the + * name of that property. + * Should return null if no annotation is found (indicating it + * is not a serializable field); otherwise a non-null String. + * If non-null value is returned, it is used as the property + * name, except for empty String ("") which is taken to mean + * "use the field name as is". + */ + public abstract String findSerializablePropertyName(AnnotatedField af); + + /* + /********************************************************** + /* Deserialization: general annotations + /********************************************************** + */ + + /** + * Method for getting a deserializer definition on specified method + * or field. + * Type of definition is either instance (of type + * {@link JsonDeserializer}) or Class (of type + * <code>Class<JsonDeserializer></code>); if value of different + * type is returned, a runtime exception may be thrown by caller. + *<p> + * Note: this variant was briefly deprecated for 1.7; but it turns out + * we really should not try to push BeanProperty through at this point + */ + public abstract Object findDeserializer(Annotated am); + + /** + * Method for getting a deserializer definition for keys of + * associated <code>Map</code> property. + * Type of definition is either instance (of type + * {@link JsonDeserializer}) or Class (of type + * <code>Class<JsonDeserializer></code>); if value of different + * type is returned, a runtime exception may be thrown by caller. + * + * @since 1.3 + */ + public abstract Class<? extends KeyDeserializer> findKeyDeserializer(Annotated am); + + /** + * Method for getting a deserializer definition for content (values) of + * associated <code>Collection</code>, <code>array</code> or + * <code>Map</code> property. + * Type of definition is either instance (of type + * {@link JsonDeserializer}) or Class (of type + * <code>Class<JsonDeserializer></code>); if value of different + * type is returned, a runtime exception may be thrown by caller. + * + * @since 1.3 + */ + public abstract Class<? extends JsonDeserializer<?>> findContentDeserializer(Annotated am); + + /** + * Method for accessing annotated type definition that a + * method can have, to be used as the type for serialization + * instead of the runtime type. + * Type must be a narrowing conversion + * (i.e.subtype of declared type). + * Declared return type of the method is also considered acceptable. + * + * @param baseType Assumed type before considering annotations + * @param propName Logical property name of the property that uses + * type, if known; null for types not associated with property + * + * @return Class to use for deserialization instead of declared type + */ + public abstract Class<?> findDeserializationType(Annotated am, JavaType baseType, + String propName); + + /** + * Method for accessing additional narrowing type definition that a + * method can have, to define more specific key type to use. + * It should be only be used with {@link java.util.Map} types. + * + * @param baseKeyType Assumed key type before considering annotations + * @param propName Logical property name of the property that uses + * type, if known; null for types not associated with property + * + * @return Class specifying more specific type to use instead of + * declared type, if annotation found; null if not + */ + public abstract Class<?> findDeserializationKeyType(Annotated am, JavaType baseKeyType, + String propName); + + /** + * Method for accessing additional narrowing type definition that a + * method can have, to define more specific content type to use; + * content refers to Map values and Collection/array elements. + * It should be only be used with Map, Collection and array types. + * + * @param baseContentType Assumed content (value) type before considering annotations + * @param propName Logical property name of the property that uses + * type, if known; null for types not associated with property + * + * @return Class specifying more specific type to use instead of + * declared type, if annotation found; null if not + */ + public abstract Class<?> findDeserializationContentType(Annotated am, JavaType baseContentType, + String propName); + + /* + /********************************************************** + /* Deserialization: class annotations + /********************************************************** + */ + + /** + * Method getting {@link ValueInstantiator} to use for given + * type (class): return value can either be an instance of + * instantiator, or class of instantiator to create. + * + * @since 1.9 + */ + public Object findValueInstantiator(AnnotatedClass ac) { + return null; + } + + /* + /********************************************************** + /* Deserialization: method annotations + /********************************************************** + */ + + /** + * Method for checking whether given method has an annotation + * that suggests property name associated with method that + * may be a "setter". Should return null if no annotation + * is found; otherwise a non-null String. + * If non-null value is returned, it is used as the property + * name, except for empty String ("") which is taken to mean + * "use standard bean name detection if applicable; + * method name if not". + */ + public abstract String findSettablePropertyName(AnnotatedMethod am); + + /** + * Method for checking whether given method has an annotation + * that suggests that the method is to serve as "any setter"; + * method to be used for setting values of any properties for + * which no dedicated setter method is found. + * + * @return True if such annotation is found (and is not disabled), + * false otherwise + */ + public boolean hasAnySetterAnnotation(AnnotatedMethod am) { + return false; + } + + /** + * Method for checking whether given method has an annotation + * that suggests that the method is to serve as "any setter"; + * method to be used for accessing set of miscellaneous "extra" + * properties, often bound with matching "any setter" method. + * + * @return True if such annotation is found (and is not disabled), + * false otherwise + * + * @since 1.6 + */ + public boolean hasAnyGetterAnnotation(AnnotatedMethod am) { + return false; + } + + /** + * Method for checking whether given annotated item (method, constructor) + * has an annotation + * that suggests that the method is a "creator" (aka factory) + * method to be used for construct new instances of deserialized + * values. + * + * @return True if such annotation is found (and is not disabled), + * false otherwise + */ + public boolean hasCreatorAnnotation(Annotated a) { + return false; + } + + /* + /********************************************************** + /* Deserialization: field annotations + /********************************************************** + */ + + /** + * Method for checking whether given member field represent + * a deserializable logical property; and if so, returns the + * name of that property. + * Should return null if no annotation is found (indicating it + * is not a deserializable field); otherwise a non-null String. + * If non-null value is returned, it is used as the property + * name, except for empty String ("") which is taken to mean + * "use the field name as is". + */ + public abstract String findDeserializablePropertyName(AnnotatedField af); + + /* + /********************************************************** + /* Deserialization: parameter annotations (for + /* creator method parameters) + /********************************************************** + */ + + /** + * Method for checking whether given set of annotations indicates + * property name for associated parameter. + * No actual parameter object can be passed since JDK offers no + * representation; just annotations. + */ + public abstract String findPropertyNameForParam(AnnotatedParameter param); + + /* + /********************************************************** + /* Helper classes + /********************************************************** + */ + + /** + * Helper class that allows using 2 introspectors such that one + * introspector acts as the primary one to use; and second one + * as a fallback used if the primary does not provide conclusive + * or useful result for a method. + *<p> + * An obvious consequence of priority is that it is easy to construct + * longer chains of introspectors by linking multiple pairs. + * Currently most likely combination is that of using the default + * Jackson provider, along with JAXB annotation introspector (available + * since version 1.1). + */ + public static class Pair + extends AnnotationIntrospector + { + protected final AnnotationIntrospector _primary, _secondary; + + public Pair(AnnotationIntrospector p, + AnnotationIntrospector s) + { + _primary = p; + _secondary = s; + } + + /** + * Helper method for constructing a Pair from two given introspectors (if + * neither is null); or returning non-null introspector if one is null + * (and return just null if both are null) + * + * @since 1.7 + */ + public static AnnotationIntrospector create(AnnotationIntrospector primary, + AnnotationIntrospector secondary) + { + if (primary == null) { + return secondary; + } + if (secondary == null) { + return primary; + } + return new Pair(primary, secondary); + } + + @Override + public Collection<AnnotationIntrospector> allIntrospectors() { + return allIntrospectors(new ArrayList<AnnotationIntrospector>()); + } + + @Override + public Collection<AnnotationIntrospector> allIntrospectors(Collection<AnnotationIntrospector> result) + { + _primary.allIntrospectors(result); + _secondary.allIntrospectors(result); + return result; + } + + // // // Generic annotation properties, lookup + + @Override + public boolean isHandled(Annotation ann) + { + return _primary.isHandled(ann) || _secondary.isHandled(ann); + } + + /* + /****************************************************** + /* General class annotations + /****************************************************** + */ + + @Override + public Boolean findCachability(AnnotatedClass ac) + { + Boolean result = _primary.findCachability(ac); + if (result == null) { + result = _secondary.findCachability(ac); + } + return result; + } + + @Override + public String findRootName(AnnotatedClass ac) + { + String name1 = _primary.findRootName(ac); + if (name1 == null) { + return _secondary.findRootName(ac); + } else if (name1.length() > 0) { + return name1; + } + // name1 is empty; how about secondary? + String name2 = _secondary.findRootName(ac); + return (name2 == null) ? name1 : name2; + } + + @Override + public String[] findPropertiesToIgnore(AnnotatedClass ac) + { + String[] result = _primary.findPropertiesToIgnore(ac); + if (result == null) { + result = _secondary.findPropertiesToIgnore(ac); + } + return result; + } + + @Override + public Boolean findIgnoreUnknownProperties(AnnotatedClass ac) + { + Boolean result = _primary.findIgnoreUnknownProperties(ac); + if (result == null) { + result = _secondary.findIgnoreUnknownProperties(ac); + } + return result; + } + + @Override + public Boolean isIgnorableType(AnnotatedClass ac) + { + Boolean result = _primary.isIgnorableType(ac); + if (result == null) { + result = _secondary.isIgnorableType(ac); + } + return result; + } + + @Override + public Object findFilterId(AnnotatedClass ac) + { + Object id = _primary.findFilterId(ac); + if (id == null) { + id = _secondary.findFilterId(ac); + } + return id; + } + + /* + /****************************************************** + /* Property auto-detection + /****************************************************** + */ + + @Override + public VisibilityChecker<?> findAutoDetectVisibility(AnnotatedClass ac, + VisibilityChecker<?> checker) + { + /* Note: to have proper priorities, we must actually call delegatees + * in reverse order: + */ + checker = _secondary.findAutoDetectVisibility(ac, checker); + return _primary.findAutoDetectVisibility(ac, checker); + } + + /* + /****************************************************** + /* Type handling + /****************************************************** + */ + + @Override + public TypeResolverBuilder<?> findTypeResolver(MapperConfig<?> config, + AnnotatedClass ac, JavaType baseType) + { + TypeResolverBuilder<?> b = _primary.findTypeResolver(config, ac, baseType); + if (b == null) { + b = _secondary.findTypeResolver(config, ac, baseType); + } + return b; + } + + @Override + public TypeResolverBuilder<?> findPropertyTypeResolver(MapperConfig<?> config, + AnnotatedMember am, JavaType baseType) + { + TypeResolverBuilder<?> b = _primary.findPropertyTypeResolver(config, am, baseType); + if (b == null) { + b = _secondary.findPropertyTypeResolver(config, am, baseType); + } + return b; + } + + @Override + public TypeResolverBuilder<?> findPropertyContentTypeResolver(MapperConfig<?> config, + AnnotatedMember am, JavaType baseType) + { + TypeResolverBuilder<?> b = _primary.findPropertyContentTypeResolver(config, am, baseType); + if (b == null) { + b = _secondary.findPropertyContentTypeResolver(config, am, baseType); + } + return b; + } + + @Override + public List<NamedType> findSubtypes(Annotated a) + { + List<NamedType> types1 = _primary.findSubtypes(a); + List<NamedType> types2 = _secondary.findSubtypes(a); + if (types1 == null || types1.isEmpty()) return types2; + if (types2 == null || types2.isEmpty()) return types1; + ArrayList<NamedType> result = new ArrayList<NamedType>(types1.size() + types2.size()); + result.addAll(types1); + result.addAll(types2); + return result; + } + + @Override + public String findTypeName(AnnotatedClass ac) + { + String name = _primary.findTypeName(ac); + if (name == null || name.length() == 0) { + name = _secondary.findTypeName(ac); + } + return name; + } + + // // // General member (field, method/constructor) annotations + + @Override + public ReferenceProperty findReferenceType(AnnotatedMember member) + { + ReferenceProperty ref = _primary.findReferenceType(member); + if (ref == null) { + ref = _secondary.findReferenceType(member); + } + return ref; + } + + @Override + public Boolean shouldUnwrapProperty(AnnotatedMember member) + { + Boolean value = _primary.shouldUnwrapProperty(member); + if (value == null) { + value = _secondary.shouldUnwrapProperty(member); + } + return value; + } + + @Override + public Object findInjectableValueId(AnnotatedMember m) + { + Object value = _primary.findInjectableValueId(m); + if (value == null) { + value = _secondary.findInjectableValueId(m); + } + return value; + } + + @Override + public boolean hasIgnoreMarker(AnnotatedMember m) { + return _primary.hasIgnoreMarker(m) || _secondary.hasIgnoreMarker(m); + } + + // // // General method annotations + + @Override + public boolean isIgnorableMethod(AnnotatedMethod m) { + return _primary.isIgnorableMethod(m) || _secondary.isIgnorableMethod(m); + } + + @Override + public boolean isIgnorableConstructor(AnnotatedConstructor c) { + return _primary.isIgnorableConstructor(c) || _secondary.isIgnorableConstructor(c); + } + + // // // General field annotations + + @Override + public boolean isIgnorableField(AnnotatedField f) + { + return _primary.isIgnorableField(f) || _secondary.isIgnorableField(f); + } + + // // // Serialization: general annotations + + @Override + public Object findSerializer(Annotated am) + { + Object result = _primary.findSerializer(am); + if (result == null) { + result = _secondary.findSerializer(am); + } + return result; + } + + @Override + public Class<? extends JsonSerializer<?>> findKeySerializer(Annotated a) + { + Class<? extends JsonSerializer<?>> result = _primary.findKeySerializer(a); + if (result == null || result == JsonSerializer.None.class) { + result = _secondary.findKeySerializer(a); + } + return result; + } + + @Override + public Class<? extends JsonSerializer<?>> findContentSerializer(Annotated a) + { + Class<? extends JsonSerializer<?>> result = _primary.findContentSerializer(a); + if (result == null || result == JsonSerializer.None.class) { + result = _secondary.findContentSerializer(a); + } + return result; + } + + @Override + public JsonSerialize.Inclusion findSerializationInclusion(Annotated a, + JsonSerialize.Inclusion defValue) + { + /* This is bit trickier: need to combine results in a meaningful + * way. Seems like it should be a disjoint; that is, most + * restrictive value should be returned. + * For enumerations, comparison is done by indexes, which + * works: largest value is the last one, which is the most + * restrictive value as well. + */ + /* 09-Mar-2010, tatu: Actually, as per [JACKSON-256], it is probably better to just + * use strict overriding. Simpler, easier to understand. + */ + // note: call secondary first, to give lower priority + defValue = _secondary.findSerializationInclusion(a, defValue); + defValue = _primary.findSerializationInclusion(a, defValue); + return defValue; + } + + @Override + public Class<?> findSerializationType(Annotated a) + { + Class<?> result = _primary.findSerializationType(a); + if (result == null) { + result = _secondary.findSerializationType(a); + } + return result; + } + + @Override + public Class<?> findSerializationKeyType(Annotated am, JavaType baseType) + { + Class<?> result = _primary.findSerializationKeyType(am, baseType); + if (result == null) { + result = _secondary.findSerializationKeyType(am, baseType); + } + return result; + } + + @Override + public Class<?> findSerializationContentType(Annotated am, JavaType baseType) + { + Class<?> result = _primary.findSerializationContentType(am, baseType); + if (result == null) { + result = _secondary.findSerializationContentType(am, baseType); + } + return result; + } + + @Override + public JsonSerialize.Typing findSerializationTyping(Annotated a) + { + JsonSerialize.Typing result = _primary.findSerializationTyping(a); + if (result == null) { + result = _secondary.findSerializationTyping(a); + } + return result; + } + + @Override + public Class<?>[] findSerializationViews(Annotated a) + { + /* Theoretically this could be trickier, if multiple introspectors + * return non-null entries. For now, though, we'll just consider + * first one to return non-null to win. + */ + Class<?>[] result = _primary.findSerializationViews(a); + if (result == null) { + result = _secondary.findSerializationViews(a); + } + return result; + } + + // // // Serialization: class annotations + + @Override + public String[] findSerializationPropertyOrder(AnnotatedClass ac) { + String[] result = _primary.findSerializationPropertyOrder(ac); + if (result == null) { + result = _secondary.findSerializationPropertyOrder(ac); + } + return result; + } + + /** + * Method for checking whether an annotation indicates that serialized properties + * for which no explicit is defined should be alphabetically (lexicograpically) + * ordered + */ + @Override + public Boolean findSerializationSortAlphabetically(AnnotatedClass ac) { + Boolean result = _primary.findSerializationSortAlphabetically(ac); + if (result == null) { + result = _secondary.findSerializationSortAlphabetically(ac); + } + return result; + } + + // // // Serialization: method annotations + + @Override + public String findGettablePropertyName(AnnotatedMethod am) + { + String result = _primary.findGettablePropertyName(am); + if (result == null) { + result = _secondary.findGettablePropertyName(am); + } else if (result.length() == 0) { + /* Empty String is a default; can be overridden by + * more explicit answer from secondary entry + */ + String str2 = _secondary.findGettablePropertyName(am); + if (str2 != null) { + result = str2; + } + } + return result; + } + + @Override + public boolean hasAsValueAnnotation(AnnotatedMethod am) + { + return _primary.hasAsValueAnnotation(am) || _secondary.hasAsValueAnnotation(am); + } + + @Override + public String findEnumValue(Enum<?> value) + { + String result = _primary.findEnumValue(value); + if (result == null) { + result = _secondary.findEnumValue(value); + } + return result; + } + + // // // Serialization: field annotations + + @Override + public String findSerializablePropertyName(AnnotatedField af) + { + String result = _primary.findSerializablePropertyName(af); + if (result == null) { + result = _secondary.findSerializablePropertyName(af); + } else if (result.length() == 0) { + /* Empty String is a default; can be overridden by + * more explicit answer from secondary entry + */ + String str2 = _secondary.findSerializablePropertyName(af); + if (str2 != null) { + result = str2; + } + } + return result; + } + + // // // Deserialization: general annotations + + @Override + public Object findDeserializer(Annotated am) + { + Object result = _primary.findDeserializer(am); + if (result == null) { + result = _secondary.findDeserializer(am); + } + return result; + } + + @Override + public Class<? extends KeyDeserializer> findKeyDeserializer(Annotated am) + { + Class<? extends KeyDeserializer> result = _primary.findKeyDeserializer(am); + if (result == null || result == KeyDeserializer.None.class) { + result = _secondary.findKeyDeserializer(am); + } + return result; + } + + @Override + public Class<? extends JsonDeserializer<?>> findContentDeserializer(Annotated am) + { + Class<? extends JsonDeserializer<?>> result = _primary.findContentDeserializer(am); + if (result == null || result == JsonDeserializer.None.class) { + result = _secondary.findContentDeserializer(am); + } + return result; + } + + @Override + public Class<?> findDeserializationType(Annotated am, JavaType baseType, + String propName) + { + Class<?> result = _primary.findDeserializationType(am, baseType, propName); + if (result == null) { + result = _secondary.findDeserializationType(am, baseType, propName); + } + return result; + } + + @Override + public Class<?> findDeserializationKeyType(Annotated am, JavaType baseKeyType, + String propName) + { + Class<?> result = _primary.findDeserializationKeyType(am, baseKeyType, propName); + if (result == null) { + result = _secondary.findDeserializationKeyType(am, baseKeyType, propName); + } + return result; + } + + @Override + public Class<?> findDeserializationContentType(Annotated am, JavaType baseContentType, + String propName) + { + Class<?> result = _primary.findDeserializationContentType(am, baseContentType, propName); + if (result == null) { + result = _secondary.findDeserializationContentType(am, baseContentType, propName); + } + return result; + } + + // // // Deserialization: class annotations + + @Override + public Object findValueInstantiator(AnnotatedClass ac) + { + Object result = _primary.findValueInstantiator(ac); + if (result == null) { + result = _secondary.findValueInstantiator(ac); + } + return result; + } + + // // // Deserialization: method annotations + + @Override + public String findSettablePropertyName(AnnotatedMethod am) + { + String result = _primary.findSettablePropertyName(am); + if (result == null) { + result = _secondary.findSettablePropertyName(am); + } else if (result.length() == 0) { + /* Empty String is a default; can be overridden by + * more explicit answer from secondary entry + */ + String str2 = _secondary.findSettablePropertyName(am); + if (str2 != null) { + result = str2; + } + } + return result; + } + + @Override + public boolean hasAnySetterAnnotation(AnnotatedMethod am) + { + return _primary.hasAnySetterAnnotation(am) || _secondary.hasAnySetterAnnotation(am); + } + + @Override + public boolean hasAnyGetterAnnotation(AnnotatedMethod am) + { + return _primary.hasAnyGetterAnnotation(am) || _secondary.hasAnyGetterAnnotation(am); + } + + @Override + public boolean hasCreatorAnnotation(Annotated a) + { + return _primary.hasCreatorAnnotation(a) || _secondary.hasCreatorAnnotation(a); + } + + // // // Deserialization: field annotations + + @Override + public String findDeserializablePropertyName(AnnotatedField af) + { + String result = _primary.findDeserializablePropertyName(af); + if (result == null) { + result = _secondary.findDeserializablePropertyName(af); + } else if (result.length() == 0) { + /* Empty String is a default; can be overridden by + * more explicit answer from secondary entry + */ + String str2 = _secondary.findDeserializablePropertyName(af); + if (str2 != null) { + result = str2; + } + } + return result; + } + + // // // Deserialization: parameter annotations (for creators) + + @Override + public String findPropertyNameForParam(AnnotatedParameter param) + { + String result = _primary.findPropertyNameForParam(param); + if (result == null) { + result = _secondary.findPropertyNameForParam(param); + } + return result; + } + } + +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/BeanDescription.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/BeanDescription.java new file mode 100644 index 0000000..7b3d098 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/BeanDescription.java
@@ -0,0 +1,167 @@ +package org.codehaus.jackson.map; + +import java.util.*; + +import org.codehaus.jackson.map.introspect.AnnotatedClass; +import org.codehaus.jackson.map.introspect.AnnotatedConstructor; +import org.codehaus.jackson.map.introspect.AnnotatedField; +import org.codehaus.jackson.map.introspect.AnnotatedMember; +import org.codehaus.jackson.map.introspect.AnnotatedMethod; +import org.codehaus.jackson.map.introspect.VisibilityChecker; +import org.codehaus.jackson.map.type.TypeBindings; +import org.codehaus.jackson.map.util.Annotations; +import org.codehaus.jackson.type.JavaType; + +/** + * Basic container for information gathered by {@link ClassIntrospector} to + * help in constructing serializers and deserializers. + * Note that the main implementation type is + * {@link org.codehaus.jackson.map.introspect.BasicBeanDescription}, + * meaning that it is safe to upcast to this type. + * + * @author tatu + */ +public abstract class BeanDescription +{ + /* + /********************************************************** + /* Configuration + /********************************************************** + */ + + /** + * Bean type information, including raw class and possible + * * generics information + */ + protected final JavaType _type; + + /* + /********************************************************** + /* Life-cycle + /********************************************************** + */ + + protected BeanDescription(JavaType type) + { + _type = type; + } + + /* + /********************************************************** + /* Simple accesors + /********************************************************** + */ + + /** + * Method for accessing declared type of bean being introspected, + * including full generic type information (from declaration) + */ + public JavaType getType() { return _type; } + + public Class<?> getBeanClass() { return _type.getRawClass(); } + + public abstract AnnotatedClass getClassInfo(); + + public abstract boolean hasKnownClassAnnotations(); + + /** + * Accessor for type bindings that may be needed to fully resolve + * types of member object, such as return and argument types of + * methods and constructors, and types of fields. + */ + public abstract TypeBindings bindingsForBeanType(); + + /** + * Method for resolving given JDK type, using this bean as the + * generic type resolution context. + * + * @since 1.9 + */ + public abstract JavaType resolveType(java.lang.reflect.Type jdkType); + + /** + * Method for accessing collection of annotations the bean + * class has. + * + * @since 1.7 + */ + public abstract Annotations getClassAnnotations(); + + /* + /********************************************************** + /* Basic API for finding properties, related + /********************************************************** + */ + + /** + * @return Ordered Map with logical property name as key, and + * matching getter method as value. + * + * @since 1.9 + */ + public abstract List<BeanPropertyDefinition> findProperties(); + + /** + * @since 1.9 + */ + public abstract Map<Object, AnnotatedMember> findInjectables(); + + /** + * @since 1.9 + */ + public abstract AnnotatedMethod findAnyGetter(); + + /** + * @since 1.9 + */ + public abstract AnnotatedMethod findAnySetter(); + + /** + * @since 1.9 + */ + public abstract AnnotatedMethod findJsonValueMethod(); + + /** + * @since 1.9 + */ + public abstract AnnotatedConstructor findDefaultConstructor(); + + /** + * @since 1.9 + */ + public abstract Set<String> getIgnoredPropertyNames(); + + /* + /********************************************************** + /* Deprecated methods + /********************************************************** + */ + + /** + * @deprecated Since 1.9 use {@link #findProperties} + */ + @Deprecated + public abstract LinkedHashMap<String,AnnotatedMethod> findGetters(VisibilityChecker<?> visibilityChecker, + Collection<String> ignoredProperties); + + /** + * @deprecated Since 1.9 use {@link #findProperties} + */ + @Deprecated + public abstract LinkedHashMap<String,AnnotatedMethod> findSetters(VisibilityChecker<?> visibilityChecker); + + /** + * @deprecated Since 1.9 use {@link #findProperties} + */ + @Deprecated + public abstract LinkedHashMap<String,AnnotatedField> findDeserializableFields(VisibilityChecker<?> visibilityChecker, + Collection<String> ignoredProperties); + + /** + * @deprecated Since 1.9 use the non-deprecated version + */ + @Deprecated + public abstract Map<String,AnnotatedField> findSerializableFields(VisibilityChecker<?> visibilityChecker, + Collection<String> ignoredProperties); + +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/BeanProperty.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/BeanProperty.java new file mode 100644 index 0000000..749bf67 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/BeanProperty.java
@@ -0,0 +1,123 @@ +package org.codehaus.jackson.map; + +import java.lang.annotation.Annotation; + +import org.codehaus.jackson.map.introspect.AnnotatedMember; +import org.codehaus.jackson.map.util.Annotations; +import org.codehaus.jackson.map.util.Named; +import org.codehaus.jackson.type.JavaType; + +/** + * Bean properties are logical entities that represent data + * Java objects ("beans", although more accurately POJOs) + * contain; and that are accessed using some combination + * of methods (getter, setter), field and constructor + * parameter. + * Instances allow access to annotations directly associated + * to property (via field or method), as well as contextual + * annotations (annotations for class that contains properties). + *<p> + * Instances are passed during construction of serializers and + * deserializers, and references can be stored by serializers + * and deserializers for futher use; mostly to retain access + * to annotations when dynamically locating handlers for + * sub-properties or dynamic types. + * + * @since 1.7 + */ +public interface BeanProperty extends Named +{ + /** + * Method to get logical name of the property + */ + @Override + public String getName(); + + /** + * Method to get declared type of the property. + */ + public JavaType getType(); + + /** + * Method for finding annotation associated with this property; + * meaning annotation associated with one of entities used to + * access property. + */ + public <A extends Annotation> A getAnnotation(Class<A> acls); + + /** + * Method for finding annotation associated with context of + * this property; usually class in which member is declared + * (or its subtype if processing subtype). + */ + public <A extends Annotation> A getContextAnnotation(Class<A> acls); + + /** + * Method for accessing primary physical entity that represents the property; + * annotated field, method or constructor property. + */ + public AnnotatedMember getMember(); + + /* + /********************************************************** + /* Simple stand-alone implementation, useful as a placeholder + /* or base class. + /********************************************************** + */ + + public static class Std implements BeanProperty + { + protected final String _name; + protected final JavaType _type; + + /** + * Physical entity (field, method or constructor argument) that + * is used to access value of property (or in case of constructor + * property, just placeholder) + */ + protected final AnnotatedMember _member; + + /** + * Annotations defined in the context class (if any); may be null + * if no annotations were found + */ + protected final Annotations _contextAnnotations; + + public Std(String name, JavaType type, Annotations contextAnnotations, AnnotatedMember member) + { + _name = name; + _type = type; + _member = member; + _contextAnnotations = contextAnnotations; + } + + public Std withType(JavaType type) { + return new Std(_name, type, _contextAnnotations, _member); + } + + @Override + public <A extends Annotation> A getAnnotation(Class<A> acls) { + return _member.getAnnotation(acls); + } + + @Override + public <A extends Annotation> A getContextAnnotation(Class<A> acls) { + return (_contextAnnotations == null) ? null : _contextAnnotations.get(acls); + } + + @Override + public String getName() { + return _name; + } + + @Override + public JavaType getType() { + return _type; + } + + @Override + public AnnotatedMember getMember() { + return _member; + } + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/BeanPropertyDefinition.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/BeanPropertyDefinition.java new file mode 100644 index 0000000..d2e7611 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/BeanPropertyDefinition.java
@@ -0,0 +1,79 @@ +package org.codehaus.jackson.map; + +import org.codehaus.jackson.map.introspect.AnnotatedField; +import org.codehaus.jackson.map.introspect.AnnotatedMember; +import org.codehaus.jackson.map.introspect.AnnotatedMethod; +import org.codehaus.jackson.map.introspect.AnnotatedParameter; +import org.codehaus.jackson.map.util.Named; + +/** + * Simple value classes that contain definitions of properties, + * used during introspection of properties to use for + * serialization and deserialization purposes. + * These instances are created before actual {@link BeanProperty} + * instances are created, i.e. they are used earlier in the process + * flow. + * + * @since 1.9 + */ +public abstract class BeanPropertyDefinition + implements Named +{ + /** + * Accessor for name used for external representation (in JSON). + */ + @Override // from Named + public abstract String getName(); + + /** + * Accessor that can be used to determine implicit name from underlying + * element(s) before possible renaming. This is the "internal" + * name derived from accessor ("x" from "getX"), and is not based on + * annotations or naming strategy. + */ + public abstract String getInternalName(); + + /** + * Accessor that can be called to check whether property was included + * due to an explicit marker (usually annotation), or just by naming + * convention. + * + * @return True if property was explicitly included (usually by having + * one of components being annotated); false if inclusion was purely + * due to naming or visibility definitions (that is, implicit) + * + * @since 1.9.6 + */ + public abstract boolean isExplicitlyIncluded(); + + public abstract boolean hasGetter(); + public abstract boolean hasSetter(); + public abstract boolean hasField(); + public abstract boolean hasConstructorParameter(); + + public boolean couldDeserialize() { + return getMutator() != null; + } + public boolean couldSerialize() { + return getAccessor() != null; + } + + public abstract AnnotatedMethod getGetter(); + public abstract AnnotatedMethod getSetter(); + public abstract AnnotatedField getField(); + public abstract AnnotatedParameter getConstructorParameter(); + + /** + * Method used to find accessor (getter, field to access) to use for accessing + * value of the property. + * Null if no such member exists. + */ + public abstract AnnotatedMember getAccessor(); + + /** + * Method used to find mutator (constructor parameter, setter, field) to use for + * changing value of the property. + * Null if no such member exists. + */ + public abstract AnnotatedMember getMutator(); +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ClassIntrospector.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ClassIntrospector.java new file mode 100644 index 0000000..be3ed2e --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ClassIntrospector.java
@@ -0,0 +1,117 @@ +package org.codehaus.jackson.map; + +import org.codehaus.jackson.type.JavaType; + +/** + * Helper class used to introspect features of POJO value classes + * used with Jackson. The main use is for finding out + * POJO construction (creator) and value access (getters, setters) + * methods and annotations that define configuration of using + * those methods. + */ +public abstract class ClassIntrospector<T extends BeanDescription> +{ + /* + /********************************************************** + /* Helper interfaces + /********************************************************** + */ + + /** + * Interface used for decoupling details of how mix-in annotation + * definitions are accessed (via this interface), and how + * they are stored (defined by classes that implement the interface) + */ + public interface MixInResolver + { + /** + * Method that will check if there are "mix-in" classes (with mix-in + * annotations) for given class + */ + public Class<?> findMixInClassFor(Class<?> cls); + } + + protected ClassIntrospector() { } + + /* + /********************************************************** + /* Public API: factory methods + /********************************************************** + */ + + /** + * Factory method that constructs an introspector that has all + * information needed for serialization purposes. + */ + public abstract T forSerialization(SerializationConfig cfg, JavaType type, + MixInResolver r); + + /** + * Factory method that constructs an introspector that has all + * information needed for deserialization purposes. + */ + public abstract T forDeserialization(DeserializationConfig cfg, JavaType type, + MixInResolver r); + + /** + * Factory method that constructs an introspector that has + * information necessary for creating instances of given + * class ("creator"), as well as class annotations, but + * no information on member methods + */ + public abstract T forCreation(DeserializationConfig cfg, JavaType type, + MixInResolver r); + + /** + * Factory method that constructs an introspector that only has + * information regarding annotations class itself (or its supertypes) has, + * but nothing on methods or constructors. + */ + public abstract T forClassAnnotations(MapperConfig<?> cfg, JavaType type, + MixInResolver r); + + /** + * Factory method that constructs an introspector that only has + * information regarding annotations class itself has (but NOT including + * its supertypes), but nothing on methods or constructors. + * + * @since 1.5 + */ + public abstract T forDirectClassAnnotations(MapperConfig<?> cfg, JavaType type, + MixInResolver r); + + /* + /********************************************************** + /* Deprecated methods + /********************************************************** + */ + + /** + * Factory method that constructs an introspector that only has + * information regarding annotations class itself (or its supertypes) has, + * but nothing on methods or constructors. + * + * @deprecated since 1.9, use variant that takes JavaType + */ + @Deprecated + public T forClassAnnotations(MapperConfig<?> cfg, Class<?> cls, + MixInResolver r) { + return forClassAnnotations(cfg, cfg.constructType(cls), r); + } + + /** + * Factory method that constructs an introspector that only has + * information regarding annotations class itself has (but NOT including + * its supertypes), but nothing on methods or constructors. + * + * @since 1.5 + * + * @deprecated since 1.9, use variant that takes JavaType + */ + @Deprecated + public T forDirectClassAnnotations(MapperConfig<?> cfg, Class<?> cls, + MixInResolver r) { + return forDirectClassAnnotations(cfg, cfg.constructType(cls), r); + } +} +
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ContextualDeserializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ContextualDeserializer.java new file mode 100644 index 0000000..47654ce --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ContextualDeserializer.java
@@ -0,0 +1,38 @@ +package org.codehaus.jackson.map; + +/** + * Add-on interface that {@link JsonDeserializer}s can implement to get a callback + * that can be used to create contextual instances of deserializer to use for + * handling properties of supported type. This can be useful + * for deserializers that can be configured by annotations, or should otherwise + * have differing behavior depending on what kind of property is being deserialized. + * + * @param <T> Type of deserializer to contextualize + * + * @since 1.7 + */ +public interface ContextualDeserializer<T> +{ + /** + * Method called to see if a different (or differently configured) deserializer + * is needed to deserialize values of specified property. + * Note that instance that this method is called on is typically shared one and + * as a result method should <b>NOT</b> modify this instance but rather construct + * and return a new instance. This instance should only be returned as-is, in case + * it is already suitable for use. + * + * @param config Current deserialization configuration + * @param property Method, field or constructor parameter that represents the property + * (and is used to assign deserialized value). + * Should be available; but there may be cases where caller can not provide it and + * null is passed instead (in which case impls usually pass 'this' deserializer as is) + * + * @return Deserializer to use for deserializing values of specified property; + * may be this instance or a new instance. + * + * @throws JsonMappingException + */ + public JsonDeserializer<T> createContextual(DeserializationConfig config, + BeanProperty property) + throws JsonMappingException; +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ContextualKeyDeserializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ContextualKeyDeserializer.java new file mode 100644 index 0000000..8b2df0c --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ContextualKeyDeserializer.java
@@ -0,0 +1,33 @@ +package org.codehaus.jackson.map; + +/** + * Add-on interface that {@link KeyDeserializer}s can implement to get a callback + * that can be used to create contextual instances of key deserializer to use for + * handling Map keys of supported type. This can be useful + * for key deserializers that can be configured by annotations, or should otherwise + * have differing behavior depending on what kind of Map property keys are being deserialized. + * + * @since 1.8 + */ +public interface ContextualKeyDeserializer +{ + /** + * Method called to see if a different (or differently configured) key deserializer + * is needed to deserialize keys of specified Map property. + * Note that instance that this method is called on is typically shared one and + * as a result method should <b>NOT</b> modify this instance but rather construct + * and return a new instance. This instance should only be returned as-is, in case + * it is already suitable for use. + * + * @param config Current deserialization configuration + * @param property Method, field or constructor parameter that declared Map for which + * contextual instance will be used. Will not be available when deserializing root-level + * Map value; otherwise should not be null. + * + * @return Key deserializer to use for deserializing keys specified Map property, + * may be this instance or a new instance. + */ + public KeyDeserializer createContextual(DeserializationConfig config, + BeanProperty property) + throws JsonMappingException; +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ContextualSerializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ContextualSerializer.java new file mode 100644 index 0000000..ac022bf --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ContextualSerializer.java
@@ -0,0 +1,38 @@ +package org.codehaus.jackson.map; + +/** + * Add-on interface that {@link JsonSerializer}s can implement to get a callback + * that can be used to create contextual instances of serializer to use for + * handling properties of supported type. This can be useful + * for serializers that can be configured by annotations, or should otherwise + * have differing behavior depending on what kind of property is being serialized. + * + * @param <T> Type of serializer to contextualize + * + * @since 1.7 + */ +public interface ContextualSerializer<T> +{ + /** + * Method called to see if a different (or differently configured) serializer + * is needed to serialize values of specified property. + * Note that instance that this method is called on is typically shared one and + * as a result method should <b>NOT</b> modify this instance but rather construct + * and return a new instance. This instance should only be returned as-is, in case + * it is already suitable for use. + * + * @param config Current serialization configuration + * @param property Method or field that represents the property + * (and is used to access value to serialize). + * Should be available; but there may be cases where caller can not provide it and + * null is passed instead (in which case impls usually pass 'this' serializer as is) + * + * @return Serializer to use for serializing values of specified property; + * may be this instance or a new instance. + * + * @throws JsonMappingException + */ + public JsonSerializer<T> createContextual(SerializationConfig config, + BeanProperty property) + throws JsonMappingException; +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/DeserializationConfig.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/DeserializationConfig.java new file mode 100644 index 0000000..beaadb1 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/DeserializationConfig.java
@@ -0,0 +1,925 @@ +package org.codehaus.jackson.map; + +import java.text.DateFormat; +import java.util.*; + +import org.codehaus.jackson.Base64Variant; +import org.codehaus.jackson.Base64Variants; +import org.codehaus.jackson.annotate.*; +import org.codehaus.jackson.annotate.JsonAutoDetect.Visibility; +import org.codehaus.jackson.map.deser.ValueInstantiator; +import org.codehaus.jackson.map.introspect.Annotated; +import org.codehaus.jackson.map.introspect.AnnotatedClass; +import org.codehaus.jackson.map.introspect.NopAnnotationIntrospector; +import org.codehaus.jackson.map.introspect.VisibilityChecker; +import org.codehaus.jackson.map.jsontype.SubtypeResolver; +import org.codehaus.jackson.map.jsontype.TypeResolverBuilder; +import org.codehaus.jackson.map.type.ClassKey; +import org.codehaus.jackson.map.type.TypeFactory; +import org.codehaus.jackson.map.util.ClassUtil; +import org.codehaus.jackson.map.util.LinkedNode; +import org.codehaus.jackson.node.JsonNodeFactory; +import org.codehaus.jackson.type.JavaType; + +/** + * Object that contains baseline configuration for deserialization + * process. An instance is owned by {@link ObjectMapper}, which makes + * a copy that is passed during serialization process to + * {@link DeserializerProvider} and {@link DeserializerFactory}. + *<p> + * Note: although configuration settings can be changed at any time + * (for factories and instances), they are not guaranteed to have + * effect if called after constructing relevant mapper or deserializer + * instance. This because some objects may be configured, constructed and + * cached first time they are needed. + *<p> + * As of version 1.9, the goal is to make this class eventually immutable. + * Because of this, existing methods that allow changing state of this + * instance are deprecated in favor of methods that create new instances + * with different configuration ("fluent factories") + */ +public class DeserializationConfig + extends MapperConfig.Impl<DeserializationConfig.Feature, DeserializationConfig> +{ + /** + * Enumeration that defines togglable features that guide + * the serialization feature. + */ + public enum Feature implements MapperConfig.ConfigFeature + { + /* + /****************************************************** + * Introspection features + /****************************************************** + */ + + /** + * Feature that determines whether annotation introspection + * is used for configuration; if enabled, configured + * {@link AnnotationIntrospector} will be used: if disabled, + * no annotations are considered. + *<P> + * Feature is enabled by default. + * + * @since 1.2 + */ + USE_ANNOTATIONS(true), + + /** + * Feature that determines whether "setter" methods are + * automatically detected based on standard Bean naming convention + * or not. If yes, then all public one-argument methods that + * start with prefix "set" + * are considered setters. If disabled, only methods explicitly + * annotated are considered setters. + *<p> + * Note that this feature has lower precedence than per-class + * annotations, and is only used if there isn't more granular + * configuration available. + *<P> + * Feature is enabled by default. + */ + AUTO_DETECT_SETTERS(true), + + /** + * Feature that determines whether "creator" methods are + * automatically detected by consider public constructors, + * and static single argument methods with name "valueOf". + * If disabled, only methods explicitly annotated are considered + * creator methods (except for the no-arg default constructor which + * is always considered a factory method). + *<p> + * Note that this feature has lower precedence than per-class + * annotations, and is only used if there isn't more granular + * configuration available. + *<P> + * Feature is enabled by default. + */ + AUTO_DETECT_CREATORS(true), + + /** + * Feature that determines whether non-static fields are recognized as + * properties. + * If yes, then all public member fields + * are considered as properties. If disabled, only fields explicitly + * annotated are considered property fields. + *<p> + * Note that this feature has lower precedence than per-class + * annotations, and is only used if there isn't more granular + * configuration available. + *<P> + * Feature is enabled by default. + * + * @since 1.1 + */ + AUTO_DETECT_FIELDS(true), + + /** + * Feature that determines whether otherwise regular "getter" + * methods (but only ones that handle Collections and Maps, + * not getters of other type) + * can be used for purpose of getting a reference to a Collection + * and Map to modify the property, without requiring a setter + * method. + * This is similar to how JAXB framework sets Collections and + * Maps: no setter is involved, just setter. + *<p> + * Note that such getters-as-setters methods have lower + * precedence than setters, so they are only used if no + * setter is found for the Map/Collection property. + *<p> + * Feature is enabled by default. + */ + USE_GETTERS_AS_SETTERS(true), + + /** + * Feature that determines whether method and field access + * modifier settings can be overridden when accessing + * properties. If enabled, method + * {@link java.lang.reflect.AccessibleObject#setAccessible} + * may be called to enable access to otherwise unaccessible + * objects. + */ + CAN_OVERRIDE_ACCESS_MODIFIERS(true), + + /* + /****************************************************** + /* Type conversion features + /****************************************************** + */ + + /** + * Feature that determines whether Json floating point numbers + * are to be deserialized into {@link java.math.BigDecimal}s + * if only generic type description (either {@link Object} or + * {@link Number}, or within untyped {@link java.util.Map} + * or {@link java.util.Collection} context) is available. + * If enabled such values will be deserialized as {@link java.math.BigDecimal}s; + * if disabled, will be deserialized as {@link Double}s. + * <p> + * Feature is disabled by default, meaning that "untyped" floating + * point numbers will by default be deserialized as {@link Double}s + * (choice is for performance reason -- BigDecimals are slower than + * Doubles) + */ + USE_BIG_DECIMAL_FOR_FLOATS(false), + + /** + * Feature that determines whether Json integral (non-floating-point) + * numbers are to be deserialized into {@link java.math.BigInteger}s + * if only generic type description (either {@link Object} or + * {@link Number}, or within untyped {@link java.util.Map} + * or {@link java.util.Collection} context) is available. + * If enabled such values will be deserialized as + * {@link java.math.BigInteger}s; + * if disabled, will be deserialized as "smallest" available type, + * which is either {@link Integer}, {@link Long} or + * {@link java.math.BigInteger}, depending on number of digits. + * <p> + * Feature is disabled by default, meaning that "untyped" floating + * point numbers will by default be deserialized using whatever + * is the most compact integral type, to optimize efficiency. + */ + USE_BIG_INTEGER_FOR_INTS(false), + + // [JACKSON-652] + /** + * Feature that determines whether JSON Array is mapped to + * <code>Object[]</code> or <code>List<Object></code> when binding + * "untyped" objects (ones with nominal type of <code>java.lang.Object</code>). + * If true, binds as <code>Object[]</code>; if false, as <code>List<Object></code>. + *<p> + * Feature is disabled by default, meaning that JSON arrays are bound as + * {@link java.util.List}s. + * + * @since 1.9 + */ + USE_JAVA_ARRAY_FOR_JSON_ARRAY(false), + + /** + * Feature that determines standard deserialization mechanism used for + * Enum values: if enabled, Enums are assumed to have been serialized using + * return value of <code>Enum.toString()</code>; + * if disabled, return value of <code>Enum.name()</code> is assumed to have been used. + * Since pre-1.6 method was to use Enum name, this is the default. + *<p> + * Note: this feature should usually have same value + * as {@link SerializationConfig.Feature#WRITE_ENUMS_USING_TO_STRING}. + *<p> + * For further details, check out [JACKSON-212] + * + * @since 1.6 + */ + READ_ENUMS_USING_TO_STRING(false), + + /* + /****************************************************** + * Error handling features + /****************************************************** + */ + + /** + * Feature that determines whether encountering of unknown + * properties (ones that do not map to a property, and there is + * no "any setter" or handler that can handle it) + * should result in a failure (by throwing a + * {@link JsonMappingException}) or not. + * This setting only takes effect after all other handling + * methods for unknown properties have been tried, and + * property remains unhandled. + *<p> + * Feature is enabled by default, meaning that + * {@link JsonMappingException} is thrown if an unknown property + * is encountered. This is the implicit default prior to + * introduction of the feature. + * + * @since 1.2 + */ + FAIL_ON_UNKNOWN_PROPERTIES(true), + + /** + * Feature that determines whether encountering of JSON null + * is an error when deserializing into Java primitive types + * (like 'int' or 'double'). If it is, a JsonProcessingException + * is thrown to indicate this; if not, default value is used + * (0 for 'int', 0.0 for double, same defaulting as what JVM uses). + *<p> + * Feature is disabled by default (to be consistent with behavior + * of Jackson 1.6), + * i.e. to allow use of nulls for primitive properties. + * + * @since 1.7 + */ + FAIL_ON_NULL_FOR_PRIMITIVES(false), + + /** + * Feature that determines whether JSON integer numbers are valid + * values to be used for deserializing Java enum values. + * If set to 'false' numbers are acceptable and are used to map to + * ordinal() of matching enumeration value; if 'true', numbers are + * not allowed and a {@link JsonMappingException} will be thrown. + * Latter behavior makes sense if there is concern that accidental + * mapping from integer values to enums might happen (and when enums + * are always serialized as JSON Strings) + *<p> + * Feature is disabled by default (to be consistent with behavior + * of Jackson 1.6), + * i.e. to allow use of JSON integers for Java enums. + * + * @since 1.7 + */ + FAIL_ON_NUMBERS_FOR_ENUMS(false), + + /** + * Feature that determines whether Jackson code should catch + * and wrap {@link Exception}s (but never {@link Error}s!) + * to add additional information about + * location (within input) of problem or not. If enabled, + * most exceptions will be caught and re-thrown (exception + * specifically being that {@link java.io.IOException}s may be passed + * as is, since they are declared as throwable); this can be + * convenient both in that all exceptions will be checked and + * declared, and so there is more contextual information. + * However, sometimes calling application may just want "raw" + * unchecked exceptions passed as is. + *<p> + * Feature is enabled by default, and is similar in behavior + * to default prior to 1.7. + * + * @since 1.7 + */ + WRAP_EXCEPTIONS(true), + + /* + /****************************************************** + * Structural conversion features + /****************************************************** + */ + + /** + * Feature that determines whether it is acceptable to coerce non-array + * (in JSON) values to work with Java collection (arrays, java.util.Collection) + * types. If enabled, collection deserializers will try to handle non-array + * values as if they had "implicit" surrounding JSON array. + * This feature is meant to be used for compatibility/interoperability reasons, + * to work with packages (such as XML-to-JSON converters) that leave out JSON + * array in cases where there is just a single element in array. + * + * @since 1.8 + */ + ACCEPT_SINGLE_VALUE_AS_ARRAY(false), + + /** + * Feature to allow "unwrapping" root-level JSON value, to match setting of + * {@link SerializationConfig.Feature#WRAP_ROOT_VALUE} used for serialization. + * Will verify that the root JSON value is a JSON Object, and that it has + * a single property with expected root name. If not, a + * {@link JsonMappingException} is thrown; otherwise value of the wrapped property + * will be deserialized as if it was the root value. + * + * @since 1.9 + */ + UNWRAP_ROOT_VALUE(false), + + /* + /****************************************************** + * Value conversion features + /****************************************************** + */ + + /** + * Feature that can be enabled to allow JSON empty String + * value ("") to be bound to POJOs as null. + * If disabled, standard POJOs can only be bound from JSON null or + * JSON Object (standard meaning that no custom deserializers or + * constructors are defined; both of which can add support for other + * kinds of JSON values); if enable, empty JSON String can be taken + * to be equivalent of JSON null. + * + * @since 1.8 + */ + ACCEPT_EMPTY_STRING_AS_NULL_OBJECT(false) + + ; + + final boolean _defaultState; + + private Feature(boolean defaultState) { + _defaultState = defaultState; + } + + @Override + public boolean enabledByDefault() { return _defaultState; } + + @Override + public int getMask() { return (1 << ordinal()); } + } + + /* + /********************************************************** + /* Configuration settings for deserialization + /********************************************************** + */ + + /** + * Linked list that contains all registered problem handlers. + * Implementation as front-added linked list allows for sharing + * of the list (tail) without copying the list. + */ + protected LinkedNode<DeserializationProblemHandler> _problemHandlers; + + /** + * Factory used for constructing {@link org.codehaus.jackson.JsonNode} instances. + * + * @since 1.6 + */ + protected final JsonNodeFactory _nodeFactory; + + /** + * Feature flag from {@link SerializationConfig} which is needed to + * know if serializer will by default sort properties in + * alphabetic order. + *<p> + * Note that although this property is not marked as final, + * it is handled like it was, except for the fact that it is + * assigned with a call to {@link #passSerializationFeatures} + * instead of constructor. + * + * @since 1.9 + */ + protected boolean _sortPropertiesAlphabetically; + + /* + /********************************************************** + /* Life-cycle, constructors + /********************************************************** + */ + + /** + * Constructor used by ObjectMapper to create default configuration object instance. + */ + public DeserializationConfig(ClassIntrospector<? extends BeanDescription> intr, + AnnotationIntrospector annIntr, VisibilityChecker<?> vc, + SubtypeResolver subtypeResolver, PropertyNamingStrategy propertyNamingStrategy, + TypeFactory typeFactory, HandlerInstantiator handlerInstantiator) + { + super(intr, annIntr, vc, subtypeResolver, propertyNamingStrategy, typeFactory, handlerInstantiator, + collectFeatureDefaults(DeserializationConfig.Feature.class)); + _nodeFactory = JsonNodeFactory.instance; + } + + /** + * @since 1.8 + */ + protected DeserializationConfig(DeserializationConfig src) { + this(src, src._base); + } + + /** + * Copy constructor used to create a non-shared instance with given mix-in + * annotation definitions and subtype resolver. + * + * @since 1.8 + */ + private DeserializationConfig(DeserializationConfig src, + HashMap<ClassKey,Class<?>> mixins, SubtypeResolver str) + { + this(src, src._base); + _mixInAnnotations = mixins; + _subtypeResolver = str; + } + + /** + * @since 1.8 + */ + protected DeserializationConfig(DeserializationConfig src, MapperConfig.Base base) + { + super(src, base, src._subtypeResolver); + _problemHandlers = src._problemHandlers; + _nodeFactory = src._nodeFactory; + _sortPropertiesAlphabetically = src._sortPropertiesAlphabetically; + } + + /** + * @since 1.8 + */ + protected DeserializationConfig(DeserializationConfig src, JsonNodeFactory f) + { + super(src); + _problemHandlers = src._problemHandlers; + _nodeFactory = f; + _sortPropertiesAlphabetically = src._sortPropertiesAlphabetically; + } + + /** + * @since 1.9 + */ + protected DeserializationConfig(DeserializationConfig src, int featureFlags) + { + super(src, featureFlags); + _problemHandlers = src._problemHandlers; + _nodeFactory = src._nodeFactory; + _sortPropertiesAlphabetically = src._sortPropertiesAlphabetically; + } + + /** + * Helper method to be called right after creating a non-shared + * instance, needed to pass state of feature(s) shared with + * SerializationConfig. + * + * Since 1.9 + */ + protected DeserializationConfig passSerializationFeatures(int serializationFeatureFlags) + { + _sortPropertiesAlphabetically = (serializationFeatureFlags + & SerializationConfig.Feature.SORT_PROPERTIES_ALPHABETICALLY.getMask()) != 0; + return this; + } + + /* + /********************************************************** + /* Life-cycle, factory methods from MapperConfig + /********************************************************** + */ + + @Override + public DeserializationConfig withClassIntrospector(ClassIntrospector<? extends BeanDescription> ci) { + return new DeserializationConfig(this, _base.withClassIntrospector(ci)); + } + + @Override + public DeserializationConfig withAnnotationIntrospector(AnnotationIntrospector ai) { + return new DeserializationConfig(this, _base.withAnnotationIntrospector(ai)); + } + + @Override + public DeserializationConfig withVisibilityChecker(VisibilityChecker<?> vc) { + return new DeserializationConfig(this, _base.withVisibilityChecker(vc)); + } + + @Override + public DeserializationConfig withVisibility(JsonMethod forMethod, JsonAutoDetect.Visibility visibility) { + return new DeserializationConfig(this, _base.withVisibility(forMethod, visibility)); + } + + @Override + public DeserializationConfig withTypeResolverBuilder(TypeResolverBuilder<?> trb) { + return new DeserializationConfig(this, _base.withTypeResolverBuilder(trb)); + } + + @Override + public DeserializationConfig withSubtypeResolver(SubtypeResolver str) + { + DeserializationConfig cfg = new DeserializationConfig(this); + cfg._subtypeResolver = str; + return cfg; + } + + @Override + public DeserializationConfig withPropertyNamingStrategy(PropertyNamingStrategy pns) { + return new DeserializationConfig(this, _base.withPropertyNamingStrategy(pns)); + } + + @Override + public DeserializationConfig withTypeFactory(TypeFactory tf) { + return (tf == _base.getTypeFactory()) ? this : new DeserializationConfig(this, _base.withTypeFactory(tf)); + } + + @Override + public DeserializationConfig withDateFormat(DateFormat df) { + return (df == _base.getDateFormat()) ? this : new DeserializationConfig(this, _base.withDateFormat(df)); + } + + @Override + public DeserializationConfig withHandlerInstantiator(HandlerInstantiator hi) { + return (hi == _base.getHandlerInstantiator()) ? this : new DeserializationConfig(this, _base.withHandlerInstantiator(hi)); + } + + @Override + public DeserializationConfig withInsertedAnnotationIntrospector(AnnotationIntrospector ai) { + return new DeserializationConfig(this, _base.withInsertedAnnotationIntrospector(ai)); + } + + @Override + public DeserializationConfig withAppendedAnnotationIntrospector(AnnotationIntrospector ai) { + return new DeserializationConfig(this, _base.withAppendedAnnotationIntrospector(ai)); + } + + /* + /********************************************************** + /* Life-cycle, deserialization-specific factory methods + /********************************************************** + */ + + /** + * Fluent factory method that will construct a new instance with + * specified {@link JsonNodeFactory} + * + * @since 1.8 + */ + public DeserializationConfig withNodeFactory(JsonNodeFactory f) { + return new DeserializationConfig(this, f); + } + + /** + * Fluent factory method that will construct and return a new configuration + * object instance with specified features enabled. + * + * @since 1.9 + */ + @Override + public DeserializationConfig with(DeserializationConfig.Feature... features) + { + int flags = _featureFlags; + for (Feature f : features) { + flags |= f.getMask(); + } + return new DeserializationConfig(this, flags); + } + + /** + * Fluent factory method that will construct and return a new configuration + * object instance with specified features disabled. + * + * @since 1.9 + */ + @Override + public DeserializationConfig without(DeserializationConfig.Feature... features) + { + int flags = _featureFlags; + for (Feature f : features) { + flags &= ~f.getMask(); + } + return new DeserializationConfig(this, flags); + } + + /* + /********************************************************** + /* MapperConfig implementation + /********************************************************** + */ + + /** + * Method that checks class annotations that the argument Object has, + * and modifies settings of this configuration object accordingly, + * similar to how those annotations would affect actual value classes + * annotated with them, but with global scope. Note that not all + * annotations have global significance, and thus only subset of + * Jackson annotations will have any effect. + *<p> + * Ones that are known to have effect are: + *<ul> + * <li>{@link JsonAutoDetect}</li> + *</ul> + * + * @param cls Class of which class annotations to use + * for changing configuration settings + * + * @deprecated Since 1.9, it is preferably to explicitly configure + * instances; this method also modifies existing instance which is + * against immutable design goals of this class. + */ + @Deprecated + @Override + public void fromAnnotations(Class<?> cls) + { + /* no class annotation for: + * + * - CAN_OVERRIDE_ACCESS_MODIFIERS + * - USE_BIG_DECIMAL_FOR_FLOATS + * - USE_BIG_INTEGER_FOR_INTS + * - USE_GETTERS_AS_SETTERS + */ + + /* 10-Jul-2009, tatu: Should be able to just pass null as + * 'MixInResolver'; no mix-ins set at this point + */ + AnnotationIntrospector ai = getAnnotationIntrospector(); + AnnotatedClass ac = AnnotatedClass.construct(cls, ai, null); + // visibility checks handled via separate checker object... + VisibilityChecker<?> prevVc = getDefaultVisibilityChecker(); + _base = _base.withVisibilityChecker(ai.findAutoDetectVisibility(ac, prevVc)); + } + + /** + * Method that is called to create a non-shared copy of the configuration + * to be used for a deserialization operation. + * Note that if sub-classing + * and sub-class has additional instance methods, + * this method <b>must</b> be overridden to produce proper sub-class + * instance. + */ + @Override + public DeserializationConfig createUnshared(SubtypeResolver subtypeResolver) + { + HashMap<ClassKey,Class<?>> mixins = _mixInAnnotations; + // ensure that we assume sharing at this point: + _mixInAnnotationsShared = true; + return new DeserializationConfig(this, mixins, subtypeResolver); + } + + /** + * Method for getting {@link AnnotationIntrospector} configured + * to introspect annotation values used for configuration. + */ + @Override + public AnnotationIntrospector getAnnotationIntrospector() + { + /* 29-Jul-2009, tatu: it's now possible to disable use of + * annotations; can be done using "no-op" introspector + */ + if (isEnabled(Feature.USE_ANNOTATIONS)) { + return super.getAnnotationIntrospector(); + } + return NopAnnotationIntrospector.instance; + } + + /** + * Accessor for getting bean description that only contains class + * annotations: useful if no getter/setter/creator information is needed. + *<p> + * Note: part of {@link MapperConfig} since 1.7 + */ + @SuppressWarnings("unchecked") + @Override + public <T extends BeanDescription> T introspectClassAnnotations(JavaType type) { + return (T) getClassIntrospector().forClassAnnotations(this, type, this); + } + + /** + * Accessor for getting bean description that only contains immediate class + * annotations: ones from the class, and its direct mix-in, if any, but + * not from super types. + *<p> + * Note: part of {@link MapperConfig} since 1.7 + */ + @Override + @SuppressWarnings("unchecked") + public <T extends BeanDescription> T introspectDirectClassAnnotations(JavaType type) { + return (T) getClassIntrospector().forDirectClassAnnotations(this, type, this); + } + + @Override + public boolean isAnnotationProcessingEnabled() { + return isEnabled(Feature.USE_ANNOTATIONS); + } + + @Override + public boolean canOverrideAccessModifiers() { + return isEnabled(Feature.CAN_OVERRIDE_ACCESS_MODIFIERS); + } + + @Override + public boolean shouldSortPropertiesAlphabetically() { + return _sortPropertiesAlphabetically; + } + + @Override + public VisibilityChecker<?> getDefaultVisibilityChecker() + { + VisibilityChecker<?> vchecker = super.getDefaultVisibilityChecker(); + if (!isEnabled(DeserializationConfig.Feature.AUTO_DETECT_SETTERS)) { + vchecker = vchecker.withSetterVisibility(Visibility.NONE); + } + if (!isEnabled(DeserializationConfig.Feature.AUTO_DETECT_CREATORS)) { + vchecker = vchecker.withCreatorVisibility(Visibility.NONE); + } + if (!isEnabled(DeserializationConfig.Feature.AUTO_DETECT_FIELDS)) { + vchecker = vchecker.withFieldVisibility(Visibility.NONE); + } + return vchecker; + } + + /* + /********************************************************** + /* MapperConfig overrides for 1.8 backwards compatibility + /********************************************************** + */ + + /* NOTE: these are overloads we MUST have, but that were missing + * from 1.9.0 and 1.9.1. Type erasure can bite in the ass... + *<p> + * NOTE: will remove either these variants, or base class one, in 2.0. + */ + + /** + * An overload for {@link MapperConfig#isEnabled(MapperConfig.ConfigFeature)}, + * needed for backwards-compatibility. + *<p> + * NOTE: will remove either this variant, or base class one, in 2.0./ + * + * @since 1.0 However, note that version 1.9.0 and 1.9.1 accidentally missed + * this overloaded variant + */ + public boolean isEnabled(DeserializationConfig.Feature f) { + return (_featureFlags & f.getMask()) != 0; + } + + /** + * @deprecated Since 1.9, it is preferable to use {@link #with} instead; + * this method is deprecated as it modifies current instance instead of + * creating a new one (as the goal is to make this class immutable) + */ + @Deprecated + @Override + public void enable(DeserializationConfig.Feature f) { + super.enable(f); + } + + /** + * @deprecated Since 1.9, it is preferable to use {@link #without} instead; + * this method is deprecated as it modifies current instance instead of + * creating a new one (as the goal is to make this class immutable) + */ + @Deprecated + @Override + public void disable(DeserializationConfig.Feature f) { + super.disable(f); + } + + /** + * @deprecated Since 1.9, it is preferable to use {@link #without} and {@link #with} instead; + * this method is deprecated as it modifies current instance instead of + * creating a new one (as the goal is to make this class immutable) + */ + @Deprecated + @Override + public void set(DeserializationConfig.Feature f, boolean state) { + super.set(f, state); + } + + /* + /********************************************************** + /* Problem handlers + /********************************************************** + */ + + /** + * Method for getting head of the problem handler chain. May be null, + * if no handlers have been added. + */ + public LinkedNode<DeserializationProblemHandler> getProblemHandlers() + { + return _problemHandlers; + } + + /** + * Method that can be used to add a handler that can (try to) + * resolve non-fatal deserialization problems. + */ + public void addHandler(DeserializationProblemHandler h) + { + /* Sanity check: let's prevent adding same handler multiple + * times + */ + if (!LinkedNode.contains(_problemHandlers, h)) { + _problemHandlers = new LinkedNode<DeserializationProblemHandler>(h, _problemHandlers); + } + } + + /** + * Method for removing all configured problem handlers; usually done to replace + * existing handler(s) with different one(s) + * + * @since 1.1 + */ + public void clearHandlers() + { + _problemHandlers = null; + } + + /* + /********************************************************** + /* Other configuration + /********************************************************** + */ + + /** + * Method called during deserialization if Base64 encoded content + * needs to be decoded. Default version just returns default Jackson + * uses, which is modified-mime which does not add linefeeds (because + * those would have to be escaped in JSON strings). + */ + public Base64Variant getBase64Variant() { + return Base64Variants.getDefaultVariant(); + } + + /** + * @since 1.6 + */ + public final JsonNodeFactory getNodeFactory() { + return _nodeFactory; + } + + /* + /********************************************************** + /* Introspection methods + /********************************************************** + */ + + /** + * Method that will introspect full bean properties for the purpose + * of building a bean deserializer + * + * @param type Type of class to be introspected + */ + @SuppressWarnings("unchecked") + public <T extends BeanDescription> T introspect(JavaType type) { + return (T) getClassIntrospector().forDeserialization(this, type, this); + } + + /** + * Method that will introspect subset of bean properties needed to + * construct bean instance. + */ + @SuppressWarnings("unchecked") + public <T extends BeanDescription> T introspectForCreation(JavaType type) { + return (T) getClassIntrospector().forCreation(this, type, this); + } + + /* + /********************************************************** + /* Extended API: handler instantiation + /********************************************************** + */ + + @SuppressWarnings("unchecked") + public JsonDeserializer<Object> deserializerInstance(Annotated annotated, + Class<? extends JsonDeserializer<?>> deserClass) + { + HandlerInstantiator hi = getHandlerInstantiator(); + if (hi != null) { + JsonDeserializer<?> deser = hi.deserializerInstance(this, annotated, deserClass); + if (deser != null) { + return (JsonDeserializer<Object>) deser; + } + } + return (JsonDeserializer<Object>) ClassUtil.createInstance(deserClass, canOverrideAccessModifiers()); + } + + public KeyDeserializer keyDeserializerInstance(Annotated annotated, + Class<? extends KeyDeserializer> keyDeserClass) + { + HandlerInstantiator hi = getHandlerInstantiator(); + if (hi != null) { + KeyDeserializer keyDeser = hi.keyDeserializerInstance(this, annotated, keyDeserClass); + if (keyDeser != null) { + return (KeyDeserializer) keyDeser; + } + } + return (KeyDeserializer) ClassUtil.createInstance(keyDeserClass, canOverrideAccessModifiers()); + } + + public ValueInstantiator valueInstantiatorInstance(Annotated annotated, + Class<? extends ValueInstantiator> instClass) + { + HandlerInstantiator hi = getHandlerInstantiator(); + if (hi != null) { + ValueInstantiator inst = hi.valueInstantiatorInstance(this, annotated, instClass); + if (inst != null) { + return (ValueInstantiator) inst; + } + } + return (ValueInstantiator) ClassUtil.createInstance(instClass, canOverrideAccessModifiers()); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/DeserializationContext.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/DeserializationContext.java new file mode 100644 index 0000000..99c5925 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/DeserializationContext.java
@@ -0,0 +1,258 @@ +package org.codehaus.jackson.map; + +import java.io.IOException; +import java.util.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.type.TypeFactory; +import org.codehaus.jackson.map.util.ArrayBuilders; +import org.codehaus.jackson.map.util.ObjectBuffer; +import org.codehaus.jackson.node.JsonNodeFactory; +import org.codehaus.jackson.type.JavaType; + +/** + * Context for deserialization process. Used to allow passing in configuration + * settings and reusable temporary objects (scrap arrays, containers). + */ +public abstract class DeserializationContext +{ + protected final DeserializationConfig _config; + + /** + * @since 1.7 + */ + protected final int _featureFlags; + + /* + /********************************************************** + /* Life-cycle + /********************************************************** + */ + + protected DeserializationContext(DeserializationConfig config) + { + _config = config; + _featureFlags = config._featureFlags; + } + + /* + /********************************************************** + /* Configuration methods + /********************************************************** + */ + + /** + * Method for accessing configuration setting object for + * currently active deserialization. + */ + public DeserializationConfig getConfig() { return _config; } + + /** + * Returns provider that can be used for dynamically locating + * other deserializers during runtime. + * + * @since 1.5 + */ + public DeserializerProvider getDeserializerProvider() { + // will be overridden by impl class + return null; + } + + /** + * Convenience method for checking whether specified on/off + * feature is enabled + */ + public boolean isEnabled(DeserializationConfig.Feature feat) { + /* 03-Dec-2010, tatu: minor shortcut; since this is called quite often, + * let's use a local copy of feature settings: + */ + return (_featureFlags & feat.getMask()) != 0; + } + + /** + * Convenience method for accessing the default Base64 encoding + * used for decoding base64 encoded binary content. + * Same as calling: + *<pre> + * getConfig().getBase64Variant(); + *</pre> + */ + public Base64Variant getBase64Variant() { + return _config.getBase64Variant(); + } + + /** + * Accessor for getting access to the underlying JSON parser used + * for deserialization. + */ + public abstract JsonParser getParser(); + + public final JsonNodeFactory getNodeFactory() { + return _config.getNodeFactory(); + } + + /** + * @since 1.8 + */ + public JavaType constructType(Class<?> cls) { + return _config.constructType(cls); + } + + /** + * @since 1.9 + */ + public TypeFactory getTypeFactory() { + return _config.getTypeFactory(); + } + + /** + * @since 1.9 + */ + public abstract Object findInjectableValue(Object valueId, + BeanProperty forProperty, Object beanInstance); + + /* + /********************************************************** + /* Methods for accessing reusable/recyclable helper objects + /********************************************************** + */ + + /** + * Method that can be used to get access to a reusable ObjectBuffer, + * useful for efficiently constructing Object arrays and Lists. + * Note that leased buffers should be returned once deserializer + * is done, to allow for reuse during same round of deserialization. + */ + public abstract ObjectBuffer leaseObjectBuffer(); + + /** + * Method to call to return object buffer previously leased with + * {@link #leaseObjectBuffer}. + * + * @param buf Returned object buffer + */ + public abstract void returnObjectBuffer(ObjectBuffer buf); + + /** + * Method for accessing object useful for building arrays of + * primitive types (such as int[]). + */ + public abstract ArrayBuilders getArrayBuilders(); + + /* + /********************************************************** + /* Parsing methods that may use reusable/-cyclable objects + /********************************************************** + */ + + /** + * Convenience method for parsing a Date from given String, using + * currently configured date format (accessed using + * {@link DeserializationConfig#getDateFormat()}). + *<p> + * Implementation will handle thread-safety issues related to + * date formats such that first time this method is called, + * date format is cloned, and cloned instance will be retained + * for use during this deserialization round. + */ + public abstract java.util.Date parseDate(String dateStr) + throws IllegalArgumentException; + + /** + * Convenience method for constructing Calendar instance set + * to specified time, to be modified and used by caller. + */ + public abstract Calendar constructCalendar(Date d); + + /* + /********************************************************** + /* Methods for problem handling, reporting + /********************************************************** + */ + + /** + * Method deserializers can call to inform configured {@link DeserializationProblemHandler}s + * of an unrecognized property. + * + * @return True if there was a configured problem handler that was able to handle the + * proble + * + * @since 1.5 + */ + public abstract boolean handleUnknownProperty(JsonParser jp, JsonDeserializer<?> deser, Object instanceOrClass, String propName) + throws IOException, JsonProcessingException; + + /** + * Helper method for constructing generic mapping exception for specified type + */ + public abstract JsonMappingException mappingException(Class<?> targetClass); + + /** + * @since 1.9 + */ + public abstract JsonMappingException mappingException(Class<?> targetClass, JsonToken t); + + /** + * Helper method for constructing generic mapping exception with specified + * message and current location information + * + * @since 1.7 + */ + public JsonMappingException mappingException(String message) + { + return JsonMappingException.from(getParser(), message); + } + + /** + * Helper method for constructing instantiation exception for specified type, + * to indicate problem with physically constructing instance of + * specified class (missing constructor, exception from constructor) + */ + public abstract JsonMappingException instantiationException(Class<?> instClass, Throwable t); + + public abstract JsonMappingException instantiationException(Class<?> instClass, String msg); + + /** + * Helper method for constructing exception to indicate that input JSON + * String was not in recognized format for deserializing into given type. + */ + public abstract JsonMappingException weirdStringException(Class<?> instClass, String msg); + + /** + * Helper method for constructing exception to indicate that input JSON + * Number was not suitable for deserializing into given type. + */ + public abstract JsonMappingException weirdNumberException(Class<?> instClass, String msg); + + /** + * Helper method for constructing exception to indicate that given JSON + * Object field name was not in format to be able to deserialize specified + * key type. + */ + public abstract JsonMappingException weirdKeyException(Class<?> keyClass, String keyValue, String msg); + + /** + * Helper method for indicating that the current token was expected to be another + * token. + */ + public abstract JsonMappingException wrongTokenException(JsonParser jp, JsonToken expToken, String msg); + + /** + * Helper method for constructing exception to indicate that JSON Object + * field name did not map to a known property of type being + * deserialized. + * + * @param instanceOrClass Either value being populated (if one has been + * instantiated), or Class that indicates type that would be (or + * have been) instantiated + */ + public abstract JsonMappingException unknownFieldException(Object instanceOrClass, String fieldName); + + /** + * Helper method for constructing exception to indicate that given + * type id (parsed from JSON) could not be converted to a Java type. + * + * @since 1.5 + */ + public abstract JsonMappingException unknownTypeException(JavaType baseType, String id); +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/DeserializationProblemHandler.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/DeserializationProblemHandler.java new file mode 100644 index 0000000..925ff14 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/DeserializationProblemHandler.java
@@ -0,0 +1,56 @@ +package org.codehaus.jackson.map; + +import java.io.IOException; + +import org.codehaus.jackson.JsonProcessingException; + +/** + * This is the class that can be registered (via + * {@link DeserializationConfig} object owner by + * {@link ObjectMapper}) to get calledn when a potentially + * recoverable problem is encountered during deserialization + * process. Handlers can try to resolve the problem, throw + * an exception or do nothing. + *<p> + * Default implementations for all methods implemented minimal + * "do nothing" functionality, which is roughly equivalent to + * not having a registered listener at all. This allows for + * only implemented handler methods one is interested in, without + * handling other cases. + * + * @author tatu + */ +public abstract class DeserializationProblemHandler +{ + /** + * Method called when a Json Map ("Object") entry with an unrecognized + * name is encountered. + * Content (supposedly) matching the property are accessible via + * parser that can be obtained from passed deserialization context. + * Handler can also choose to skip the content; if so, it MUST return + * true to indicate it did handle property succesfully. + * Skipping is usually done like so: + *<pre> + * ctxt.getParser().skipChildren(); + *</pre> + *<p> + * Note: version 1.2 added new deserialization feature + * (<code>DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES</code>). + * It will only have effect <b>after</b> handler is called, and only + * if handler did <b>not</b> handle the problem. + * + * @param beanOrClass Either bean instance being deserialized (if one + * has been instantiated so far); or Class that indicates type that + * will be instantiated (if no instantiation done yet: for example + * when bean uses non-default constructors) + * + * @return True if the problem was succesfully resolved (and content available + * used or skipped); false if listen + */ + public boolean handleUnknownProperty(DeserializationContext ctxt, JsonDeserializer<?> deserializer, + Object beanOrClass, String propertyName) + throws IOException, JsonProcessingException + { + return false; + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/DeserializerFactory.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/DeserializerFactory.java new file mode 100644 index 0000000..29d2cc7 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/DeserializerFactory.java
@@ -0,0 +1,352 @@ +package org.codehaus.jackson.map; + +import org.codehaus.jackson.map.deser.BeanDeserializerModifier; +import org.codehaus.jackson.map.deser.ValueInstantiator; +import org.codehaus.jackson.map.deser.ValueInstantiators; +import org.codehaus.jackson.map.introspect.BasicBeanDescription; +import org.codehaus.jackson.map.type.*; +import org.codehaus.jackson.type.JavaType; + +/** + * Abstract class that defines API used by {@link DeserializerProvider} + * to obtain actual + * {@link JsonDeserializer} instances from multiple distinct factories. + *<p> + * Since there are multiple broad categories of deserializers, there are + * multiple factory methods: + *<ul> + * <li>For JSON "Array" type, we need 2 methods: one to deal with expected + * Java arrays ({@link #createArrayDeserializer}) + * and the other for other Java containers like {@link java.util.List}s + * and {@link java.util.Set}s ({@link #createCollectionDeserializer(DeserializationConfig, DeserializerProvider, CollectionType, BeanProperty)}) + * </li> + * <li>For JSON "Object" type, we need 2 methods: one to deal with + * expected Java {@link java.util.Map}s + * ({@link #createMapDeserializer}), and another for POJOs + * ({@link #createBeanDeserializer(DeserializationConfig, DeserializerProvider, JavaType, BeanProperty)}. + * </li> + * <li>For Tree Model ({@link org.codehaus.jackson.JsonNode}) properties there is + * {@link #createTreeDeserializer(DeserializationConfig, DeserializerProvider, JavaType, BeanProperty)} + * <li>For enumerated types ({@link java.lang.Enum}) there is + * {@link #createEnumDeserializer(DeserializationConfig, DeserializerProvider, JavaType, BeanProperty)} + * </li> + * <li>For all other types, {@link #createBeanDeserializer(DeserializationConfig, DeserializerProvider, JavaType, BeanProperty)} + * is used. + * </ul> + *<p> + * All above methods take 2 type arguments, except for the first one + * which takes just a single argument. + */ +public abstract class DeserializerFactory +{ + protected final static Deserializers[] NO_DESERIALIZERS = new Deserializers[0]; + + /* + /********************************************************** + /* Helper class to contain configuration settings + /********************************************************** + */ + + /** + * Configuration settings container class for bean deserializer factory + * + * @since 1.7 + */ + public abstract static class Config + { + /** + * Fluent/factory method used to construct a configuration object that + * has same deserializer providers as this instance, plus one specified + * as argument. Additional provider will be added before existing ones, + * meaning it has priority over existing definitions. + */ + public abstract Config withAdditionalDeserializers(Deserializers additional); + + /** + * Fluent/factory method used to construct a configuration object that + * has same key deserializer providers as this instance, plus one specified + * as argument. Additional provider will be added before existing ones, + * meaning it has priority over existing definitions. + */ + public abstract Config withAdditionalKeyDeserializers(KeyDeserializers additional); + + /** + * Fluent/factory method used to construct a configuration object that + * has same configuration as this instance plus one additional + * deserialiazer modifier. Added modifier has the highest priority (that is, it + * gets called before any already registered modifier). + */ + public abstract Config withDeserializerModifier(BeanDeserializerModifier modifier); + + /** + * Fluent/factory method used to construct a configuration object that + * has same configuration as this instance plus one additional + * abstract type resolver. + * Added resolver has the highest priority (that is, it + * gets called before any already registered resolver). + * + * @since 1.8 + */ + public abstract Config withAbstractTypeResolver(AbstractTypeResolver resolver); + + /** + * Fluent/factory method used to construct a configuration object that + * has same configuration as this instance plus specified additional + * value instantiator provider object. + * Added instantiator provider has the highest priority (that is, it + * gets called before any already registered resolver). + * + * @param instantiators Object that can provide {@link org.codehaus.jackson.map.deser.ValueInstantiator}s for + * constructing POJO values during deserialization + * + * @since 1.9 + */ + public abstract Config withValueInstantiators(ValueInstantiators instantiators); + + public abstract Iterable<Deserializers> deserializers(); + + /** + * @since 1.8 + */ + public abstract Iterable<KeyDeserializers> keyDeserializers(); + + public abstract Iterable<BeanDeserializerModifier> deserializerModifiers(); + + /** + * @since 1.8 + */ + public abstract Iterable<AbstractTypeResolver> abstractTypeResolvers(); + + /** + * @since 1.9 + */ + public abstract Iterable<ValueInstantiators> valueInstantiators(); + + public abstract boolean hasDeserializers(); + + /** + * @since 1.8 + */ + public abstract boolean hasKeyDeserializers(); + + public abstract boolean hasDeserializerModifiers(); + + /** + * @since 1.8 + */ + public abstract boolean hasAbstractTypeResolvers(); + + /** + * @since 1.9 + */ + public abstract boolean hasValueInstantiators(); + } + + /* + /******************************************************** + /* Configuration handling + /******************************************************** + */ + + /** + * @since 1.7 + */ + public abstract Config getConfig(); + + /** + * Method used for creating a new instance of this factory, but with different + * configuration. Reason for specifying factory method (instead of plain constructor) + * is to allow proper sub-classing of factories. + *<p> + * Note that custom sub-classes <b>must override</b> implementation + * of this method, as it usually requires instantiating a new instance of + * factory type. Check out javadocs for + * {@link org.codehaus.jackson.map.deser.BeanDeserializerFactory} for more details. + * + * @since 1.7 + */ + public abstract DeserializerFactory withConfig(Config config); + + /** + * Convenience method for creating a new factory instance with additional deserializer + * provider. + * + * @since 1.7 + */ + public final DeserializerFactory withAdditionalDeserializers(Deserializers additional) { + return withConfig(getConfig().withAdditionalDeserializers(additional)); + } + + /** + * Convenience method for creating a new factory instance with additional + * {@link KeyDeserializers}. + * + * @since 1.8 + */ + public final DeserializerFactory withAdditionalKeyDeserializers(KeyDeserializers additional) { + return withConfig(getConfig().withAdditionalKeyDeserializers(additional)); + } + + /** + * Convenience method for creating a new factory instance with additional + * {@link BeanDeserializerModifier}. + * + * @since 1.7 + */ + public final DeserializerFactory withDeserializerModifier(BeanDeserializerModifier modifier) { + return withConfig(getConfig().withDeserializerModifier(modifier)); + } + + /** + * Convenience method for creating a new factory instance with additional + * {@link AbstractTypeResolver}. + * + * @since 1.7 + */ + public final DeserializerFactory withAbstractTypeResolver(AbstractTypeResolver resolver) { + return withConfig(getConfig().withAbstractTypeResolver(resolver)); + } + + /** + * Convenience method for creating a new factory instance with additional + * {@link ValueInstantiators}. + * + * @since 1.9 + */ + public final DeserializerFactory withValueInstantiators(ValueInstantiators instantiators) { + return withConfig(getConfig().withValueInstantiators(instantiators)); + } + + /* + /********************************************************** + /* Basic DeserializerFactory API: + /********************************************************** + */ + + /** + * Method that can be called to try to resolve an abstract type + * (interface, abstract class) into a concrete type, or at least + * something "more concrete" (abstract class instead of interface). + * Will either return passed type, or a more specific type. + * + * @since 1.9 + */ + public abstract JavaType mapAbstractType(DeserializationConfig config, JavaType type) + throws JsonMappingException; + + /** + * Method that is to find all creators (constructors, factory methods) + * for the bean type to deserialize. + * + * @since 1.9 + */ + public abstract ValueInstantiator findValueInstantiator(DeserializationConfig config, + BasicBeanDescription beanDesc) + throws JsonMappingException; + + /** + * Method called to create (or, for completely immutable deserializers, + * reuse) a deserializer that can convert JSON content into values of + * specified Java "bean" (POJO) type. + * At this point it is known that the type is not otherwise recognized + * as one of structured types (array, Collection, Map) or a well-known + * JDK type (enum, primitives/wrappers, String); this method only + * gets called if other options are exhausted. This also means that + * this method can be overridden to add support for custom types. + * + * @param type Type to be deserialized + * @param p Provider that can be called to create deserializers for + * contained member types + */ + public abstract JsonDeserializer<Object> createBeanDeserializer(DeserializationConfig config, DeserializerProvider p, + JavaType type, BeanProperty property) + throws JsonMappingException; + + /** + * Method called to create (or, for completely immutable deserializers, + * reuse) a deserializer that can convert JSON content into values of + * specified Java type. + * + * @param type Type to be deserialized + * @param p Provider that can be called to create deserializers for + * contained member types + */ + public abstract JsonDeserializer<?> createArrayDeserializer(DeserializationConfig config, DeserializerProvider p, + ArrayType type, BeanProperty property) + throws JsonMappingException; + + public abstract JsonDeserializer<?> createCollectionDeserializer(DeserializationConfig config, + DeserializerProvider p, CollectionType type, BeanProperty property) + throws JsonMappingException; + + /** + * @since 1.8 + */ + public abstract JsonDeserializer<?> createCollectionLikeDeserializer(DeserializationConfig config, + DeserializerProvider p, CollectionLikeType type, BeanProperty property) + throws JsonMappingException; + + public abstract JsonDeserializer<?> createEnumDeserializer(DeserializationConfig config, + DeserializerProvider p, JavaType type, BeanProperty property) + throws JsonMappingException; + + public abstract JsonDeserializer<?> createMapDeserializer(DeserializationConfig config, + DeserializerProvider p, MapType type, BeanProperty property) + throws JsonMappingException; + + /** + * @since 1.8 + */ + public abstract JsonDeserializer<?> createMapLikeDeserializer(DeserializationConfig config, + DeserializerProvider p, MapLikeType type, BeanProperty property) + throws JsonMappingException; + + /** + * Method called to create and return a deserializer that can construct + * JsonNode(s) from JSON content. + */ + public abstract JsonDeserializer<?> createTreeDeserializer(DeserializationConfig config, DeserializerProvider p, + JavaType type, BeanProperty property) + throws JsonMappingException; + + /** + * Method called to find if factory knows how to create a key deserializer + * for specified type; currently this means checking if a module has registered + * possible deserializers. + * + * @return Key deserializer to use for specified type, if one found; null if not + * (and default key deserializer should be used) + * + * @since 1.8 + */ + public KeyDeserializer createKeyDeserializer(DeserializationConfig config, JavaType type, + BeanProperty property) + throws JsonMappingException + { + // Default implementation returns null for backwards compatibility reasons + return null; + } + + /** + * Method called to find and create a type information deserializer for given base type, + * if one is needed. If not needed (no polymorphic handling configured for type), + * should return null. + *<p> + * Note that this method is usually only directly called for values of container (Collection, + * array, Map) types and root values, but not for bean property values. + * + * @param baseType Declared base type of the value to deserializer (actual + * deserializer type will be this type or its subtype) + * + * @return Type deserializer to use for given base type, if one is needed; null if not. + * + * @since 1.5 + */ + public TypeDeserializer findTypeDeserializer(DeserializationConfig config, JavaType baseType, + BeanProperty property) + throws JsonMappingException + { + // Default implementation returns null for backwards compatibility reasons + return null; + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/DeserializerProvider.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/DeserializerProvider.java new file mode 100644 index 0000000..30ccc48 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/DeserializerProvider.java
@@ -0,0 +1,185 @@ +package org.codehaus.jackson.map; + +import org.codehaus.jackson.io.SerializedString; +import org.codehaus.jackson.map.deser.BeanDeserializerModifier; +import org.codehaus.jackson.map.deser.ValueInstantiators; +import org.codehaus.jackson.type.JavaType; + +/** + * Abstract class that defines API used by {@link ObjectMapper} and + * {@link JsonDeserializer}s to obtain deserializers capable of + * re-constructing instances of handled type from JSON content. + */ +public abstract class DeserializerProvider +{ + protected DeserializerProvider() { } + + /* + /********************************************************** + /* Fluent factory methods + /********************************************************** + */ + + /** + * Method that sub-classes need to override, to ensure that fluent-factory + * methods will produce proper sub-type. + * + * @since 1.9 + */ + public abstract DeserializerProvider withFactory(DeserializerFactory factory); + + /** + * Method that is to configure {@link DeserializerFactory} that provider has + * to use specified deserializer provider, with highest precedence (that is, + * additional providers have higher precedence than default one or previously + * added ones) + * + * @since 1.7 + */ + public abstract DeserializerProvider withAdditionalDeserializers(Deserializers d); + + /** + * @since 1.8 + */ + public abstract DeserializerProvider withAdditionalKeyDeserializers(KeyDeserializers d); + + /** + * @since 1.7 + */ + public abstract DeserializerProvider withDeserializerModifier(BeanDeserializerModifier modifier); + + /** + * @since 1.8 + */ + public abstract DeserializerProvider withAbstractTypeResolver(AbstractTypeResolver resolver); + + /** + * Method that will construct a new instance with specified additional value instantiators + * (i.e. does NOT replace existing ones) + * + * @since 1.9 + */ + public abstract DeserializerProvider withValueInstantiators(ValueInstantiators instantiators); + + /* + /********************************************************** + /* General deserializer locating method + /********************************************************** + */ + + /** + * Method called to get hold of a deserializer for a value of given type; + * or if no such deserializer can be found, a default handler (which + * may do a best-effort generic serialization or just simply + * throw an exception when invoked). + *<p> + * Note: this method is only called for value types; not for keys. + * Key deserializers can be accessed using {@link #findKeyDeserializer}. + * + * @param config Deserialization configuration + * @param propertyType Declared type of the value to deserializer (obtained using + * 'setter' method signature and/or type annotations + * @param property Object that represents accessor for property value; field, + * setter method or constructor parameter. + * + * @throws JsonMappingException if there are fatal problems with + * accessing suitable deserializer; including that of not + * finding any serializer + */ + public abstract JsonDeserializer<Object> findValueDeserializer(DeserializationConfig config, + JavaType propertyType, BeanProperty property) + throws JsonMappingException; + + /** + * Method called to locate deserializer for given type, as well as matching + * type deserializer (if one is needed); and if type deserializer is needed, + * construct a "wrapped" deserializer that can extract and use type information + * for calling actual deserializer. + *<p> + * Since this method is only called for root elements, no referral information + * is taken. + * + * @since 1.5 + */ + public abstract JsonDeserializer<Object> findTypedValueDeserializer(DeserializationConfig config, + JavaType type, BeanProperty property) + throws JsonMappingException; + + /** + * Method called to get hold of a deserializer to use for deserializing + * keys for {@link java.util.Map}. + * + * @throws JsonMappingException if there are fatal problems with + * accessing suitable key deserializer; including that of not + * finding any serializer + */ + public abstract KeyDeserializer findKeyDeserializer(DeserializationConfig config, + JavaType keyType, BeanProperty property) + throws JsonMappingException; + + /** + * Method called to find out whether provider would be able to find + * a deserializer for given type, using a root reference (i.e. not + * through fields or membership in an array or collection) + */ + public abstract boolean hasValueDeserializerFor(DeserializationConfig config, JavaType type); + + /* + /********************************************************** + /* Additional type handling methods, related + /********************************************************** + */ + + /** + * Method that can be called to try to resolve an abstract type + * (interface, abstract class) into a concrete type, or at least + * something "more concrete" (abstract class instead of interface). + * Will either return passed type, or a more specific type. + * + * @since 1.9 + */ + public abstract JavaType mapAbstractType(DeserializationConfig config, JavaType type) + throws JsonMappingException; + + + /** + * Method that can be used to try find expected root name for given type + * + * @since 1.9 + */ + public abstract SerializedString findExpectedRootName(DeserializationConfig config, JavaType type) + throws JsonMappingException; + + /* + /********************************************************** + /* Access to caching aspects + /********************************************************** + */ + + /** + * Method that can be used to determine how many deserializers this + * provider is caching currently + * (if it does caching: default implementation does) + * Exact count depends on what kind of deserializers get cached; + * default implementation caches only dynamically constructed deserializers, + * but not eagerly constructed standard deserializers (which is different + * from how serializer provider works). + *<p> + * The main use case for this method is to allow conditional flushing of + * deserializer cache, if certain number of entries is reached. + * + * @since 1.4 + */ + public abstract int cachedDeserializersCount(); + + /** + * Method that will drop all dynamically constructed deserializers (ones that + * are counted as result value for {@link #cachedDeserializersCount}). + * This can be used to remove memory usage (in case some deserializers are + * only used once or so), or to force re-construction of deserializers after + * configuration changes for mapper than owns the provider. + * + * @since 1.4 + */ + public abstract void flushCachedDeserializers(); +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/Deserializers.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/Deserializers.java new file mode 100644 index 0000000..175281e --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/Deserializers.java
@@ -0,0 +1,335 @@ +package org.codehaus.jackson.map; + +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.map.type.*; +import org.codehaus.jackson.type.JavaType; + +/** + * Interface that defines API for simple extensions that can provide additional deserializers + * for various types. Access is by a single callback method; instance is to either return + * a configured {@link JsonDeserializer} for specified type, or null to indicate that it + * does not support handling of the type. In latter case, further calls can be made + * for other providers; in former case returned deserializer is used for handling of + * instances of specified type. + *<p> + * Unlike with {@link Serializers}, multiple different methods are used since different + * kinds of types typically require different kinds of inputs. + * + * @since 1.7 + */ +public interface Deserializers +{ + /** + * Method called to locate serializer for specified array type. + *<p> + * Deserializer for element type may be passed, if configured explicitly at higher level (by + * annotations, typically), but usually are not. + * Type deserializer for element is passed if one is needed based on contextual information + * (annotations on declared element class; or on field or method type is associated with). + * + * @param type Type of array instances to deserialize + * @param config Configuration in effect + * @param provider Provider that can be used to locate deserializer for component type (if + * one not provided, or needs to be overridden) + * @param property Property that contains array value (null for root values) + * @param elementTypeDeserializer If element type needs polymorphic type handling, this is + * the type information deserializer to use; should usually be used as is when constructing + * array deserializer. + * @param elementDeserializer Deserializer to use for elements, if explicitly defined (by using + * annotations, for exmple). May be null, in which case it should be resolved here (or using + * {@link ResolvableDeserializer} callback) + * + * @return Deserializer to use for the type; or null if this provider does not know how to construct it + */ + public JsonDeserializer<?> findArrayDeserializer(ArrayType type, DeserializationConfig config, + DeserializerProvider provider, + BeanProperty property, + TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer) + throws JsonMappingException; + + /** + * Method called to locate serializer for specified {@link java.util.Collection} (List, Set etc) type. + *<p> + * Deserializer for element type may be passed, if configured explicitly at higher level (by + * annotations, typically), but usually are not. + * Type deserializer for element is passed if one is needed based on contextual information + * (annotations on declared element class; or on field or method type is associated with). + * + * @param type Type of collection instances to deserialize + * @param config Configuration in effect + * @param provider Provider that can be used to locate dependant deserializers if and as necessary + * (but note that in many cases resolution must be deferred by using {@link ResolvableDeserializer} callback) + * @param property Property that contains array value (null for root values) + * @param beanDesc Definition of the enumeration type that contains class annotations and + * other information typically needed for building deserializers (note: always instance + * of {@link org.codehaus.jackson.map.introspect.BasicBeanDescription}) + * @param elementTypeDeserializer If element type needs polymorphic type handling, this is + * the type information deserializer to use; should usually be used as is when constructing + * array deserializer. + * @param elementDeserializer Deserializer to use for elements, if explicitly defined (by using + * annotations, for exmple). May be null, in which case it should be resolved here (or using + * {@link ResolvableDeserializer} callback) + * + * @return Deserializer to use for the type; or null if this provider does not know how to construct it + */ + public JsonDeserializer<?> findCollectionDeserializer(CollectionType type, DeserializationConfig config, + DeserializerProvider provider, BeanDescription beanDesc, BeanProperty property, + TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer) + throws JsonMappingException; + + /** + * Method called to locate serializer for specified + * "Collection-like" type (one that acts + * like {@link java.util.Collection} but does not implement it). + *<p> + * Deserializer for element type may be passed, if configured explicitly at higher level (by + * annotations, typically), but usually are not. + * Type deserializer for element is passed if one is needed based on contextual information + * (annotations on declared element class; or on field or method type is associated with). + * + * @param type Type of instances to deserialize + * @param config Configuration in effect + * @param provider Provider that can be used to locate dependant deserializers if and as necessary + * (but note that in many cases resolution must be deferred by using {@link ResolvableDeserializer} callback) + * @param property Property that contains array value (null for root values) + * @param beanDesc Definition of the enumeration type that contains class annotations and + * other information typically needed for building deserializers (note: always instance + * of {@link org.codehaus.jackson.map.introspect.BasicBeanDescription}) + * @param elementTypeDeserializer If element type needs polymorphic type handling, this is + * the type information deserializer to use; should usually be used as is when constructing + * array deserializer. + * @param elementDeserializer Deserializer to use for elements, if explicitly defined (by using + * annotations, for exmple). May be null, in which case it should be resolved here (or using + * {@link ResolvableDeserializer} callback) + * + * @return Deserializer to use for the type; or null if this provider does not know how to construct it + * + * @since 1.8 + */ + public JsonDeserializer<?> findCollectionLikeDeserializer(CollectionLikeType type, DeserializationConfig config, + DeserializerProvider provider, BeanDescription beanDesc, BeanProperty property, + TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer) + throws JsonMappingException; + + /** + * Method called to locate deserializer for specified {@link java.lang.Enum} type. + * + * @param type Type of {@link java.lang.Enum} instances to deserialize + * @param config Configuration in effect + * @param beanDesc Definition of the enumeration type that contains class annotations and + * other information typically needed for building deserializers (note: always instance + * of {@link org.codehaus.jackson.map.introspect.BasicBeanDescription}) + * + * @return Deserializer to use for the type; or null if this provider does not know how to construct it + */ + public JsonDeserializer<?> findEnumDeserializer(Class<?> type, DeserializationConfig config, + BeanDescription beanDesc, BeanProperty property) + throws JsonMappingException; + + /** + * Method called to locate deserializer for specified {@link java.util.Map} type. + *<p> + * Deserializer for element type may be passed, if configured explicitly at higher level (by + * annotations, typically), but usually are not. + * Type deserializer for element is passed if one is needed based on contextual information + * (annotations on declared element class; or on field or method type is associated with). + *<p> + * Similarly, a {@link KeyDeserializer} may be passed, but this is only done if there is + * a specific configuration override (annotations) to indicate instance to use. Otherwise + * null is passed, and key deserializer needs to be obtained using {@link DeserializerProvider} + * + * @param type Type of {@link java.util.Map} instances to deserialize + * @param config Configuration in effect + * @param provider Provider that can be used to locate dependant deserializers if and as necessary + * (but note that in many cases resolution must be deferred by using {@link ResolvableDeserializer} callback) + * @param beanDesc Definition of the enumeration type that contains class annotations and + * other information typically needed for building deserializers (note: always instance + * of {@link org.codehaus.jackson.map.introspect.BasicBeanDescription}) + * @param keyDeserializer Key deserializer use, if it is defined via annotations or other configuration; + * null if default key deserializer for key type can be used. + * @param elementTypeDeserializer If element type needs polymorphic type handling, this is + * the type information deserializer to use; should usually be used as is when constructing + * array deserializer. + * @param elementDeserializer Deserializer to use for elements, if explicitly defined (by using + * annotations, for exmple). May be null, in which case it should be resolved here (or using + * {@link ResolvableDeserializer} callback) + * + * @return Deserializer to use for the type; or null if this provider does not know how to construct it + */ + public JsonDeserializer<?> findMapDeserializer(MapType type, DeserializationConfig config, + DeserializerProvider provider, BeanDescription beanDesc, BeanProperty property, + KeyDeserializer keyDeserializer, + TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer) + throws JsonMappingException; + + /** + * Method called to locate serializer for specified + * "Map-like" type (one that acts + * like {@link java.util.Map} but does not implement it). + *<p> + * Deserializer for element type may be passed, if configured explicitly at higher level (by + * annotations, typically), but usually are not. + * Type deserializer for element is passed if one is needed based on contextual information + * (annotations on declared element class; or on field or method type is associated with). + *<p> + * Similarly, a {@link KeyDeserializer} may be passed, but this is only done if there is + * a specific configuration override (annotations) to indicate instance to use. Otherwise + * null is passed, and key deserializer needs to be obtained using {@link DeserializerProvider} + * + * @param type Type of {@link java.util.Map} instances to deserialize + * @param config Configuration in effect + * @param provider Provider that can be used to locate dependant deserializers if and as necessary + * (but note that in many cases resolution must be deferred by using {@link ResolvableDeserializer} callback) + * @param beanDesc Definition of the enumeration type that contains class annotations and + * other information typically needed for building deserializers (note: always instance + * of {@link org.codehaus.jackson.map.introspect.BasicBeanDescription}) + * @param keyDeserializer Key deserializer use, if it is defined via annotations or other configuration; + * null if default key deserializer for key type can be used. + * @param elementTypeDeserializer If element type needs polymorphic type handling, this is + * the type information deserializer to use; should usually be used as is when constructing + * array deserializer. + * @param elementDeserializer Deserializer to use for elements, if explicitly defined (by using + * annotations, for exmple). May be null, in which case it should be resolved here (or using + * {@link ResolvableDeserializer} callback) + * + * @return Deserializer to use for the type; or null if this provider does not know how to construct it + * + * @since 1.8 + */ + public JsonDeserializer<?> findMapLikeDeserializer(MapLikeType type, DeserializationConfig config, + DeserializerProvider provider, BeanDescription beanDesc, BeanProperty property, + KeyDeserializer keyDeserializer, + TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer) + throws JsonMappingException; + + /** + * Method called to locate deserializer for specified JSON tree node type. + * + * @param nodeType Specific type of JSON tree nodes to deserialize (subtype of {@link org.codehaus.jackson.JsonNode}) + * @param config Configuration in effect + * + * @return Deserializer to use for the type; or null if this provider does not know how to construct it + */ + public JsonDeserializer<?> findTreeNodeDeserializer(Class<? extends JsonNode> nodeType, DeserializationConfig config, + BeanProperty property) + throws JsonMappingException; + + /** + * Method called to locate deserializer for specified value type which does not belong to any other + * category (not an Enum, Collection, Map, Array or tree node) + * + * @param type Bean type to deserialize + * @param config Configuration in effect + * @param provider Provider that can be used to locate dependant deserializers if and as necessary + * (but note that in many cases resolution must be deferred by using {@link ResolvableDeserializer} callback) + * @param beanDesc Definition of the enumeration type that contains class annotations and + * other information typically needed for building deserializers (note: always instance + * of {@link org.codehaus.jackson.map.introspect.BasicBeanDescription}) + * + * @return Deserializer to use for the type; or null if this provider does not know how to construct it + */ + public JsonDeserializer<?> findBeanDeserializer(JavaType type, DeserializationConfig config, + DeserializerProvider provider, BeanDescription beanDesc, + BeanProperty property) + throws JsonMappingException; + + /* + /********************************************************** + /* Helper classes + /********************************************************** + */ + + /** + * Basic {@link Deserializers} implementation that implements all methods but provides + * no deserializers. Its main purpose is to serve as a base class so that + * sub-classes only need to override methods they need, as most of the time some + * of methods are not needed (especially enumeration and array deserializers are + * very rarely overridden). + * + * @since 1.9 + */ + public static class Base implements Deserializers + { + @Override + public JsonDeserializer<?> findArrayDeserializer(ArrayType type, DeserializationConfig config, + DeserializerProvider provider, BeanProperty property, + TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer) + throws JsonMappingException + { + return null; + } + + @Override + public JsonDeserializer<?> findCollectionDeserializer(CollectionType type, DeserializationConfig config, + DeserializerProvider provider, BeanDescription beanDesc, BeanProperty property, + TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer) + throws JsonMappingException + { + return null; + } + + @Override + public JsonDeserializer<?> findCollectionLikeDeserializer(CollectionLikeType type, DeserializationConfig config, + DeserializerProvider provider, BeanDescription beanDesc, BeanProperty property, + TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer) + throws JsonMappingException + { + return null; + } + + @Override + public JsonDeserializer<?> findMapDeserializer(MapType type, DeserializationConfig config, + DeserializerProvider provider, BeanDescription beanDesc, BeanProperty property, + KeyDeserializer keyDeserializer, + TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer) + throws JsonMappingException + { + return null; + } + + @Override + public JsonDeserializer<?> findMapLikeDeserializer(MapLikeType type, DeserializationConfig config, + DeserializerProvider provider, BeanDescription beanDesc, BeanProperty property, + KeyDeserializer keyDeserializer, + TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer) + throws JsonMappingException + { + return null; + } + + @Override + public JsonDeserializer<?> findEnumDeserializer(Class<?> type, DeserializationConfig config, + BeanDescription beanDesc, + BeanProperty property) + throws JsonMappingException + { + return null; + } + + @Override + public JsonDeserializer<?> findTreeNodeDeserializer(Class<? extends JsonNode> nodeType, + DeserializationConfig config, + BeanProperty property) + throws JsonMappingException + { + return null; + } + + @Override + public JsonDeserializer<?> findBeanDeserializer(JavaType type, DeserializationConfig config, + DeserializerProvider provider, + BeanDescription beanDesc, + BeanProperty property) + throws JsonMappingException + { + return null; + } + } + + + /** + * @deprecated As of 1.9, use {@link Base} instead + */ + @Deprecated + public static class None extends Base { } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/HandlerInstantiator.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/HandlerInstantiator.java new file mode 100644 index 0000000..3ae2e0b --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/HandlerInstantiator.java
@@ -0,0 +1,115 @@ +package org.codehaus.jackson.map; + +import org.codehaus.jackson.map.deser.ValueInstantiator; +import org.codehaus.jackson.map.introspect.Annotated; +import org.codehaus.jackson.map.jsontype.TypeIdResolver; +import org.codehaus.jackson.map.jsontype.TypeResolverBuilder; + +/** + * Helper class used for handling details of creating handler instances (things + * like {@link JsonSerializer}s, {@link JsonDeserializer}s, various type + * handlers) of specific types. Actual handler type has been resolved at this + * point, so instantiator is strictly responsible for providing a configured + * instance by constructing and configuring a new instance, or possibly by + * recycling a shared instance. One use case is that of allowing + * dependency injection, which would otherwise be difficult to do. + *<p> + * Custom instances are allowed to return null to indicate that caller should + * use the default instantiation handling (which just means calling no-argument + * constructor via reflection). + *<p> + * Care has to be taken to ensure that if instance returned is shared, it will + * be thread-safe; caller will not synchronize access to returned instances. + * + * @since 1.8 + */ +public abstract class HandlerInstantiator +{ + /* + /********************************************************** + /* Public API + /********************************************************** + */ + + /** + * Method called to get an instance of deserializer of specified type. + * + * @param config Deserialization configuration in effect + * @param annotated Element (Class, Method, Field, constructor parameter) that + * had annotation defining class of deserializer to construct (to allow + * implementation use information from other annotations) + * @param deserClass Class of deserializer instance to return + * + * @return Deserializer instance to use + */ + public abstract JsonDeserializer<?> deserializerInstance(DeserializationConfig config, + Annotated annotated, Class<? extends JsonDeserializer<?>> deserClass); + + /** + * Method called to get an instance of key deserializer of specified type. + * + * @param config Deserialization configuration in effect + * @param annotated Element (Class, Method, Field, constructor parameter) that + * had annotation defining class of key deserializer to construct (to allow + * implementation use information from other annotations) + * @param keyDeserClass Class of key deserializer instance to return + * + * @return Key deserializer instance to use + */ + public abstract KeyDeserializer keyDeserializerInstance(DeserializationConfig config, + Annotated annotated, Class<? extends KeyDeserializer> keyDeserClass); + + /** + * Method called to get an instance of serializer of specified type. + * + * @param config Serialization configuration in effect + * @param annotated Element (Class, Method, Field) that + * had annotation defining class of serializer to construct (to allow + * implementation use information from other annotations) + * @param serClass Class of serializer instance to return + * + * @return Serializer instance to use + */ + public abstract JsonSerializer<?> serializerInstance(SerializationConfig config, + Annotated annotated, Class<? extends JsonSerializer<?>> serClass); + + /** + * Method called to get an instance of TypeResolverBuilder of specified type. + * + * @param config Mapper configuration in effect (either SerializationConfig or + * DeserializationConfig, depending on when instance is being constructed) + * @param annotated annotated Element (Class, Method, Field) that + * had annotation defining class of builder to construct (to allow + * implementation use information from other annotations) + * @param builderClass Class of builder instance to return + * + * @return TypeResolverBuilder instance to use + */ + public abstract TypeResolverBuilder<?> typeResolverBuilderInstance(MapperConfig<?> config, + Annotated annotated, Class<? extends TypeResolverBuilder<?>> builderClass); + + /** + * Method called to get an instance of TypeIdResolver of specified type. + * + * @param config Mapper configuration in effect (either SerializationConfig or + * DeserializationConfig, depending on when instance is being constructed) + * @param annotated annotated Element (Class, Method, Field) that + * had annotation defining class of resolver to construct (to allow + * implementation use information from other annotations) + * @param resolverClass Class of resolver instance to return + * + * @return TypeResolverBuilder instance to use + */ + public abstract TypeIdResolver typeIdResolverInstance(MapperConfig<?> config, + Annotated annotated, Class<? extends TypeIdResolver> resolverClass); + + /** + * Method called to construct an instance of ValueInstantiator of specified type. + * + * @since 1.9 + */ + public ValueInstantiator valueInstantiatorInstance(MapperConfig<?> config, + Annotated annotated, Class<? extends ValueInstantiator> resolverClass) { + return null; + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/InjectableValues.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/InjectableValues.java new file mode 100644 index 0000000..8613159 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/InjectableValues.java
@@ -0,0 +1,84 @@ +package org.codehaus.jackson.map; + +import java.util.*; + +/** + * Abstract class that defines API for objects that provide value to + * "inject" during deserialization. An instance of this object + * + * @since 1.9 + */ +public abstract class InjectableValues +{ + /** + * Method called to find value identified by id <code>valueId</code> to + * inject as value of specified property during deserialization, passing + * POJO instance in which value will be injected if it is available + * (will be available when injected via field or setter; not available + * when injected via constructor or factory method argument). + * + * @param valueId Object that identifies value to inject; may be a simple + * name or more complex identifier object, whatever provider needs + * @param ctxt Deserialization context + * @param forProperty Bean property in which value is to be injected + * @param beanInstance Bean instance that contains property to inject, + * if available; null if bean has not yet been constructed. + */ + public abstract Object findInjectableValue(Object valueId, + DeserializationContext ctxt, BeanProperty forProperty, + Object beanInstance); + + /* + /********************************************************** + /* Standard implementation + /********************************************************** + */ + + /** + * Simple standard implementation which uses a simple Map to + * store values to inject, identified by simple String keys. + */ + public static class Std + extends InjectableValues + { + protected final Map<String,Object> _values; + + public Std() { + this(new HashMap<String,Object>()); + } + + public Std(Map<String,Object> values) { + _values = values; + } + + public Std addValue(String key, Object value) + { + _values.put(key, value); + return this; + } + + public Std addValue(Class<?> classKey, Object value) + { + _values.put(classKey.getName(), value); + return this; + } + + @Override + public Object findInjectableValue(Object valueId, + DeserializationContext ctxt, BeanProperty forProperty, + Object beanInstance) + { + if (!(valueId instanceof String)) { + String type = (valueId == null) ? "[null]" : valueId.getClass().getName(); + throw new IllegalArgumentException("Unrecognized inject value id type ("+type+"), expecting String"); + } + String key = (String) valueId; + Object ob = _values.get(key); + if (ob == null && !_values.containsKey(key)) { + throw new IllegalArgumentException("No injectable id with value '"+key+"' found (for property '" + +forProperty.getName()+"')"); + } + return ob; + } + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/JsonDeserializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/JsonDeserializer.java new file mode 100644 index 0000000..fe71740 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/JsonDeserializer.java
@@ -0,0 +1,164 @@ +package org.codehaus.jackson.map; + +import java.io.IOException; + +import org.codehaus.jackson.*; + +/** + * Abstract class that defines API used by {@link ObjectMapper} (and + * other chained {@link JsonDeserializer}s too) to deserialize Objects of + * arbitrary types from JSON, using provided {@link JsonParser}. + */ +public abstract class JsonDeserializer<T> +{ + /* + /********************************************************** + /* Main deserialization methods + /********************************************************** + */ + + /** + * Method that can be called to ask implementation to deserialize + * JSON content into the value type this serializer handles. + * Returned instance is to be constructed by method itself. + *<p> + * Pre-condition for this method is that the parser points to the + * first event that is part of value to deserializer (and which + * is never JSON 'null' literal, more on this below): for simple + * types it may be the only value; and for structured types the + * Object start marker. + * Post-condition is that the parser will point to the last + * event that is part of deserialized value (or in case deserialization + * fails, event that was not recognized or usable, which may be + * the same event as the one it pointed to upon call). + *<p> + * Note that this method is never called for JSON null literal, + * and thus deserializers need (and should) not check for it. + * + * @param jp Parsed used for reading JSON content + * @param ctxt Context that can be used to access information about + * this deserialization activity. + * + * @return Deserializer value + */ + public abstract T deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException; + + /** + * Alternate deserialization method (compared to the most commonly + * used, {@link #deserialize(JsonParser, DeserializationContext)}), + * which takes in initialized value instance, to be + * configured and/or populated by deserializer. + * Method is not necessarily used for all supported types; most commonly + * it is used + * for Collections and Maps. + *<p> + * Default implementation just throws + * {@link UnsupportedOperationException}, to indicate that types + * that do not explicitly add support do not expect to get the call. + */ + public T deserialize(JsonParser jp, DeserializationContext ctxt, + T intoValue) + throws IOException, JsonProcessingException + { + throw new UnsupportedOperationException(); + } + + /** + * Deserialization called when type being deserialized is defined to + * contain additional type identifier, to allow for correctly + * instantiating correct subtype. This can be due to annotation on + * type (or its supertype), or due to global settings without + * annotations. + *<p> + * Default implementation may work for some types, but ideally subclasses + * should not rely on current default implementation. + * Implementation is mostly provided to avoid compilation errors with older + * code. + * + * @param typeDeserializer Deserializer to use for handling type information + * + * @since 1.5 + */ + @SuppressWarnings("unchecked") + public Object deserializeWithType(JsonParser jp, DeserializationContext ctxt, + TypeDeserializer typeDeserializer) + throws IOException, JsonProcessingException + { + // We could try calling + return (T) typeDeserializer.deserializeTypedFromAny(jp, ctxt); + } + + /* + /********************************************************** + /* Fluent factory methods for constructing decorated versions + /********************************************************** + */ + + /** + * Method that will return deserializer instance that is able + * to handle "unwrapped" value instances + * If no unwrapped instance can be constructed, will simply + * return this object as-is. + *<p> + * Default implementation just returns 'this' + * indicating that no unwrapped variant exists + * + * @since 1.9 + */ + public JsonDeserializer<T> unwrappingDeserializer() { + return this; + } + + /* + /********************************************************** + /* Other accessors + /********************************************************** + */ + + /** + * Method that can be called to determine value to be used for + * representing null values (values deserialized when JSON token + * is {@link JsonToken#VALUE_NULL}). Usually this is simply + * Java null, but for some types (especially primitives) it may be + * necessary to use non-null values. + *<p> + * Note that deserializers are allowed to call this just once and + * then reuse returned value; that is, method is not guaranteed to + * be called once for each conversion. + *<p> + * Default implementation simply returns null. + */ + public T getNullValue() { return null; } + + /** + * Method called to determine value to be used for "empty" values + * (most commonly when deserializing from empty JSON Strings). + * Usually this is same as {@link #getNullValue} (which in turn + * is usually simply Java null), but it can be overridden + * for types. Or, if type should never be converted from empty + * String, method can also throw an exception. + *<p> + * Default implementation simple calls {@link #getNullValue} and + * returns value. + * + * @since 1.9 + */ + public T getEmptyValue() { return getNullValue(); } + + /* + /********************************************************** + /* Helper classes + /********************************************************** + */ + + /** + * This marker class is only to be used with annotations, to + * indicate that <b>no deserializer is configured</b>. + *<p> + * Specifically, this class is to be used as the marker for + * annotation {@link org.codehaus.jackson.map.annotate.JsonDeserialize} + */ + public abstract static class None + extends JsonDeserializer<Object> { } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/JsonMappingException.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/JsonMappingException.java new file mode 100644 index 0000000..19affd6 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/JsonMappingException.java
@@ -0,0 +1,329 @@ +package org.codehaus.jackson.map; + +import java.io.Serializable; +import java.util.*; + +import org.codehaus.jackson.*; + +/** + * Checked exception used to signal fatal problems with mapping of + * content. + *<p> + * One additional feature is the ability to denote relevant path + * of references (during serialization/deserialization) to help in + * troubleshooting. + */ +public class JsonMappingException + extends JsonProcessingException +{ + private static final long serialVersionUID = 1L; + + /** + * Let's limit length of reference chain, to limit damage in cases + * of infinite recursion. + */ + final static int MAX_REFS_TO_LIST = 1000; + + /* + /********************************************************** + /* Helper classes + /********************************************************** + */ + + /** + * Simple bean class used to contain references. References + * can be added to indicate execution/reference path that + * lead to the problem that caused this exception to be + * thrown. + */ + public static class Reference implements Serializable + { + private static final long serialVersionUID = 1L; + + /** + * Object through which reference was resolved. Can be either + * actual instance (usually the case for serialization), or + * Class (usually the case for deserialization). + */ + protected Object _from; + + /** + * Name of field (for beans) or key (for Maps) that is part + * of the reference. May be null for Collection types (which + * generally have {@link #_index} defined), or when resolving + * Map classes without (yet) having an instance to operate on. + */ + protected String _fieldName; + + /** + * Index within a {@link Collection} instance that contained + * the reference; used if index is relevant and available. + * If either not applicable, or not available, -1 is used to + * denote "not known". + */ + protected int _index = -1; + + /** + * Default constructor for deserialization/sub-classing purposes + */ + protected Reference() { } + + public Reference(Object from) { _from = from; } + + public Reference(Object from, String fieldName) { + _from = from; + if (fieldName == null) { + throw new NullPointerException("Can not pass null fieldName"); + } + _fieldName = fieldName; + } + + public Reference(Object from, int index) { + _from = from; + _index = index; + } + + public void setFrom(Object o) { _from = o; } + public void setFieldName(String n) { _fieldName = n; } + public void setIndex(int ix) { _index = ix; } + + public Object getFrom() { return _from; } + public String getFieldName() { return _fieldName; } + public int getIndex() { return _index; } + + @Override public String toString() { + StringBuilder sb = new StringBuilder(); + Class<?> cls = (_from instanceof Class<?>) ? + ((Class<?>)_from) : _from.getClass(); + /* Hmmh. Although Class.getName() is mostly ok, it does look + * butt-ugly for arrays. So let's use getSimpleName() instead; + * but have to prepend package name too. + */ + Package pkg = cls.getPackage(); + if (pkg != null) { + sb.append(pkg.getName()); + sb.append('.'); + } + sb.append(cls.getSimpleName()); + sb.append('['); + if (_fieldName != null) { + sb.append('"'); + sb.append(_fieldName); + sb.append('"'); + } else if (_index >= 0) { + sb.append(_index); + } else { + sb.append('?'); + } + sb.append(']'); + return sb.toString(); + } + } + + /* + /********************************************************** + /* State/configuration + /********************************************************** + */ + + /** + * Path through which problem that triggering throwing of + * this exception was reached. + */ + protected LinkedList<Reference> _path; + + /* + /********************************************************** + /* Life-cycle + /********************************************************** + */ + + public JsonMappingException(String msg) + { + super(msg); + } + + public JsonMappingException(String msg, Throwable rootCause) + { + super(msg, rootCause); + } + + public JsonMappingException(String msg, JsonLocation loc) + { + super(msg, loc); + } + + public JsonMappingException(String msg, JsonLocation loc, Throwable rootCause) + { + super(msg, loc, rootCause); + } + + public static JsonMappingException from(JsonParser jp, String msg) + { + return new JsonMappingException(msg, jp.getTokenLocation()); + } + + public static JsonMappingException from(JsonParser jp, String msg, + Throwable problem) + { + return new JsonMappingException(msg, jp.getTokenLocation(), problem); + } + + /** + * Method that can be called to either create a new JsonMappingException + * (if underlying exception is not a JsonMappingException), or augment + * given exception with given path/reference information. + * + * This version of method is called when the reference is through a + * non-indexed object, such as a Map or POJO/bean. + */ + public static JsonMappingException wrapWithPath(Throwable src, Object refFrom, + String refFieldName) + { + return wrapWithPath(src, new Reference(refFrom, refFieldName)); + } + + /** + * Method that can be called to either create a new JsonMappingException + * (if underlying exception is not a JsonMappingException), or augment + * given exception with given path/reference information. + * + * This version of method is called when the reference is through an + * index, which happens with arrays and Collections. + */ + public static JsonMappingException wrapWithPath(Throwable src, Object refFrom, + int index) + { + return wrapWithPath(src, new Reference(refFrom, index)); + } + + /** + * Method that can be called to either create a new JsonMappingException + * (if underlying exception is not a JsonMappingException), or augment + * given exception with given path/reference information. + */ + public static JsonMappingException wrapWithPath(Throwable src, Reference ref) + { + JsonMappingException jme; + if (src instanceof JsonMappingException) { + jme = (JsonMappingException) src; + } else { + String msg = src.getMessage(); + /* Related to [JACKSON-62], let's use a more meaningful placeholder + * if all we have is null + */ + if (msg == null || msg.length() == 0) { + msg = "(was "+src.getClass().getName()+")"; + } + jme = new JsonMappingException(msg, null, src); + } + jme.prependPath(ref); + return jme; + } + + /* + /********************************************************** + /* Accessors/mutators + /********************************************************** + */ + + public List<Reference> getPath() + { + if (_path == null) { + return Collections.emptyList(); + } + return Collections.unmodifiableList(_path); + } + + /** + * Method called to prepend a reference information in front of + * current path + */ + public void prependPath(Object referrer, String fieldName) + { + Reference ref = new Reference(referrer, fieldName); + prependPath(ref); + } + /** + * Method called to prepend a reference information in front of + * current path + */ + public void prependPath(Object referrer, int index) + { + Reference ref = new Reference(referrer, index); + prependPath(ref); + } + + public void prependPath(Reference r) + { + if (_path == null) { + _path = new LinkedList<Reference>(); + } + /* Also: let's not increase without bounds. Could choose either + * head or tail; tail is easier (no need to ever remove), as + * well as potentially more useful so let's use it: + */ + if (_path.size() < MAX_REFS_TO_LIST) { + _path.addFirst(r); + } + } + + /* + /********************************************************** + /* Overridden methods + /********************************************************** + */ + + /** + * Method is overridden so that we can properly inject description + * of problem path, if such is defined. + */ + @Override + public String getMessage() + { + /* First: if we have no path info, let's just use parent's + * definition as is + */ + String msg = super.getMessage(); + if (_path == null) { + return msg; + } + /* 19-Feb-2009, tatu: Null and empty messages are not very + * useful (plus nulls would lead to NPEs), so let's + * use something else + */ + StringBuilder sb = (msg == null) ? new StringBuilder() : new StringBuilder(msg); + /* 18-Feb-2009, tatu: initially there was a linefeed between + * message and path reference; but unfortunately many systems + * (loggers, junit) seem to assume linefeeds are only added to + * separate stack trace. + */ + sb.append(" (through reference chain: "); + _appendPathDesc(sb); + sb.append(')'); + return sb.toString(); + } + + @Override + public String toString() + { + return getClass().getName()+": "+getMessage(); + } + + /* + /********************************************************** + /* Internal methods + /********************************************************** + */ + + protected void _appendPathDesc(StringBuilder sb) + { + Iterator<Reference> it = _path.iterator(); + while (it.hasNext()) { + sb.append(it.next().toString()); + if (it.hasNext()) { + sb.append("->"); + } + } + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/JsonSerializable.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/JsonSerializable.java new file mode 100644 index 0000000..7bce91b --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/JsonSerializable.java
@@ -0,0 +1,33 @@ +package org.codehaus.jackson.map; + +import java.io.IOException; + +import org.codehaus.jackson.*; + +/** + * Interface that can be implemented by objects that know how to + * serialize themselves to JSON, using {@link JsonGenerator} + * (and {@link SerializerProvider} if necessary). + *<p> + * Note that implementing this interface binds implementing object + * closely to Jackson API, and that it is often not necessary to do + * so -- if class is a bean, it can be serialized without + * implementing this interface. + *<p> + * NOTE: as of version 1.5, this interface is missing one crucial + * aspect, that of dealing with type information embedding. + * Because of this, this interface is deprecated, although will be + * fully supported for all 1.x releases, and will work except for + * cases where polymorphic type information handling is needed for + * type (in which case implementing if {@link JsonSerializableWithType} is crucial). + * + * @see org.codehaus.jackson.map.JsonSerializableWithType + * + * @since 1.5 + */ +@Deprecated +public interface JsonSerializable +{ + public void serialize(JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonProcessingException; +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/JsonSerializableWithType.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/JsonSerializableWithType.java new file mode 100644 index 0000000..5e8f489 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/JsonSerializableWithType.java
@@ -0,0 +1,22 @@ +package org.codehaus.jackson.map; + +import java.io.IOException; + +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.JsonProcessingException; + +/** + * Interface that is to replace {@link JsonSerializable} to + * allow for dynamic type information embedding. + * + * @since 1.5 + * @author tatu + */ +@SuppressWarnings("deprecation") +public interface JsonSerializableWithType + extends JsonSerializable +{ + public void serializeWithType(JsonGenerator jgen, SerializerProvider provider, + TypeSerializer typeSer) + throws IOException, JsonProcessingException; +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/JsonSerializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/JsonSerializer.java new file mode 100644 index 0000000..53a3beac --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/JsonSerializer.java
@@ -0,0 +1,137 @@ +package org.codehaus.jackson.map; + +import java.io.IOException; + +import org.codehaus.jackson.*; + +/** + * Abstract class that defines API used by {@link ObjectMapper} (and + * other chained {@link JsonSerializer}s too) to serialize Objects of + * arbitrary types into JSON, using provided {@link JsonGenerator}. + *<p> + * NOTE: it is recommended that custom serializers extend + * {@link org.codehaus.jackson.map.ser.std.SerializerBase} instead + * of this class, since it will implement many of optional + * methods of this class. + */ +public abstract class JsonSerializer<T> +{ + /* + /********************************************************** + /* Fluent factory methods for constructing decorated versions + /********************************************************** + */ + + /** + * Method that will return serializer instance that produces + * "unwrapped" serialization, if applicable for type being + * serialized (which is the case for some serializers + * that produce JSON Objects as output). + * If no unwrapped serializer can be constructed, will simply + * return serializer as-is. + *<p> + * Default implementation just returns serializer as-is, + * indicating that no unwrapped variant exists + * + * @since 1.9 + */ + public JsonSerializer<T> unwrappingSerializer() { + return this; + } + + /** + * Accessor for checking whether this serializer is an + * "unwrapping" serializer; this is necessary to know since + * it may also require caller to suppress writing of the + * leading property name. + * + * @since 1.9 + */ + public boolean isUnwrappingSerializer() { + return false; + } + + /* + /********************************************************** + /* Serialization methods + /********************************************************** + */ + + /** + * Method that can be called to ask implementation to serialize + * values of type this serializer handles. + * + * @param value Value to serialize; can <b>not</b> be null. + * @param jgen Generator used to output resulting Json content + * @param provider Provider that can be used to get serializers for + * serializing Objects value contains, if any. + */ + public abstract void serialize(T value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonProcessingException; + + /** + * Method that can be called to ask implementation to serialize + * values of type this serializer handles, using specified type serializer + * for embedding necessary type information. + *<p> + * Default implementation will ignore serialization of type information, + * and just calls {@link #serialize}: serializers that can embed + * type information should override this to implement actual handling. + * Most common such handling is done by something like: + *<pre> + * // note: method to call depends on whether this type is serialized as JSON scalar, object or Array! + * typeSer.writeTypePrefixForScalar(value, jgen); + * serialize(value, jgen, provider); + * typeSer.writeTypeSuffixForScalar(value, jgen); + *</pre> + * + * @param value Value to serialize; can <b>not</b> be null. + * @param jgen Generator used to output resulting Json content + * @param provider Provider that can be used to get serializers for + * serializing Objects value contains, if any. + * @param typeSer Type serializer to use for including type information + * + * @since 1.5 + */ + public void serializeWithType(T value, JsonGenerator jgen, SerializerProvider provider, + TypeSerializer typeSer) + throws IOException, JsonProcessingException + { + serialize(value, jgen, provider); + } + + /* + /********************************************************** + /* Introspection methods needed for type handling + /********************************************************** + */ + + /** + * Method for accessing type of Objects this serializer can handle. + * Note that this information is not guaranteed to be exact -- it + * may be a more generic (super-type) -- but it should not be + * incorrect (return a non-related type). + *<p> + * Default implementation will return null, which essentially means + * same as returning <code>Object.class</code> would; that is, that + * nothing is known about handled type. + *<p> + */ + public Class<T> handledType() { return null; } + + /* + /********************************************************** + /* Helper class(es) + /********************************************************** + */ + + /** + * This marker class is only to be used with annotations, to + * indicate that <b>no serializer is configured</b>. + *<p> + * Specifically, this class is to be used as the marker for + * annotation {@link org.codehaus.jackson.map.annotate.JsonSerialize}. + */ + public abstract static class None + extends JsonSerializer<Object> { } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/KeyDeserializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/KeyDeserializer.java new file mode 100644 index 0000000..76a3e0b --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/KeyDeserializer.java
@@ -0,0 +1,31 @@ +package org.codehaus.jackson.map; + +import java.io.IOException; + +import org.codehaus.jackson.*; + +/** + * Abstract class that defines API used for deserializing JSON content + * field names into Java Map keys. These deserializers are only used + * if the Map key class is not <code>String</code> or <code>Object</code>. + */ +public abstract class KeyDeserializer +{ + /** + * Method called to deserialize a {@link java.util.Map} key from JSON property name. + */ + public abstract Object deserializeKey(String key, DeserializationContext ctxt) + throws IOException, JsonProcessingException; + + /** + * This marker class is only to be used with annotations, to + * indicate that <b>no deserializer is configured</b>. + *<p> + * Specifically, this class is to be used as the marker for + * annotation {@link org.codehaus.jackson.map.annotate.JsonDeserialize}. + * + * @since 1.3 + */ + public abstract static class None + extends KeyDeserializer { } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/KeyDeserializers.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/KeyDeserializers.java new file mode 100644 index 0000000..dbc2e4c --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/KeyDeserializers.java
@@ -0,0 +1,21 @@ +package org.codehaus.jackson.map; + +import org.codehaus.jackson.type.JavaType; + +/** + * Interface that defines API for simple extensions that can provide additional deserializers + * for deserializer Map keys of various types, from JSON property names. + * Access is by a single callback method; instance is to either return + * a configured {@link KeyDeserializer} for specified type, or null to indicate that it + * does not support handling of the type. In latter case, further calls can be made + * for other providers; in former case returned key deserializer is used for handling of + * key instances of specified type. + * + * @since 1.8 + */ +public interface KeyDeserializers +{ + public KeyDeserializer findKeyDeserializer(JavaType type, DeserializationConfig config, + BeanDescription beanDesc, BeanProperty property) + throws JsonMappingException; +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/MapperConfig.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/MapperConfig.java new file mode 100644 index 0000000..75a86d1 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/MapperConfig.java
@@ -0,0 +1,1154 @@ +package org.codehaus.jackson.map; + +import java.text.DateFormat; +import java.util.HashMap; +import java.util.Map; + +import org.codehaus.jackson.annotate.JsonAutoDetect; +import org.codehaus.jackson.annotate.JsonMethod; +import org.codehaus.jackson.map.introspect.Annotated; +import org.codehaus.jackson.map.introspect.VisibilityChecker; +import org.codehaus.jackson.map.jsontype.SubtypeResolver; +import org.codehaus.jackson.map.jsontype.TypeIdResolver; +import org.codehaus.jackson.map.jsontype.TypeResolverBuilder; +import org.codehaus.jackson.map.jsontype.impl.StdSubtypeResolver; +import org.codehaus.jackson.map.type.ClassKey; +import org.codehaus.jackson.map.type.TypeBindings; +import org.codehaus.jackson.map.type.TypeFactory; +import org.codehaus.jackson.map.util.ClassUtil; +import org.codehaus.jackson.map.util.StdDateFormat; +import org.codehaus.jackson.type.JavaType; +import org.codehaus.jackson.type.TypeReference; + +/** + * Interface that defines functionality accessible through both + * serialization and deserialization configuration objects; + * accessors to mode-independent configuration settings + * and such. + *<p> + * As of version 1.9, the goal is to make this class eventually immutable. + * Because of this, existing methods that allow changing state of this + * instance are deprecated in favor of methods that create new instances + * with different configuration ("fluent factories"). + * One major remaining issue is that of handling mix-in annotations, which + * still represent a bit of mutable state; may need to implement a + * functional-style immutable map for storing those. + * + * @since 1.2 -- major change in 1.8, changed from interface to + * abstract class + */ +public abstract class MapperConfig<T extends MapperConfig<T>> + implements ClassIntrospector.MixInResolver +{ + /* + /********************************************************** + /* Constants, default values + /********************************************************** + */ + + /** + * This is the default {@link DateFormat} used unless overridden by + * custom implementation. + */ + protected final static DateFormat DEFAULT_DATE_FORMAT = StdDateFormat.instance; + + /* + /********************************************************** + /* Simple immutable basic settings + /********************************************************** + */ + + /** + * Immutable container object for simple configuration settings. + *<p> + * Note: ideally this would be final, but until we can eliminate + * mutators, must keep it mutable. + */ + protected Base _base; + + /* + /********************************************************** + /* Mix-in annotations + /********************************************************** + */ + + /** + * Mapping that defines how to apply mix-in annotations: key is + * the type to received additional annotations, and value is the + * type that has annotations to "mix in". + *<p> + * Annotations associated with the value classes will be used to + * override annotations of the key class, associated with the + * same field or method. They can be further masked by sub-classes: + * you can think of it as injecting annotations between the target + * class and its sub-classes (or interfaces) + * + * @since 1.2 + */ + protected HashMap<ClassKey,Class<?>> _mixInAnnotations; + + /** + * Flag used to detect when a copy if mix-in annotations is + * needed: set when current copy is shared, cleared when a + * fresh copy is made + * + * @since 1.2 + */ + protected boolean _mixInAnnotationsShared; + + /* + /********************************************************** + /* "Late bound" settings + /********************************************************** + */ + + /** + * Registered concrete subtypes that can be used instead of (or + * in addition to) ones declared using annotations. + * Unlike most other settings, it is not configured as early + * as it is set, but rather only when a non-shared instance + * is constructed by <code>ObjectMapper</code> (or -Reader + * or -Writer) + *<p> + * Note: this is the only property left as non-final, to allow + * lazy construction of the instance as necessary. + * + * @since 1.6 + */ + protected SubtypeResolver _subtypeResolver; + + /* + /********************************************************** + /* Life-cycle: constructors + /********************************************************** + */ + + protected MapperConfig(ClassIntrospector<? extends BeanDescription> ci, AnnotationIntrospector ai, + VisibilityChecker<?> vc, SubtypeResolver str, PropertyNamingStrategy pns, TypeFactory tf, + HandlerInstantiator hi) + { + _base = new Base(ci, ai, vc, pns, tf, null, DEFAULT_DATE_FORMAT, hi); + _subtypeResolver = str; + // by default, assumed to be shared; only cleared when explicit copy is made + _mixInAnnotationsShared = true; + } + + /** + * Simple copy constructor + * + * @since 1.8 + */ + protected MapperConfig(MapperConfig<T> src) { + this(src, src._base, src._subtypeResolver); + } + + /** + * @since 1.8 + */ + protected MapperConfig(MapperConfig<T> src, MapperConfig.Base base, SubtypeResolver str) + { + _base = base; + _subtypeResolver = str; + // by default, assumed to be shared; only cleared when explicit copy is made + _mixInAnnotationsShared = true; + _mixInAnnotations = src._mixInAnnotations; + } + + /* + /********************************************************** + /* Life-cycle: factory methods + /********************************************************** + */ + + /** + * Method that checks class annotations that the argument Object has, + * and modifies settings of this configuration object accordingly, + * similar to how those annotations would affect actual value classes + * annotated with them, but with global scope. Note that not all + * annotations have global significance, and thus only subset of + * Jackson annotations will have any effect. + * + * @deprecated Since 1.9, it is preferably to explicitly configure + * instances; this method also modifies existing instance which is + * against immutable design goals of this class. + */ + @Deprecated + public abstract void fromAnnotations(Class<?> cls); + + /** + * Method to use for constructing an instance that is not shared + * between multiple operations but only used for a single one + * (which may be this instance, if it is immutable; if not, a copy + * is constructed with same settings) + * + * @since 1.8 + */ + public abstract T createUnshared(SubtypeResolver subtypeResolver); + + /** + * Method for constructing and returning a new instance with different + * {@link ClassIntrospector} + * to use. + *<p> + * NOTE: make sure to register new instance with <code>ObjectMapper</code> + * if directly calling this method. + * + * @since 1.8 + */ + public abstract T withClassIntrospector(ClassIntrospector<? extends BeanDescription> ci); + + /** + * Method for constructing and returning a new instance with different + * {@link AnnotationIntrospector} to use (replacing old one). + *<p> + * NOTE: make sure to register new instance with <code>ObjectMapper</code> + * if directly calling this method. + * + * @since 1.8 + */ + public abstract T withAnnotationIntrospector(AnnotationIntrospector ai); + + /** + * Method for constructing and returning a new instance with different + * {@link VisibilityChecker} + * to use. + *<p> + * NOTE: make sure to register new instance with <code>ObjectMapper</code> + * if directly calling this method. + * + * @since 1.8 + */ + public abstract T withVisibilityChecker(VisibilityChecker<?> vc); + + /** + * Method for constructing and returning a new instance with different + * minimal visibility level for specified property type + *<p> + * NOTE: make sure to register new instance with <code>ObjectMapper</code> + * if directly calling this method. + * + * @since 1.9 + */ + public abstract T withVisibility(JsonMethod forMethod, JsonAutoDetect.Visibility visibility); + + /** + * Method for constructing and returning a new instance with different + * {@link TypeResolverBuilder} + * to use. + *<p> + * NOTE: make sure to register new instance with <code>ObjectMapper</code> + * if directly calling this method. + * + * @since 1.8 + */ + public abstract T withTypeResolverBuilder(TypeResolverBuilder<?> trb); + + /** + * Method for constructing and returning a new instance with different + * {@link SubtypeResolver} + * to use. + *<p> + * NOTE: make sure to register new instance with <code>ObjectMapper</code> + * if directly calling this method. + * + * @since 1.8 + */ + public abstract T withSubtypeResolver(SubtypeResolver str); + + /** + * Method for constructing and returning a new instance with different + * {@link PropertyNamingStrategy} + * to use. + *<p> + * NOTE: make sure to register new instance with <code>ObjectMapper</code> + * if directly calling this method. + * + * @since 1.8 + */ + public abstract T withPropertyNamingStrategy(PropertyNamingStrategy strategy); + + /** + * Method for constructing and returning a new instance with different + * {@link TypeFactory} + * to use. + *<p> + * NOTE: make sure to register new instance with <code>ObjectMapper</code> + * if directly calling this method. + * + * @since 1.8 + */ + public abstract T withTypeFactory(TypeFactory typeFactory); + + /** + * Method for constructing and returning a new instance with different + * {@link DateFormat} + * to use. + *<p> + * NOTE: make sure to register new instance with <code>ObjectMapper</code> + * if directly calling this method. + * + * @since 1.8 + */ + public abstract T withDateFormat(DateFormat df); + + /** + * Method for constructing and returning a new instance with different + * {@link HandlerInstantiator} + * to use. + *<p> + * NOTE: make sure to register new instance with <code>ObjectMapper</code> + * if directly calling this method. + * + * @since 1.8 + */ + public abstract T withHandlerInstantiator(HandlerInstantiator hi); + + /** + * Method for constructing and returning a new instance with additional + * {@link AnnotationIntrospector} inserted (as the highest priority one) + * + * @since 1.9 + */ + public abstract T withInsertedAnnotationIntrospector(AnnotationIntrospector introspector); + + /** + * Method for constructing and returning a new instance with additional + * {@link AnnotationIntrospector} appended (as the lowest priority one) + * + * @since 1.9 + */ + public abstract T withAppendedAnnotationIntrospector(AnnotationIntrospector introspector); + + /* + /********************************************************** + /* Configuration: simple features + /********************************************************** + */ + + /** + * Method for checking whether given feature is enabled or not + */ + public abstract boolean isEnabled(ConfigFeature f); + + /** + * Method for determining whether annotation processing is enabled or not + * (default settings are typically that it is enabled; must explicitly disable). + * + * @return True if annotation processing is enabled; false if not + * + * @since 1.8 + */ + public abstract boolean isAnnotationProcessingEnabled(); + + /** + * Accessor for determining whether it is ok to try to force override of access + * modifiers to be able to get or set values of non-public Methods, Fields; + * to invoke non-public Constructors, Methods; or to instantiate non-public + * Classes. By default this is enabled, but on some platforms it needs to be + * prevented since if this would violate security constraints and cause failures. + * + * @return True if access modifier overriding is allowed (and may be done for + * any Field, Method, Constructor or Class); false to prevent any attempts + * to override. + * + * @since 1.8 + */ + public abstract boolean canOverrideAccessModifiers(); + + /** + * Accessor for checking whether default settings for property handling + * indicate that properties should be alphabetically ordered or not. + * + * @since 1.9 + */ + public abstract boolean shouldSortPropertiesAlphabetically(); + + /* + /********************************************************** + /* Configuration: introspectors, mix-ins + /********************************************************** + */ + + public ClassIntrospector<? extends BeanDescription> getClassIntrospector() { + return _base.getClassIntrospector(); + } + + /** + * Method for getting {@link AnnotationIntrospector} configured + * to introspect annotation values used for configuration. + *<p> + * Non-final since it is actually overridden by sub-classes (for now?) + */ + public AnnotationIntrospector getAnnotationIntrospector() { + return _base.getAnnotationIntrospector(); + } + + /** + * Method for registering specified {@link AnnotationIntrospector} as the highest + * priority introspector (will be chained with existing introspector(s) which + * will be used as fallbacks for cases this introspector does not handle) + * + * @param introspector Annotation introspector to register. + * + * @since 1.7 + * + * @deprecated Since 1.9 use {@link #withInsertedAnnotationIntrospector(AnnotationIntrospector)} instead; + * this method is deprecated as it changes state, preventing immutability of instances + */ + @Deprecated + public final void insertAnnotationIntrospector(AnnotationIntrospector introspector) { + _base = _base.withAnnotationIntrospector(AnnotationIntrospector.Pair.create(introspector, + getAnnotationIntrospector())); + } + + /** + * Method for registering specified {@link AnnotationIntrospector} as the lowest + * priority introspector, chained with existing introspector(s) and called + * as fallback for cases not otherwise handled. + * + * @param introspector Annotation introspector to register. + * + * @since 1.7 + * + * @deprecated Since 1.9 use {@link #withAppendedAnnotationIntrospector(AnnotationIntrospector)} instead; + * this method is deprecated as it changes state, preventing immutability of instances + */ + @Deprecated + public final void appendAnnotationIntrospector(AnnotationIntrospector introspector) { + _base = _base.withAnnotationIntrospector(AnnotationIntrospector.Pair.create(getAnnotationIntrospector(), + introspector)); + } + + /** + * Accessor for object used for determining whether specific property elements + * (method, constructors, fields) can be auto-detected based on + * their visibility (access modifiers). Can be changed to allow + * different minimum visibility levels for auto-detection. Note + * that this is the global handler; individual types (classes) + * can further override active checker used (using + * {@link JsonAutoDetect} annotation) + * + * @since 1.5 + */ + public VisibilityChecker<?> getDefaultVisibilityChecker() { + return _base.getVisibilityChecker(); + } + + /** + * @since 1.8 + */ + public final PropertyNamingStrategy getPropertyNamingStrategy() { + return _base.getPropertyNamingStrategy(); + } + + /** + * @since 1.8 + */ + public final HandlerInstantiator getHandlerInstantiator() { + return _base.getHandlerInstantiator(); + } + + /* + /********************************************************** + /* Configuration: mix-in annotations + /********************************************************** + */ + + /** + * Method to use for defining mix-in annotations to use for augmenting + * annotations that processable (serializable / deserializable) + * classes have. + * Mixing in is done when introspecting class annotations and properties. + * Map passed contains keys that are target classes (ones to augment + * with new annotation overrides), and values that are source classes + * (have annotations to use for augmentation). + * Annotations from source classes (and their supertypes) + * will <b>override</b> + * annotations that target classes (and their super-types) have. + * + * @since 1.2 + */ + public final void setMixInAnnotations(Map<Class<?>, Class<?>> sourceMixins) + { + HashMap<ClassKey,Class<?>> mixins = null; + if (sourceMixins != null && sourceMixins.size() > 0) { + mixins = new HashMap<ClassKey,Class<?>>(sourceMixins.size()); + for (Map.Entry<Class<?>,Class<?>> en : sourceMixins.entrySet()) { + mixins.put(new ClassKey(en.getKey()), en.getValue()); + } + } + _mixInAnnotationsShared = false; + _mixInAnnotations = mixins; + } + + /** + * Method to use for adding mix-in annotations to use for augmenting + * specified class or interface. All annotations from + * <code>mixinSource</code> are taken to override annotations + * that <code>target</code> (or its supertypes) has. + * + * @since 1.2 + * + * @param target Class (or interface) whose annotations to effectively override + * @param mixinSource Class (or interface) whose annotations are to + * be "added" to target's annotations, overriding as necessary + */ + public final void addMixInAnnotations(Class<?> target, Class<?> mixinSource) + { + if (_mixInAnnotations == null) { + _mixInAnnotationsShared = false; + _mixInAnnotations = new HashMap<ClassKey,Class<?>>(); + } else if (_mixInAnnotationsShared) { + _mixInAnnotationsShared = false; + _mixInAnnotations = new HashMap<ClassKey,Class<?>>(_mixInAnnotations); + } + _mixInAnnotations.put(new ClassKey(target), mixinSource); + } + + // ClassIntrospector.MixInResolver impl: + + /** + * Method that will check if there are "mix-in" classes (with mix-in + * annotations) for given class + * + * @since 1.2 + */ + @Override + public final Class<?> findMixInClassFor(Class<?> cls) { + return (_mixInAnnotations == null) ? null : _mixInAnnotations.get(new ClassKey(cls)); + } + + /** + * @since 1.8.1 + */ + public final int mixInCount() { + return (_mixInAnnotations == null) ? 0 : _mixInAnnotations.size(); + } + + /* + /********************************************************** + /* Configuration: type and subtype handling + /********************************************************** + */ + + /** + * Method called to locate a type info handler for types that do not have + * one explicitly declared via annotations (or other configuration). + * If such default handler is configured, it is returned; otherwise + * null is returned. + * + * @since 1.5 + */ + public final TypeResolverBuilder<?> getDefaultTyper(JavaType baseType) { + return _base.getTypeResolverBuilder(); + } + + /** + * Accessor for object used for finding out all reachable subtypes + * for supertypes; needed when a logical type name is used instead + * of class name (or custom scheme). + * + * @since 1.6 + */ + public final SubtypeResolver getSubtypeResolver() { + if (_subtypeResolver == null) { + _subtypeResolver = new StdSubtypeResolver(); + } + return _subtypeResolver; + } + + /** + * @since 1.8 + */ + public final TypeFactory getTypeFactory() { + return _base.getTypeFactory(); + } + + /** + * Helper method that will construct {@link JavaType} for given + * raw class. + * This is a simple short-cut for: + *<pre> + * getTypeFactory().constructType(cls); + *</pre> + * + * @since 1.8 + */ + public final JavaType constructType(Class<?> cls) { + return getTypeFactory().constructType(cls, (TypeBindings) null); + } + + /** + * Helper method that will construct {@link JavaType} for given + * type reference + * This is a simple short-cut for: + *<pre> + * getTypeFactory().constructType(valueTypeRef); + *</pre> + * + * @since 1.9 + */ + public final JavaType constructType(TypeReference<?> valueTypeRef) { + return getTypeFactory().constructType(valueTypeRef.getType(), (TypeBindings) null); + } + + /** + * @since 1.9.1 + */ + public JavaType constructSpecializedType(JavaType baseType, Class<?> subclass) { + return getTypeFactory().constructSpecializedType(baseType, subclass); + } + + /* + /********************************************************** + /* Configuration: other + /********************************************************** + */ + + /** + * Method for accessing currently configured (textual) date format + * that will be used for reading or writing date values (in case + * of writing, only if textual output is configured; not if dates + * are to be serialized as time stamps). + *<p> + * Note that typically {@link DateFormat} instances are <b>not thread-safe</b> + * (at least ones provided by JDK): + * this means that calling code should clone format instance before + * using it. + *<p> + * This method is usually only called by framework itself, since there + * are convenience methods available via + * {@link DeserializationContext} and {@link SerializerProvider} that + * take care of cloning and thread-safe reuse. + */ + public final DateFormat getDateFormat() { return _base.getDateFormat(); } + + /** + * Accessor for getting bean description that only contains class + * annotations: useful if no getter/setter/creator information is needed. + * + * @since 1.7 + */ + @SuppressWarnings("unchecked") + public <DESC extends BeanDescription> DESC introspectClassAnnotations(Class<?> cls) { + return (DESC) introspectClassAnnotations(constructType(cls)); + } + + /** + * Accessor for getting bean description that only contains class + * annotations: useful if no getter/setter/creator information is needed. + * + * @since 1.9 + */ + public abstract <DESC extends BeanDescription> DESC introspectClassAnnotations(JavaType type); + + /** + * Accessor for getting bean description that only contains immediate class + * annotations: ones from the class, and its direct mix-in, if any, but + * not from super types. + * + * @since 1.7 + */ + @SuppressWarnings("unchecked") + public <DESC extends BeanDescription> DESC introspectDirectClassAnnotations(Class<?> cls) { + return (DESC) introspectDirectClassAnnotations(constructType(cls)); + } + /** + * Accessor for getting bean description that only contains immediate class + * annotations: ones from the class, and its direct mix-in, if any, but + * not from super types. + */ + public abstract <DESC extends BeanDescription> DESC introspectDirectClassAnnotations(JavaType type); + + /* + /********************************************************** + /* Methods for instantiating handlers + /********************************************************** + */ + + /** + * Method that can be called to obtain an instance of <code>TypeIdResolver</code> of + * specified type. + * + * @since 1.8 + */ + public TypeResolverBuilder<?> typeResolverBuilderInstance(Annotated annotated, + Class<? extends TypeResolverBuilder<?>> builderClass) + { + HandlerInstantiator hi = getHandlerInstantiator(); + if (hi != null) { + TypeResolverBuilder<?> builder = hi.typeResolverBuilderInstance(this, annotated, builderClass); + if (builder != null) { + return builder; + } + } + return (TypeResolverBuilder<?>) ClassUtil.createInstance(builderClass, canOverrideAccessModifiers()); + } + + /** + * Method that can be called to obtain an instance of <code>TypeIdResolver</code> of + * specified type. + * + * @since 1.8 + */ + public TypeIdResolver typeIdResolverInstance(Annotated annotated, + Class<? extends TypeIdResolver> resolverClass) + { + HandlerInstantiator hi = getHandlerInstantiator(); + if (hi != null) { + TypeIdResolver builder = hi.typeIdResolverInstance(this, annotated, resolverClass); + if (builder != null) { + return builder; + } + } + return (TypeIdResolver) ClassUtil.createInstance(resolverClass, canOverrideAccessModifiers()); + } + + /* + /********************************************************** + /* Deprecated methods + /********************************************************** + */ + + /** + * Method for replacing existing annotation introspector(s) with specified + * introspector. + * Since this method modifies state of configuration object directly, its use + * is not recommended. + * + * @deprecated Since 1.8, use either + * {@link #withAnnotationIntrospector(AnnotationIntrospector)} or + * Module API instead + */ + @Deprecated + public final void setAnnotationIntrospector(AnnotationIntrospector ai) { + _base = _base.withAnnotationIntrospector(ai); + } + + /** + * Method that will define specific date format to use for reading/writing + * Date and Calendar values. + * If null is passed, will use {@link StdDateFormat}. + * Instance is used as is, without creating a clone. + * Format object in use can be accessed using {@link #getDateFormat}. + * + * @param df Date format to use, if not null; if null, the default format + * will be used + * + * @deprecated As of version 1.8, it is preferable to call method in + * {@link ObjectMapper} instead; or construct new instance with + * {@link #withDateFormat(DateFormat)} + */ + @Deprecated + public void setDateFormat(DateFormat df) { + if (df == null) { + df = DEFAULT_DATE_FORMAT; + } + _base = _base.withDateFormat(df); + } + + /* + /********************************************************** + /* Helper interface used with simple on/off features + /********************************************************** + */ + + /** + * Interface that actual Feature enumerations used by + * {@link MapperConfig} implementations must implement. + * Necessary since enums can not be extended using normal + * inheritance, but can implement interfaces + * + * @since 1.9 + */ + public interface ConfigFeature + { + /** + * Accessor for checking whether this feature is enabled by default. + */ + public boolean enabledByDefault(); + + /** + * Returns bit mask for this feature instance + */ + public int getMask(); + } + + /* + /********************************************************** + /* Helper class to contain basic state needed to implement + /* MapperConfig. + /********************************************************** + */ + + /** + * Immutable container class used to store simple configuration + * settings. Since instances are fully immutable, instances can + * be freely shared and used without synchronization. + */ + public static class Base + { + /* + /********************************************************** + /* Configuration settings; introspection, related + /********************************************************** + */ + + /** + * Introspector used to figure out Bean properties needed for bean serialization + * and deserialization. Overridable so that it is possible to change low-level + * details of introspection, like adding new annotation types. + */ + protected final ClassIntrospector<? extends BeanDescription> _classIntrospector; + + /** + * Introspector used for accessing annotation value based configuration. + */ + protected final AnnotationIntrospector _annotationIntrospector; + + /** + * Object used for determining whether specific property elements + * (method, constructors, fields) can be auto-detected based on + * their visibility (access modifiers). Can be changed to allow + * different minimum visibility levels for auto-detection. Note + * that this is the global handler; individual types (classes) + * can further override active checker used (using + * {@link JsonAutoDetect} annotation) + * + * @since 1.5 + */ + protected final VisibilityChecker<?> _visibilityChecker; + + /** + * Custom property naming strategy in use, if any. + * + * @since 1.8 + */ + protected final PropertyNamingStrategy _propertyNamingStrategy; + + /** + * Specific factory used for creating {@link JavaType} instances; + * needed to allow modules to add more custom type handling + * (mostly to support types of non-Java JVM languages) + */ + protected final TypeFactory _typeFactory; + + /* + /********************************************************** + /* Configuration settings; type resolution + /********************************************************** + */ + + /** + * Type information handler used for "untyped" values (ones declared + * to have type <code>Object.class</code>) + * + * @since 1.5 + */ + protected final TypeResolverBuilder<?> _typeResolverBuilder; + + /* + /********************************************************** + /* Configuration settings; other + /********************************************************** + */ + + /** + * Custom date format to use for de-serialization. If specified, will be + * used instead of {@link org.codehaus.jackson.map.util.StdDateFormat}. + *<p> + * Note that the configured format object will be cloned once per + * deserialization process (first time it is needed) + */ + protected final DateFormat _dateFormat; + + /** + * Object used for creating instances of handlers (serializers, deserializers, + * type and type id resolvers), given class to instantiate. This is typically + * used to do additional configuration (with dependency injection, for example) + * beyond simply construction of instances; or to use alternative constructors. + */ + protected final HandlerInstantiator _handlerInstantiator; + + /* + /********************************************************** + /* Construction + /********************************************************** + */ + + public Base(ClassIntrospector<? extends BeanDescription> ci, AnnotationIntrospector ai, + VisibilityChecker<?> vc, PropertyNamingStrategy pns, TypeFactory tf, + TypeResolverBuilder<?> typer, DateFormat dateFormat, HandlerInstantiator hi) + { + _classIntrospector = ci; + _annotationIntrospector = ai; + _visibilityChecker = vc; + _propertyNamingStrategy = pns; + _typeFactory = tf; + _typeResolverBuilder = typer; + _dateFormat = dateFormat; + _handlerInstantiator = hi; + } + + /* + /********************************************************** + /* Factory methods + /********************************************************** + */ + + public Base withClassIntrospector(ClassIntrospector<? extends BeanDescription> ci) { + return new Base(ci, _annotationIntrospector, _visibilityChecker, _propertyNamingStrategy, _typeFactory, + _typeResolverBuilder, _dateFormat, _handlerInstantiator); + } + + public Base withAnnotationIntrospector(AnnotationIntrospector ai) { + return new Base(_classIntrospector, ai, _visibilityChecker, _propertyNamingStrategy, _typeFactory, + _typeResolverBuilder, _dateFormat, _handlerInstantiator); + } + + public Base withInsertedAnnotationIntrospector(AnnotationIntrospector ai) { + return withAnnotationIntrospector(AnnotationIntrospector.Pair.create(ai, _annotationIntrospector)); + } + + public Base withAppendedAnnotationIntrospector(AnnotationIntrospector ai) { + return withAnnotationIntrospector(AnnotationIntrospector.Pair.create(_annotationIntrospector, ai)); + } + + public Base withVisibilityChecker(VisibilityChecker<?> vc) { + return new Base(_classIntrospector, _annotationIntrospector, vc, _propertyNamingStrategy, _typeFactory, + _typeResolverBuilder, _dateFormat, _handlerInstantiator); + } + + public Base withVisibility(JsonMethod forMethod, JsonAutoDetect.Visibility visibility) { + return new Base(_classIntrospector, _annotationIntrospector, + _visibilityChecker.withVisibility(forMethod, visibility), + _propertyNamingStrategy, _typeFactory, + _typeResolverBuilder, _dateFormat, _handlerInstantiator); + } + + public Base withPropertyNamingStrategy(PropertyNamingStrategy pns) { + return new Base(_classIntrospector, _annotationIntrospector, _visibilityChecker, pns, _typeFactory, + _typeResolverBuilder, _dateFormat, _handlerInstantiator); + } + + public Base withTypeFactory(TypeFactory tf) { + return new Base(_classIntrospector, _annotationIntrospector, _visibilityChecker, _propertyNamingStrategy, tf, + _typeResolverBuilder, _dateFormat, _handlerInstantiator); + } + + public Base withTypeResolverBuilder(TypeResolverBuilder<?> typer) { + return new Base(_classIntrospector, _annotationIntrospector, _visibilityChecker, _propertyNamingStrategy, _typeFactory, + typer, _dateFormat, _handlerInstantiator); + } + + public Base withDateFormat(DateFormat df) { + return new Base(_classIntrospector, _annotationIntrospector, _visibilityChecker, _propertyNamingStrategy, _typeFactory, + _typeResolverBuilder, df, _handlerInstantiator); + } + + public Base withHandlerInstantiator(HandlerInstantiator hi) { + return new Base(_classIntrospector, _annotationIntrospector, _visibilityChecker, _propertyNamingStrategy, _typeFactory, + _typeResolverBuilder, _dateFormat, hi); + } + + /* + /********************************************************** + /* API + /********************************************************** + */ + + public ClassIntrospector<? extends BeanDescription> getClassIntrospector() { + return _classIntrospector; + } + + public AnnotationIntrospector getAnnotationIntrospector() { + return _annotationIntrospector; + } + + + public VisibilityChecker<?> getVisibilityChecker() { + return _visibilityChecker; + } + + public PropertyNamingStrategy getPropertyNamingStrategy() { + return _propertyNamingStrategy; + } + + public TypeFactory getTypeFactory() { + return _typeFactory; + } + + public TypeResolverBuilder<?> getTypeResolverBuilder() { + return _typeResolverBuilder; + } + + public DateFormat getDateFormat() { + return _dateFormat; + } + + public HandlerInstantiator getHandlerInstantiator() { + return _handlerInstantiator; + } + } + + /* + /********************************************************** + /* Basic extension; added to avoid having to change generic + /* signature of MapperConfig + /* + /* NOTE: May be merge in MapperConfig for 2.0, depending + /* on how much we value backwards compatibility + /********************************************************** + */ + + static abstract class Impl<CFG extends MapperConfig.ConfigFeature, + T extends Impl<CFG,T>> + extends MapperConfig<T> + { + /** + *<p> + * Note: moved to base class in 1.9; was stored by sub-class earlier + */ + protected int _featureFlags; + + /* + /********************************************************** + /* Construction + /********************************************************** + */ + + protected Impl(ClassIntrospector<? extends BeanDescription> ci, AnnotationIntrospector ai, + VisibilityChecker<?> vc, SubtypeResolver str, PropertyNamingStrategy pns, TypeFactory tf, + HandlerInstantiator hi, + int defaultFeatures) + { + super(ci, ai, vc, str, pns, tf, hi); + _featureFlags = defaultFeatures; + } + + protected Impl(Impl<CFG,T> src) { + super(src); + _featureFlags = src._featureFlags; + } + + protected Impl(Impl<CFG,T> src, int features) { + super(src); + _featureFlags = features; + } + + /** + * @since 1.8 + */ + protected Impl(Impl<CFG,T> src, MapperConfig.Base base, SubtypeResolver str) + { + super(src, base, str); + _featureFlags = src._featureFlags; + } + + /** + * Method that calculates bit set (flags) of all features that + * are enabled by default. + */ + static <F extends Enum<F> & MapperConfig.ConfigFeature> int collectFeatureDefaults(Class<F> enumClass) + { + int flags = 0; + for (F value : enumClass.getEnumConstants()) { + if (value.enabledByDefault()) { + flags |= value.getMask(); + } + } + return flags; + } + + /* + /********************************************************** + /* Additional fluent-factory methods + /********************************************************** + */ + + /** + * Fluent factory method that will construct and return a new configuration + * object instance with specified features enabled. + * + * @since 1.9 + */ + public abstract T with(CFG... features); + + /** + * Fluent factory method that will construct and return a new configuration + * object instance with specified features disabled. + * + * @since 1.9 + */ + public abstract T without(CFG... features); + + /* + /********************************************************** + /* Configuration: simple features + /********************************************************** + */ + + /* NOTE: this method was added in 1.9, but should be + * removed from 2.0 -- overloads do not work nicely with + * enums, so we better not try + *<p> + * Also note that we can NOT use type variable CFG here, because + * non-generic base class had to use base type. + * + * @Deprecated + */ + @Override + public boolean isEnabled(MapperConfig.ConfigFeature f) { + return (_featureFlags & f.getMask()) != 0; + } + + /* + /********************************************************** + /* Configuration: deprecated methods + /********************************************************** + */ + + /** + * Method for enabling specified feature. + * + * @deprecated Since 1.9, it is preferable to use {@link #with} instead; + * this method is deprecated as it modifies current instance instead of + * creating a new one (as the goal is to make this class immutable) + */ + @Deprecated + public void enable(CFG f) { + _featureFlags |= f.getMask(); + } + + /** + * Method for disabling specified feature. + * + * @deprecated Since 1.9, it is preferable to use {@link #without} instead; + * this method is deprecated as it modifies current instance instead of + * creating a new one (as the goal is to make this class immutable) + */ + @Deprecated + public void disable(CFG f) { + _featureFlags &= ~f.getMask(); + } + + /** + * Method for enabling or disabling specified feature. + * + * @deprecated Since 1.9, it is preferable to use {@link #with} and + * {@link #without} methods instead; + * this method is deprecated as it modifies current instance instead of + * creating a new one (as the goal is to make this class immutable) + */ + @SuppressWarnings("deprecation") + @Deprecated + public void set(CFG f, boolean state) + { + if (state) { + enable(f); + } else { + disable(f); + } + } + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/MappingIterator.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/MappingIterator.java new file mode 100644 index 0000000..22505c9 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/MappingIterator.java
@@ -0,0 +1,187 @@ +package org.codehaus.jackson.map; + +import java.io.IOException; +import java.util.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.type.JavaType; + +/** + * Iterator exposed by {@link ObjectMapper} when binding sequence of + * objects. Extension is done to allow more convenient exposing of + * {@link IOException} (which basic {@link Iterator} does not expose) + * + * @since 1.8 + */ +public class MappingIterator<T> implements Iterator<T> +{ + protected final static MappingIterator<?> EMPTY_ITERATOR = + new MappingIterator<Object>(null, null, null, null, false, null); + + protected final JavaType _type; + + protected final DeserializationContext _context; + + protected final JsonDeserializer<T> _deserializer; + + protected JsonParser _parser; + + /** + * Flag that indicates whether input {@link JsonParser} should be closed + * when we are done or not; generally only called when caller did not + * pass JsonParser. + */ + protected final boolean _closeParser; + + /** + * Flag that is set when we have determined what {@link #hasNextValue()} + * should value; reset when {@link #nextValue} is called + */ + protected boolean _hasNextChecked; + + /** + * If not null, "value to update" instead of creating a new instance + * for each call. + */ + protected final T _updatedValue; + + protected MappingIterator(JavaType type, JsonParser jp, DeserializationContext ctxt, + JsonDeserializer<?> deser) + { + this(type, jp, ctxt, deser, true, null); + } + + /** + * @since 1.9.3 + */ + @SuppressWarnings("unchecked") + protected MappingIterator(JavaType type, JsonParser jp, DeserializationContext ctxt, JsonDeserializer<?> deser, + boolean closeParser, Object valueToUpdate) + { + _type = type; + _parser = jp; + _context = ctxt; + _deserializer = (JsonDeserializer<T>) deser; + + /* One more thing: if we are at START_ARRAY (but NOT root-level + * one!), advance to next token (to allow matching END_ARRAY) + */ + if (jp != null && jp.getCurrentToken() == JsonToken.START_ARRAY) { + JsonStreamContext sc = jp.getParsingContext(); + // safest way to skip current token is to clear it (so we'll advance soon) + if (!sc.inRoot()) { + jp.clearCurrentToken(); + } + } + _closeParser = closeParser; + if (valueToUpdate == null) { + _updatedValue = null; + } else { + _updatedValue = (T) valueToUpdate; + } + } + + @SuppressWarnings("unchecked") + protected static <T> MappingIterator<T> emptyIterator() { + return (MappingIterator<T>) EMPTY_ITERATOR; + } + + /* + /********************************************************** + /* Basic iterator impl + /********************************************************** + */ + + @Override + public boolean hasNext() + { + try { + return hasNextValue(); + } catch (JsonMappingException e) { + throw new RuntimeJsonMappingException(e.getMessage(), e); + } catch (IOException e) { + throw new RuntimeException(e.getMessage(), e); + } + } + + @Override + public T next() + { + try { + return nextValue(); + } catch (JsonMappingException e) { + throw new RuntimeJsonMappingException(e.getMessage(), e); + } catch (IOException e) { + throw new RuntimeException(e.getMessage(), e); + } + } + + @Override public void remove() { + throw new UnsupportedOperationException(); + } + + /* + /********************************************************** + /* Extended API + /********************************************************** + */ + + /** + * Equivalent of {@link #next} but one that may throw checked + * exceptions from Jackson due to invalid input. + */ + public boolean hasNextValue() throws IOException + { + if (_parser == null) { + return false; + } + if (!_hasNextChecked) { + JsonToken t = _parser.getCurrentToken(); + _hasNextChecked = true; + if (t == null) { // un-initialized or cleared; find next + t = _parser.nextToken(); + // If EOF, no more + if (t == null) { + JsonParser jp = _parser; + _parser = null; + if (_closeParser) { + jp.close(); + } + return false; + } + /* And similarly if we hit END_ARRAY; except that we won't close parser + * (because it's not a root-level iterator) + */ + if (t == JsonToken.END_ARRAY) { + return false; + } + } + } + return true; + } + + public T nextValue() throws IOException + { + // caller should always call 'hasNext[Value]' first; but let's ensure: + if (!_hasNextChecked) { + if (!hasNextValue()) { + throw new NoSuchElementException(); + } + } + if (_parser == null) { + throw new NoSuchElementException(); + } + _hasNextChecked = false; + T result; + + if (_updatedValue == null) { + result = _deserializer.deserialize(_parser, _context); + } else{ + _deserializer.deserialize(_parser, _context, _updatedValue); + result = _updatedValue; + } + // Need to consume the token too + _parser.clearCurrentToken(); + return result; + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/MappingJsonFactory.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/MappingJsonFactory.java new file mode 100644 index 0000000..6c081d0 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/MappingJsonFactory.java
@@ -0,0 +1,80 @@ +/* Jackson JSON-processor. + * + * Copyright (c) 2007- Tatu Saloranta, tatu.saloranta@iki.fi + * + * Licensed under the License specified in file LICENSE, included with + * the source code and binary code bundles. + * You may not use this file except in compliance with the License. + * + * 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.codehaus.jackson.map; + +import java.io.IOException; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.format.InputAccessor; +import org.codehaus.jackson.format.MatchStrength; + +/** + * Sub-class of {@link JsonFactory} that will create a proper + * {@link ObjectCodec} to allow seamless conversions between + * Json content and Java objects (POJOs). + * The only addition to regular {@link JsonFactory} currently + * is that {@link ObjectMapper} is constructed and passed as + * the codec to use. + */ +public class MappingJsonFactory + extends JsonFactory +{ + public MappingJsonFactory() + { + this(null); + } + + public MappingJsonFactory(ObjectMapper mapper) + { + super(mapper); + if (mapper == null) { + setCodec(new ObjectMapper(this)); + } + } + + /** + * We'll override the method to return more specific type; co-variance + * helps here + */ + @Override + public final ObjectMapper getCodec() { return (ObjectMapper) _objectCodec; } + + /* + /********************************************************** + /* Format detection functionality (since 1.8) + /********************************************************** + */ + + /** + * Sub-classes need to override this method (as of 1.8) + */ + @Override + public String getFormatName() + { + /* since non-JSON factories typically should not extend this class, + * let's just always return JSON as name. + */ + return FORMAT_NAME_JSON; + } + + /** + * Sub-classes need to override this method (as of 1.8) + */ + @Override + public MatchStrength hasFormat(InputAccessor acc) throws IOException + { + return hasJSONFormat(acc); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/Module.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/Module.java new file mode 100644 index 0000000..f4fac8e --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/Module.java
@@ -0,0 +1,255 @@ +package org.codehaus.jackson.map; + +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.Version; +import org.codehaus.jackson.Versioned; +import org.codehaus.jackson.map.deser.BeanDeserializerModifier; +import org.codehaus.jackson.map.deser.ValueInstantiators; +import org.codehaus.jackson.map.ser.BeanSerializerModifier; +import org.codehaus.jackson.map.type.TypeModifier; + +/** + * Simple interface for extensions that can be registered with {@link ObjectMapper} + * to provide a well-defined set of extensions to default functionality; such as + * support for new data types. + * + * @since 1.7 + */ +public abstract class Module + implements Versioned +{ + /* + /********************************************************** + /* Simple accessors + /********************************************************** + */ + + /** + * Method that returns identifier for module; this can be used by Jackson + * for informational purposes, as well as in associating extensions with + * module that provides them. + */ + public abstract String getModuleName(); + + /** + * Method that returns version of this module. Can be used by Jackson for + * informational purposes. + */ + @Override + public abstract Version version(); + + /* + /********************************************************** + /* Life-cycle: registration + /********************************************************** + */ + + /** + * Method called by {@link ObjectMapper} when module is registered. + * It is called to let module register functionality it provides, + * using callback methods passed-in context object exposes. + */ + public abstract void setupModule(SetupContext context); + + /* + /********************************************************** + /* Helper types + /********************************************************** + */ + + /** + * Interface Jackson exposes to modules for purpose of registering + * extended functionality. + */ + public interface SetupContext + { + /* + /********************************************************** + /* Simple accessors + /********************************************************** + */ + + /** + * Method that returns version information about {@link ObjectMapper} + * that implements this context. Modules can use this to choose + * different settings or initialization order; or even decide to fail + * set up completely if version is compatible with module. + */ + public Version getMapperVersion(); + + /** + * Method that returns current deserialization configuration + * settings. Since modules may be interested in these settings, + * caller should make sure to make changes to settings before + * module registrations. + */ + public DeserializationConfig getDeserializationConfig(); + + /** + * Method that returns current serialization configuration + * settings. Since modules may be interested in these settings, + * caller should make sure to make changes to settings before + * module registrations. + * + * @since 1.7.1 (1.7.0 unfortunately had a typo in method name!) + */ + public SerializationConfig getSerializationConfig(); + + /** + * @since 1.9.0 + */ + public boolean isEnabled(DeserializationConfig.Feature f); + + /** + * @since 1.9.0 + */ + public boolean isEnabled(SerializationConfig.Feature f); + + /** + * @since 1.9.0 + */ + public boolean isEnabled(JsonParser.Feature f); + + /** + * @since 1.9.0 + */ + public boolean isEnabled(JsonGenerator.Feature f); + + /* + /********************************************************** + /* Handler registration; serializers/deserializers + /********************************************************** + */ + + /** + * Method that module can use to register additional deserializers to use for + * handling types. + * + * @param d Object that can be called to find deserializer for types supported + * by module (null returned for non-supported types) + */ + public void addDeserializers(Deserializers d); + + /** + * Method that module can use to register additional deserializers to use for + * handling Map key values (which are separate from value deserializers because + * they are always serialized from String values) + * + * @since 1.8 + */ + public void addKeyDeserializers(KeyDeserializers s); + + /** + * Method that module can use to register additional serializers to use for + * handling types. + * + * @param s Object that can be called to find serializer for types supported + * by module (null returned for non-supported types) + */ + public void addSerializers(Serializers s); + + /** + * Method that module can use to register additional serializers to use for + * handling Map key values (which are separate from value serializers because + * they must write <code>JsonToken.FIELD_NAME</code> instead of String value). + * + * @since 1.8 + */ + public void addKeySerializers(Serializers s); + + /* + /********************************************************** + /* Handler registration; other + /********************************************************** + */ + + /** + * Method that module can use to register additional modifier objects to + * customize configuration and construction of bean deserializers. + * + * @param mod Modifier to register + */ + public void addBeanDeserializerModifier(BeanDeserializerModifier mod); + + /** + * Method that module can use to register additional modifier objects to + * customize configuration and construction of bean serializers. + * + * @param mod Modifier to register + */ + public void addBeanSerializerModifier(BeanSerializerModifier mod); + + /** + * Method that module can use to register additional + * {@link AbstractTypeResolver} instance, to handle resolution of + * abstract to concrete types (either by defaulting, or by materializing). + * + * @param resolver Resolver to add. + * + * @since 1.8 + */ + public void addAbstractTypeResolver(AbstractTypeResolver resolver); + + /** + * Method that module can use to register additional + * {@link TypeModifier} instance, which can augment {@link org.codehaus.jackson.type.JavaType} + * instances constructed by {@link org.codehaus.jackson.map.type.TypeFactory}. + * + * @param modifier to add + * + * @since 1.8 + */ + public void addTypeModifier(TypeModifier modifier); + + /** + * Method that module can use to register additional {@link org.codehaus.jackson.map.deser.ValueInstantiator}s, + * by adding {@link ValueInstantiators} object that gets called when + * instantatiator is needed by a deserializer. + * + * @param instantiators Object that can provide {@link org.codehaus.jackson.map.deser.ValueInstantiator}s for + * constructing POJO values during deserialization + * + * @since 1.9 + */ + public void addValueInstantiators(ValueInstantiators instantiators); + + /** + * Method for registering specified {@link AnnotationIntrospector} as the highest + * priority introspector (will be chained with existing introspector(s) which + * will be used as fallbacks for cases this introspector does not handle) + * + * @param ai Annotation introspector to register. + */ + public void insertAnnotationIntrospector(AnnotationIntrospector ai); + + /** + * Method for registering specified {@link AnnotationIntrospector} as the lowest + * priority introspector, chained with existing introspector(s) and called + * as fallback for cases not otherwise handled. + * + * @param ai Annotation introspector to register. + */ + public void appendAnnotationIntrospector(AnnotationIntrospector ai); + + /** + * Method used for defining mix-in annotations to use for augmenting + * specified class or interface. + * All annotations from + * <code>mixinSource</code> are taken to override annotations + * that <code>target</code> (or its supertypes) has. + *<p> + * Note: mix-ins are registered both for serialization and deserialization + * (which can be different internally). + *<p> + * Note: currently only one set of mix-in annotations can be defined for + * a single class; so if multiple modules register mix-ins, highest + * priority one (last one registered) will have priority over other modules. + * + * @param target Class (or interface) whose annotations to effectively override + * @param mixinSource Class (or interface) whose annotations are to + * be "added" to target's annotations, overriding as necessary + */ + public void setMixInAnnotations(Class<?> target, Class<?> mixinSource); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ObjectMapper.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ObjectMapper.java new file mode 100644 index 0000000..41b9f91 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ObjectMapper.java
@@ -0,0 +1,2852 @@ +package org.codehaus.jackson.map; + +import java.io.*; +import java.lang.reflect.Type; +import java.net.URL; +import java.text.DateFormat; +import java.util.Collection; +import java.util.concurrent.ConcurrentHashMap; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.annotate.JsonAutoDetect; +import org.codehaus.jackson.annotate.JsonMethod; +import org.codehaus.jackson.annotate.JsonTypeInfo; +import org.codehaus.jackson.io.SegmentedStringWriter; +import org.codehaus.jackson.io.SerializedString; +import org.codehaus.jackson.map.annotate.JsonSerialize; +import org.codehaus.jackson.map.deser.*; +import org.codehaus.jackson.map.introspect.BasicClassIntrospector; +import org.codehaus.jackson.map.introspect.JacksonAnnotationIntrospector; +import org.codehaus.jackson.map.introspect.VisibilityChecker; +import org.codehaus.jackson.map.ser.*; +import org.codehaus.jackson.map.jsontype.NamedType; +import org.codehaus.jackson.map.jsontype.SubtypeResolver; +import org.codehaus.jackson.map.jsontype.TypeResolverBuilder; +import org.codehaus.jackson.map.jsontype.impl.StdSubtypeResolver; +import org.codehaus.jackson.map.jsontype.impl.StdTypeResolverBuilder; +import org.codehaus.jackson.map.type.SimpleType; +import org.codehaus.jackson.map.type.TypeFactory; +import org.codehaus.jackson.map.type.TypeModifier; +import org.codehaus.jackson.node.*; +import org.codehaus.jackson.schema.JsonSchema; +import org.codehaus.jackson.type.JavaType; +import org.codehaus.jackson.type.TypeReference; +import org.codehaus.jackson.util.*; + +/** + * This mapper (or, data binder, or codec) provides functionality for + * converting between Java objects (instances of JDK provided core classes, + * beans), and matching JSON constructs. + * It will use instances of {@link JsonParser} and {@link JsonGenerator} + * for implementing actual reading/writing of JSON. + *<p> + * The main conversion API is defined in {@link ObjectCodec}, so that + * implementation details of this class need not be exposed to + * streaming parser and generator classes. + *<p> + * Note on caching: root-level deserializers are always cached, and accessed + * using full (generics-aware) type information. This is different from + * caching of referenced types, which is more limited and is done only + * for a subset of all deserializer types. The main reason for difference + * is that at root-level there is no incoming reference (and hence no + * referencing property, no referral information or annotations to + * produce differing deserializers), and that the performance impact + * greatest at root level (since it'll essentially cache the full + * graph of deserializers involved). + */ +public class ObjectMapper + extends ObjectCodec + implements Versioned +{ + /* + /********************************************************** + /* Helper classes, enums + /********************************************************** + */ + + /** + * Enumeration used with {@link ObjectMapper#enableDefaultTyping()} + * to specify what kind of types (classes) default typing should + * be used for. It will only be used if no explicit type information + * is found, but this enumeration further limits subset of those + * types. + * + * @since 1.5 + */ + public enum DefaultTyping { + /** + * This value means that only properties that have + * {@link java.lang.Object} as declared type (including + * generic types without explicit type) will use default + * typing. + */ + JAVA_LANG_OBJECT, + + /** + * Value that means that default typing will be used for + * properties with declared type of {@link java.lang.Object} + * or an abstract type (abstract class or interface). + * Note that this does <b>not</b> include array types. + */ + OBJECT_AND_NON_CONCRETE, + + /** + * Value that means that default typing will be used for + * all types covered by {@link #OBJECT_AND_NON_CONCRETE} + * plus all array types for them. + */ + NON_CONCRETE_AND_ARRAYS, + + /** + * Value that means that default typing will be used for + * all non-final types, with exception of small number of + * "natural" types (String, Boolean, Integer, Double), which + * can be correctly inferred from JSON; as well as for + * all arrays of non-final types. + */ + NON_FINAL + } + + /** + * Customized {@link TypeResolverBuilder} that provides type resolver builders + * used with so-called "default typing" + * (see {@link ObjectMapper#enableDefaultTyping()} for details). + *<p> + * Type resolver construction is based on configuration: implementation takes care + * of only providing builders in cases where type information should be applied. + * This is important since build calls may be sent for any and all types, and + * type information should NOT be applied to all of them. + */ + public static class DefaultTypeResolverBuilder + extends StdTypeResolverBuilder + { + /** + * Definition of what types is this default typer valid for. + */ + protected final DefaultTyping _appliesFor; + + public DefaultTypeResolverBuilder(DefaultTyping t) { + _appliesFor = t; + } + + @Override + public TypeDeserializer buildTypeDeserializer(DeserializationConfig config, + JavaType baseType, Collection<NamedType> subtypes, BeanProperty property) + { + return useForType(baseType) ? super.buildTypeDeserializer(config, baseType, subtypes, property) : null; + } + + @Override + public TypeSerializer buildTypeSerializer(SerializationConfig config, + JavaType baseType, Collection<NamedType> subtypes, BeanProperty property) + { + return useForType(baseType) ? super.buildTypeSerializer(config, baseType, subtypes, property) : null; + } + + /** + * Method called to check if the default type handler should be + * used for given type. + * Note: "natural types" (String, Boolean, Integer, Double) will never + * use typing; that is both due to them being concrete and final, + * and since actual serializers and deserializers will also ignore any + * attempts to enforce typing. + */ + public boolean useForType(JavaType t) + { + switch (_appliesFor) { + case NON_CONCRETE_AND_ARRAYS: + while (t.isArrayType()) { + t = t.getContentType(); + } + // fall through + case OBJECT_AND_NON_CONCRETE: + return (t.getRawClass() == Object.class) || !t.isConcrete(); + case NON_FINAL: + while (t.isArrayType()) { + t = t.getContentType(); + } + return !t.isFinal(); // includes Object.class + default: + //case JAVA_LANG_OBJECT: + return (t.getRawClass() == Object.class); + } + } + } + + /* + /********************************************************** + /* Internal constants, singletons + /********************************************************** + */ + + // Quick little shortcut, to avoid having to use global TypeFactory instance... + private final static JavaType JSON_NODE_TYPE = SimpleType.constructUnsafe(JsonNode.class); + + /* !!! 03-Apr-2009, tatu: Should try to avoid direct reference... but not + * sure what'd be simple and elegant way. So until then: + */ + protected final static ClassIntrospector<? extends BeanDescription> DEFAULT_INTROSPECTOR = BasicClassIntrospector.instance; + + // 16-May-2009, tatu: Ditto ^^^ + protected final static AnnotationIntrospector DEFAULT_ANNOTATION_INTROSPECTOR = new JacksonAnnotationIntrospector(); + + /** + * @since 1.5 + */ + protected final static VisibilityChecker<?> STD_VISIBILITY_CHECKER = VisibilityChecker.Std.defaultInstance(); + + /* + /********************************************************** + /* Configuration settings, shared + /********************************************************** + */ + + /** + * Factory used to create {@link JsonParser} and {@link JsonGenerator} + * instances as necessary. + */ + protected final JsonFactory _jsonFactory; + + /** + * Registered concrete subtypes that can be used instead of (or + * in addition to) ones declared using annotations. + * + * @since 1.6 + */ + protected SubtypeResolver _subtypeResolver; + + /** + * Specific factory used for creating {@link JavaType} instances; + * needed to allow modules to add more custom type handling + * (mostly to support types of non-Java JVM languages) + */ + protected TypeFactory _typeFactory; + + /** + * Provider for values to inject in deserialized POJOs. + * + * @since 1.9 + */ + protected InjectableValues _injectableValues; + + /* + /********************************************************** + /* Configuration settings, serialization + /********************************************************** + */ + + /** + * Configuration object that defines basic global + * settings for the serialization process + */ + protected SerializationConfig _serializationConfig; + + /** + * Object that manages access to serializers used for serialization, + * including caching. + * It is configured with {@link #_serializerFactory} to allow + * for constructing custom serializers. + */ + protected SerializerProvider _serializerProvider; + + /** + * Serializer factory used for constructing serializers. + */ + protected SerializerFactory _serializerFactory; + + /* + /********************************************************** + /* Configuration settings, deserialization + /********************************************************** + */ + + /** + * Configuration object that defines basic global + * settings for the serialization process + */ + protected DeserializationConfig _deserializationConfig; + + /** + * Object that manages access to deserializers used for deserializing + * JSON content into Java objects, including possible caching + * of the deserializers. It contains a reference to + * {@link DeserializerFactory} to use for constructing acutal deserializers. + */ + protected DeserializerProvider _deserializerProvider; + + /* + /********************************************************** + /* Caching + /********************************************************** + */ + + /* Note: handling of serializers and deserializers is not symmetric; + * and as a result, only root-level deserializers can be cached here. + * This is mostly because typing and resolution for deserializers is + * fully static; whereas it is quite dynamic for serialization. + */ + + /** + * We will use a separate main-level Map for keeping track + * of root-level deserializers. This is where most succesful + * cache lookups get resolved. + * Map will contain resolvers for all kinds of types, including + * container types: this is different from the component cache + * which will only cache bean deserializers. + *<p> + * Given that we don't expect much concurrency for additions + * (should very quickly converge to zero after startup), let's + * explicitly define a low concurrency setting. + *<p> + * Since version 1.5, these may are either "raw" deserializers (when + * no type information is needed for base type), or type-wrapped + * deserializers (if it is needed) + */ + final protected ConcurrentHashMap<JavaType, JsonDeserializer<Object>> _rootDeserializers + = new ConcurrentHashMap<JavaType, JsonDeserializer<Object>>(64, 0.6f, 2); + + /* + /********************************************************** + /* Life-cycle: constructing instance + /********************************************************** + */ + + /** + * Default constructor, which will construct the default + * {@link JsonFactory} as necessary, use + * {@link StdSerializerProvider} as its + * {@link SerializerProvider}, and + * {@link BeanSerializerFactory} as its + * {@link SerializerFactory}. + * This means that it + * can serialize all standard JDK types, as well as regular + * Java Beans (based on method names and Jackson-specific annotations), + * but does not support JAXB annotations. + */ + public ObjectMapper() + { + this(null, null, null); + } + + /** + * Construct mapper that uses specified {@link JsonFactory} + * for constructing necessary {@link JsonParser}s and/or + * {@link JsonGenerator}s. + */ + public ObjectMapper(JsonFactory jf) + { + this(jf, null, null); + } + + /** + * Construct mapper that uses specified {@link SerializerFactory} + * for constructing necessary serializers. + * + * @deprecated Use other constructors instead; note that + * you can just set serializer factory with {@link #setSerializerFactory} + */ + @Deprecated + public ObjectMapper(SerializerFactory sf) + { + this(null, null, null); + setSerializerFactory(sf); + } + + public ObjectMapper(JsonFactory jf, + SerializerProvider sp, DeserializerProvider dp) + { + this(jf, sp, dp, null, null); + } + + /** + * + * @param jf JsonFactory to use: if null, a new {@link MappingJsonFactory} will be constructed + * @param sp SerializerProvider to use: if null, a {@link StdSerializerProvider} will be constructed + * @param dp DeserializerProvider to use: if null, a {@link StdDeserializerProvider} will be constructed + * @param sconfig Serialization configuration to use; if null, basic {@link SerializationConfig} + * will be constructed + * @param dconfig Deserialization configuration to use; if null, basic {@link DeserializationConfig} + * will be constructed + */ + public ObjectMapper(JsonFactory jf, + SerializerProvider sp, DeserializerProvider dp, + SerializationConfig sconfig, DeserializationConfig dconfig) + { + /* 02-Mar-2009, tatu: Important: we MUST default to using + * the mapping factory, otherwise tree serialization will + * have problems with POJONodes. + * 03-Jan-2010, tatu: and obviously we also must pass 'this', + * to create actual linking. + */ + if (jf == null) { + _jsonFactory = new MappingJsonFactory(this); + } else { + _jsonFactory = jf; + if (jf.getCodec() == null) { // as per [JACKSON-741] + _jsonFactory.setCodec(this); + } + } + // and default type factory is shared one + _typeFactory = TypeFactory.defaultInstance(); + _serializationConfig = (sconfig != null) ? sconfig : + new SerializationConfig(DEFAULT_INTROSPECTOR, DEFAULT_ANNOTATION_INTROSPECTOR, STD_VISIBILITY_CHECKER, + null, null, _typeFactory, null); + _deserializationConfig = (dconfig != null) ? dconfig : + new DeserializationConfig(DEFAULT_INTROSPECTOR, DEFAULT_ANNOTATION_INTROSPECTOR, STD_VISIBILITY_CHECKER, + null, null, _typeFactory, null); + _serializerProvider = (sp == null) ? new StdSerializerProvider() : sp; + _deserializerProvider = (dp == null) ? new StdDeserializerProvider() : dp; + + // Default serializer factory is stateless, can just assign + _serializerFactory = BeanSerializerFactory.instance; + } + + /* + /********************************************************** + /* Versioned impl + /********************************************************** + */ + + /** + * Method that will return version information stored in and read from jar + * that contains this class. + * + * @since 1.6 + */ + @Override + public Version version() { + return VersionUtil.versionFor(getClass()); + } + + /* + /********************************************************** + /* Module registration + /********************************************************** + */ + + /** + * Method for registering a module that can extend functionality + * provided by this mapper; for example, by adding providers for + * custom serializers and deserializers. + * + * @param module Module to register + * + * @since 1.7 + */ + public void registerModule(Module module) + { + /* Let's ensure we have access to name and version information, + * even if we do not have immediate use for either. This way we know + * that they will be available from beginning + */ + String name = module.getModuleName(); + if (name == null) { + throw new IllegalArgumentException("Module without defined name"); + } + Version version = module.version(); + if (version == null) { + throw new IllegalArgumentException("Module without defined version"); + } + + final ObjectMapper mapper = this; + + // And then call registration + module.setupModule(new Module.SetupContext() + { + // // // Accessors + + @Override + public Version getMapperVersion() { + return version(); + } + + @Override + public DeserializationConfig getDeserializationConfig() { + return mapper.getDeserializationConfig(); + } + + @Override + public SerializationConfig getSerializationConfig() { + return mapper.getSerializationConfig(); + } + + @Override + public boolean isEnabled(DeserializationConfig.Feature f) { + return mapper.isEnabled(f); + } + + @Override + public boolean isEnabled(SerializationConfig.Feature f) { + return mapper.isEnabled(f); + } + + @Override + public boolean isEnabled(JsonParser.Feature f) { + return mapper.isEnabled(f); + } + + @Override + public boolean isEnabled(JsonGenerator.Feature f) { + return mapper.isEnabled(f); + } + + // // // Methods for registering handlers: deserializers, serializers + + @Override + public void addDeserializers(Deserializers d) { + mapper._deserializerProvider = mapper._deserializerProvider.withAdditionalDeserializers(d); + } + + @Override + public void addKeyDeserializers(KeyDeserializers d) { + mapper._deserializerProvider = mapper._deserializerProvider.withAdditionalKeyDeserializers(d); + } + + @Override + public void addSerializers(Serializers s) { + mapper._serializerFactory = mapper._serializerFactory.withAdditionalSerializers(s); + } + + @Override + public void addKeySerializers(Serializers s) { + mapper._serializerFactory = mapper._serializerFactory.withAdditionalKeySerializers(s); + } + + @Override + public void addBeanSerializerModifier(BeanSerializerModifier modifier) { + mapper._serializerFactory = mapper._serializerFactory.withSerializerModifier(modifier); + } + + @Override + public void addBeanDeserializerModifier(BeanDeserializerModifier modifier) { + mapper._deserializerProvider = mapper._deserializerProvider.withDeserializerModifier(modifier); + } + + // // // Methods for registering handlers: other + + @Override + public void addAbstractTypeResolver(AbstractTypeResolver resolver) { + mapper._deserializerProvider = mapper._deserializerProvider.withAbstractTypeResolver(resolver); + } + + @Override + public void addTypeModifier(TypeModifier modifier) { + TypeFactory f = mapper._typeFactory; + f = f.withModifier(modifier); + mapper.setTypeFactory(f); + } + + @Override + public void addValueInstantiators(ValueInstantiators instantiators) { + mapper._deserializerProvider = mapper._deserializerProvider.withValueInstantiators(instantiators); + } + + @Override + public void insertAnnotationIntrospector(AnnotationIntrospector ai) { + mapper._deserializationConfig = mapper._deserializationConfig.withInsertedAnnotationIntrospector(ai); + mapper._serializationConfig = mapper._serializationConfig.withInsertedAnnotationIntrospector(ai); + } + + @Override + public void appendAnnotationIntrospector(AnnotationIntrospector ai) { + mapper._deserializationConfig = mapper._deserializationConfig.withAppendedAnnotationIntrospector(ai); + mapper._serializationConfig = mapper._serializationConfig.withAppendedAnnotationIntrospector(ai); + } + + @Override + public void setMixInAnnotations(Class<?> target, Class<?> mixinSource) { + mapper._deserializationConfig.addMixInAnnotations(target, mixinSource); + mapper._serializationConfig.addMixInAnnotations(target, mixinSource); + } + }); + } + + /** + * Fluent-style alternative to {@link #registerModule}; functionally equivalent to: + *<pre> + * mapper.registerModule(module); + * return mapper; + *</pre> + * NOTE: name is unfortunately misleading in suggesting that a new instance + * might be created (as is the case with most other 'withXxx()' methods + * for Jackson core objects) -- this is not the case; rather, this is just + * a variant of {@link #registerModule} but one that returns 'this' + * (like it should return, but does not for historical reasons). + * + * @since 1.8 + */ + public ObjectMapper withModule(Module module) + { + registerModule(module); + return this; + } + + /* + /********************************************************** + /* Configuration: main config object access + /********************************************************** + */ + + /** + * Method that returns the shared default {@link SerializationConfig} + * object that defines configuration settings for serialization. + * Returned object is "live" meaning that changes will be used + * for future serialization operations for this mapper when using + * mapper's default configuration + */ + public SerializationConfig getSerializationConfig() { + return _serializationConfig; + } + + /** + * Method that creates a copy of + * the shared default {@link SerializationConfig} object + * that defines configuration settings for serialization. + * Since it is a copy, any changes made to the configuration + * object will NOT directly affect serialization done using + * basic serialization methods that use the shared object (that is, + * ones that do not take separate {@link SerializationConfig} + * argument. + *<p> + * The use case is that of changing object settings of the configuration + * (like date format being used, see {@link SerializationConfig#setDateFormat}). + */ + public SerializationConfig copySerializationConfig() { + return _serializationConfig.createUnshared(_subtypeResolver); + } + + /** + * Method for replacing the shared default serialization configuration + * object. + */ + public ObjectMapper setSerializationConfig(SerializationConfig cfg) { + _serializationConfig = cfg; + return this; + } + + /** + * Method that returns + * the shared default {@link DeserializationConfig} object + * that defines configuration settings for deserialization. + * Returned object is "live" meaning that changes will be used + * for future deserialization operations for this mapper when using + * mapper's default configuration + */ + public DeserializationConfig getDeserializationConfig() { + return _deserializationConfig; + } + + /** + * Method that creates a copy of + * the shared default {@link DeserializationConfig} object + * that defines configuration settings for deserialization. + * Since it is a copy, any changes made to the configuration + * object will NOT directly affect deserialization done using + * basic deserialization methods that use the shared object (that is, + * ones that do not take separate {@link DeserializationConfig} + * argument. + *<p> + * The use case is that of changing object settings of the configuration + * (like deserialization problem handler, + * see {@link DeserializationConfig#addHandler}) + */ + public DeserializationConfig copyDeserializationConfig() { + return _deserializationConfig.createUnshared(_subtypeResolver) + .passSerializationFeatures(_serializationConfig._featureFlags); + } + + /** + * Method for replacing the shared default deserialization configuration + * object. + */ + public ObjectMapper setDeserializationConfig(DeserializationConfig cfg) { + _deserializationConfig = cfg; + return this; + } + + /* + /********************************************************** + /* Configuration: ser/deser factory, provider access + /********************************************************** + */ + + /** + * Method for setting specific {@link SerializerFactory} to use + * for constructing (bean) serializers. + */ + public ObjectMapper setSerializerFactory(SerializerFactory f) { + _serializerFactory = f; + return this; + } + + /** + * Method for setting specific {@link SerializerProvider} to use + * for handling caching of {@link JsonSerializer} instances. + */ + public ObjectMapper setSerializerProvider(SerializerProvider p) { + _serializerProvider = p; + return this; + } + + /** + * @since 1.4 + */ + public SerializerProvider getSerializerProvider() { + return _serializerProvider; + } + + /** + * Method for setting specific {@link DeserializerProvider} to use + * for handling caching of {@link JsonDeserializer} instances. + */ + public ObjectMapper setDeserializerProvider(DeserializerProvider p) { + _deserializerProvider = p; + return this; + } + + /** + * @since 1.4 + */ + public DeserializerProvider getDeserializerProvider() { + return _deserializerProvider; + } + + /* + /********************************************************** + /* Configuration, introspection + /********************************************************** + */ + + /** + * Method for accessing currently configured visibility checker; + * object used for determining whether given property element + * (method, field, constructor) can be auto-detected or not. + * + * @since 1.5 + */ + public VisibilityChecker<?> getVisibilityChecker() { + return _serializationConfig.getDefaultVisibilityChecker(); + } + + /** + * Method for setting currently configured visibility checker; + * object used for determining whether given property element + * (method, field, constructor) can be auto-detected or not. + * This default checker is used if no per-class overrides + * are defined. + * + * @since 1.5 + */ + public void setVisibilityChecker(VisibilityChecker<?> vc) { + _deserializationConfig = _deserializationConfig.withVisibilityChecker(vc); + _serializationConfig = _serializationConfig.withVisibilityChecker(vc); + } + + /** + * Convenience method that allows changing configuration for + * underlying {@link VisibilityChecker}s, to change details of what kinds of + * properties are auto-detected. + * Basically short cut for doing: + *<pre> + * mapper.setVisibilityChecker( + * mapper.getVisibilityChecker().withVisibility(forMethod, visibility) + * ); + *</pre> + * one common use case would be to do: + *<pre> + * mapper.setVisibility(JsonMethod.FIELD, Visibility.ANY); + *</pre> + * which would make all member fields serializable without further annotations, + * instead of just public fields (default setting). + * + * @param forMethod Type of property descriptor affected (field, getter/isGetter, + * setter, creator) + * @param visibility Minimum visibility to require for the property descriptors of type + * + * @return Modified mapper instance (that is, "this"), to allow chaining + * of configuration calls + * + * @since 1.9 + */ + public ObjectMapper setVisibility(JsonMethod forMethod, JsonAutoDetect.Visibility visibility) + { + _deserializationConfig = _deserializationConfig.withVisibility(forMethod, visibility); + _serializationConfig = _serializationConfig.withVisibility(forMethod, visibility); + return this; + } + + /** + * Method for accessing subtype resolver in use. + * + * @since 1.6 + */ + public SubtypeResolver getSubtypeResolver() { + if (_subtypeResolver == null) { + _subtypeResolver = new StdSubtypeResolver(); + } + return _subtypeResolver; + } + + /** + * Method for setting custom subtype resolver to use. + * + * @since 1.6 + */ + public void setSubtypeResolver(SubtypeResolver r) { + _subtypeResolver = r; + } + + /** + * Method for changing {@link AnnotationIntrospector} used by this + * mapper instance for both serialization and deserialization + * + * @since 1.8 + */ + public ObjectMapper setAnnotationIntrospector(AnnotationIntrospector ai) { + _serializationConfig = _serializationConfig.withAnnotationIntrospector(ai); + _deserializationConfig = _deserializationConfig.withAnnotationIntrospector(ai); + return this; + } + + /** + * Method for setting custom property naming strategy to use. + * + * @since 1.8 + */ + public ObjectMapper setPropertyNamingStrategy(PropertyNamingStrategy s) { + _serializationConfig = _serializationConfig.withPropertyNamingStrategy(s); + _deserializationConfig = _deserializationConfig.withPropertyNamingStrategy(s); + return this; + } + + /** + * Method for setting defalt POJO property inclusion strategy for serialization. + * Equivalent to: + *<pre> + * mapper.setSerializationConfig(mapper.getSerializationConfig().withSerializationInclusion(incl)); + *</pre> + * + * @since 1.9 + */ + public ObjectMapper setSerializationInclusion(JsonSerialize.Inclusion incl) { + _serializationConfig = _serializationConfig.withSerializationInclusion(incl); + return this; + } + + /* + /********************************************************** + /* Type information configuration (1.5+) + /********************************************************** + */ + + /** + * Convenience method that is equivalent to calling + *<pre> + * enableObjectTyping(DefaultTyping.OBJECT_AND_NON_CONCRETE); + *</pre> + */ + public ObjectMapper enableDefaultTyping() { + return enableDefaultTyping(DefaultTyping.OBJECT_AND_NON_CONCRETE); + } + + /** + * Convenience method that is equivalent to calling + *<pre> + * enableObjectTyping(dti, JsonTypeInfo.As.WRAPPER_ARRAY); + *</pre> + */ + public ObjectMapper enableDefaultTyping(DefaultTyping dti) { + return enableDefaultTyping(dti, JsonTypeInfo.As.WRAPPER_ARRAY); + } + + /** + * Method for enabling automatic inclusion of type information, needed + * for proper deserialization of polymorphic types (unless types + * have been annotated with {@link org.codehaus.jackson.annotate.JsonTypeInfo}). + * + * @param applicability Defines kinds of types for which additional type information + * is added; see {@link DefaultTyping} for more information. + */ + public ObjectMapper enableDefaultTyping(DefaultTyping applicability, JsonTypeInfo.As includeAs) + { + TypeResolverBuilder<?> typer = new DefaultTypeResolverBuilder(applicability); + // we'll always use full class name, when using defaulting + typer = typer.init(JsonTypeInfo.Id.CLASS, null); + typer = typer.inclusion(includeAs); + return setDefaultTyping(typer); + } + + /** + * Method for enabling automatic inclusion of type information -- needed + * for proper deserialization of polymorphic types (unless types + * have been annotated with {@link org.codehaus.jackson.annotate.JsonTypeInfo}) -- + * using "As.PROPERTY" inclusion mechanism and specified property name + * to use for inclusion (default being "@class" since default type information + * always uses class name as type identifier) + * + * @since 1.7 + */ + public ObjectMapper enableDefaultTypingAsProperty(DefaultTyping applicability, String propertyName) + { + TypeResolverBuilder<?> typer = new DefaultTypeResolverBuilder(applicability); + // we'll always use full class name, when using defaulting + typer = typer.init(JsonTypeInfo.Id.CLASS, null); + typer = typer.inclusion(JsonTypeInfo.As.PROPERTY); + typer = typer.typeProperty(propertyName); + return setDefaultTyping(typer); + } + + /** + * Method for disabling automatic inclusion of type information; if so, only + * explicitly annotated types (ones with + * {@link org.codehaus.jackson.annotate.JsonTypeInfo}) will have + * additional embedded type information. + */ + public ObjectMapper disableDefaultTyping() { + return setDefaultTyping(null); + } + + /** + * Method for enabling automatic inclusion of type information, using + * specified handler object for determining which types this affects, + * as well as details of how information is embedded. + * + * @param typer Type information inclusion handler + * + * + */ + public ObjectMapper setDefaultTyping(TypeResolverBuilder<?> typer) { + _deserializationConfig = _deserializationConfig.withTypeResolverBuilder(typer); + _serializationConfig = _serializationConfig.withTypeResolverBuilder(typer); + return this; + } + + /** + * Method for registering specified class as a subtype, so that + * typename-based resolution can link supertypes to subtypes + * (as an alternative to using annotations). + * Type for given class is determined from appropriate annotation; + * or if missing, default name (unqualified class name) + * + * @since 1.6 + */ + public void registerSubtypes(Class<?>... classes) { + getSubtypeResolver().registerSubtypes(classes); + } + + /** + * Method for registering specified class as a subtype, so that + * typename-based resolution can link supertypes to subtypes + * (as an alternative to using annotations). + * Name may be provided as part of argument, but if not will + * be based on annotations or use default name (unqualified + * class name). + * + * @since 1.6 + */ + public void registerSubtypes(NamedType... types) { + getSubtypeResolver().registerSubtypes(types); + } + + /* + /********************************************************** + /* Configuration, basic type handling + /********************************************************** + */ + + /** + * Accessor for getting currently configured {@link TypeFactory} instance. + * + * @since 1.8 + */ + public TypeFactory getTypeFactory() { + return _typeFactory; + } + + /** + * Method that can be used to override {@link TypeFactory} instance + * used by this mapper. + *<p> + * Note: will also set {@link TypeFactory} that deserialization and + * serialization config objects use. + */ + public ObjectMapper setTypeFactory(TypeFactory f) + { + _typeFactory = f; + _deserializationConfig = _deserializationConfig.withTypeFactory(f); + _serializationConfig = _serializationConfig.withTypeFactory(f); + return this; + } + + /** + * Convenience method for constructing {@link JavaType} out of given + * type (typically <code>java.lang.Class</code>), but without explicit + * context. + * + * @since 1.8 + */ + public JavaType constructType(Type t) { + return _typeFactory.constructType(t); + } + + /* + /********************************************************** + /* Configuration, deserialization + /********************************************************** + */ + + /** + * Method for specifying {@link JsonNodeFactory} to use for + * constructing root level tree nodes (via method + * {@link #createObjectNode} + * + * @since 1.2 + */ + public ObjectMapper setNodeFactory(JsonNodeFactory f) { + _deserializationConfig = _deserializationConfig.withNodeFactory(f); + return this; + } + + /* + /********************************************************** + /* Configuration, serialization + /********************************************************** + */ + + /** + * Convenience method that is equivalent to: + *<pre> + * mapper.setFilters(mapper.getSerializationConfig().withFilters(filterProvider)); + *</pre> + *<p> + * Note that usually it is better to use method {@link #filteredWriter}; however, sometimes + * this method is more convenient. For example, some frameworks only allow configuring + * of ObjectMapper instances and not ObjectWriters. + * + * @since 1.8 + */ + public void setFilters(FilterProvider filterProvider) { + _serializationConfig = _serializationConfig.withFilters(filterProvider); + } + + /* + /********************************************************** + /* Configuration, other + /********************************************************** + */ + + /** + * Method that can be used to get hold of {@link JsonFactory} that this + * mapper uses if it needs to construct {@link JsonParser}s + * and/or {@link JsonGenerator}s. + * + * @return {@link JsonFactory} that this mapper uses when it needs to + * construct Json parser and generators + */ + public JsonFactory getJsonFactory() { return _jsonFactory; } + + /** + * Method for configuring the default {@link DateFormat} to use when serializing time + * values as Strings, and deserializing from JSON Strings. + * This is preferably to directly modifying {@link SerializationConfig} and + * {@link DeserializationConfig} instances. + * If you need per-request configuration, use {@link #writer(DateFormat)} to + * create properly configured {@link ObjectWriter} and use that; this because + * {@link ObjectWriter}s are thread-safe whereas ObjectMapper itself is only + * thread-safe when configuring methods (such as this one) are NOT called. + * + * @since 1.8 + */ + public void setDateFormat(DateFormat dateFormat) + { + _deserializationConfig = _deserializationConfig.withDateFormat(dateFormat); + _serializationConfig = _serializationConfig.withDateFormat(dateFormat); + } + + /** + * Method for configuring {@link HandlerInstantiator} to use for creating + * instances of handlers (such as serializers, deserializers, type and type + * id resolvers), given a class. + * + * @param hi Instantiator to use; if null, use the default implementation + */ + public void setHandlerInstantiator(HandlerInstantiator hi) + { + _deserializationConfig = _deserializationConfig.withHandlerInstantiator(hi); + _serializationConfig = _serializationConfig.withHandlerInstantiator(hi); + } + + /** + * @since 1.9 + */ + public ObjectMapper setInjectableValues(InjectableValues injectableValues) { + _injectableValues = injectableValues; + return this; + } + + /* + /********************************************************** + /* Configuration, simple features + /********************************************************** + */ + + /** + * Method for changing state of an on/off serialization feature for + * this object mapper. + *<p> + * This is method is basically a shortcut method for calling + * {@link SerializationConfig#set} on the shared {@link SerializationConfig} + * object with given arguments. + */ + @SuppressWarnings("deprecation") + public ObjectMapper configure(SerializationConfig.Feature f, boolean state) { + _serializationConfig.set(f, state); + return this; + } + + /** + * Method for changing state of an on/off deserialization feature for + * this object mapper. + *<p> + * This is method is basically a shortcut method for calling + * {@link DeserializationConfig#set} on the shared {@link DeserializationConfig} + * object with given arguments. + */ + @SuppressWarnings("deprecation") + public ObjectMapper configure(DeserializationConfig.Feature f, boolean state) { + _deserializationConfig.set(f, state); + return this; + } + + /** + * Method for changing state of an on/off {@link JsonParser} feature for + * {@link JsonFactory} instance this object mapper uses. + *<p> + * This is method is basically a shortcut method for calling + * {@link JsonFactory#setParserFeature} on the shared + * {@link JsonFactory} this mapper uses (which is accessible + * using {@link #getJsonFactory}). + * + * @since 1.2 + */ + public ObjectMapper configure(JsonParser.Feature f, boolean state) { + _jsonFactory.configure(f, state); + return this; + } + + /** + * Method for changing state of an on/off {@link JsonGenerator} feature for + * {@link JsonFactory} instance this object mapper uses. + *<p> + * This is method is basically a shortcut method for calling + * {@link JsonFactory#setGeneratorFeature} on the shared + * {@link JsonFactory} this mapper uses (which is accessible + * using {@link #getJsonFactory}). + * + * @since 1.2 + */ + public ObjectMapper configure(JsonGenerator.Feature f, boolean state) { + _jsonFactory.configure(f, state); + return this; + } + + /** + * Method for enabling specified {@link DeserializationConfig} features. + * Modifies and returns this instance; no new object is created. + * + * @since 1.9 + */ + public ObjectMapper enable(DeserializationConfig.Feature... f) { + _deserializationConfig = _deserializationConfig.with(f); + return this; + } + + /** + * Method for enabling specified {@link DeserializationConfig} features. + * Modifies and returns this instance; no new object is created. + * + * @since 1.9 + */ + public ObjectMapper disable(DeserializationConfig.Feature... f) { + _deserializationConfig = _deserializationConfig.without(f); + return this; + } + + /** + * Method for enabling specified {@link DeserializationConfig} features. + * Modifies and returns this instance; no new object is created. + * + * @since 1.9 + */ + public ObjectMapper enable(SerializationConfig.Feature... f) { + _serializationConfig = _serializationConfig.with(f); + return this; + } + + /** + * Method for enabling specified {@link DeserializationConfig} features. + * Modifies and returns this instance; no new object is created. + * + * @since 1.9 + */ + public ObjectMapper disable(SerializationConfig.Feature... f) { + _serializationConfig = _serializationConfig.without(f); + return this; + } + + /** + * Convenience method, equivalent to: + *<pre> + * getSerializationConfig().isEnabled(f); + *</pre> + * + * @since 1.9 + */ + public boolean isEnabled(SerializationConfig.Feature f) { + return _serializationConfig.isEnabled(f); + } + + /** + * Convenience method, equivalent to: + *<pre> + * getDeserializationConfig().isEnabled(f); + *</pre> + * + * @since 1.9 + */ + public boolean isEnabled(DeserializationConfig.Feature f) { + return _deserializationConfig.isEnabled(f); + } + + /** + * Convenience method, equivalent to: + *<pre> + * getJsonFactory().isEnabled(f); + *</pre> + * + * @since 1.9 + */ + public boolean isEnabled(JsonParser.Feature f) { + return _jsonFactory.isEnabled(f); + } + + /** + * Convenience method, equivalent to: + *<pre> + * getJsonFactory().isEnabled(f); + *</pre> + * + * @since 1.9 + */ + public boolean isEnabled(JsonGenerator.Feature f) { + return _jsonFactory.isEnabled(f); + } + + /** + * Method that can be used to get hold of {@link JsonNodeFactory} + * that this mapper will use when directly constructing + * root {@link JsonNode} instances for Trees. + *<p> + * Note: this is just a shortcut for calling + *<pre> + * getDeserializationConfig().getNodeFactory() + *</pre> + * + * @since 1.2 + */ + public JsonNodeFactory getNodeFactory() { + return _deserializationConfig.getNodeFactory(); + } + + /* + /********************************************************** + /* Public API (from ObjectCodec): deserialization + /* (mapping from JSON to Java types); + /* main methods + /********************************************************** + */ + + /** + * Method to deserialize JSON content into a non-container + * type (it can be an array type, however): typically a bean, array + * or a wrapper type (like {@link java.lang.Boolean}). + *<p> + * Note: this method should NOT be used if the result type is a + * container ({@link java.util.Collection} or {@link java.util.Map}. + * The reason is that due to type erasure, key and value types + * can not be introspected when using this method. + */ + @Override + @SuppressWarnings("unchecked") + public <T> T readValue(JsonParser jp, Class<T> valueType) + throws IOException, JsonParseException, JsonMappingException + { +// !!! TODO +// _setupClassLoaderForDeserialization(valueType); + return (T) _readValue(copyDeserializationConfig(), jp, _typeFactory.constructType(valueType)); + } + + /** + * Method to deserialize JSON content into a Java type, reference + * to which is passed as argument. Type is passed using so-called + * "super type token" (see ) + * and specifically needs to be used if the root type is a + * parameterized (generic) container type. + */ + @Override + @SuppressWarnings("unchecked") + public <T> T readValue(JsonParser jp, TypeReference<?> valueTypeRef) + throws IOException, JsonParseException, JsonMappingException + { + return (T) _readValue(copyDeserializationConfig(), jp, _typeFactory.constructType(valueTypeRef)); + } + + /** + * Method to deserialize JSON content into a Java type, reference + * to which is passed as argument. Type is passed using + * Jackson specific type; instance of which can be constructed using + * {@link TypeFactory}. + */ + @Override + @SuppressWarnings("unchecked") + public <T> T readValue(JsonParser jp, JavaType valueType) + throws IOException, JsonParseException, JsonMappingException + { + return (T) _readValue(copyDeserializationConfig(), jp, valueType); + } + + /** + * Method to deserialize JSON content as tree expressed + * using set of {@link JsonNode} instances. Returns + * root of the resulting tree (where root can consist + * of just a single node if the current event is a + * value event, not container). + */ + @Override + public JsonNode readTree(JsonParser jp) + throws IOException, JsonProcessingException + { + /* 02-Mar-2009, tatu: One twist; deserialization provider + * will map JSON null straight into Java null. But what + * we want to return is the "null node" instead. + */ + /* 05-Aug-2011, tatu: Also, must check for EOF here before + * calling readValue(), since that'll choke on it otherwise + */ + DeserializationConfig cfg = copyDeserializationConfig(); + JsonToken t = jp.getCurrentToken(); + if (t == null) { + t = jp.nextToken(); + if (t == null) { + return null; + } + } + JsonNode n = (JsonNode) _readValue(cfg, jp, JSON_NODE_TYPE); + return (n == null) ? getNodeFactory().nullNode() : n; + } + + /** + * Method for reading sequence of Objects from parser stream. + *<p> + * Note that {@link ObjectReader} has more complete set of variants. + * + * @since 1.8 + */ + @Override + public <T> MappingIterator<T> readValues(JsonParser jp, JavaType valueType) + throws IOException, JsonProcessingException + { + DeserializationConfig config = copyDeserializationConfig(); + DeserializationContext ctxt = _createDeserializationContext(jp, config); + JsonDeserializer<?> deser = _findRootDeserializer(config, valueType); + // false -> do NOT close JsonParser (since caller passed it) + return new MappingIterator<T>(valueType, jp, ctxt, deser, + false, null); + } + + /** + * Method for reading sequence of Objects from parser stream. + * + * @since 1.8 + */ + @Override + public <T> MappingIterator<T> readValues(JsonParser jp, Class<T> valueType) + throws IOException, JsonProcessingException + { + return readValues(jp, _typeFactory.constructType(valueType)); + } + + /** + * Method for reading sequence of Objects from parser stream. + * + * @since 1.8 + */ + @Override + public <T> MappingIterator<T> readValues(JsonParser jp, TypeReference<?> valueTypeRef) + throws IOException, JsonProcessingException + { + return readValues(jp, _typeFactory.constructType(valueTypeRef)); + } + + /* + /********************************************************** + /* Public API not included in ObjectCodec: deserialization + /* (mapping from JSON to Java types) + /********************************************************** + */ + + /** + * Method to deserialize JSON content into a non-container + * type (it can be an array type, however): typically a bean, array + * or a wrapper type (like {@link java.lang.Boolean}). + *<p> + * Note: this method should NOT be used if the result type is a + * container ({@link java.util.Collection} or {@link java.util.Map}. + * The reason is that due to type erasure, key and value types + * can not be introspected when using this method. + * @since 1.1 + * + * @param cfg Specific deserialization configuration to use for + * this operation. Note that not all config settings can + * be changed on per-operation basis: some changeds only take effect + * before calling the operation for the first time (for the mapper + * instance) + */ + @SuppressWarnings("unchecked") + public <T> T readValue(JsonParser jp, Class<T> valueType, + DeserializationConfig cfg) + throws IOException, JsonParseException, JsonMappingException + { + // !!! TODO +// _setupClassLoaderForDeserialization(valueType); + return (T) _readValue(cfg, jp, _typeFactory.constructType(valueType)); + } + + /** + * Method to deserialize JSON content into a Java type, reference + * to which is passed as argument. Type is passed using so-called + * "super type token" (see ) + * and specifically needs to be used if the root type is a + * parameterized (generic) container type. + * + * @param cfg Specific deserialization configuration to use for + * this operation. Note that not all config settings can + * be changed on per-operation basis: some changeds only take effect + * before calling the operation for the first time (for the mapper + * instance) + * + * @since 1.1 + */ + @SuppressWarnings("unchecked") + public <T> T readValue(JsonParser jp, TypeReference<?> valueTypeRef, + DeserializationConfig cfg) + throws IOException, JsonParseException, JsonMappingException + { + return (T) _readValue(cfg, jp, _typeFactory.constructType(valueTypeRef)); + } + + /** + * Method to deserialize JSON content into a Java type, reference + * to which is passed as argument. Type is passed using + * Jackson specific type; instance of which can be constructed using + * {@link TypeFactory}. + * + * @param cfg Specific deserialization configuration to use for + * this operation. Note that not all config settings can + * be changed on per-operation basis: some changeds only take effect + * before calling the operation for the first time (for the mapper + * instance) + * + * @since 1.1 + */ + @SuppressWarnings("unchecked") + public <T> T readValue(JsonParser jp, JavaType valueType, + DeserializationConfig cfg) + throws IOException, JsonParseException, JsonMappingException + { + return (T) _readValue(cfg, jp, valueType); + } + + /** + * Method to deserialize JSON content as tree expressed + * using set of {@link JsonNode} instances. Returns + * root of the resulting tree (where root can consist + * of just a single node if the current event is a + * value event, not container). + * + * @param cfg Specific deserialization configuration to use for + * this operation. Note that not all config settings can + * be changed on per-operation basis: some changeds only take effect + * before calling the operation for the first time (for the mapper + * instance) + * + * @since 1.1 + */ + public JsonNode readTree(JsonParser jp, DeserializationConfig cfg) + throws IOException, JsonProcessingException + { + JsonNode n = (JsonNode) _readValue(cfg, jp, JSON_NODE_TYPE); + return (n == null) ? NullNode.instance : n; + } + + /** + * Method to deserialize JSON content as tree expressed + * using set of {@link JsonNode} instances. + * Returns root of the resulting tree (where root can consist + * of just a single node if the current event is a + * value event, not container). + * + * @param in Input stream used to read JSON content + * for building the JSON tree. + * + * @since 1.3 + */ + public JsonNode readTree(InputStream in) + throws IOException, JsonProcessingException + { + JsonNode n = (JsonNode) _readMapAndClose(_jsonFactory.createJsonParser(in), JSON_NODE_TYPE); + return (n == null) ? NullNode.instance : n; + } + + /** + * Method to deserialize JSON content as tree expressed + * using set of {@link JsonNode} instances. + * Returns root of the resulting tree (where root can consist + * of just a single node if the current event is a + * value event, not container). + * + * @param r Reader used to read JSON content + * for building the JSON tree. + * + * @since 1.3 + */ + public JsonNode readTree(Reader r) + throws IOException, JsonProcessingException + { + JsonNode n = (JsonNode) _readMapAndClose(_jsonFactory.createJsonParser(r), JSON_NODE_TYPE); + return (n == null) ? NullNode.instance : n; + } + + /** + * Method to deserialize JSON content as tree expressed using set of {@link JsonNode} instances. + * Returns root of the resulting tree (where root can consist of just a single node if the current + * event is a value event, not container). + * + * @param content JSON content to parse to build the JSON tree. + * + * @since 1.3 + */ + public JsonNode readTree(String content) + throws IOException, JsonProcessingException + { + JsonNode n = (JsonNode) _readMapAndClose(_jsonFactory.createJsonParser(content), JSON_NODE_TYPE); + return (n == null) ? NullNode.instance : n; + } + + /** + * Method to deserialize JSON content as tree expressed using set of {@link JsonNode} instances. + * Returns root of the resulting tree (where root can consist of just a single node if the current + * event is a value event, not container). + * + * @param content JSON content to parse to build the JSON tree. + * + * @since 1.9 + */ + public JsonNode readTree(byte[] content) + throws IOException, JsonProcessingException + { + JsonNode n = (JsonNode) _readMapAndClose(_jsonFactory.createJsonParser(content), JSON_NODE_TYPE); + return (n == null) ? NullNode.instance : n; + } + + /** + * Method to deserialize JSON content as tree expressed using set of {@link JsonNode} instances. + * Returns root of the resulting tree (where root can consist of just a single node if the current + * event is a value event, not container). + * + * @param file File of which contents to parse as JSON for building a tree instance + * + * @since 1.9 + */ + public JsonNode readTree(File file) + throws IOException, JsonProcessingException + { + JsonNode n = (JsonNode) _readMapAndClose(_jsonFactory.createJsonParser(file), JSON_NODE_TYPE); + return (n == null) ? NullNode.instance : n; + } + + /** + * Method to deserialize JSON content as tree expressed using set of {@link JsonNode} instances. + * Returns root of the resulting tree (where root can consist of just a single node if the current + * event is a value event, not container). + * + * @param source URL to use for fetching contents to parse as JSON for building a tree instance + * + * @since 1.9 + */ + public JsonNode readTree(URL source) + throws IOException, JsonProcessingException + { + JsonNode n = (JsonNode) _readMapAndClose(_jsonFactory.createJsonParser(source), JSON_NODE_TYPE); + return (n == null) ? NullNode.instance : n; + } + + /* + /********************************************************** + /* Public API (from ObjectCodec): serialization + /* (mapping from Java types to Json) + /********************************************************** + */ + + /** + * Method that can be used to serialize any Java value as + * JSON output, using provided {@link JsonGenerator}. + */ + @Override + public void writeValue(JsonGenerator jgen, Object value) + throws IOException, JsonGenerationException, JsonMappingException + { + SerializationConfig config = copySerializationConfig(); + if (config.isEnabled(SerializationConfig.Feature.CLOSE_CLOSEABLE) && (value instanceof Closeable)) { + _writeCloseableValue(jgen, value, config); + } else { + _serializerProvider.serializeValue(config, jgen, value, _serializerFactory); + if (config.isEnabled(SerializationConfig.Feature.FLUSH_AFTER_WRITE_VALUE)) { + jgen.flush(); + } + } + } + + /** + * Method that can be used to serialize any Java value as + * JSON output, using provided {@link JsonGenerator}, + * configured as per passed configuration object. + * + * @since 1.1 + */ + public void writeValue(JsonGenerator jgen, Object value, SerializationConfig config) + throws IOException, JsonGenerationException, JsonMappingException + { + // [JACKSON-282] Consider java.util.Closeable + if (config.isEnabled(SerializationConfig.Feature.CLOSE_CLOSEABLE) && (value instanceof Closeable)) { + _writeCloseableValue(jgen, value, config); + } else { + _serializerProvider.serializeValue(config, jgen, value, _serializerFactory); + if (config.isEnabled(SerializationConfig.Feature.FLUSH_AFTER_WRITE_VALUE)) { + jgen.flush(); + } + } + } + + /** + * Method to serialize given JSON Tree, using generator + * provided. + */ + @Override + public void writeTree(JsonGenerator jgen, JsonNode rootNode) + throws IOException, JsonProcessingException + { + SerializationConfig config = copySerializationConfig(); + _serializerProvider.serializeValue(config, jgen, rootNode, _serializerFactory); + if (config.isEnabled(SerializationConfig.Feature.FLUSH_AFTER_WRITE_VALUE)) { + jgen.flush(); + } + } + + /** + * Method to serialize given Json Tree, using generator + * provided. + * + * @since 1.1 + */ + public void writeTree(JsonGenerator jgen, JsonNode rootNode, + SerializationConfig cfg) + throws IOException, JsonProcessingException + { + _serializerProvider.serializeValue(cfg, jgen, rootNode, _serializerFactory); + if (cfg.isEnabled(SerializationConfig.Feature.FLUSH_AFTER_WRITE_VALUE)) { + jgen.flush(); + } + } + + /* + /********************************************************** + /* Public API (from ObjectCodec): Tree Model support + /********************************************************** + */ + + /** + *<p> + * Note: return type is co-variant, as basic ObjectCodec + * abstraction can not refer to concrete node types (as it's + * part of core package, whereas impls are part of mapper + * package) + * + * @since 1.2 + */ + @Override + public ObjectNode createObjectNode() { + return _deserializationConfig.getNodeFactory().objectNode(); + } + + /** + *<p> + * Note: return type is co-variant, as basic ObjectCodec + * abstraction can not refer to concrete node types (as it's + * part of core package, whereas impls are part of mapper + * package) + * + * @since 1.2 + */ + @Override + public ArrayNode createArrayNode() { + return _deserializationConfig.getNodeFactory().arrayNode(); + } + + /** + * Method for constructing a {@link JsonParser} out of JSON tree + * representation. + * + * @param n Root node of the tree that resulting parser will read from + * + * @since 1.3 + */ + @Override + public JsonParser treeAsTokens(JsonNode n) + { + return new TreeTraversingParser(n, this); + } + + /** + * Convenience conversion method that will bind data given JSON tree + * contains into specific value (usually bean) type. + *<p> + * Equivalent to: + *<pre> + * objectMapper.convertValue(n, valueClass); + *</pre> + */ + @Override + public <T> T treeToValue(JsonNode n, Class<T> valueType) + throws IOException, JsonParseException, JsonMappingException + { + return readValue(treeAsTokens(n), valueType); + } + + /** + * Reverse of {@link #treeToValue}; given a value (usually bean), will + * construct equivalent JSON Tree representation. Functionally same + * as if serializing value into JSON and parsing JSON as tree, but + * more efficient. + * + * @param <T> Actual node type; usually either basic {@link JsonNode} or + * {@link org.codehaus.jackson.node.ObjectNode} + * @param fromValue Bean value to convert + * @return Root node of the resulting JSON tree + * + * @since 1.6 + */ + @SuppressWarnings("unchecked") + public <T extends JsonNode> T valueToTree(Object fromValue) + throws IllegalArgumentException + { + if (fromValue == null) return null; + TokenBuffer buf = new TokenBuffer(this); + JsonNode result; + try { + writeValue(buf, fromValue); + JsonParser jp = buf.asParser(); + result = readTree(jp); + jp.close(); + } catch (IOException e) { // should not occur, no real i/o... + throw new IllegalArgumentException(e.getMessage(), e); + } + return (T) result; + } + + /* + /********************************************************** + /* Extended Public API, accessors + /********************************************************** + */ + + /** + * Method that can be called to check whether mapper thinks + * it could serialize an instance of given Class. + * Check is done + * by checking whether a serializer can be found for the type. + * + * @return True if mapper can find a serializer for instances of + * given class (potentially serializable), false otherwise (not + * serializable) + */ + public boolean canSerialize(Class<?> type) + { + return _serializerProvider.hasSerializerFor(copySerializationConfig(), + type, _serializerFactory); + } + + /** + * Method that can be called to check whether mapper thinks + * it could deserialize an Object of given type. + * Check is done + * by checking whether a deserializer can be found for the type. + * + * @return True if mapper can find a serializer for instances of + * given class (potentially serializable), false otherwise (not + * serializable) + */ + public boolean canDeserialize(JavaType type) + { + return _deserializerProvider.hasValueDeserializerFor(copyDeserializationConfig(), type); + } + + /* + /********************************************************** + /* Extended Public API, deserialization, + /* convenience methods + /********************************************************** + */ + + @SuppressWarnings("unchecked") + public <T> T readValue(File src, Class<T> valueType) + throws IOException, JsonParseException, JsonMappingException + { + // !!! TODO +// _setupClassLoaderForDeserialization(valueType); + return (T) _readMapAndClose(_jsonFactory.createJsonParser(src), _typeFactory.constructType(valueType)); + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + public <T> T readValue(File src, TypeReference valueTypeRef) + throws IOException, JsonParseException, JsonMappingException + { + return (T) _readMapAndClose(_jsonFactory.createJsonParser(src), _typeFactory.constructType(valueTypeRef)); + } + + @SuppressWarnings("unchecked") + public <T> T readValue(File src, JavaType valueType) + throws IOException, JsonParseException, JsonMappingException + { + return (T) _readMapAndClose(_jsonFactory.createJsonParser(src), valueType); + } + + @SuppressWarnings("unchecked") + public <T> T readValue(URL src, Class<T> valueType) + throws IOException, JsonParseException, JsonMappingException + { + // !!! TODO +// _setupClassLoaderForDeserialization(valueType); + return (T) _readMapAndClose(_jsonFactory.createJsonParser(src), _typeFactory.constructType(valueType)); + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + public <T> T readValue(URL src, TypeReference valueTypeRef) + throws IOException, JsonParseException, JsonMappingException + { + return (T) _readMapAndClose(_jsonFactory.createJsonParser(src), _typeFactory.constructType(valueTypeRef)); + } + + @SuppressWarnings("unchecked") + public <T> T readValue(URL src, JavaType valueType) + throws IOException, JsonParseException, JsonMappingException + { + return (T) _readMapAndClose(_jsonFactory.createJsonParser(src), valueType); + } + + @SuppressWarnings("unchecked") + public <T> T readValue(String content, Class<T> valueType) + throws IOException, JsonParseException, JsonMappingException + { + // !!! TODO +// _setupClassLoaderForDeserialization(valueType); + return (T) _readMapAndClose(_jsonFactory.createJsonParser(content), _typeFactory.constructType(valueType)); + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + public <T> T readValue(String content, TypeReference valueTypeRef) + throws IOException, JsonParseException, JsonMappingException + { + return (T) _readMapAndClose(_jsonFactory.createJsonParser(content), _typeFactory.constructType(valueTypeRef)); + } + + @SuppressWarnings("unchecked") + public <T> T readValue(String content, JavaType valueType) + throws IOException, JsonParseException, JsonMappingException + { + return (T) _readMapAndClose(_jsonFactory.createJsonParser(content), valueType); + } + + @SuppressWarnings("unchecked") + public <T> T readValue(Reader src, Class<T> valueType) + throws IOException, JsonParseException, JsonMappingException + { + // !!! TODO +// _setupClassLoaderForDeserialization(valueType); + return (T) _readMapAndClose(_jsonFactory.createJsonParser(src), _typeFactory.constructType(valueType)); + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + public <T> T readValue(Reader src, TypeReference valueTypeRef) + throws IOException, JsonParseException, JsonMappingException + { + return (T) _readMapAndClose(_jsonFactory.createJsonParser(src), _typeFactory.constructType(valueTypeRef)); + } + + @SuppressWarnings("unchecked") + public <T> T readValue(Reader src, JavaType valueType) + throws IOException, JsonParseException, JsonMappingException + { + return (T) _readMapAndClose(_jsonFactory.createJsonParser(src), valueType); + } + + @SuppressWarnings("unchecked") + public <T> T readValue(InputStream src, Class<T> valueType) + throws IOException, JsonParseException, JsonMappingException + { + // !!! TODO +// _setupClassLoaderForDeserialization(valueType); + return (T) _readMapAndClose(_jsonFactory.createJsonParser(src), _typeFactory.constructType(valueType)); + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + public <T> T readValue(InputStream src, TypeReference valueTypeRef) + throws IOException, JsonParseException, JsonMappingException + { + return (T) _readMapAndClose(_jsonFactory.createJsonParser(src), _typeFactory.constructType(valueTypeRef)); + } + + @SuppressWarnings("unchecked") + public <T> T readValue(InputStream src, JavaType valueType) + throws IOException, JsonParseException, JsonMappingException + { + return (T) _readMapAndClose(_jsonFactory.createJsonParser(src), valueType); + } + + /** + * @since 1.8 + */ + @SuppressWarnings("unchecked") + public <T> T readValue(byte[] src, Class<T> valueType) + throws IOException, JsonParseException, JsonMappingException + { + // !!! TODO +// _setupClassLoaderForDeserialization(valueType); + return (T) _readMapAndClose(_jsonFactory.createJsonParser(src), _typeFactory.constructType(valueType)); + } + + @SuppressWarnings("unchecked") + public <T> T readValue(byte[] src, int offset, int len, + Class<T> valueType) + throws IOException, JsonParseException, JsonMappingException + { + // !!! TODO +// _setupClassLoaderForDeserialization(valueType); + return (T) _readMapAndClose(_jsonFactory.createJsonParser(src, offset, len), _typeFactory.constructType(valueType)); + } + + /** + * @since 1.8 + */ + @SuppressWarnings({ "unchecked", "rawtypes" }) + public <T> T readValue(byte[] src, TypeReference valueTypeRef) + throws IOException, JsonParseException, JsonMappingException + { + return (T) _readMapAndClose(_jsonFactory.createJsonParser(src), _typeFactory.constructType(valueTypeRef)); + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + public <T> T readValue(byte[] src, int offset, int len, + TypeReference valueTypeRef) + throws IOException, JsonParseException, JsonMappingException + { + return (T) _readMapAndClose(_jsonFactory.createJsonParser(src, offset, len), _typeFactory.constructType(valueTypeRef)); + } + + /** + * @since 1.8 + */ + @SuppressWarnings("unchecked") + public <T> T readValue(byte[] src, JavaType valueType) + throws IOException, JsonParseException, JsonMappingException + { + return (T) _readMapAndClose(_jsonFactory.createJsonParser(src), valueType); + } + + @SuppressWarnings("unchecked") + public <T> T readValue(byte[] src, int offset, int len, + JavaType valueType) + throws IOException, JsonParseException, JsonMappingException + { + return (T) _readMapAndClose(_jsonFactory.createJsonParser(src, offset, len), valueType); + } + + /** + * Convenience method for converting results from given JSON tree into given + * value type. Basically short-cut for: + *<pre> + * mapper.readValue(mapper.treeAsTokens(root), valueType); + *</pre> + * + * @since 1.6 + */ + @SuppressWarnings("unchecked") + public <T> T readValue(JsonNode root, Class<T> valueType) + throws IOException, JsonParseException, JsonMappingException + { + // !!! TODO +// _setupClassLoaderForDeserialization(valueType); + return (T) _readValue(copyDeserializationConfig(), treeAsTokens(root), _typeFactory.constructType(valueType)); + } + + /** + * Convenience method for converting results from given JSON tree into given + * value type. Basically short-cut for: + *<pre> + * mapper.readValue(mapper.treeAsTokens(root), valueType); + *</pre> + * + * @since 1.6 + */ + @SuppressWarnings({ "unchecked", "rawtypes" }) + public <T> T readValue(JsonNode root, TypeReference valueTypeRef) + throws IOException, JsonParseException, JsonMappingException + { + return (T) _readValue(copyDeserializationConfig(), treeAsTokens(root), _typeFactory.constructType(valueTypeRef)); + } + + /** + * Convenience method for converting results from given JSON tree into given + * value type. Basically short-cut for: + *<pre> + * mapper.readValue(mapper.treeAsTokens(root), valueType); + *</pre> + * + * @since 1.6 + */ + @SuppressWarnings("unchecked") + public <T> T readValue(JsonNode root, JavaType valueType) + throws IOException, JsonParseException, JsonMappingException + { + return (T) _readValue(copyDeserializationConfig(), treeAsTokens(root), valueType); + } + + /* + /********************************************************** + /* Extended Public API: serialization + /* (mapping from Java types to Json) + /********************************************************** + */ + + /** + * Method that can be used to serialize any Java value as + * JSON output, written to File provided. + */ + public void writeValue(File resultFile, Object value) + throws IOException, JsonGenerationException, JsonMappingException + { + _configAndWriteValue(_jsonFactory.createJsonGenerator(resultFile, JsonEncoding.UTF8), value); + } + + /** + * Method that can be used to serialize any Java value as + * JSON output, using output stream provided (using encoding + * {@link JsonEncoding#UTF8}). + *<p> + * Note: method does not close the underlying stream explicitly + * here; however, {@link JsonFactory} this mapper uses may choose + * to close the stream depending on its settings (by default, + * it will try to close it when {@link JsonGenerator} we construct + * is closed). + */ + public void writeValue(OutputStream out, Object value) + throws IOException, JsonGenerationException, JsonMappingException + { + _configAndWriteValue(_jsonFactory.createJsonGenerator(out, JsonEncoding.UTF8), value); + } + + /** + * Method that can be used to serialize any Java value as + * JSON output, using Writer provided. + *<p> + * Note: method does not close the underlying stream explicitly + * here; however, {@link JsonFactory} this mapper uses may choose + * to close the stream depending on its settings (by default, + * it will try to close it when {@link JsonGenerator} we construct + * is closed). + */ + public void writeValue(Writer w, Object value) + throws IOException, JsonGenerationException, JsonMappingException + { + _configAndWriteValue(_jsonFactory.createJsonGenerator(w), value); + } + + /** + * Method that can be used to serialize any Java value as + * a String. Functionally equivalent to calling + * {@link #writeValue(Writer,Object)} with {@link java.io.StringWriter} + * and constructing String, but more efficient. + * + * @since 1.3 + */ + public String writeValueAsString(Object value) + throws IOException, JsonGenerationException, JsonMappingException + { + // alas, we have to pull the recycler directly here... + SegmentedStringWriter sw = new SegmentedStringWriter(_jsonFactory._getBufferRecycler()); + _configAndWriteValue(_jsonFactory.createJsonGenerator(sw), value); + return sw.getAndClear(); + } + + /** + * Method that can be used to serialize any Java value as + * a byte array. Functionally equivalent to calling + * {@link #writeValue(Writer,Object)} with {@link java.io.ByteArrayOutputStream} + * and getting bytes, but more efficient. + * Encoding used will be UTF-8. + * + * @since 1.5 + */ + public byte[] writeValueAsBytes(Object value) + throws IOException, JsonGenerationException, JsonMappingException + { + ByteArrayBuilder bb = new ByteArrayBuilder(_jsonFactory._getBufferRecycler()); + _configAndWriteValue(_jsonFactory.createJsonGenerator(bb, JsonEncoding.UTF8), value); + byte[] result = bb.toByteArray(); + bb.release(); + return result; + } + + /* + /********************************************************** + /* Extended Public API: constructing ObjectWriters + /* for more advanced configuration + /********************************************************** + */ + + /** + * Convenience method for constructing {@link ObjectWriter} + * with default settings. + * + * @since 1.6 + */ + public ObjectWriter writer() { + return new ObjectWriter(this, copySerializationConfig()); + } + + /** + * Factory method for constructing {@link ObjectWriter} that will + * serialize objects using specified {@link DateFormat}; or, if + * null passed, using timestamp (64-bit number. + * + * @since 1.9 + */ + public ObjectWriter writer(DateFormat df) { + return new ObjectWriter(this, + copySerializationConfig().withDateFormat(df)); + } + + /** + * Factory method for constructing {@link ObjectWriter} that will + * serialize objects using specified JSON View (filter). + * + * @since 1.9 + */ + public ObjectWriter writerWithView(Class<?> serializationView) { + return new ObjectWriter(this, copySerializationConfig().withView(serializationView)); + } + + /** + * Factory method for constructing {@link ObjectWriter} that will + * serialize objects using specified root type, instead of actual + * runtime type of value. Type must be a super-type of runtime + * type. + * + * @since 1.9 + */ + public ObjectWriter writerWithType(Class<?> rootType) { + JavaType t = (rootType == null) ? null : _typeFactory.constructType(rootType); + return new ObjectWriter(this, copySerializationConfig(), t, /*PrettyPrinter*/null); + } + + /** + * Factory method for constructing {@link ObjectWriter} that will + * serialize objects using specified root type, instead of actual + * runtime type of value. Type must be a super-type of runtime type. + * + * @since 1.9 + */ + public ObjectWriter writerWithType(JavaType rootType) { + return new ObjectWriter(this, copySerializationConfig(), rootType, /*PrettyPrinter*/null); + } + + /** + * Factory method for constructing {@link ObjectWriter} that will + * serialize objects using specified root type, instead of actual + * runtime type of value. Type must be a super-type of runtime type. + * + * @since 1.9 + */ + public ObjectWriter writerWithType(TypeReference<?> rootType) { + JavaType t = (rootType == null) ? null : _typeFactory.constructType(rootType); + return new ObjectWriter(this, copySerializationConfig(), t, /*PrettyPrinter*/null); + } + + /** + * Factory method for constructing {@link ObjectWriter} that will + * serialize objects using specified pretty printer for indentation + * (or if null, no pretty printer) + * + * @since 1.9 + */ + public ObjectWriter writer(PrettyPrinter pp) { + if (pp == null) { // need to use a marker to indicate explicit disabling of pp + pp = ObjectWriter.NULL_PRETTY_PRINTER; + } + return new ObjectWriter(this, copySerializationConfig(), /*root type*/ null, pp); + } + + /** + * Factory method for constructing {@link ObjectWriter} that will + * serialize objects using the default pretty printer for indentation + * + * @since 1.9 + */ + public ObjectWriter writerWithDefaultPrettyPrinter() { + return new ObjectWriter(this, copySerializationConfig(), + /*root type*/ null, _defaultPrettyPrinter()); + } + + /** + * Factory method for constructing {@link ObjectWriter} that will + * serialize objects using specified filter provider. + * + * @since 1.9 + */ + public ObjectWriter writer(FilterProvider filterProvider) { + return new ObjectWriter(this, + copySerializationConfig().withFilters(filterProvider)); + } + + /** + * Factory method for constructing {@link ObjectWriter} that will + * pass specific schema object to {@link JsonGenerator} used for + * writing content. + * + * @param schema Schema to pass to generator + * + * @since 1.9 + */ + public ObjectWriter writer(FormatSchema schema) { + return new ObjectWriter(this, copySerializationConfig(), schema); + } + + /* + /********************************************************** + /* Deprecated ObjectWriter creator methods + /********************************************************** + */ + + /** + * @deprecated Since 1.9, use {@link #writerWithType(Class)} instead. + */ + @Deprecated + public ObjectWriter typedWriter(Class<?> rootType) { + return writerWithType(rootType); + } + + /** + * @deprecated Since 1.9, use {@link #writerWithType(JavaType)} instead. + */ + @Deprecated + public ObjectWriter typedWriter(JavaType rootType) { + return writerWithType(rootType); + } + + /** + * @deprecated Since 1.9, use {@link #writerWithType(TypeReference)} instead. + */ + @Deprecated + public ObjectWriter typedWriter(TypeReference<?> rootType) { + return writerWithType(rootType); + } + + /** + * @deprecated Since 1.9, use {@link #writerWithView(Class)} instead. + */ + @Deprecated + public ObjectWriter viewWriter(Class<?> serializationView) { + return writerWithView(serializationView); + } + + /** + * @deprecated Since 1.9, use {@link #writer(FilterProvider)} instead. + */ + @Deprecated + public ObjectWriter prettyPrintingWriter(PrettyPrinter pp) { + return writer(pp); + } + + /** + * @deprecated Since 1.9, use {@link #writerWithDefaultPrettyPrinter} instead. + */ + @Deprecated + public ObjectWriter defaultPrettyPrintingWriter() { + return writerWithDefaultPrettyPrinter(); + } + + /** + * @deprecated Since 1.9, use {@link #writer(FilterProvider)} instead. + */ + @Deprecated + public ObjectWriter filteredWriter(FilterProvider filterProvider) { + return writer(filterProvider); + } + + /** + * @deprecated Since 1.9, use {@link #writer(FilterProvider)} instead. + */ + @Deprecated + public ObjectWriter schemaBasedWriter(FormatSchema schema) { + return writer(schema); + } + + /* + /********************************************************** + /* Extended Public API: constructing ObjectReaders + /* for more advanced configuration + /********************************************************** + */ + + /** + * Factory method for constructing {@link ObjectReader} with + * default settings. Note that the resulting instance is NOT usable as is, + * without defining expected value type. + * + * @since 1.6 + */ + public ObjectReader reader() { + return new ObjectReader(this, copyDeserializationConfig()) + .withInjectableValues(_injectableValues); + } + + /** + * Factory method for constructing {@link ObjectReader} that will + * update given Object (usually Bean, but can be a Collection or Map + * as well, but NOT an array) with JSON data. Deserialization occurs + * normally except that the root-level value in JSON is not used for + * instantiating a new object; instead give updateable object is used + * as root. + * Runtime type of value object is used for locating deserializer, + * unless overridden by other factory methods of {@link ObjectReader} + * + * @since 1.9 + */ + public ObjectReader readerForUpdating(Object valueToUpdate) + { + JavaType t = _typeFactory.constructType(valueToUpdate.getClass()); + return new ObjectReader(this, copyDeserializationConfig(), t, valueToUpdate, + null, _injectableValues); + } + + /** + * Factory method for constructing {@link ObjectReader} that will + * read or update instances of specified type + * + * @since 1.6 + */ + public ObjectReader reader(JavaType type) + { + return new ObjectReader(this, copyDeserializationConfig(), type, null, + null, _injectableValues); + } + + /** + * Factory method for constructing {@link ObjectReader} that will + * read or update instances of specified type + * + * @since 1.6 + */ + public ObjectReader reader(Class<?> type) + { + return reader(_typeFactory.constructType(type)); + } + + /** + * Factory method for constructing {@link ObjectReader} that will + * read or update instances of specified type + * + * @since 1.6 + */ + public ObjectReader reader(TypeReference<?> type) + { + return reader(_typeFactory.constructType(type)); + } + + /** + * Factory method for constructing {@link ObjectReader} that will + * use specified {@link JsonNodeFactory} for constructing JSON trees. + * + * @since 1.6 + */ + public ObjectReader reader(JsonNodeFactory f) + { + return new ObjectReader(this, copyDeserializationConfig()).withNodeFactory(f); + } + + /** + * Factory method for constructing {@link ObjectReader} that will + * pass specific schema object to {@link JsonParser} used for + * reading content. + * + * @param schema Schema to pass to parser + * + * @since 1.8 + */ + public ObjectReader reader(FormatSchema schema) { + return new ObjectReader(this, copyDeserializationConfig(), null, null, + schema, _injectableValues); + } + + /** + * Factory method for constructing {@link ObjectReader} that will + * use specified injectable values. + * + * @param injectableValues Injectable values to use + * + * @since 1.9 + */ + public ObjectReader reader(InjectableValues injectableValues) { + return new ObjectReader(this, copyDeserializationConfig(), null, null, + null, injectableValues); + } + + /* + /********************************************************** + /* Deprecated ObjectReader creator methods + /********************************************************** + */ + + /** + * @deprecated Since 1.9, use {@link #readerForUpdating} instead. + */ + @Deprecated + public ObjectReader updatingReader(Object valueToUpdate) { + return readerForUpdating(valueToUpdate); + } + + /** + * @deprecated Since 1.9, use {@link #reader(FormatSchema)} instead. + */ + @Deprecated + public ObjectReader schemaBasedReader(FormatSchema schema) { + return reader(schema); + } + + /* + /********************************************************** + /* Extended Public API: convenience type conversion + /********************************************************** + */ + + /** + * Convenience method for doing two-step conversion from given value, into + * instance of given value type. This is functionality equivalent to first + * serializing given value into JSON, then binding JSON data into value + * of given type, but may be executed without fully serializing into + * JSON. Same converters (serializers, deserializers) will be used as for + * data binding, meaning same object mapper configuration works. + * + * @throws IllegalArgumentException If conversion fails due to incompatible type; + * if so, root cause will contain underlying checked exception data binding + * functionality threw + */ + @SuppressWarnings("unchecked") + public <T> T convertValue(Object fromValue, Class<T> toValueType) + throws IllegalArgumentException + { + return (T) _convert(fromValue, _typeFactory.constructType(toValueType)); + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + public <T> T convertValue(Object fromValue, TypeReference toValueTypeRef) + throws IllegalArgumentException + { + return (T) _convert(fromValue, _typeFactory.constructType(toValueTypeRef)); + } + + @SuppressWarnings("unchecked") + public <T> T convertValue(Object fromValue, JavaType toValueType) + throws IllegalArgumentException + { + return (T) _convert(fromValue, toValueType); + } + + protected Object _convert(Object fromValue, JavaType toValueType) + throws IllegalArgumentException + { + // sanity check for null first: + if (fromValue == null) return null; + /* Then use TokenBuffer, which is a JsonGenerator: + * (see [JACKSON-175]) + */ + TokenBuffer buf = new TokenBuffer(this); + try { + writeValue(buf, fromValue); + // and provide as with a JsonParser for contents as well! + JsonParser jp = buf.asParser(); + Object result = readValue(jp, toValueType); + jp.close(); + return result; + } catch (IOException e) { // should not occur, no real i/o... + throw new IllegalArgumentException(e.getMessage(), e); + } + } + + /* + /********************************************************** + /* Extended Public API: JSON Schema generation + /********************************************************** + */ + + /** + * Generate <a href="http://json-schema.org/">Json-schema</a> + * instance for specified class. + * + * @param t The class to generate schema for + * @return Constructed JSON schema. + */ + public JsonSchema generateJsonSchema(Class<?> t) + throws JsonMappingException + { + return generateJsonSchema(t, copySerializationConfig()); + } + + /** + * Generate <a href="http://json-schema.org/">Json-schema</a> + * instance for specified class, using specific + * serialization configuration + * + * @param t The class to generate schema for + * @return Constructed JSON schema. + */ + public JsonSchema generateJsonSchema(Class<?> t, SerializationConfig cfg) + throws JsonMappingException + { + return _serializerProvider.generateJsonSchema(t, cfg, _serializerFactory); + } + + /* + /********************************************************** + /* Internal methods for serialization, overridable + /********************************************************** + */ + + /** + * Helper method that should return default pretty-printer to + * use for generators constructed by this mapper, when instructed + * to use default pretty printer. + * + * @since 1.7 + */ + protected PrettyPrinter _defaultPrettyPrinter() { + return new DefaultPrettyPrinter(); + } + + /** + * Method called to configure the generator as necessary and then + * call write functionality + */ + protected final void _configAndWriteValue(JsonGenerator jgen, Object value) + throws IOException, JsonGenerationException, JsonMappingException + { + SerializationConfig cfg = copySerializationConfig(); + // [JACKSON-96]: allow enabling pretty printing for ObjectMapper directly + if (cfg.isEnabled(SerializationConfig.Feature.INDENT_OUTPUT)) { + jgen.useDefaultPrettyPrinter(); + } + // [JACKSON-282]: consider Closeable + if (cfg.isEnabled(SerializationConfig.Feature.CLOSE_CLOSEABLE) && (value instanceof Closeable)) { + _configAndWriteCloseable(jgen, value, cfg); + return; + } + boolean closed = false; + try { + _serializerProvider.serializeValue(cfg, jgen, value, _serializerFactory); + closed = true; + jgen.close(); + } finally { + /* won't try to close twice; also, must catch exception (so it + * will not mask exception that is pending) + */ + if (!closed) { + try { + jgen.close(); + } catch (IOException ioe) { } + } + } + } + + protected final void _configAndWriteValue(JsonGenerator jgen, Object value, Class<?> viewClass) + throws IOException, JsonGenerationException, JsonMappingException + { + SerializationConfig cfg = copySerializationConfig().withView(viewClass); + if (cfg.isEnabled(SerializationConfig.Feature.INDENT_OUTPUT)) { + jgen.useDefaultPrettyPrinter(); + } + // [JACKSON-282]: consider Closeable + if (cfg.isEnabled(SerializationConfig.Feature.CLOSE_CLOSEABLE) && (value instanceof Closeable)) { + _configAndWriteCloseable(jgen, value, cfg); + return; + } + boolean closed = false; + try { + _serializerProvider.serializeValue(cfg, jgen, value, _serializerFactory); + closed = true; + jgen.close(); + } finally { + if (!closed) { + try { + jgen.close(); + } catch (IOException ioe) { } + } + } + } + + /** + * Helper method used when value to serialize is {@link Closeable} and its <code>close()</code> + * method is to be called right after serialization has been called + */ + private final void _configAndWriteCloseable(JsonGenerator jgen, Object value, SerializationConfig cfg) + throws IOException, JsonGenerationException, JsonMappingException + { + Closeable toClose = (Closeable) value; + try { + _serializerProvider.serializeValue(cfg, jgen, value, _serializerFactory); + JsonGenerator tmpJgen = jgen; + jgen = null; + tmpJgen.close(); + Closeable tmpToClose = toClose; + toClose = null; + tmpToClose.close(); + } finally { + /* Need to close both generator and value, as long as they haven't yet + * been closed + */ + if (jgen != null) { + try { + jgen.close(); + } catch (IOException ioe) { } + } + if (toClose != null) { + try { + toClose.close(); + } catch (IOException ioe) { } + } + } + } + + /** + * Helper method used when value to serialize is {@link Closeable} and its <code>close()</code> + * method is to be called right after serialization has been called + */ + private final void _writeCloseableValue(JsonGenerator jgen, Object value, SerializationConfig cfg) + throws IOException, JsonGenerationException, JsonMappingException + { + Closeable toClose = (Closeable) value; + try { + _serializerProvider.serializeValue(cfg, jgen, value, _serializerFactory); + if (cfg.isEnabled(SerializationConfig.Feature.FLUSH_AFTER_WRITE_VALUE)) { + jgen.flush(); + } + Closeable tmpToClose = toClose; + toClose = null; + tmpToClose.close(); + } finally { + if (toClose != null) { + try { + toClose.close(); + } catch (IOException ioe) { } + } + } + } + + /* + /********************************************************** + /* Internal methods for deserialization, overridable + /********************************************************** + */ + + /** + * Actual implementation of value reading+binding operation. + */ + protected Object _readValue(DeserializationConfig cfg, JsonParser jp, JavaType valueType) + throws IOException, JsonParseException, JsonMappingException + { + /* First: may need to read the next token, to initialize + * state (either before first read from parser, or after + * previous token has been cleared) + */ + Object result; + JsonToken t = _initForReading(jp); + if (t == JsonToken.VALUE_NULL) { + // [JACKSON-643]: Ask JsonDeserializer what 'null value' to use: + result = _findRootDeserializer(cfg, valueType).getNullValue(); + } else if (t == JsonToken.END_ARRAY || t == JsonToken.END_OBJECT) { + result = null; + } else { // pointing to event other than null + DeserializationContext ctxt = _createDeserializationContext(jp, cfg); + JsonDeserializer<Object> deser = _findRootDeserializer(cfg, valueType); + // ok, let's get the value + if (cfg.isEnabled(DeserializationConfig.Feature.UNWRAP_ROOT_VALUE)) { + result = _unwrapAndDeserialize(jp, valueType, ctxt, deser); + } else { + result = deser.deserialize(jp, ctxt); + } + } + // Need to consume the token too + jp.clearCurrentToken(); + return result; + } + + + protected Object _readMapAndClose(JsonParser jp, JavaType valueType) + throws IOException, JsonParseException, JsonMappingException + { + try { + Object result; + JsonToken t = _initForReading(jp); + if (t == JsonToken.VALUE_NULL) { + // [JACKSON-643]: Ask JsonDeserializer what 'null value' to use: + // (note: probably no need to make a copy of config for just this access) + result = _findRootDeserializer(this._deserializationConfig, valueType).getNullValue(); + } else if (t == JsonToken.END_ARRAY || t == JsonToken.END_OBJECT) { + result = null; + } else { + DeserializationConfig cfg = copyDeserializationConfig(); + DeserializationContext ctxt = _createDeserializationContext(jp, cfg); + JsonDeserializer<Object> deser = _findRootDeserializer(cfg, valueType); + if (cfg.isEnabled(DeserializationConfig.Feature.UNWRAP_ROOT_VALUE)) { + result = _unwrapAndDeserialize(jp, valueType, ctxt, deser); + } else { + result = deser.deserialize(jp, ctxt); + } + } + // Need to consume the token too + jp.clearCurrentToken(); + return result; + } finally { + try { + jp.close(); + } catch (IOException ioe) { } + } + } + + /** + * Method called to ensure that given parser is ready for reading + * content for data binding. + * + * @return First token to be used for data binding after this call: + * can never be null as exception will be thrown if parser can not + * provide more tokens. + * + * @throws IOException if the underlying input source has problems during + * parsing + * @throws JsonParseException if parser has problems parsing content + * @throws JsonMappingException if the parser does not have any more + * content to map (note: Json "null" value is considered content; + * enf-of-stream not) + */ + protected JsonToken _initForReading(JsonParser jp) + throws IOException, JsonParseException, JsonMappingException + { + /* First: must point to a token; if not pointing to one, advance. + * This occurs before first read from JsonParser, as well as + * after clearing of current token. + */ + JsonToken t = jp.getCurrentToken(); + if (t == null) { + // and then we must get something... + t = jp.nextToken(); + if (t == null) { + /* [JACKSON-99] Should throw EOFException, closest thing + * semantically + */ + throw new EOFException("No content to map to Object due to end of input"); + } + } + return t; + } + + protected Object _unwrapAndDeserialize(JsonParser jp, JavaType rootType, + DeserializationContext ctxt, JsonDeserializer<Object> deser) + throws IOException, JsonParseException, JsonMappingException + { + SerializedString rootName = _deserializerProvider.findExpectedRootName(ctxt.getConfig(), rootType); + if (jp.getCurrentToken() != JsonToken.START_OBJECT) { + throw JsonMappingException.from(jp, "Current token not START_OBJECT (needed to unwrap root name '" + +rootName+"'), but "+jp.getCurrentToken()); + } + if (jp.nextToken() != JsonToken.FIELD_NAME) { + throw JsonMappingException.from(jp, "Current token not FIELD_NAME (to contain expected root name '" + +rootName+"'), but "+jp.getCurrentToken()); + } + String actualName = jp.getCurrentName(); + if (!rootName.getValue().equals(actualName)) { + throw JsonMappingException.from(jp, "Root name '"+actualName+"' does not match expected ('"+rootName + +"') for type "+rootType); + } + // ok, then move to value itself.... + jp.nextToken(); + + Object result = deser.deserialize(jp, ctxt); + // and last, verify that we now get matching END_OBJECT + if (jp.nextToken() != JsonToken.END_OBJECT) { + throw JsonMappingException.from(jp, "Current token not END_OBJECT (to match wrapper object with root name '" + +rootName+"'), but "+jp.getCurrentToken()); + } + return result; + } + + /* + /********************************************************** + /* Internal methods, other + /********************************************************** + */ + + /** + * Method called to locate deserializer for the passed root-level value. + */ + protected JsonDeserializer<Object> _findRootDeserializer(DeserializationConfig cfg, JavaType valueType) + throws JsonMappingException + { + // First: have we already seen it? + JsonDeserializer<Object> deser = _rootDeserializers.get(valueType); + if (deser != null) { + return deser; + } + // Nope: need to ask provider to resolve it + deser = _deserializerProvider.findTypedValueDeserializer(cfg, valueType, null); + if (deser == null) { // can this happen? + throw new JsonMappingException("Can not find a deserializer for type "+valueType); + } + _rootDeserializers.put(valueType, deser); + return deser; + } + + protected DeserializationContext _createDeserializationContext(JsonParser jp, DeserializationConfig cfg) + { + return new StdDeserializationContext(cfg, jp, _deserializerProvider, + _injectableValues); + } + + //Allows use of the correct classloader (primarily for OSGi), separating framework from application + //should be safe to use in all contexts + /* + protected <T> void _setupClassLoaderForDeserialization(Class<T> valueType) + { + ClassLoader loader = (valueType.getClassLoader() == null) ? Thread.currentThread().getContextClassLoader() : valueType.getClassLoader(); + Thread.currentThread().setContextClassLoader(loader); + } + */ +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ObjectReader.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ObjectReader.java new file mode 100644 index 0000000..b57115a --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ObjectReader.java
@@ -0,0 +1,944 @@ +package org.codehaus.jackson.map; + +import java.io.*; +import java.net.URL; +import java.util.Iterator; +import java.util.concurrent.ConcurrentHashMap; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.io.SerializedString; +import org.codehaus.jackson.map.deser.StdDeserializationContext; +import org.codehaus.jackson.map.type.SimpleType; +import org.codehaus.jackson.node.JsonNodeFactory; +import org.codehaus.jackson.node.NullNode; +import org.codehaus.jackson.node.TreeTraversingParser; +import org.codehaus.jackson.type.JavaType; +import org.codehaus.jackson.type.TypeReference; +import org.codehaus.jackson.util.VersionUtil; + +/** + * Builder object that can be used for per-serialization configuration of + * deserialization parameters, such as root type to use or object + * to update (instead of constructing new instance). + * Uses "fluid" (aka builder) pattern so that instances are immutable + * (and thus fully thread-safe with no external synchronization); + * new instances are constructed for different configurations. + * Instances are initially constructed by {@link ObjectMapper} and can be + * reused. + * + * @author tatu + * @since 1.6 + */ +public class ObjectReader + extends ObjectCodec + implements Versioned +{ + private final static JavaType JSON_NODE_TYPE = SimpleType.constructUnsafe(JsonNode.class); + + /* + /********************************************************** + /* Immutable configuration from ObjectMapper + /********************************************************** + */ + + /** + * General serialization configuration settings; while immutable, + * can use copy-constructor to create modified instances as necessary. + */ + protected final DeserializationConfig _config; + + /** + * Flag that indicates whether root values are expected to be unwrapped + * or not + * + * @since 1.9 + */ + protected final boolean _unwrapRoot; + + /** + * Root-level cached deserializers + */ + final protected ConcurrentHashMap<JavaType, JsonDeserializer<Object>> _rootDeserializers; + + protected final DeserializerProvider _provider; + + /** + * Factory used for constructing {@link JsonGenerator}s + */ + protected final JsonFactory _jsonFactory; + + /* + /********************************************************** + /* Configuration that can be changed during building + /********************************************************** + */ + + /** + * Declared type of value to instantiate during deserialization. + * Defines which deserializer to use; as well as base type of instance + * to construct if an updatable value is not configured to be used + * (subject to changes by embedded type information, for polymorphic + * types). If {@link #_valueToUpdate} is non-null, only used for + * locating deserializer. + */ + protected final JavaType _valueType; + + /** + * Instance to update with data binding; if any. If null, + * a new instance is created, if non-null, properties of + * this value object will be updated instead. + * Note that value can be of almost any type, except not + * {@link org.codehaus.jackson.map.type.ArrayType}; array + * types can not be modified because array size is immutable. + */ + protected final Object _valueToUpdate; + + /** + * When using data format that uses a schema, schema is passed + * to parser. + * + * @since 1.8 + */ + protected final FormatSchema _schema; + + /** + * Values that can be injected during deserialization, if any. + * + * @since 1.9 + */ + protected final InjectableValues _injectableValues; + + /* + /********************************************************** + /* Life-cycle + /********************************************************** + */ + + /** + * Constructor used by {@link ObjectMapper} for initial instantiation + * + * @since 1.8 + */ + protected ObjectReader(ObjectMapper mapper, DeserializationConfig config) + { + this(mapper, config, null, null, null, null); + } + + protected ObjectReader(ObjectMapper mapper, DeserializationConfig config, + JavaType valueType, Object valueToUpdate, FormatSchema schema, + InjectableValues injectableValues) + { + _config = config; + _rootDeserializers = mapper._rootDeserializers; + _provider = mapper._deserializerProvider; + _jsonFactory = mapper._jsonFactory; + _valueType = valueType; + _valueToUpdate = valueToUpdate; + if (valueToUpdate != null && valueType.isArrayType()) { + throw new IllegalArgumentException("Can not update an array value"); + } + _schema = schema; + _injectableValues = injectableValues; + _unwrapRoot = config.isEnabled(DeserializationConfig.Feature.UNWRAP_ROOT_VALUE); + } + + /** + * Copy constructor used for building variations. + */ + protected ObjectReader(ObjectReader base, DeserializationConfig config, + JavaType valueType, Object valueToUpdate, FormatSchema schema, + InjectableValues injectableValues) + { + _config = config; + + _rootDeserializers = base._rootDeserializers; + _provider = base._provider; + _jsonFactory = base._jsonFactory; + + _valueType = valueType; + _valueToUpdate = valueToUpdate; + if (valueToUpdate != null && valueType.isArrayType()) { + throw new IllegalArgumentException("Can not update an array value"); + } + _schema = schema; + _injectableValues = injectableValues; + _unwrapRoot = config.isEnabled(DeserializationConfig.Feature.UNWRAP_ROOT_VALUE); + } + + /** + * Method that will return version information stored in and read from jar + * that contains this class. + * + * @since 1.6 + */ + @Override + public Version version() { + return VersionUtil.versionFor(getClass()); + } + + /** + * Method for constructing a new reader instance that is configured + * to data bind into specified type. + *<p> + * Note that the method does NOT change state of this reader, but + * rather construct and returns a newly configured instance. + */ + public ObjectReader withType(JavaType valueType) + { + if (valueType == _valueType) return this; + // type is stored here, no need to make a copy of config + return new ObjectReader(this, _config, valueType, _valueToUpdate, + _schema, _injectableValues); + } + + /** + * Method for constructing a new reader instance that is configured + * to data bind into specified type. + *<p> + * Note that the method does NOT change state of this reader, but + * rather construct and returns a newly configured instance. + */ + public ObjectReader withType(Class<?> valueType) + { + return withType(_config.constructType(valueType)); + } + + /** + * Method for constructing a new reader instance that is configured + * to data bind into specified type. + *<p> + * Note that the method does NOT change state of this reader, but + * rather construct and returns a newly configured instance. + */ + public ObjectReader withType(java.lang.reflect.Type valueType) + { + return withType(_config.getTypeFactory().constructType(valueType)); + } + + /** + * Method for constructing a new reader instance that is configured + * to data bind into specified type. + *<p> + * Note that the method does NOT change state of this reader, but + * rather construct and returns a newly configured instance. + * + * @since 1.8 + */ + public ObjectReader withType(TypeReference<?> valueTypeRef) + { + return withType(_config.getTypeFactory().constructType(valueTypeRef.getType())); + } + + /** + * Method for constructing a new reader instance with configuration that uses + * passed {@link JsonNodeFactory} for constructing {@link JsonNode} + * instances. + *<p> + * Note that the method does NOT change state of this reader, but + * rather construct and returns a newly configured instance. + */ + public ObjectReader withNodeFactory(JsonNodeFactory f) + { + // node factory is stored within config, so need to copy that first + if (f == _config.getNodeFactory()) return this; + return new ObjectReader(this, _config.withNodeFactory(f), _valueType, _valueToUpdate, + _schema, _injectableValues); + } + + /** + * Method for constructing a new instance with configuration that + * updates passed Object (as root value), instead of constructing + * a new value. + *<p> + * Note that the method does NOT change state of this reader, but + * rather construct and returns a newly configured instance. + */ + public ObjectReader withValueToUpdate(Object value) + { + if (value == _valueToUpdate) return this; + if (value == null) { + throw new IllegalArgumentException("cat not update null value"); + } + JavaType t = (_valueType == null) ? _config.constructType(value.getClass()) : _valueType; + return new ObjectReader(this, _config, t, value, + _schema, _injectableValues); + } + + /** + * Method for constructing a new instance with configuration that + * passes specified {@link FormatSchema} to {@link JsonParser} that + * is constructed for parsing content. + *<p> + * Note that the method does NOT change state of this reader, but + * rather construct and returns a newly configured instance. + * + * @since 1.8 + */ + public ObjectReader withSchema(FormatSchema schema) + { + if (_schema == schema) { + return this; + } + return new ObjectReader(this, _config, _valueType, _valueToUpdate, + schema, _injectableValues); + } + + /** + * Method for constructing a new instance with configuration that uses + * passed {@link InjectableValues} to provide injectable values. + *<p> + * Note that the method does NOT change state of this reader, but + * rather construct and returns a newly configured instance. + * + * @since 1.9 + */ + public ObjectReader withInjectableValues(InjectableValues injectableValues) + { + if (_injectableValues == injectableValues) { + return this; + } + return new ObjectReader(this, _config, _valueType, _valueToUpdate, + _schema, injectableValues); + } + + /* + /********************************************************** + /* Deserialization methods; basic ones to support ObjectCodec first + /* (ones that take JsonParser) + /********************************************************** + */ + + /** + * Method that binds content read using given parser, using + * configuration of this reader, including expected result type. + * Value return is either newly constructed, or root value that + * was specified with {@link #withValueToUpdate(Object)}. + */ + @SuppressWarnings("unchecked") + public <T> T readValue(JsonParser jp) + throws IOException, JsonProcessingException + { + return (T) _bind(jp); + } + + /** + * Convenience method that binds content read using given parser, using + * configuration of this reader, except that expected value type + * is specified with the call (instead of currently configured root type). + * Value return is either newly constructed, or root value that + * was specified with {@link #withValueToUpdate(Object)}. + */ + @SuppressWarnings("unchecked") + @Override + public <T> T readValue(JsonParser jp, Class<T> valueType) + throws IOException, JsonProcessingException + { + return (T) withType(valueType).readValue(jp); + } + + /** + * Convenience method that binds content read using given parser, using + * configuration of this reader, except that expected value type + * is specified with the call (instead of currently configured root type). + * Value return is either newly constructed, or root value that + * was specified with {@link #withValueToUpdate(Object)}. + */ + @SuppressWarnings("unchecked") + @Override + public <T> T readValue(JsonParser jp, TypeReference<?> valueTypeRef) + throws IOException, JsonProcessingException + { + return (T) withType(valueTypeRef).readValue(jp); + } + + /** + * Convenience method that binds content read using given parser, using + * configuration of this reader, except that expected value type + * is specified with the call (instead of currently configured root type). + * Value return is either newly constructed, or root value that + * was specified with {@link #withValueToUpdate(Object)}. + */ + @SuppressWarnings("unchecked") + @Override + public <T> T readValue(JsonParser jp, JavaType valueType) throws IOException, JsonProcessingException { + return (T) withType(valueType).readValue(jp); + } + + /** + * Convenience method that binds content read using given parser, using + * configuration of this reader, except that content is bound as + * JSON tree instead of configured root value type. + *<p> + * Note: if an object was specified with {@link #withValueToUpdate}, it + * will be ignored. + */ + @Override + public JsonNode readTree(JsonParser jp) + throws IOException, JsonProcessingException + { + return _bindAsTree(jp); + } + + /** + * Convenience method that is equivalent to: + *<pre> + * withType(valueType).readValues(jp); + *</pre> + */ + @Override + public <T> Iterator<T> readValues(JsonParser jp, Class<T> valueType) + throws IOException, JsonProcessingException { + return withType(valueType).readValues(jp); + } + + /** + * Convenience method that is equivalent to: + *<pre> + * withType(valueTypeRef).readValues(jp); + *</pre> + */ + @Override + public <T> Iterator<T> readValues(JsonParser jp, TypeReference<?> valueTypeRef) + throws IOException, JsonProcessingException { + return withType(valueTypeRef).readValues(jp); + } + + /** + * Convenience method that is equivalent to: + *<pre> + * withType(valueType).readValues(jp); + *</pre> + */ + @Override + public <T> Iterator<T> readValues(JsonParser jp, JavaType valueType) + throws IOException, JsonProcessingException { + return withType(valueType).readValues(jp); + } + + /* + /********************************************************** + /* Deserialization methods; others similar to what ObjectMapper has + /********************************************************** + */ + + /** + * Method that binds content read from given input source, + * using configuration of this reader. + * Value return is either newly constructed, or root value that + * was specified with {@link #withValueToUpdate(Object)}. + */ + @SuppressWarnings("unchecked") + public <T> T readValue(InputStream src) + throws IOException, JsonProcessingException + { + return (T) _bindAndClose(_jsonFactory.createJsonParser(src)); + } + + /** + * Method that binds content read from given input source, + * using configuration of this reader. + * Value return is either newly constructed, or root value that + * was specified with {@link #withValueToUpdate(Object)}. + */ + @SuppressWarnings("unchecked") + public <T> T readValue(Reader src) + throws IOException, JsonProcessingException + { + return (T) _bindAndClose(_jsonFactory.createJsonParser(src)); + } + + /** + * Method that binds content read from given JSON string, + * using configuration of this reader. + * Value return is either newly constructed, or root value that + * was specified with {@link #withValueToUpdate(Object)}. + */ + @SuppressWarnings("unchecked") + public <T> T readValue(String src) + throws IOException, JsonProcessingException + { + return (T) _bindAndClose(_jsonFactory.createJsonParser(src)); + } + + /** + * Method that binds content read from given byte array, + * using configuration of this reader. + * Value return is either newly constructed, or root value that + * was specified with {@link #withValueToUpdate(Object)}. + */ + @SuppressWarnings("unchecked") + public <T> T readValue(byte[] src) + throws IOException, JsonProcessingException + { + return (T) _bindAndClose(_jsonFactory.createJsonParser(src)); + } + + /** + * Method that binds content read from given byte array, + * using configuration of this reader. + * Value return is either newly constructed, or root value that + * was specified with {@link #withValueToUpdate(Object)}. + */ + @SuppressWarnings("unchecked") + public <T> T readValue(byte[] src, int offset, int length) + throws IOException, JsonProcessingException + { + return (T) _bindAndClose(_jsonFactory.createJsonParser(src, offset, length)); + } + + @SuppressWarnings("unchecked") + public <T> T readValue(File src) + throws IOException, JsonProcessingException + { + return (T) _bindAndClose(_jsonFactory.createJsonParser(src)); + } + + /** + * Method that binds content read from given input source, + * using configuration of this reader. + * Value return is either newly constructed, or root value that + * was specified with {@link #withValueToUpdate(Object)}. + */ + @SuppressWarnings("unchecked") + public <T> T readValue(URL src) + throws IOException, JsonProcessingException + { + return (T) _bindAndClose(_jsonFactory.createJsonParser(src)); + } + + /** + * Convenience method for converting results from given JSON tree into given + * value type. Basically short-cut for: + *<pre> + * objectReader.readValue(src.traverse()) + *</pre> + */ + @SuppressWarnings("unchecked") + public <T> T readValue(JsonNode src) + throws IOException, JsonProcessingException + { + return (T) _bindAndClose(treeAsTokens(src)); + } + + /** + * Method that reads content from given input source, + * using configuration of this reader, and binds it as JSON Tree. + *<p> + * Note that if an object was specified with a call to + * {@link #withValueToUpdate(Object)} + * it will just be ignored; result is always a newly constructed + * {@link JsonNode} instance. + */ + public JsonNode readTree(InputStream in) + throws IOException, JsonProcessingException + { + return _bindAndCloseAsTree(_jsonFactory.createJsonParser(in)); + } + + /** + * Method that reads content from given input source, + * using configuration of this reader, and binds it as JSON Tree. + *<p> + * Note that if an object was specified with a call to + * {@link #withValueToUpdate(Object)} + * it will just be ignored; result is always a newly constructed + * {@link JsonNode} instance. + */ + public JsonNode readTree(Reader r) + throws IOException, JsonProcessingException + { + return _bindAndCloseAsTree(_jsonFactory.createJsonParser(r)); + } + + /** + * Method that reads content from given JSON input String, + * using configuration of this reader, and binds it as JSON Tree. + *<p> + * Note that if an object was specified with a call to + * {@link #withValueToUpdate(Object)} + * it will just be ignored; result is always a newly constructed + * {@link JsonNode} instance. + */ + public JsonNode readTree(String content) + throws IOException, JsonProcessingException + { + return _bindAndCloseAsTree(_jsonFactory.createJsonParser(content)); + } + + /* + /********************************************************** + /* Deserialization methods; reading sequence of values + /********************************************************** + */ + + /** + * Method for reading sequence of Objects from parser stream. + * + * @since 1.8 + */ + public <T> MappingIterator<T> readValues(JsonParser jp) + throws IOException, JsonProcessingException + { + DeserializationContext ctxt = _createDeserializationContext(jp, _config); + // false -> do not close as caller gave parser instance + return new MappingIterator<T>(_valueType, jp, ctxt, + _findRootDeserializer(_config, _valueType), + false, _valueToUpdate); + } + + /** + * Method for reading sequence of Objects from parser stream. + * + * @since 1.8 + */ + public <T> MappingIterator<T> readValues(InputStream src) + throws IOException, JsonProcessingException + { + JsonParser jp = _jsonFactory.createJsonParser(src); + if (_schema != null) { + jp.setSchema(_schema); + } + DeserializationContext ctxt = _createDeserializationContext(jp, _config); + return new MappingIterator<T>(_valueType, jp, ctxt, + _findRootDeserializer(_config, _valueType), + true, _valueToUpdate); + } + + /** + * Method for reading sequence of Objects from parser stream. + * + * @since 1.8 + */ + public <T> MappingIterator<T> readValues(Reader src) + throws IOException, JsonProcessingException + { + JsonParser jp = _jsonFactory.createJsonParser(src); + if (_schema != null) { + jp.setSchema(_schema); + } + DeserializationContext ctxt = _createDeserializationContext(jp, _config); + return new MappingIterator<T>(_valueType, jp, ctxt, + _findRootDeserializer(_config, _valueType), true, _valueToUpdate); + } + + /** + * Method for reading sequence of Objects from parser stream. + * + * @since 1.8 + */ + public <T> MappingIterator<T> readValues(String json) + throws IOException, JsonProcessingException + { + JsonParser jp = _jsonFactory.createJsonParser(json); + if (_schema != null) { + jp.setSchema(_schema); + } + DeserializationContext ctxt = _createDeserializationContext(jp, _config); + return new MappingIterator<T>(_valueType, jp, ctxt, + _findRootDeserializer(_config, _valueType), true, _valueToUpdate); + } + + /** + * Method for reading sequence of Objects from parser stream. + * + * @since 1.8 + */ + public <T> MappingIterator<T> readValues(byte[] src, int offset, int length) + throws IOException, JsonProcessingException + { + JsonParser jp = _jsonFactory.createJsonParser(src, offset, length); + if (_schema != null) { + jp.setSchema(_schema); + } + DeserializationContext ctxt = _createDeserializationContext(jp, _config); + return new MappingIterator<T>(_valueType, jp, ctxt, + _findRootDeserializer(_config, _valueType), true, _valueToUpdate); + } + + /** + * Since 1.9.3 + */ + public final <T> MappingIterator<T> readValues(byte[] src) + throws IOException, JsonProcessingException { + return readValues(src, 0, src.length); + } + + /** + * Method for reading sequence of Objects from parser stream. + * + * @since 1.8 + */ + public <T> MappingIterator<T> readValues(File src) + throws IOException, JsonProcessingException + { + JsonParser jp = _jsonFactory.createJsonParser(src); + if (_schema != null) { + jp.setSchema(_schema); + } + DeserializationContext ctxt = _createDeserializationContext(jp, _config); + return new MappingIterator<T>(_valueType, jp, ctxt, + _findRootDeserializer(_config, _valueType), true, _valueToUpdate); + } + + /** + * Method for reading sequence of Objects from parser stream. + * + * @since 1.8 + */ + public <T> MappingIterator<T> readValues(URL src) + throws IOException, JsonProcessingException + { + JsonParser jp = _jsonFactory.createJsonParser(src); + if (_schema != null) { + jp.setSchema(_schema); + } + DeserializationContext ctxt = _createDeserializationContext(jp, _config); + return new MappingIterator<T>(_valueType, jp, ctxt, + _findRootDeserializer(_config, _valueType), true, _valueToUpdate); + } + + /* + /********************************************************** + /* Helper methods + /********************************************************** + */ + + /** + * Actual implementation of value reading+binding operation. + */ + protected Object _bind(JsonParser jp) + throws IOException, JsonParseException, JsonMappingException + { + /* First: may need to read the next token, to initialize state (either + * before first read from parser, or after previous token has been cleared) + */ + Object result; + JsonToken t = _initForReading(jp); + if (t == JsonToken.VALUE_NULL) { + if (_valueToUpdate == null) { + result = _findRootDeserializer(_config, _valueType).getNullValue(); + } else { + result = _valueToUpdate; + } + } else if (t == JsonToken.END_ARRAY || t == JsonToken.END_OBJECT) { + result = _valueToUpdate; + } else { // pointing to event other than null + DeserializationContext ctxt = _createDeserializationContext(jp, _config); + JsonDeserializer<Object> deser = _findRootDeserializer(_config, _valueType); + if (_unwrapRoot) { + result = _unwrapAndDeserialize(jp, ctxt, _valueType, deser); + } else { + if (_valueToUpdate == null) { + result = deser.deserialize(jp, ctxt); + } else { + deser.deserialize(jp, ctxt, _valueToUpdate); + result = _valueToUpdate; + } + } + } + // Need to consume the token too + jp.clearCurrentToken(); + return result; + } + + protected Object _bindAndClose(JsonParser jp) + throws IOException, JsonParseException, JsonMappingException + { + if (_schema != null) { + jp.setSchema(_schema); + } + try { + Object result; + JsonToken t = _initForReading(jp); + if (t == JsonToken.VALUE_NULL) { + if (_valueToUpdate == null) { + result = _findRootDeserializer(_config, _valueType).getNullValue(); + } else { + result = _valueToUpdate; + } + } else if (t == JsonToken.END_ARRAY || t == JsonToken.END_OBJECT) { + result = _valueToUpdate; + } else { + DeserializationContext ctxt = _createDeserializationContext(jp, _config); + JsonDeserializer<Object> deser = _findRootDeserializer(_config, _valueType); + if (_unwrapRoot) { + result = _unwrapAndDeserialize(jp, ctxt, _valueType, deser); + } else { + if (_valueToUpdate == null) { + result = deser.deserialize(jp, ctxt); + } else { + deser.deserialize(jp, ctxt, _valueToUpdate); + result = _valueToUpdate; + } + } + } + return result; + } finally { + try { + jp.close(); + } catch (IOException ioe) { } + } + } + + protected JsonNode _bindAsTree(JsonParser jp) + throws IOException, JsonParseException, JsonMappingException + { + JsonNode result; + JsonToken t = _initForReading(jp); + if (t == JsonToken.VALUE_NULL || t == JsonToken.END_ARRAY || t == JsonToken.END_OBJECT) { + result = NullNode.instance; + } else { + DeserializationContext ctxt = _createDeserializationContext(jp, _config); + JsonDeserializer<Object> deser = _findRootDeserializer(_config, JSON_NODE_TYPE); + if (_unwrapRoot) { + result = (JsonNode) _unwrapAndDeserialize(jp, ctxt, JSON_NODE_TYPE, deser); + } else { + result = (JsonNode) deser.deserialize(jp, ctxt); + } + } + // Need to consume the token too + jp.clearCurrentToken(); + return result; + } + + protected JsonNode _bindAndCloseAsTree(JsonParser jp) + throws IOException, JsonParseException, JsonMappingException + { + if (_schema != null) { + jp.setSchema(_schema); + } + try { + return _bindAsTree(jp); + } finally { + try { + jp.close(); + } catch (IOException ioe) { } + } + } + + protected static JsonToken _initForReading(JsonParser jp) + throws IOException, JsonParseException, JsonMappingException + { + /* First: must point to a token; if not pointing to one, advance. + * This occurs before first read from JsonParser, as well as + * after clearing of current token. + */ + JsonToken t = jp.getCurrentToken(); + if (t == null) { // and then we must get something... + t = jp.nextToken(); + if (t == null) { // [JACKSON-99] Should throw EOFException? + throw new EOFException("No content to map to Object due to end of input"); + } + } + return t; + } + + /** + * Method called to locate deserializer for the passed root-level value. + */ + protected JsonDeserializer<Object> _findRootDeserializer(DeserializationConfig cfg, JavaType valueType) + throws JsonMappingException + { + // Sanity check: must have actual type... + if (valueType == null) { + throw new JsonMappingException("No value type configured for ObjectReader"); + } + + // First: have we already seen it? + JsonDeserializer<Object> deser = _rootDeserializers.get(valueType); + if (deser != null) { + return deser; + } + + // Nope: need to ask provider to resolve it + deser = _provider.findTypedValueDeserializer(cfg, valueType, null); + if (deser == null) { // can this happen? + throw new JsonMappingException("Can not find a deserializer for type "+valueType); + } + _rootDeserializers.put(valueType, deser); + return deser; + } + + protected DeserializationContext _createDeserializationContext(JsonParser jp, DeserializationConfig cfg) { + // 04-Jan-2010, tatu: we do actually need the provider too... (for polymorphic deser) + return new StdDeserializationContext(cfg, jp, _provider, _injectableValues); + } + + protected Object _unwrapAndDeserialize(JsonParser jp, DeserializationContext ctxt, + JavaType rootType, JsonDeserializer<Object> deser) + throws IOException, JsonParseException, JsonMappingException + { + SerializedString rootName = _provider.findExpectedRootName(ctxt.getConfig(), rootType); + if (jp.getCurrentToken() != JsonToken.START_OBJECT) { + throw JsonMappingException.from(jp, "Current token not START_OBJECT (needed to unwrap root name '" + +rootName+"'), but "+jp.getCurrentToken()); + } + if (jp.nextToken() != JsonToken.FIELD_NAME) { + throw JsonMappingException.from(jp, "Current token not FIELD_NAME (to contain expected root name '" + +rootName+"'), but "+jp.getCurrentToken()); + } + String actualName = jp.getCurrentName(); + if (!rootName.getValue().equals(actualName)) { + throw JsonMappingException.from(jp, "Root name '"+actualName+"' does not match expected ('"+rootName + +"') for type "+rootType); + } + // ok, then move to value itself.... + jp.nextToken(); + Object result; + if (_valueToUpdate == null) { + result = deser.deserialize(jp, ctxt); + } else { + deser.deserialize(jp, ctxt, _valueToUpdate); + result = _valueToUpdate; + } + // and last, verify that we now get matching END_OBJECT + if (jp.nextToken() != JsonToken.END_OBJECT) { + throw JsonMappingException.from(jp, "Current token not END_OBJECT (to match wrapper object with root name '" + +rootName+"'), but "+jp.getCurrentToken()); + } + return result; + } + + /* + /********************************************************** + /* Implementation of rest of ObjectCodec methods + /********************************************************** + */ + + @Override + public JsonNode createArrayNode() { + return _config.getNodeFactory().arrayNode(); + } + + @Override + public JsonNode createObjectNode() { + return _config.getNodeFactory().objectNode(); + } + + @Override + public JsonParser treeAsTokens(JsonNode n) { + return new TreeTraversingParser(n, this); + } + + @Override + public <T> T treeToValue(JsonNode n, Class<T> valueType) + throws IOException, JsonProcessingException + { + return readValue(treeAsTokens(n), valueType); + } + + /** + * NOTE: NOT implemented for {@link ObjectReader}. + */ + @Override + public void writeTree(JsonGenerator jgen, JsonNode rootNode) throws IOException, JsonProcessingException + { + throw new UnsupportedOperationException("Not implemented for ObjectReader"); + } + + @Override + public void writeValue(JsonGenerator jgen, Object value) throws IOException, JsonProcessingException + { + throw new UnsupportedOperationException("Not implemented for ObjectReader"); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ObjectWriter.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ObjectWriter.java new file mode 100644 index 0000000..d8c36f3 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ObjectWriter.java
@@ -0,0 +1,543 @@ +package org.codehaus.jackson.map; + +import java.io.*; +import java.text.DateFormat; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.io.SegmentedStringWriter; +import org.codehaus.jackson.map.ser.FilterProvider; +import org.codehaus.jackson.type.JavaType; +import org.codehaus.jackson.type.TypeReference; +import org.codehaus.jackson.util.ByteArrayBuilder; +import org.codehaus.jackson.util.DefaultPrettyPrinter; +import org.codehaus.jackson.util.MinimalPrettyPrinter; +import org.codehaus.jackson.util.VersionUtil; + +/** + * Builder object that can be used for per-serialization configuration of + * serialization parameters, such as JSON View and root type to use. + * (and thus fully thread-safe with no external synchronization); + * new instances are constructed for different configurations. + * Instances are initially constructed by {@link ObjectMapper} and can be + * reused in completely thread-safe manner with no explicit synchronization + * + * @author tatu + * @since 1.5 + */ +public class ObjectWriter + implements Versioned // since 1.6 +{ + /** + * We need to keep track of explicit disabling of pretty printing; + * easiest to do by a token value. + */ + protected final static PrettyPrinter NULL_PRETTY_PRINTER = new MinimalPrettyPrinter(); + + /* + /********************************************************** + /* Immutable configuration from ObjectMapper + /********************************************************** + */ + + /** + * General serialization configuration settings + */ + protected final SerializationConfig _config; + + protected final SerializerProvider _provider; + + protected final SerializerFactory _serializerFactory; + + /** + * Factory used for constructing {@link JsonGenerator}s + */ + protected final JsonFactory _jsonFactory; + + /* + /********************************************************** + /* Configuration that can be changed during building + /********************************************************** + */ + + /** + * Specified root serialization type to use; can be same + * as runtime type, but usually one of its super types + */ + protected final JavaType _rootType; + + /** + * To allow for dynamic enabling/disabling of pretty printing, + * pretty printer can be optionally configured for writer + * as well + */ + protected final PrettyPrinter _prettyPrinter; + + /** + * When using data format that uses a schema, schema is passed + * to generator. + * + * @since 1.8 + */ + protected final FormatSchema _schema; + + /* + /********************************************************** + /* Life-cycle, constructors + /********************************************************** + */ + + /** + * Constructor used by {@link ObjectMapper} for initial instantiation + */ + protected ObjectWriter(ObjectMapper mapper, SerializationConfig config, + JavaType rootType, PrettyPrinter pp) + { + _config = config; + + _provider = mapper._serializerProvider; + _serializerFactory = mapper._serializerFactory; + _jsonFactory = mapper._jsonFactory; + + _rootType = rootType; + _prettyPrinter = pp; + _schema = null; + } + + /** + * Alternative constructor for initial instantiation. + * + * @since 1.7 + */ + protected ObjectWriter(ObjectMapper mapper, SerializationConfig config) + { + _config = config; + + _provider = mapper._serializerProvider; + _serializerFactory = mapper._serializerFactory; + _jsonFactory = mapper._jsonFactory; + + _rootType = null; + _prettyPrinter = null; + _schema = null; + } + + /** + * Alternative constructor for initial instantiation. + * + * @since 1.7 + */ + protected ObjectWriter(ObjectMapper mapper, SerializationConfig config, + FormatSchema s) + { + _config = config; + + _provider = mapper._serializerProvider; + _serializerFactory = mapper._serializerFactory; + _jsonFactory = mapper._jsonFactory; + + _rootType = null; + _prettyPrinter = null; + _schema = s; + } + + /** + * Copy constructor used for building variations. + */ + protected ObjectWriter(ObjectWriter base, SerializationConfig config, + JavaType rootType, PrettyPrinter pp, FormatSchema s) + { + _config = config; + + _provider = base._provider; + _serializerFactory = base._serializerFactory; + _jsonFactory = base._jsonFactory; + + _rootType = rootType; + _prettyPrinter = pp; + _schema = s; + } + + /** + * Copy constructor used for building variations. + * + * @since 1.7 + */ + protected ObjectWriter(ObjectWriter base, SerializationConfig config) + { + _config = config; + + _provider = base._provider; + _serializerFactory = base._serializerFactory; + _jsonFactory = base._jsonFactory; + _schema = base._schema; + + _rootType = base._rootType; + _prettyPrinter = base._prettyPrinter; + } + + /** + * Method that will return version information stored in and read from jar + * that contains this class. + * + * @since 1.6 + */ + @Override + public Version version() { + return VersionUtil.versionFor(getClass()); + } + + /* + /********************************************************** + /* Life-cycle, fluent factories + /********************************************************** + */ + + /** + * Method that will construct a new instance that uses specified + * serialization view for serialization (with null basically disables + * view processing) + */ + public ObjectWriter withView(Class<?> view) + { + if (view == _config.getSerializationView()) return this; + return new ObjectWriter(this, _config.withView(view)); + } + + /** + * Method that will construct a new instance that uses specific type + * as the root type for serialization, instead of runtime dynamic + * type of the root object itself. + */ + public ObjectWriter withType(JavaType rootType) + { + if (rootType == _rootType) return this; + // type is stored here, no need to make a copy of config + return new ObjectWriter(this, _config, rootType, _prettyPrinter, _schema); + } + + /** + * Method that will construct a new instance that uses specific type + * as the root type for serialization, instead of runtime dynamic + * type of the root object itself. + */ + public ObjectWriter withType(Class<?> rootType) + { + return withType(_config.constructType(rootType)); + } + + /** + * @since 1.7 + */ + public ObjectWriter withType(TypeReference<?> rootType) + { + return withType(_config.getTypeFactory().constructType(rootType.getType())); + } + + /** + * Method that will construct a new instance that will use specified pretty + * printer (or, if null, will not do any pretty-printing) + * + * @since 1.6 + */ + public ObjectWriter withPrettyPrinter(PrettyPrinter pp) + { + if (pp == _prettyPrinter) { + return this; + } + // since null would mean "don't care", need to use placeholder to indicate "disable" + if (pp == null) { + pp = NULL_PRETTY_PRINTER; + } + return new ObjectWriter(this, _config, _rootType, pp, _schema); + } + + /** + * Method that will construct a new instance that will use the default + * pretty printer for serialization. + * + * @since 1.6 + */ + public ObjectWriter withDefaultPrettyPrinter() + { + return withPrettyPrinter(new DefaultPrettyPrinter()); + } + + /** + * Method that will construct a new instance that uses specified + * provider for resolving filter instances by id. + * + * @since 1.7 + */ + public ObjectWriter withFilters(FilterProvider filterProvider) + { + if (filterProvider == _config.getFilterProvider()) { // no change? + return this; + } + return new ObjectWriter(this, _config.withFilters(filterProvider)); + } + + /** + * @since 1.8 + */ + public ObjectWriter withSchema(FormatSchema schema) + { + if (_schema == schema) { + return this; + } + return new ObjectWriter(this, _config, _rootType, _prettyPrinter, schema); + } + + /** + * Fluent factory method that will construct a new writer instance that will + * use specified date format for serializing dates; or if null passed, one + * that will serialize dates as numeric timestamps. + * + * @since 1.9 + */ + public ObjectWriter withDateFormat(DateFormat df) + { + SerializationConfig newConfig = _config.withDateFormat(df); + if (newConfig == _config) { + return this; + } + return new ObjectWriter(this, newConfig); + } + + /* + /********************************************************** + /* Serialization methods; ones from ObjectCodec first + /********************************************************** + */ + + /** + * Method that can be used to serialize any Java value as + * JSON output, using provided {@link JsonGenerator}. + */ + public void writeValue(JsonGenerator jgen, Object value) + throws IOException, JsonGenerationException, JsonMappingException + { + if (_config.isEnabled(SerializationConfig.Feature.CLOSE_CLOSEABLE) && (value instanceof Closeable)) { + _writeCloseableValue(jgen, value, _config); + } else { + if (_rootType == null) { + _provider.serializeValue(_config, jgen, value, _serializerFactory); + } else { + _provider.serializeValue(_config, jgen, value, _rootType, _serializerFactory); + } + if (_config.isEnabled(SerializationConfig.Feature.FLUSH_AFTER_WRITE_VALUE)) { + jgen.flush(); + } + } + } + + /* + /********************************************************** + /* Serialization methods, others + /********************************************************** + */ + + /** + * Method that can be used to serialize any Java value as + * JSON output, written to File provided. + */ + public void writeValue(File resultFile, Object value) + throws IOException, JsonGenerationException, JsonMappingException + { + _configAndWriteValue(_jsonFactory.createJsonGenerator(resultFile, JsonEncoding.UTF8), value); + } + + /** + * Method that can be used to serialize any Java value as + * JSON output, using output stream provided (using encoding + * {@link JsonEncoding#UTF8}). + *<p> + * Note: method does not close the underlying stream explicitly + * here; however, {@link JsonFactory} this mapper uses may choose + * to close the stream depending on its settings (by default, + * it will try to close it when {@link JsonGenerator} we construct + * is closed). + */ + public void writeValue(OutputStream out, Object value) + throws IOException, JsonGenerationException, JsonMappingException + { + _configAndWriteValue(_jsonFactory.createJsonGenerator(out, JsonEncoding.UTF8), value); + } + + /** + * Method that can be used to serialize any Java value as + * JSON output, using Writer provided. + *<p> + * Note: method does not close the underlying stream explicitly + * here; however, {@link JsonFactory} this mapper uses may choose + * to close the stream depending on its settings (by default, + * it will try to close it when {@link JsonGenerator} we construct + * is closed). + */ + public void writeValue(Writer w, Object value) + throws IOException, JsonGenerationException, JsonMappingException + { + _configAndWriteValue(_jsonFactory.createJsonGenerator(w), value); + } + + /** + * Method that can be used to serialize any Java value as + * a String. Functionally equivalent to calling + * {@link #writeValue(Writer,Object)} with {@link java.io.StringWriter} + * and constructing String, but more efficient. + */ + public String writeValueAsString(Object value) + throws IOException, JsonGenerationException, JsonMappingException + { + // alas, we have to pull the recycler directly here... + SegmentedStringWriter sw = new SegmentedStringWriter(_jsonFactory._getBufferRecycler()); + _configAndWriteValue(_jsonFactory.createJsonGenerator(sw), value); + return sw.getAndClear(); + } + + /** + * Method that can be used to serialize any Java value as + * a byte array. Functionally equivalent to calling + * {@link #writeValue(Writer,Object)} with {@link java.io.ByteArrayOutputStream} + * and getting bytes, but more efficient. + * Encoding used will be UTF-8. + */ + public byte[] writeValueAsBytes(Object value) + throws IOException, JsonGenerationException, JsonMappingException + { + ByteArrayBuilder bb = new ByteArrayBuilder(_jsonFactory._getBufferRecycler()); + _configAndWriteValue(_jsonFactory.createJsonGenerator(bb, JsonEncoding.UTF8), value); + byte[] result = bb.toByteArray(); + bb.release(); + return result; + } + + /* + /********************************************************** + /* Other public methods + /********************************************************** + */ + + public boolean canSerialize(Class<?> type) + { + return _provider.hasSerializerFor(_config, type, _serializerFactory); + } + + /* + /********************************************************** + /* Internal methods + /********************************************************** + */ + + /** + * Method called to configure the generator as necessary and then + * call write functionality + */ + protected final void _configAndWriteValue(JsonGenerator jgen, Object value) + throws IOException, JsonGenerationException, JsonMappingException + { + if (_prettyPrinter != null) { + PrettyPrinter pp = _prettyPrinter; + jgen.setPrettyPrinter((pp == NULL_PRETTY_PRINTER) ? null : pp); + } else if (_config.isEnabled(SerializationConfig.Feature.INDENT_OUTPUT)) { + jgen.useDefaultPrettyPrinter(); + } + // [JACKSON-520]: add support for pass-through schema: + if (_schema != null) { + jgen.setSchema(_schema); + } + // [JACKSON-282]: consider Closeable + if (_config.isEnabled(SerializationConfig.Feature.CLOSE_CLOSEABLE) && (value instanceof Closeable)) { + _configAndWriteCloseable(jgen, value, _config); + return; + } + boolean closed = false; + try { + if (_rootType == null) { + _provider.serializeValue(_config, jgen, value, _serializerFactory); + } else { + _provider.serializeValue(_config, jgen, value, _rootType, _serializerFactory); + } + closed = true; + jgen.close(); + } finally { + /* won't try to close twice; also, must catch exception (so it + * will not mask exception that is pending) + */ + if (!closed) { + try { + jgen.close(); + } catch (IOException ioe) { } + } + } + } + + /** + * Helper method used when value to serialize is {@link Closeable} and its <code>close()</code> + * method is to be called right after serialization has been called + */ + private final void _configAndWriteCloseable(JsonGenerator jgen, Object value, SerializationConfig cfg) + throws IOException, JsonGenerationException, JsonMappingException + { + Closeable toClose = (Closeable) value; + try { + if (_rootType == null) { + _provider.serializeValue(cfg, jgen, value, _serializerFactory); + } else { + _provider.serializeValue(cfg, jgen, value, _rootType, _serializerFactory); + } + // [JACKSON-520]: add support for pass-through schema: + if (_schema != null) { + jgen.setSchema(_schema); + } + JsonGenerator tmpJgen = jgen; + jgen = null; + tmpJgen.close(); + Closeable tmpToClose = toClose; + toClose = null; + tmpToClose.close(); + } finally { + /* Need to close both generator and value, as long as they haven't yet + * been closed + */ + if (jgen != null) { + try { + jgen.close(); + } catch (IOException ioe) { } + } + if (toClose != null) { + try { + toClose.close(); + } catch (IOException ioe) { } + } + } + } + + /** + * Helper method used when value to serialize is {@link Closeable} and its <code>close()</code> + * method is to be called right after serialization has been called + */ + private final void _writeCloseableValue(JsonGenerator jgen, Object value, SerializationConfig cfg) + throws IOException, JsonGenerationException, JsonMappingException + { + Closeable toClose = (Closeable) value; + try { + if (_rootType == null) { + _provider.serializeValue(cfg, jgen, value, _serializerFactory); + } else { + _provider.serializeValue(cfg, jgen, value, _rootType, _serializerFactory); + } + if (_config.isEnabled(SerializationConfig.Feature.FLUSH_AFTER_WRITE_VALUE)) { + jgen.flush(); + } + Closeable tmpToClose = toClose; + toClose = null; + tmpToClose.close(); + } finally { + if (toClose != null) { + try { + toClose.close(); + } catch (IOException ioe) { } + } + } + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/PropertyNamingStrategy.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/PropertyNamingStrategy.java new file mode 100644 index 0000000..f772d13 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/PropertyNamingStrategy.java
@@ -0,0 +1,258 @@ +package org.codehaus.jackson.map; + +import org.codehaus.jackson.map.introspect.AnnotatedField; +import org.codehaus.jackson.map.introspect.AnnotatedMethod; +import org.codehaus.jackson.map.introspect.AnnotatedParameter; + +/** + * Class that defines how names of JSON properties ("external names") + * are derived from names of POJO methods and fields ("internal names"), + * in cases where they are not + * auto-detected and no explicit annotations exist for naming. + * Methods are passed information about POJO member for which name is needed, + * as well as default name that would be used if no custom strategy was used. + *<p> + * Default implementation returns suggested ("default") name unmodified. + *<p> + * Note that the strategy is guaranteed to be called once per logical property + * (which may be represented by multiple members; such as pair of a getter and + * a setter), but may be called for each: implementations should not count on + * exact number of times, and should work for any member that represent a + * property. + *<p> + * In absence of a registered custom strategy, default Java property naming strategy + * is used, which leaves field names as is, and removes set/get/is prefix + * from methods (as well as lower-cases initial sequence of capitalized + * characters). + * + * @since 1.8 + */ +public abstract class PropertyNamingStrategy +{ + /* + /********************************************************** + /* API + /********************************************************** + */ + + /** + * Method called to find external name (name used in JSON) for given logical + * POJO property, + * as defined by given field. + * + * @param config Configuration in used: either <code>SerializationConfig</code> + * or <code>DeserializationConfig</code>, depending on whether method is called + * during serialization or deserialization + * @param field Field used to access property + * @param defaultName Default name that would be used for property in absence of custom strategy + * + * @return Logical name to use for property that the field represents + */ + public String nameForField(MapperConfig<?> config, AnnotatedField field, + String defaultName) + { + return defaultName; + } + + /** + * Method called to find external name (name used in JSON) for given logical + * POJO property, + * as defined by given getter method; typically called when building a serializer. + * (but not always -- when using "getter-as-setter", may be called during + * deserialization) + * + * @param config Configuration in used: either <code>SerializationConfig</code> + * or <code>DeserializationConfig</code>, depending on whether method is called + * during serialization or deserialization + * @param method Method used to access property. + * @param defaultName Default name that would be used for property in absence of custom strategy + * + * @return Logical name to use for property that the method represents + */ + public String nameForGetterMethod(MapperConfig<?> config, AnnotatedMethod method, + String defaultName) + { + return defaultName; + } + + /** + * Method called to find external name (name used in JSON) for given logical + * POJO property, + * as defined by given setter method; typically called when building a deserializer + * (but not necessarily only then). + * + * @param config Configuration in used: either <code>SerializationConfig</code> + * or <code>DeserializationConfig</code>, depending on whether method is called + * during serialization or deserialization + * @param method Method used to access property. + * @param defaultName Default name that would be used for property in absence of custom strategy + * + * @return Logical name to use for property that the method represents + */ + public String nameForSetterMethod(MapperConfig<?> config, AnnotatedMethod method, + String defaultName) + { + return defaultName; + } + + /** + * Method called to find external name (name used in JSON) for given logical + * POJO property, + * as defined by given constructor parameter; typically called when building a deserializer + * (but not necessarily only then). + * + * @param config Configuration in used: either <code>SerializationConfig</code> + * or <code>DeserializationConfig</code>, depending on whether method is called + * during serialization or deserialization + * @param ctorParam Constructor parameter used to pass property. + * @param defaultName Default name that would be used for property in absence of custom strategy + * @since 1.9 + */ + public String nameForConstructorParameter(MapperConfig<?> config, AnnotatedParameter ctorParam, + String defaultName) + { + return defaultName; + } + + /* + /********************************************************** + /* Standard implementations + /********************************************************** + */ + + /** + * @since 1.9 + */ + public static abstract class PropertyNamingStrategyBase extends PropertyNamingStrategy + { + @Override + public String nameForField(MapperConfig<?> config, AnnotatedField field, String defaultName) + { + return translate(defaultName); + } + + @Override + public String nameForGetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) + { + return translate(defaultName); + } + + @Override + public String nameForSetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) + { + return translate(defaultName); + } + + @Override + public String nameForConstructorParameter(MapperConfig<?> config, AnnotatedParameter ctorParam, + String defaultName) + { + return translate(defaultName); + } + + public abstract String translate(String propertyName); + } + + + /* + /********************************************************** + /* Standard implementations + /********************************************************** + */ + + /** + * See {@link LowerCaseWithUnderscoresStrategy} for details. + * + * @since 1.9 + */ + public static final PropertyNamingStrategy CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES = + new LowerCaseWithUnderscoresStrategy(); + + /** + * A {@link PropertyNamingStrategy} that translates typical camel case Java + * property names to lower case JSON element names, separated by + * underscores. This implementation is somewhat lenient, in that it + * provides some additional translations beyond strictly translating from + * camel case only. In particular, the following translations are applied + * by this PropertyNamingStrategy. + * + * <ul><li>Every upper case letter in the Java property name is translated + * into two characters, an underscore and the lower case equivalent of the + * target character, with three exceptions. + * <ol><li>For contiguous sequences of upper case letters, characters after + * the first character are replaced only by their lower case equivalent, + * and are not preceded by an underscore. + * <ul><li>This provides for reasonable translations of upper case acronyms, + * e.g., "theWWW" is translated to "the_www".</li></ul></li> + * <li>An upper case character in the first position of the Java property + * name is not preceded by an underscore character, and is translated only + * to its lower case equivalent. + * <ul><li>For example, "Results" is translated to "results", + * and not to "_results".</li></ul></li> + * <li>An upper case character in the Java property name that is already + * preceded by an underscore character is translated only to its lower case + * equivalent, and is not preceded by an additional underscore. + * <ul><li>For example, "user_Name" is translated to + * "user_name", and not to "user__name" (with two + * underscore characters).</li></ul></li></ol></li> + * <li>If the Java property name starts with an underscore, then that + * underscore is not included in the translated name, unless the Java + * property name is just one character in length, i.e., it is the + * underscore character. This applies only to the first character of the + * Java property name.</li></ul> + * + * These rules result in the following additional example translations from + * Java property names to JSON element names. + * <ul><li>"userName" is translated to "user_name"</li> + * <li>"UserName" is translated to "user_name"</li> + * <li>"USER_NAME" is translated to "user_name"</li> + * <li>"user_name" is translated to "user_name" (unchanged)</li> + * <li>"user" is translated to "user" (unchanged)</li> + * <li>"User" is translated to "user"</li> + * <li>"USER" is translated to "user"</li> + * <li>"_user" is translated to "user"</li> + * <li>"_User" is translated to "user"</li> + * <li>"__user" is translated to "_user" + * (the first of two underscores was removed)</li> + * <li>"user__name" is translated to "user__name" + * (unchanged, with two underscores)</li></ul> + * + * @since 1.9 + */ + public static class LowerCaseWithUnderscoresStrategy extends PropertyNamingStrategyBase + { + @Override + public String translate(String input) + { + if (input == null) return input; // garbage in, garbage out + int length = input.length(); + StringBuilder result = new StringBuilder(length * 2); + int resultLength = 0; + boolean wasPrevTranslated = false; + for (int i = 0; i < length; i++) + { + char c = input.charAt(i); + if (i > 0 || c != '_') // skip first starting underscore + { + if (Character.isUpperCase(c)) + { + if (!wasPrevTranslated && resultLength > 0 && result.charAt(resultLength - 1) != '_') + { + result.append('_'); + resultLength++; + } + c = Character.toLowerCase(c); + wasPrevTranslated = true; + } + else + { + wasPrevTranslated = false; + } + result.append(c); + resultLength++; + } + } + return resultLength > 0 ? result.toString() : input; + } + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ResolvableDeserializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ResolvableDeserializer.java new file mode 100644 index 0000000..f87bf1c --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ResolvableDeserializer.java
@@ -0,0 +1,23 @@ +package org.codehaus.jackson.map; + +/** + * Interface used to indicate deserializers that want to do post-processing + * after construction and being added to {@link DeserializerProvider}, + * but before being used. This is typically used to resolve references + * to other contained types; for example, bean deserializers use this + * to eagerly find deserializers for contained field types. + */ +public interface ResolvableDeserializer +{ + /** + * Method called after {@link DeserializerProvider} has registered + * the deserializer, but before it has returned it to the caller. + * Called object can then resolve its dependencies to other types, + * including self-references (direct or indirect). + * + * @param provider Provider that has constructed deserializer this method + * is called on. + */ + public abstract void resolve(DeserializationConfig config, DeserializerProvider provider) + throws JsonMappingException; +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ResolvableSerializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ResolvableSerializer.java new file mode 100644 index 0000000..17d3055 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ResolvableSerializer.java
@@ -0,0 +1,23 @@ +package org.codehaus.jackson.map; + +/** + * Interface used to indicate serializers that want to do post-processing + * after construction and being added to {@link SerializerProvider}, + * but before being used. This is typically used to resolve references + * to other contained types; for example, bean serializers use this + * to eagerly find serializers for contained field types. + */ +public interface ResolvableSerializer +{ + /** + * Method called after {@link SerializerProvider} has registered + * the serializer, but before it has returned it to the caller. + * Called object can then resolve its dependencies to other types, + * including self-references (direct or indirect). + * + * @param provider Provider that has constructed serializer this method + * is called on. + */ + public abstract void resolve(SerializerProvider provider) + throws JsonMappingException; +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/RuntimeJsonMappingException.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/RuntimeJsonMappingException.java new file mode 100644 index 0000000..c37cd3f --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/RuntimeJsonMappingException.java
@@ -0,0 +1,21 @@ +package org.codehaus.jackson.map; + +/** + * Wrapper used when interface does not allow throwing a checked + * {@link JsonMappingException} + */ +@SuppressWarnings("serial") +public class RuntimeJsonMappingException extends RuntimeException +{ + public RuntimeJsonMappingException(JsonMappingException cause) { + super(cause); + } + + public RuntimeJsonMappingException(String message) { + super(message); + } + + public RuntimeJsonMappingException(String message, JsonMappingException cause) { + super(message, cause); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/SerializationConfig.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/SerializationConfig.java new file mode 100644 index 0000000..2cfac31 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/SerializationConfig.java
@@ -0,0 +1,1039 @@ +package org.codehaus.jackson.map; + +import java.text.DateFormat; +import java.util.*; + +import org.codehaus.jackson.annotate.*; +import org.codehaus.jackson.annotate.JsonAutoDetect.Visibility; +import org.codehaus.jackson.map.annotate.JsonSerialize; +import org.codehaus.jackson.map.annotate.JsonSerialize.Inclusion; // for javadocs +import org.codehaus.jackson.map.introspect.Annotated; +import org.codehaus.jackson.map.introspect.AnnotatedClass; +import org.codehaus.jackson.map.introspect.VisibilityChecker; +import org.codehaus.jackson.map.jsontype.SubtypeResolver; +import org.codehaus.jackson.map.jsontype.TypeResolverBuilder; +import org.codehaus.jackson.map.ser.FilterProvider; +import org.codehaus.jackson.map.type.ClassKey; +import org.codehaus.jackson.map.type.TypeFactory; +import org.codehaus.jackson.map.util.ClassUtil; +import org.codehaus.jackson.type.JavaType; + +/** + * Object that contains baseline configuration for serialization + * process. An instance is owned by {@link ObjectMapper}, which makes + * a copy that is passed during serialization process to + * {@link SerializerProvider} and {@link SerializerFactory}. + *<p> + * Note: although configuration settings can be changed at any time + * (for factories and instances), they are not guaranteed to have + * effect if called after constructing relevant mapper or serializer + * instance. This because some objects may be configured, constructed and + * cached first time they are needed. + *<p> + * As of version 1.9, the goal is to make this class eventually immutable. + * Because of this, existing methods that allow changing state of this + * instance are deprecated in favor of methods that create new instances + * with different configuration ("fluent factories") + */ +public class SerializationConfig + extends MapperConfig.Impl<SerializationConfig.Feature, SerializationConfig> +{ + /** + * Enumeration that defines togglable features that guide + * the serialization feature. + */ + public enum Feature implements MapperConfig.ConfigFeature + { + /* + /****************************************************** + /* Introspection features + /****************************************************** + */ + + /** + * Feature that determines whether annotation introspection + * is used for configuration; if enabled, configured + * {@link AnnotationIntrospector} will be used: if disabled, + * no annotations are considered. + *<P> + * Feature is enabled by default. + * + * @since 1.2 + */ + USE_ANNOTATIONS(true), + + /** + * Feature that determines whether regualr "getter" methods are + * automatically detected based on standard Bean naming convention + * or not. If yes, then all public zero-argument methods that + * start with prefix "get" + * are considered as getters. + * If disabled, only methods explicitly annotated are considered getters. + *<p> + * Note that since version 1.3, this does <b>NOT</b> include + * "is getters" (see {@link #AUTO_DETECT_IS_GETTERS} for details) + *<p> + * Note that this feature has lower precedence than per-class + * annotations, and is only used if there isn't more granular + * configuration available. + *<P> + * Feature is enabled by default. + */ + AUTO_DETECT_GETTERS(true), + + /** + * Feature that determines whether "is getter" methods are + * automatically detected based on standard Bean naming convention + * or not. If yes, then all public zero-argument methods that + * start with prefix "is", and whose return type is boolean + * are considered as "is getters". + * If disabled, only methods explicitly annotated are considered getters. + *<p> + * Note that this feature has lower precedence than per-class + * annotations, and is only used if there isn't more granular + * configuration available. + *<P> + * Feature is enabled by default. + */ + AUTO_DETECT_IS_GETTERS(true), + + /** + * Feature that determines whether non-static fields are recognized as + * properties. + * If yes, then all public member fields + * are considered as properties. If disabled, only fields explicitly + * annotated are considered property fields. + *<p> + * Note that this feature has lower precedence than per-class + * annotations, and is only used if there isn't more granular + * configuration available. + *<p> + * Feature is enabled by default. + * + * @since 1.1 + */ + AUTO_DETECT_FIELDS(true), + + /** + * Feature that determines whether method and field access + * modifier settings can be overridden when accessing + * properties. If enabled, method + * {@link java.lang.reflect.AccessibleObject#setAccessible} + * may be called to enable access to otherwise unaccessible + * objects. + *<p> + * Feature is enabled by default. + */ + CAN_OVERRIDE_ACCESS_MODIFIERS(true), + + /** + * Feature that determines whether getters (getter methods) + * can be auto-detected if there is no matching mutator (setter, + * constructor parameter or field) or not: if set to true, + * only getters that match a mutator are auto-discovered; if + * false, all auto-detectable getters can be discovered. + *<p> + * Feature is disabled by default for backwards compatibility + * reasons. + * + * @since 1.9 + */ + REQUIRE_SETTERS_FOR_GETTERS(false), + + /* + /****************************************************** + /* Generic output features + /****************************************************** + */ + + /** + * Feature that determines the default settings of whether Bean + * properties with null values are to be written out. + *<p> + * Feature is enabled by default (null properties written). + *<p> + * Note too that there is annotation + * {@link org.codehaus.jackson.annotate.JsonWriteNullProperties} + * that can be used for more granular control (annotates bean + * classes or individual property access methods). + * + * @deprecated As of 1.1, use {@link SerializationConfig#setSerializationInclusion} + * instead + */ + @Deprecated + WRITE_NULL_PROPERTIES(true), + + /** + * Feature that determines whether the type detection for + * serialization should be using actual dynamic runtime type, + * or declared static type. + * Default value is false, to use dynamic runtime type. + *<p> + * This global default value can be overridden at class, method + * or field level by using {@link JsonSerialize#typing} annotation + * property + */ + USE_STATIC_TYPING(false), + + /** + * Feature that determines whether properties that have no view + * annotations are included in JSON serialization views (see + * {@link org.codehaus.jackson.map.annotate.JsonView} for more + * details on JSON Views). + * If enabled, non-annotated properties will be included; + * when disabled, they will be excluded. So this feature + * changes between "opt-in" (feature disabled) and + * "opt-out" (feature enabled) modes. + *<p> + * Default value is enabled, meaning that non-annotated + * properties are included in all views if there is no + * {@link org.codehaus.jackson.map.annotate.JsonView} annotation. + * + * @since 1.5 + */ + DEFAULT_VIEW_INCLUSION(true), + + /** + * Feature that can be enabled to make root value (usually JSON + * Object but can be any type) wrapped within a single property + * JSON object, where key as the "root name", as determined by + * annotation introspector (esp. for JAXB that uses + * <code>@XmlRootElement.name</code>) or fallback (non-qualified + * class name). + * Feature is mostly intended for JAXB compatibility. + *<p> + * Default setting is false, meaning root value is not wrapped. + * + * @since 1.7 + */ + WRAP_ROOT_VALUE(false), + + /** + * Feature that allows enabling (or disabling) indentation + * for the underlying generator, using the default pretty + * printer (see + * {@link org.codehaus.jackson.JsonGenerator#useDefaultPrettyPrinter} + * for details). + *<p> + * Note that this only affects cases where + * {@link org.codehaus.jackson.JsonGenerator} + * is constructed implicitly by ObjectMapper: if explicit + * generator is passed, its configuration is not changed. + *<p> + * Also note that if you want to configure details of indentation, + * you need to directly configure the generator: there is a + * method to use any <code>PrettyPrinter</code> instance. + * This feature will only allow using the default implementation. + */ + INDENT_OUTPUT(false), + + /** + * Feature that defines default property serialization order used + * for POJO fields (note: does <b>not</b> apply to {@link java.util.Map} + * serialization!): + * if enabled, default ordering is alphabetic (similar to + * how {@link org.codehaus.jackson.annotate.JsonPropertyOrder#alphabetic()} + * works); if disabled, order is unspecified (based on what JDK gives + * us, which may be declaration order, but not guaranteed). + *<p> + * Note that this is just the default behavior, and can be overridden by + * explicit overrides in classes. + * + * @since 1.8 + */ + SORT_PROPERTIES_ALPHABETICALLY(false), + + /* + /****************************************************** + /* Error handling features + /****************************************************** + */ + + /** + * Feature that determines what happens when no accessors are + * found for a type (and there are no annotations to indicate + * it is meant to be serialized). If enabled (default), an + * exception is thrown to indicate these as non-serializable + * types; if disabled, they are serialized as empty Objects, + * i.e. without any properties. + *<p> + * Note that empty types that this feature has only effect on + * those "empty" beans that do not have any recognized annotations + * (like <code>@JsonSerialize</code>): ones that do have annotations + * do not result in an exception being thrown. + * + * @since 1.4 + */ + FAIL_ON_EMPTY_BEANS(true), + + /** + * Feature that determines whether Jackson code should catch + * and wrap {@link Exception}s (but never {@link Error}s!) + * to add additional information about + * location (within input) of problem or not. If enabled, + * most exceptions will be caught and re-thrown (exception + * specifically being that {@link java.io.IOException}s may be passed + * as is, since they are declared as throwable); this can be + * convenient both in that all exceptions will be checked and + * declared, and so there is more contextual information. + * However, sometimes calling application may just want "raw" + * unchecked exceptions passed as is. + *<p> + * Feature is enabled by default, and is similar in behavior + * to default prior to 1.7. + * + * @since 1.7 + */ + WRAP_EXCEPTIONS(true), + + /* + /****************************************************** + /* Output life cycle features + /****************************************************** + */ + + /** + * Feature that determines whether <code>close</code> method of + * serialized <b>root level</b> objects (ones for which <code>ObjectMapper</code>'s + * writeValue() (or equivalent) method is called) + * that implement {@link java.io.Closeable} + * is called after serialization or not. If enabled, <b>close()</b> will + * be called after serialization completes (whether succesfully, or + * due to an error manifested by an exception being thrown). You can + * think of this as sort of "finally" processing. + *<p> + * NOTE: only affects behavior with <b>root</b> objects, and not other + * objects reachable from the root object. Put another way, only one + * call will be made for each 'writeValue' call. + * + * @since 1.6 (see [JACKSON-282 for details]) + */ + CLOSE_CLOSEABLE(false), + + /** + * Feature that determines whether <code>JsonGenerator.flush()</code> is + * called after <code>writeValue()</code> method <b>that takes JsonGenerator + * as an argument</b> completes (i.e. does NOT affect methods + * that use other destinations); same for methods in {@link ObjectWriter}. + * This usually makes sense; but there are cases where flushing + * should not be forced: for example when underlying stream is + * compressing and flush() causes compression state to be flushed + * (which occurs with some compression codecs). + * + * @since 1.6 (see [JACKSON-401 for details]) + */ + FLUSH_AFTER_WRITE_VALUE(true), + + /* + /****************************************************** + /* Data type - specific serialization configuration + /****************************************************** + */ + + /** + * Feature that determines whether {@link java.util.Date} values + * (and Date-based things like {@link java.util.Calendar}s) are to be + * serialized as numeric timestamps (true; the default), + * or as something else (usually textual representation). + * If textual representation is used, the actual format is + * one returned by a call to {@link #getDateFormat}. + *<p> + * Note: whether this feature affects handling of other date-related + * types depend on handlers of those types, although ideally they + * should use this feature + *<p> + * Note: whether {@link java.util.Map} keys are serialized as Strings + * or not is controlled using {@link #WRITE_DATE_KEYS_AS_TIMESTAMPS}. + */ + WRITE_DATES_AS_TIMESTAMPS(true), + + /** + * Feature that determines whether {@link java.util.Date}s + * (and sub-types) used as {@link java.util.Map} keys are serialized + * as timestamps or not (if not, will be serialized as textual + * values). + *<p> + * Default value is 'false', meaning that Date-valued Map keys are serialized + * as textual (ISO-8601) values. + * + * @since 1.9 + */ + WRITE_DATE_KEYS_AS_TIMESTAMPS(false), + + /** + * Feature that determines how type <code>char[]</code> is serialized: + * when enabled, will be serialized as an explict JSON array (with + * single-character Strings as values); when disabled, defaults to + * serializing them as Strings (which is more compact). + * + * @since 1.6 (see [JACKSON-289 for details]) + */ + WRITE_CHAR_ARRAYS_AS_JSON_ARRAYS(false), + + /** + * Feature that determines standard serialization mechanism used for + * Enum values: if enabled, return value of <code>Enum.toString()</code> + * is used; if disabled, return value of <code>Enum.name()</code> is used. + * Since pre-1.6 method was to use Enum name, this is the default. + *<p> + * Note: this feature should usually have same value + * as {@link DeserializationConfig.Feature#READ_ENUMS_USING_TO_STRING}. + *<p> + * For further details, check out [JACKSON-212] + * + * @since 1.6 + */ + WRITE_ENUMS_USING_TO_STRING(false), + + /** + * Feature that determines whethere Java Enum values are serialized + * as numbers (true), or textual values (false). If textual values are + * used, other settings are also considered. + * If this feature is enabled, + * return value of <code>Enum.ordinal()</code> + * (an integer) will be used as the serialization. + *<p> + * Note that this feature has precedence over {@link #WRITE_ENUMS_USING_TO_STRING}, + * which is only considered if this feature is set to false. + * + * @since 1.9 + */ + WRITE_ENUMS_USING_INDEX(false), + + /** + * Feature that determines whether Map entries with null values are + * to be serialized (true) or not (false). + *<p> + * For further details, check out [JACKSON-314] + * + * @since 1.6 + */ + WRITE_NULL_MAP_VALUES(true), + + /** + * Feature that determines whether Container properties (POJO properties + * with declared value of Collection or array; i.e. things that produce JSON + * arrays) that are empty (have no elements) + * will be serialized as empty JSON arrays (true), or suppressed from output (false). + *<p> + * Note that this does not change behavior of {@link java.util.Map}s, or + * "Collection-like" types. + * + * @since 1.9 + */ + WRITE_EMPTY_JSON_ARRAYS(true) + + ; + + final boolean _defaultState; + + private Feature(boolean defaultState) { + _defaultState = defaultState; + } + + @Override + public boolean enabledByDefault() { return _defaultState; } + + @Override + public int getMask() { return (1 << ordinal()); } + } + + /* + /********************************************************** + /* Configuration settings + /********************************************************** + */ + + /** + * Which Bean/Map properties are to be included in serialization? + * Default settings is to include all regardless of value; can be + * changed to only include non-null properties, or properties + * with non-default values. + *<p> + * Defaults to null for backwards compatibility; if left as null, + * will check + * deprecated {@link Feature#WRITE_NULL_PROPERTIES} + * to choose between {@link Inclusion#ALWAYS} + * and {@link Inclusion#NON_NULL}. + */ + protected JsonSerialize.Inclusion _serializationInclusion = null; + + /** + * View to use for filtering out properties to serialize. + * Null if none (will also be assigned null if <code>Object.class</code> + * is defined), meaning that all properties are to be included. + */ + protected Class<?> _serializationView; + + /** + * Object used for resolving filter ids to filter instances. + * Non-null if explicitly defined; null by default. + * + * @since 1.7 + */ + protected FilterProvider _filterProvider; + + /* + /********************************************************** + /* Life-cycle, constructors + /********************************************************** + */ + + /** + * Constructor used by ObjectMapper to create default configuration object instance. + */ + public SerializationConfig(ClassIntrospector<? extends BeanDescription> intr, + AnnotationIntrospector annIntr, VisibilityChecker<?> vc, + SubtypeResolver subtypeResolver, PropertyNamingStrategy propertyNamingStrategy, + TypeFactory typeFactory, HandlerInstantiator handlerInstantiator) + { + super(intr, annIntr, vc, subtypeResolver, propertyNamingStrategy, typeFactory, handlerInstantiator, + collectFeatureDefaults(SerializationConfig.Feature.class)); + _filterProvider = null; + } + + /** + * @since 1.8 + */ + protected SerializationConfig(SerializationConfig src) { + this(src, src._base); + } + + /** + * Constructor used to make a private copy of specific mix-in definitions. + * + * @since 1.8 + */ + protected SerializationConfig(SerializationConfig src, + HashMap<ClassKey,Class<?>> mixins, SubtypeResolver str) + { + this(src, src._base); + _mixInAnnotations = mixins; + _subtypeResolver = str; + } + + /** + * @since 1.8 + */ + protected SerializationConfig(SerializationConfig src, MapperConfig.Base base) + { + super(src, base, src._subtypeResolver); + _serializationInclusion = src._serializationInclusion; + _serializationView = src._serializationView; + _filterProvider = src._filterProvider; + } + + /** + * @since 1.8 + */ + protected SerializationConfig(SerializationConfig src, FilterProvider filters) + { + super(src); + _serializationInclusion = src._serializationInclusion; + _serializationView = src._serializationView; + _filterProvider = filters; + } + + /** + * @since 1.8 + */ + protected SerializationConfig(SerializationConfig src, Class<?> view) + { + super(src); + _serializationInclusion = src._serializationInclusion; + _serializationView = view; + _filterProvider = src._filterProvider; + } + + /** + * @since 1.9 + */ + protected SerializationConfig(SerializationConfig src, JsonSerialize.Inclusion incl) + { + super(src); + _serializationInclusion = incl; + // And for some level of backwards compatibility, also... + if (incl == JsonSerialize.Inclusion.NON_NULL) { + _featureFlags &= ~Feature.WRITE_NULL_PROPERTIES.getMask(); + } else { + _featureFlags |= Feature.WRITE_NULL_PROPERTIES.getMask(); + } + _serializationView = src._serializationView; + _filterProvider = src._filterProvider; + } + + /** + * @since 1.9 + */ + protected SerializationConfig(SerializationConfig src, int features) + { + super(src, features); + _serializationInclusion = src._serializationInclusion; + _serializationView = src._serializationView; + _filterProvider = src._filterProvider; + } + + /* + /********************************************************** + /* Life-cycle, factory methods from MapperConfig + /********************************************************** + */ + + @Override + public SerializationConfig withClassIntrospector(ClassIntrospector<? extends BeanDescription> ci) { + return new SerializationConfig(this, _base.withClassIntrospector(ci)); + } + + @Override + public SerializationConfig withAnnotationIntrospector(AnnotationIntrospector ai) { + return new SerializationConfig(this, _base.withAnnotationIntrospector(ai)); + } + + @Override + public SerializationConfig withInsertedAnnotationIntrospector(AnnotationIntrospector ai) { + return new SerializationConfig(this, _base.withInsertedAnnotationIntrospector(ai)); + } + + @Override + public SerializationConfig withAppendedAnnotationIntrospector(AnnotationIntrospector ai) { + return new SerializationConfig(this, _base.withAppendedAnnotationIntrospector(ai)); + } + + @Override + public SerializationConfig withVisibilityChecker(VisibilityChecker<?> vc) { + return new SerializationConfig(this, _base.withVisibilityChecker(vc)); + } + + @Override + public SerializationConfig withVisibility(JsonMethod forMethod, JsonAutoDetect.Visibility visibility) { + return new SerializationConfig(this, _base.withVisibility(forMethod, visibility)); + } + + @Override + public SerializationConfig withTypeResolverBuilder(TypeResolverBuilder<?> trb) { + return new SerializationConfig(this, _base.withTypeResolverBuilder(trb)); + } + + @Override + public SerializationConfig withSubtypeResolver(SubtypeResolver str) { + SerializationConfig cfg = new SerializationConfig(this); + cfg._subtypeResolver = str; + return cfg; + } + + @Override + public SerializationConfig withPropertyNamingStrategy(PropertyNamingStrategy pns) { + return new SerializationConfig(this, _base.withPropertyNamingStrategy(pns)); + } + + @Override + public SerializationConfig withTypeFactory(TypeFactory tf) { + return new SerializationConfig(this, _base.withTypeFactory(tf)); + } + + /** + * In addition to constructing instance with specified date format, + * will enable or disable <code>Feature.WRITE_DATES_AS_TIMESTAMPS</code> + * (enable if format set as null; disable if non-null) + */ + @Override + public SerializationConfig withDateFormat(DateFormat df) { + SerializationConfig cfg = new SerializationConfig(this, _base.withDateFormat(df)); + // Also need to toggle this feature based on existence of date format: + if (df == null) { + cfg = cfg.with(Feature.WRITE_DATES_AS_TIMESTAMPS); + } else { + cfg = cfg.without(Feature.WRITE_DATES_AS_TIMESTAMPS); + } + return cfg; + } + + @Override + public SerializationConfig withHandlerInstantiator(HandlerInstantiator hi) { + return new SerializationConfig(this, _base.withHandlerInstantiator(hi)); + } + + /* + /********************************************************** + /* Life-cycle, SerializationConfig specific factory methods + /********************************************************** + */ + + /** + * @since 1.7 + */ + public SerializationConfig withFilters(FilterProvider filterProvider) { + return new SerializationConfig(this, filterProvider); + } + + /** + * @since 1.8 + */ + public SerializationConfig withView(Class<?> view) { + return new SerializationConfig(this, view); + } + + /** + * @since 1.9 + */ + public SerializationConfig withSerializationInclusion(JsonSerialize.Inclusion incl) { + return new SerializationConfig(this, incl); + } + + /** + * Fluent factory method that will construct and return a new configuration + * object instance with specified features enabled. + * + * @since 1.9 + */ + @Override + public SerializationConfig with(Feature... features) + { + int flags = _featureFlags; + for (Feature f : features) { + flags |= f.getMask(); + } + return new SerializationConfig(this, flags); + } + + /** + * Fluent factory method that will construct and return a new configuration + * object instance with specified features disabled. + * + * @since 1.9 + */ + @Override + public SerializationConfig without(Feature... features) + { + int flags = _featureFlags; + for (Feature f : features) { + flags &= ~f.getMask(); + } + return new SerializationConfig(this, flags); + } + + /* + /********************************************************** + /* MapperConfig implementation/overrides + /********************************************************** + */ + + /** + * Method that checks class annotations that the argument Object has, + * and modifies settings of this configuration object accordingly, + * similar to how those annotations would affect actual value classes + * annotated with them, but with global scope. Note that not all + * annotations have global significance, and thus only subset of + * Jackson annotations will have any effect. + *<p> + * Serialization annotations that are known to have effect are: + *<ul> + * <li>{@link JsonWriteNullProperties}</li> + * <li>{@link JsonAutoDetect}</li> + * <li>{@link JsonSerialize#typing}</li> + *</ul> + * + * @param cls Class of which class annotations to use + * for changing configuration settings + * + * @deprecated Since 1.9, it is preferably to explicitly configure + * instances; this method also modifies existing instance which is + * against immutable design goals of this class. + */ + @SuppressWarnings("deprecation") + @Deprecated + @Override + public void fromAnnotations(Class<?> cls) + { + /* 10-Jul-2009, tatu: Should be able to just pass null as + * 'MixInResolver'; no mix-ins set at this point + * 29-Jul-2009, tatu: Also, we do NOT ignore annotations here, even + * if Feature.USE_ANNOTATIONS was disabled, since caller + * specifically requested annotations to be added with this call + */ + AnnotationIntrospector ai = getAnnotationIntrospector(); + AnnotatedClass ac = AnnotatedClass.construct(cls, ai, null); + _base = _base.withVisibilityChecker(ai.findAutoDetectVisibility(ac, + getDefaultVisibilityChecker())); + + // How about writing null property values? + JsonSerialize.Inclusion incl = ai.findSerializationInclusion(ac, null); + if (incl != _serializationInclusion) { + setSerializationInclusion(incl); + } + + JsonSerialize.Typing typing = ai.findSerializationTyping(ac); + if (typing != null) { + set(Feature.USE_STATIC_TYPING, (typing == JsonSerialize.Typing.STATIC)); + } + } + + @Override + public SerializationConfig createUnshared(SubtypeResolver subtypeResolver) + { + HashMap<ClassKey,Class<?>> mixins = _mixInAnnotations; + _mixInAnnotationsShared = true; + return new SerializationConfig(this, mixins, subtypeResolver); + } + + @Override + public AnnotationIntrospector getAnnotationIntrospector() + { + /* 29-Jul-2009, tatu: it's now possible to disable use of + * annotations; can be done using "no-op" introspector + */ + if (isEnabled(Feature.USE_ANNOTATIONS)) { + return super.getAnnotationIntrospector(); + } + return AnnotationIntrospector.nopInstance(); + } + + /** + * Accessor for getting bean description that only contains class + * annotations: useful if no getter/setter/creator information is needed. + *<p> + * Note: part of {@link MapperConfig} since 1.7 + */ + @SuppressWarnings("unchecked") + @Override + public <T extends BeanDescription> T introspectClassAnnotations(JavaType type) { + return (T) getClassIntrospector().forClassAnnotations(this, type, this); + } + + /** + * Accessor for getting bean description that only contains immediate class + * annotations: ones from the class, and its direct mix-in, if any, but + * not from super types. + *<p> + * Note: part of {@link MapperConfig} since 1.7 + */ + @SuppressWarnings("unchecked") + @Override + public <T extends BeanDescription> T introspectDirectClassAnnotations(JavaType type) { + return (T) getClassIntrospector().forDirectClassAnnotations(this, type, this); + } + + @Override + public boolean isAnnotationProcessingEnabled() { + return isEnabled(SerializationConfig.Feature.USE_ANNOTATIONS); + } + + @Override + public boolean canOverrideAccessModifiers() { + return isEnabled(Feature.CAN_OVERRIDE_ACCESS_MODIFIERS); + } + + @Override + public boolean shouldSortPropertiesAlphabetically() { + return isEnabled(Feature.SORT_PROPERTIES_ALPHABETICALLY); + } + + @Override + public VisibilityChecker<?> getDefaultVisibilityChecker() + { + VisibilityChecker<?> vchecker = super.getDefaultVisibilityChecker(); + if (!isEnabled(SerializationConfig.Feature.AUTO_DETECT_GETTERS)) { + vchecker = vchecker.withGetterVisibility(Visibility.NONE); + } + // then global overrides (disabling) + if (!isEnabled(SerializationConfig.Feature.AUTO_DETECT_IS_GETTERS)) { + vchecker = vchecker.withIsGetterVisibility(Visibility.NONE); + } + if (!isEnabled(SerializationConfig.Feature.AUTO_DETECT_FIELDS)) { + vchecker = vchecker.withFieldVisibility(Visibility.NONE); + } + return vchecker; + } + + /* + /********************************************************** + /* MapperConfig overrides for 1.8 backwards compatibility + /********************************************************** + */ + + /* NOTE: these are overloads we MUST have, but that were missing + * from 1.9.0 and 1.9.1. Type erasure can bite in the ass... + *<p> + * NOTE: will remove either these variants, or base class one, in 2.0. + */ + + /** + * Alias for {@link MapperConfig#isEnabled(org.codehaus.jackson.map.MapperConfig.ConfigFeature)}. + * + * @since 1.0 However, note that version 1.9.0 and 1.9.1 accidentally missed + * this overloaded variant + */ + public boolean isEnabled(SerializationConfig.Feature f) { + return (_featureFlags & f.getMask()) != 0; + } + + /** + * @deprecated Since 1.9, it is preferable to use {@link #with} instead; + * this method is deprecated as it modifies current instance instead of + * creating a new one (as the goal is to make this class immutable) + */ + @Deprecated + @Override + public void enable(SerializationConfig.Feature f) { + super.enable(f); + } + + /** + * @deprecated Since 1.9, it is preferable to use {@link #without} instead; + * this method is deprecated as it modifies current instance instead of + * creating a new one (as the goal is to make this class immutable) + */ + @Deprecated + @Override + public void disable(SerializationConfig.Feature f) { + super.disable(f); + } + + /** + * @deprecated Since 1.9, it is preferable to use {@link #without} and {@link #with} instead; + * this method is deprecated as it modifies current instance instead of + * creating a new one (as the goal is to make this class immutable) + */ + @Deprecated + @Override + public void set(SerializationConfig.Feature f, boolean state) { + super.set(f, state); + } + + /* + /********************************************************** + /* Configuration: other + /********************************************************** + */ + + /** + * Method for checking which serialization view is being used, + * if any; null if none. + * + * @since 1.4 + */ + public Class<?> getSerializationView() { return _serializationView; } + + public JsonSerialize.Inclusion getSerializationInclusion() + { + if (_serializationInclusion != null) { + return _serializationInclusion; + } + return isEnabled(Feature.WRITE_NULL_PROPERTIES) ? + JsonSerialize.Inclusion.ALWAYS : JsonSerialize.Inclusion.NON_NULL; + } + + /** + * Method that will define global setting of which + * bean/map properties are to be included in serialization. + * Can be overridden by class annotations (overriding + * settings to use for instances of that class) and + * method/field annotations (overriding settings for the value + * bean for that getter method or field) + * + * @deprecated since 1.9 should either use {@link #withSerializationInclusion} + * to construct new instance, or configure through {@link ObjectMapper} + */ + @Deprecated + public void setSerializationInclusion(JsonSerialize.Inclusion props) + { + _serializationInclusion = props; + // And for some level of backwards compatibility, also... + if (props == JsonSerialize.Inclusion.NON_NULL) { + disable(Feature.WRITE_NULL_PROPERTIES); + } else { + enable(Feature.WRITE_NULL_PROPERTIES); + } + } + + /** + * Method for getting provider used for locating filters given + * id (which is usually provided with filter annotations). + * Will be null if no provided was set for {@link ObjectWriter} + * (or if serialization directly called from {@link ObjectMapper}) + * + * @since 1.7 + */ + public FilterProvider getFilterProvider() { + return _filterProvider; + } + + /* + /********************************************************** + /* Introspection methods + /********************************************************** + */ + + /** + * Method that will introspect full bean properties for the purpose + * of building a bean serializer + */ + @SuppressWarnings("unchecked") + public <T extends BeanDescription> T introspect(JavaType type) { + return (T) getClassIntrospector().forSerialization(this, type, this); + } + + /* + /********************************************************** + /* Extended API: serializer instantiation + /********************************************************** + */ + + @SuppressWarnings("unchecked") + public JsonSerializer<Object> serializerInstance(Annotated annotated, Class<? extends JsonSerializer<?>> serClass) + { + HandlerInstantiator hi = getHandlerInstantiator(); + if (hi != null) { + JsonSerializer<?> ser = hi.serializerInstance(this, annotated, serClass); + if (ser != null) { + return (JsonSerializer<Object>) ser; + } + } + return (JsonSerializer<Object>) ClassUtil.createInstance(serClass, canOverrideAccessModifiers()); + } + + /* + /********************************************************** + /* Deprecated methods + /********************************************************** + */ + + /** + * One thing to note is that this will set {@link Feature#WRITE_DATES_AS_TIMESTAMPS} + * to false (if null format set), or true (if non-null format) + * + * @deprecated Since 1.8, use {@link #withDateFormat} instead. + */ + @SuppressWarnings("deprecation") + @Override + @Deprecated + public final void setDateFormat(DateFormat df) { + super.setDateFormat(df); + set(Feature.WRITE_DATES_AS_TIMESTAMPS, (df == null)); + } + + /** + * Method for checking which serialization view is being used, + * if any; null if none. + * + * @since 1.4 + * + * @deprecated Since 1.8, use {@link #withView} instead + */ + @Deprecated + public void setSerializationView(Class<?> view) + { + _serializationView = view; + } + + /* + /********************************************************** + /* Debug support + /********************************************************** + */ + + @Override public String toString() + { + return "[SerializationConfig: flags=0x"+Integer.toHexString(_featureFlags)+"]"; + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/SerializerFactory.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/SerializerFactory.java new file mode 100644 index 0000000..73321ec --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/SerializerFactory.java
@@ -0,0 +1,198 @@ +package org.codehaus.jackson.map; + +import org.codehaus.jackson.map.ser.BeanSerializerModifier; +import org.codehaus.jackson.type.JavaType; + +/** + * Abstract class that defines API used by {@link SerializerProvider} + * to obtain actual + * {@link JsonSerializer} instances from multiple distinct factories. + */ +public abstract class SerializerFactory +{ + + /* + /********************************************************** + /* Helper class to contain configuration settings + /********************************************************** + */ + + /** + * Configuration settings container class for bean serializer factory. + * + * @since 1.7 + */ + public abstract static class Config + { + /** + * Method for creating a new instance with additional serializer provider. + */ + public abstract Config withAdditionalSerializers(Serializers additional); + + /** + * @since 1.8 + */ + public abstract Config withAdditionalKeySerializers(Serializers additional); + + /** + * Method for creating a new instance with additional bean serializer modifier. + */ + public abstract Config withSerializerModifier(BeanSerializerModifier modifier); + + public abstract boolean hasSerializers(); + + public abstract boolean hasKeySerializers(); + + public abstract boolean hasSerializerModifiers(); + + public abstract Iterable<Serializers> serializers(); + + public abstract Iterable<Serializers> keySerializers(); + + public abstract Iterable<BeanSerializerModifier> serializerModifiers(); + } + + /* + /********************************************************** + /* Additional configuration + /********************************************************** + */ + + /** + * @since 1.7 + */ + public abstract Config getConfig(); + + /** + * Method used for creating a new instance of this factory, but with different + * configuration. Reason for specifying factory method (instead of plain constructor) + * is to allow proper sub-classing of factories. + *<p> + * Note that custom sub-classes generally <b>must override</b> implementation + * of this method, as it usually requires instantiating a new instance of + * factory type. Check out javadocs for + * {@link org.codehaus.jackson.map.ser.BeanSerializerFactory} for more details. + * + * @since 1.7 + */ + public abstract SerializerFactory withConfig(Config config); + + /** + * Convenience method for creating a new factory instance with additional serializer + * provider; equivalent to calling + *<pre> + * withConfig(getConfig().withAdditionalSerializers(additional)); + *<pre> + * + * @since 1.7 + */ + public final SerializerFactory withAdditionalSerializers(Serializers additional) { + return withConfig(getConfig().withAdditionalSerializers(additional)); + } + + /** + * @since 1.8 + */ + public final SerializerFactory withAdditionalKeySerializers(Serializers additional) { + return withConfig(getConfig().withAdditionalKeySerializers(additional)); + } + + /** + * Convenience method for creating a new factory instance with additional bean + * serializer modifier; equivalent to calling + *<pre> + * withConfig(getConfig().withSerializerModifier(modifier)); + *<pre> + * + * @since 1.7 + */ + public final SerializerFactory withSerializerModifier(BeanSerializerModifier modifier) { + return withConfig(getConfig().withSerializerModifier(modifier)); + } + + /* + /********************************************************** + /* Basic SerializerFactory API: + /********************************************************** + */ + + /** + * Method called to create (or, for immutable serializers, reuse) a serializer for given type. + */ + public abstract JsonSerializer<Object> createSerializer(SerializationConfig config, JavaType baseType, + BeanProperty property) + throws JsonMappingException; + + /** + * Method called to create a type information serializer for given base type, + * if one is needed. If not needed (no polymorphic handling configured), should + * return null. + * + * @param baseType Declared type to use as the base type for type information serializer + * + * @return Type serializer to use for the base type, if one is needed; null if not. + * + * @since 1.7 + */ + public abstract TypeSerializer createTypeSerializer(SerializationConfig config, JavaType baseType, + BeanProperty property) + throws JsonMappingException; + + /** + * Method called to create serializer to use for serializing JSON property names (which must + * be output as <code>JsonToken.FIELD_NAME</code>) for Map that has specified declared + * key type, and is for specified property (or, if property is null, as root value) + * + * @param config Serialization configuration in use + * @param baseType Declared type for Map keys + * @param property Property that contains Map being serialized; null when serializing root Map value. + * + * @return Serializer to use, if factory knows it; null if not (in which case default serializer + * is to be used) + * + * @since 1.8 + */ + public abstract JsonSerializer<Object> createKeySerializer(SerializationConfig config, JavaType baseType, + BeanProperty property) + throws JsonMappingException; + + /* + /********************************************************** + /* Deprecated (as of 1.7) SerializerFactory API: + /********************************************************** + */ + + /** + * Deprecated version of accessor for type id serializer: as of 1.7 one needs + * to instead call version that passes property information through. + * + * @since 1.5 + * + * @deprecated Since 1.7, call variant with more arguments + */ + @Deprecated + public final JsonSerializer<Object> createSerializer(JavaType type, SerializationConfig config) { + try { + return createSerializer(config, type, null); + } catch (JsonMappingException e) { // not optimal but: + throw new RuntimeJsonMappingException(e); + } + } + + /** + * Deprecated version of accessor for type id serializer: as of 1.7 one needs + * to instead call version that passes property information through. + * + * @since 1.5 + * + * @deprecated Since 1.7, call variant with more arguments + */ + @Deprecated + public final TypeSerializer createTypeSerializer(JavaType baseType, SerializationConfig config) { + try { + return createTypeSerializer(config, baseType, null); + } catch (JsonMappingException e) { // not optimal but: + throw new RuntimeException(e); + } + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/SerializerProvider.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/SerializerProvider.java new file mode 100644 index 0000000..4571213 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/SerializerProvider.java
@@ -0,0 +1,550 @@ +package org.codehaus.jackson.map; + +import java.io.IOException; +import java.lang.reflect.Type; +import java.util.Date; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.ser.FilterProvider; +import org.codehaus.jackson.map.type.TypeFactory; +import org.codehaus.jackson.schema.JsonSchema; +import org.codehaus.jackson.type.JavaType; + +/** + * Abstract class that defines API used by {@link ObjectMapper} and + * {@link JsonSerializer}s to obtain serializers capable of serializing + * instances of specific types. + *<p> + * Note about usage: for {@link JsonSerializer} instances, only accessors + * for locating other (sub-)serializers are to be used. {@link ObjectMapper}, + * on the other hand, is to initialize recursive serialization process by + * calling {@link #serializeValue}. + */ +public abstract class SerializerProvider +{ + protected final static JavaType TYPE_OBJECT = TypeFactory.defaultInstance().uncheckedSimpleType(Object.class); + + /** + * Serialization configuration to use for serialization processing. + */ + protected final SerializationConfig _config; + + /** + * View used for currently active serialization + */ + protected final Class<?> _serializationView; + + protected SerializerProvider(SerializationConfig config) + { + _config = config; + _serializationView = (config == null) ? null : _config.getSerializationView(); + } + + /* + /********************************************************** + /* Methods for configuring default settings + /********************************************************** + */ + + /** + * Method that can be used to specify serializer that will be + * used to write JSON property names matching null keys for Java + * Maps (which will throw an exception if try write such property + * name) + * + * @since 1.8 + */ + public abstract void setNullKeySerializer(JsonSerializer<Object> nks); + + /** + * Method that can be used to specify serializer that will be + * used to write JSON values matching Java null values + * instead of default one (which simply writes JSON null) + * + * @since 1.8 + */ + public abstract void setNullValueSerializer(JsonSerializer<Object> nvs); + + /** + * Method that can be used to specify serializer to use for serializing + * all non-null JSON property names, unless more specific key serializer + * is found (i.e. if not custom key serializer has been registered for + * Java type). + *<p> + * Note that key serializer registration are different from value serializer + * registrations. + * + * @since 1.8 + */ + public abstract void setDefaultKeySerializer(JsonSerializer<Object> ks); + + /* + /********************************************************** + /* Methods that ObjectMapper will call + /********************************************************** + */ + + /** + * The method to be called by {@link ObjectMapper} to + * execute recursive serialization, using serializers that + * this provider has access to. + * + * @param jsf Underlying factory object used for creating serializers + * as needed + */ + public abstract void serializeValue(SerializationConfig cfg, JsonGenerator jgen, + Object value, SerializerFactory jsf) + throws IOException, JsonGenerationException; + + /** + * The method to be called by {@link ObjectMapper} to + * execute recursive serialization, using serializers that + * this provider has access to; and using specified root type + * for locating first-level serializer. + * + * @param rootType Type to use for locating serializer to use, instead of actual + * runtime type. Must be actual type, or one of its super types + * + * @since 1.5 + */ + public abstract void serializeValue(SerializationConfig cfg, JsonGenerator jgen, + Object value, JavaType rootType, SerializerFactory jsf) + throws IOException, JsonGenerationException; + + /** + * Generate <a href="http://json-schema.org/">Json-schema</a> for + * given type. + * + * @param type The type for which to generate schema + */ + public abstract JsonSchema generateJsonSchema(Class<?> type, SerializationConfig config, SerializerFactory jsf) + throws JsonMappingException; + + /** + * Method that can be called to see if this serializer provider + * can find a serializer for an instance of given class. + *<p> + * Note that no Exceptions are thrown, including unchecked ones: + * implementations are to swallow exceptions if necessary. + */ + public abstract boolean hasSerializerFor(SerializationConfig cfg, + Class<?> cls, SerializerFactory jsf); + + /* + /********************************************************** + /* Access to configuration + /********************************************************** + */ + + /** + * Method for accessing configuration for the serialization processing. + */ + public final SerializationConfig getConfig() { return _config; } + + /** + * Convenience method for checking whether specified serialization + * feature is enabled or not. + * Shortcut for: + *<pre> + * getConfig().isEnabled(feature); + *</pre> + */ + public final boolean isEnabled(SerializationConfig.Feature feature) { + return _config.isEnabled(feature); + } + + /** + * Convenience method for accessing serialization view in use (if any); equivalent to: + *<pre> + * getConfig().getSerializationView(); + *</pre> + * + * @since 1.4 + */ + public final Class<?> getSerializationView() { return _serializationView; } + + /** + * Convenience method for accessing provider to find serialization filters used, + * equivalent to calling: + *<pre> + * getConfig().getFilterProvider(); + *</pre> + * + * @since 1.4 + */ + public final FilterProvider getFilterProvider() { + return _config.getFilterProvider(); + } + + /** + * @since 1.8 + */ + public JavaType constructType(Type type) { + return _config.getTypeFactory().constructType(type); + } + + /** + * @since 1.9.1 + */ + public JavaType constructSpecializedType(JavaType baseType, Class<?> subclass) { + return _config.constructSpecializedType(baseType, subclass); + } + + /* + /********************************************************** + /* General serializer locating functionality + /********************************************************** + */ + + /** + * Method called to get hold of a serializer for a value of given type; + * or if no such serializer can be found, a default handler (which + * may do a best-effort generic serialization or just simply + * throw an exception when invoked). + *<p> + * Note: this method is only called for non-null values; not for keys + * or null values. For these, check out other accessor methods. + *<p> + * Note that starting with version 1.5, serializers should also be type-aware + * if they handle polymorphic types. That means that it may be necessary + * to also use a {@link TypeSerializer} based on declared (static) type + * being serializer (whereas actual data may be serialized using dynamic + * type) + * + * @throws JsonMappingException if there are fatal problems with + * accessing suitable serializer; including that of not + * finding any serializer + */ + public abstract JsonSerializer<Object> findValueSerializer(Class<?> runtimeType, + BeanProperty property) + throws JsonMappingException; + + /** + * Similar to {@link #findValueSerializer(Class)}, but takes full generics-aware + * type instead of raw class. + * + * @since 1.5 + */ + public abstract JsonSerializer<Object> findValueSerializer(JavaType serializationType, + BeanProperty property) + throws JsonMappingException; + + /** + * Method called to locate regular serializer, matching type serializer, + * and if both found, wrap them in a serializer that calls both in correct + * sequence. This method is currently only used for root-level serializer + * handling to allow for simpler caching. A call can always be replaced + * by equivalent calls to access serializer and type serializer separately. + * + * @param valueType Type for purpose of locating a serializer; usually dynamic + * runtime type, but can also be static declared type, depending on configuration + * + * @param cache Whether resulting value serializer should be cached or not; this is just + * a hint + * + * @since 1.5 + */ + public abstract JsonSerializer<Object> findTypedValueSerializer(Class<?> valueType, + boolean cache, BeanProperty property) + throws JsonMappingException; + + /** + * Method called to locate regular serializer, matching type serializer, + * and if both found, wrap them in a serializer that calls both in correct + * sequence. This method is currently only used for root-level serializer + * handling to allow for simpler caching. A call can always be replaced + * by equivalent calls to access serializer and type serializer separately. + * + * @param valueType Declared type of value being serialized (which may not + * be actual runtime type); used for finding both value serializer and + * type serializer to use for adding polymorphic type (if any) + * + * @param cache Whether resulting value serializer should be cached or not; this is just + * a hint + * + * @since 1.5 + */ + public abstract JsonSerializer<Object> findTypedValueSerializer(JavaType valueType, + boolean cache, BeanProperty property) + throws JsonMappingException; + + /** + * Method called to get the serializer to use for serializing + * non-null Map keys. Separation from regular + * {@link #findValueSerializer} method is because actual write + * method must be different (@link JsonGenerator#writeFieldName}; + * but also since behavior for some key types may differ. + *<p> + * Note that the serializer itself can be called with instances + * of any Java object, but not nulls. + * + * @since 1.8 + */ + public abstract JsonSerializer<Object> findKeySerializer(JavaType keyType, + BeanProperty property) + throws JsonMappingException; + + /* + /********************************************************** + /* Deprecated serializer locating functionality + /********************************************************** + */ + + /** + * Deprecated version of accessor method that was used before version 1.7. + * Implemented as final to ensure that existing code does not accidentally + * try to redefine it (given that it is not called by core mapper code) + * + * @deprecated As of version 1.7, use version that exposes property object + * instead of just its type (needed for contextual serializers) + */ + @Deprecated + public final JsonSerializer<Object> findValueSerializer(Class<?> runtimeType) + throws JsonMappingException + { + return findValueSerializer(runtimeType, null); + } + + /** + * Deprecated version of accessor method that was used before version 1.7. + * Implemented as final to ensure that existing code does not accidentally + * try to redefine it (given that it is not called by core mapper code) + * + * @deprecated As of version 1.7, use version that exposes property object + * instead of just its type (needed for contextual serializers) + */ + @Deprecated + public final JsonSerializer<Object> findValueSerializer(JavaType serializationType) + throws JsonMappingException + { + return findValueSerializer(serializationType, null); + } + + /** + * Deprecated version of accessor method that was used before version 1.7. + * Implemented as final to ensure that existing code does not accidentally + * try to redefine it (given that it is not called by core mapper code) + * + * @deprecated As of version 1.7, use version that exposes property object + * instead of just its type (needed for contextual serializers) + */ + @Deprecated + public final JsonSerializer<Object> findTypedValueSerializer(Class<?> valueType, + boolean cache) + throws JsonMappingException + { + return findTypedValueSerializer(valueType, cache, null); + } + + /** + * Deprecated version of accessor method that was used before version 1.7. + * Implemented as final to ensure that existing code does not accidentally + * try to redefine it (given that it is not called by core mapper code) + * + * @deprecated As of version 1.7, use version that exposes property object + * instead of just its type (needed for contextual serializers) + */ + @Deprecated + public final JsonSerializer<Object> findTypedValueSerializer(JavaType valueType, + boolean cache) + throws JsonMappingException + { + return findTypedValueSerializer(valueType, cache, null); + } + + /** + * Deprecated version of accessor method that was used before version 1.7. + * Implemented as final to ensure that existing code does not accidentally + * try to redefine it (given that it is not called by core mapper code) + * + * @deprecated As of version 1.7, use version that exposes property object + * instead of just its type (needed for contextual serializers) + */ + @Deprecated + public final JsonSerializer<Object> getKeySerializer() + throws JsonMappingException + { + return findKeySerializer(TYPE_OBJECT, null); + } + + /** + * Deprecated version of accessor method that was used before version 1.8; + * renamed as {@link #findKeySerializer}, since process is now + * more complicated than simple lookup. + * + * @deprecated As of version 1.8 + */ + @Deprecated + public final JsonSerializer<Object> getKeySerializer(JavaType valueType, BeanProperty property) + throws JsonMappingException + { + return findKeySerializer(valueType, property); + } + + /* + /******************************************************** + /* Accessors for specialized serializers + /******************************************************** + */ + + /** + * Method called to get the serializer to use for serializing + * Map keys that are nulls: this is needed since JSON does not allow + * any non-String value as key, including null. + *<p> + * Typically, returned serializer + * will either throw an exception, or use an empty String; but + * other behaviors are possible. + */ + public abstract JsonSerializer<Object> getNullKeySerializer(); + + /** + * Method called to get the serializer to use for serializing + * values (root level, Array members or List field values) + * that are nulls. Specific accessor is needed because nulls + * in Java do not contain type information. + *<p> + * Typically returned serializer just writes out Json literal + * null value. + */ + public abstract JsonSerializer<Object> getNullValueSerializer(); + + /** + * Method called to get the serializer to use if provider + * can not determine an actual type-specific serializer + * to use; typically when none of {@link SerializerFactory} + * instances are able to construct a serializer. + *<p> + * Typically, returned serializer will throw an exception, + * although alternatively {@link org.codehaus.jackson.map.ser.ToStringSerializer} could + * be returned as well. + * + * @param unknownType Type for which no serializer is found + */ + public abstract JsonSerializer<Object> getUnknownTypeSerializer(Class<?> unknownType); + + /* + /******************************************************** + /* Convenience methods + /******************************************************** + */ + + /** + * Convenience method that will serialize given value (which can be + * null) using standard serializer locating functionality. It can + * be called for all values including field and Map values, but usually + * field values are best handled calling + * {@link #defaultSerializeField} instead. + */ + public final void defaultSerializeValue(Object value, JsonGenerator jgen) + throws IOException, JsonProcessingException + { + if (value == null) { + getNullValueSerializer().serialize(null, jgen, this); + } else { + Class<?> cls = value.getClass(); + findTypedValueSerializer(cls, true, null).serialize(value, jgen, this); + } + } + + /** + * Convenience method that will serialize given field with specified + * value. Value may be null. Serializer is done using the usual + * null) using standard serializer locating functionality. + */ + public final void defaultSerializeField(String fieldName, Object value, JsonGenerator jgen) + throws IOException, JsonProcessingException + { + jgen.writeFieldName(fieldName); + if (value == null) { + /* Note: can't easily check for suppression at this point + * any more; caller must check it. + */ + getNullValueSerializer().serialize(null, jgen, this); + } else { + Class<?> cls = value.getClass(); + findTypedValueSerializer(cls, true, null).serialize(value, jgen, this); + } + } + + /** + * Method that will handle serialization of Date(-like) values, using + * {@link SerializationConfig} settings to determine expected serialization + * behavior. + * Note: date here means "full" date, that is, date AND time, as per + * Java convention (and not date-only values like in SQL) + */ + public abstract void defaultSerializeDateValue(long timestamp, JsonGenerator jgen) + throws IOException, JsonProcessingException; + + /** + * Method that will handle serialization of Date(-like) values, using + * {@link SerializationConfig} settings to determine expected serialization + * behavior. + * Note: date here means "full" date, that is, date AND time, as per + * Java convention (and not date-only values like in SQL) + */ + public abstract void defaultSerializeDateValue(Date date, JsonGenerator jgen) + throws IOException, JsonProcessingException; + + + /** + * Method that will handle serialization of Dates used as {@link java.util.Map} keys, + * based on {@link SerializationConfig.Feature#WRITE_DATE_KEYS_AS_TIMESTAMPS} + * value (and if using textual representation, configured date format) + * + * @since 1.9 + */ + public abstract void defaultSerializeDateKey(long timestamp, JsonGenerator jgen) + throws IOException, JsonProcessingException; + + /** + * Method that will handle serialization of Dates used as {@link java.util.Map} keys, + * based on {@link SerializationConfig.Feature#WRITE_DATE_KEYS_AS_TIMESTAMPS} + * value (and if using textual representation, configured date format) + * + * @since 1.9 + */ + public abstract void defaultSerializeDateKey(Date date, JsonGenerator jgen) + throws IOException, JsonProcessingException; + + /** + * @since 1.7 + */ + public final void defaultSerializeNull(JsonGenerator jgen) + throws IOException, JsonProcessingException + { + getNullValueSerializer().serialize(null, jgen, this); + } + + /* + /******************************************************** + /* Access to caching details + /******************************************************** + */ + + /** + * Method that can be used to determine how many serializers this + * provider is caching currently + * (if it does caching: default implementation does) + * Exact count depends on what kind of serializers get cached; + * default implementation caches all serializers, including ones that + * are eagerly constructed (for optimal access speed) + *<p> + * The main use case for this method is to allow conditional flushing of + * serializer cache, if certain number of entries is reached. + * + * @since 1.4 + */ + public abstract int cachedSerializersCount(); + + /** + * Method that will drop all serializers currently cached by this provider. + * This can be used to remove memory usage (in case some serializers are + * only used once or so), or to force re-construction of serializers after + * configuration changes for mapper than owns the provider. + * + * @since 1.4 + */ + public abstract void flushCachedSerializers(); +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/Serializers.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/Serializers.java new file mode 100644 index 0000000..699cc68 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/Serializers.java
@@ -0,0 +1,133 @@ +package org.codehaus.jackson.map; + +import org.codehaus.jackson.type.JavaType; +import org.codehaus.jackson.map.type.*; + +/** + * Interface that defines API for simple extensions that can provide additional serializers + * for various types. Access is by a single callback method; instance is to either return + * a configured {@link JsonSerializer} for specified type, or null to indicate that it + * does not support handling of the type. In latter case, further calls can be made + * for other providers; in former case returned serializer is used for handling of + * instances of specified type. + * + * @since 1.7 + */ +public interface Serializers +{ + /** + * Method called by serialization framework first time a serializer is needed for + * specified type, which is not of a container type (for which other methods are + * called). + *<p> + * Note: in version 1.7, this method was called to find serializers for all + * type, including container types. + * + * @param type Fully resolved type of instances to serialize + * @param config Serialization configuration in use + * @param beanDesc Additional information about type; will always be of type + * {@link org.codehaus.jackson.map.introspect.BasicBeanDescription} (that is, + * safe to cast to this more specific type) + * @param property Property that contains values to serialize + * + * @return Configured serializer to use for the type; or null if implementation + * does not recognize or support type + */ + public JsonSerializer<?> findSerializer(SerializationConfig config, + JavaType type, BeanDescription beanDesc, BeanProperty property); + + /** + * Method called by serialization framework first time a serializer is needed for + * specified array type. + * Implementation should return a serializer instance if it supports + * specified type; or null if it does not. + * + * @since 1.8 + */ + public JsonSerializer<?> findArraySerializer(SerializationConfig config, + ArrayType type, BeanDescription beanDesc, BeanProperty property, + TypeSerializer elementTypeSerializer, JsonSerializer<Object> elementValueSerializer); + + public JsonSerializer<?> findCollectionSerializer(SerializationConfig config, + CollectionType type, BeanDescription beanDesc, BeanProperty property, + TypeSerializer elementTypeSerializer, JsonSerializer<Object> elementValueSerializer); + + public JsonSerializer<?> findCollectionLikeSerializer(SerializationConfig config, + CollectionLikeType type, BeanDescription beanDesc, BeanProperty property, + TypeSerializer elementTypeSerializer, JsonSerializer<Object> elementValueSerializer); + + public JsonSerializer<?> findMapSerializer(SerializationConfig config, + MapType type, BeanDescription beanDesc, BeanProperty property, + JsonSerializer<Object> keySerializer, + TypeSerializer elementTypeSerializer, JsonSerializer<Object> elementValueSerializer); + + public JsonSerializer<?> findMapLikeSerializer(SerializationConfig config, + MapLikeType type, BeanDescription beanDesc, BeanProperty property, + JsonSerializer<Object> keySerializer, + TypeSerializer elementTypeSerializer, JsonSerializer<Object> elementValueSerializer); + + /** + * Basic {@link Serializers} implementation that implements all methods but provides + * no serializers. Its main purpose is to serve as a base class so that + * sub-classes only need to override methods they need. + * + * @since 1.9 + */ + public static class Base implements Serializers + { + @Override + public JsonSerializer<?> findSerializer(SerializationConfig config, + JavaType type, BeanDescription beanDesc, BeanProperty property) + { + return null; + } + + @Override + public JsonSerializer<?> findArraySerializer(SerializationConfig config, + ArrayType type, BeanDescription beanDesc, BeanProperty property, + TypeSerializer elementTypeSerializer, JsonSerializer<Object> elementValueSerializer) + { + return null; + } + + @Override + public JsonSerializer<?> findCollectionSerializer(SerializationConfig config, + CollectionType type, BeanDescription beanDesc, BeanProperty property, + TypeSerializer elementTypeSerializer, JsonSerializer<Object> elementValueSerializer) + { + return null; + } + + @Override + public JsonSerializer<?> findCollectionLikeSerializer(SerializationConfig config, + CollectionLikeType type, BeanDescription beanDesc, BeanProperty property, + TypeSerializer elementTypeSerializer, JsonSerializer<Object> elementValueSerializer) + { + return null; + } + + @Override + public JsonSerializer<?> findMapSerializer(SerializationConfig config, + MapType type, BeanDescription beanDesc, BeanProperty property, + JsonSerializer<Object> keySerializer, + TypeSerializer elementTypeSerializer, JsonSerializer<Object> elementValueSerializer) + { + return null; + } + + @Override + public JsonSerializer<?> findMapLikeSerializer(SerializationConfig config, + MapLikeType type, BeanDescription beanDesc, BeanProperty property, + JsonSerializer<Object> keySerializer, + TypeSerializer elementTypeSerializer, JsonSerializer<Object> elementValueSerializer) + { + return null; + } + } + + /** + * @deprecated As of 1.9, use {@link Base} instead + */ + @Deprecated + public static class None extends Base { } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/TypeDeserializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/TypeDeserializer.java new file mode 100644 index 0000000..6a14763 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/TypeDeserializer.java
@@ -0,0 +1,117 @@ +package org.codehaus.jackson.map; + +import java.io.IOException; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.annotate.JsonTypeInfo.As; +import org.codehaus.jackson.map.jsontype.TypeIdResolver; + +/** + * Interface for deserializing type information from JSON content, to + * type-safely deserialize data into correct polymorphic instance + * (when type inclusion has been enabled for type handled). + *<p> + * Separate deserialization methods are needed because serialized + * form for inclusion mechanism {@link As#PROPERTY} + * is slighty different if value is not expressed as JSON Object: + * and as such both type deserializer and serializer need to + * JSON Object form (array, object or other (== scalar)) being + * used. + * + * @since 1.5 + * @author tatus + */ +public abstract class TypeDeserializer +{ + /* + /********************************************************** + /* Introspection + /********************************************************** + */ + + /** + * Accessor for type information inclusion method + * that deserializer uses; indicates how type information + * is (expected to be) embedded in JSON input. + */ + public abstract As getTypeInclusion(); + + /** + * Name of property that contains type information, if + * property-based inclusion is used. + */ + public abstract String getPropertyName(); + + /** + * Accessor for object that handles conversions between + * types and matching type ids. + */ + public abstract TypeIdResolver getTypeIdResolver(); + + /** + * Accessor for "default implementation" type; optionally defined + * class to use in cases where type id is not + * accessible for some reason (either missing, or can not be + * resolved) + * + * @since 1.9 + */ + public abstract Class<?> getDefaultImpl(); + + /* + /********************************************************* + /* Type deserialization methods + /********************************************************** + */ + + /** + * Method called to let this type deserializer handle + * deserialization of "typed" object, when value itself + * is serialized as JSON Object (regardless of Java type). + * Method needs to figure out intended + * polymorphic type, locate {@link JsonDeserializer} to use, and + * call it with JSON data to deserializer (which does not contain + * type information). + */ + public abstract Object deserializeTypedFromObject(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException; + + /** + * Method called to let this type deserializer handle + * deserialization of "typed" object, when value itself + * is serialized as JSON Array (regardless of Java type). + * Method needs to figure out intended + * polymorphic type, locate {@link JsonDeserializer} to use, and + * call it with JSON data to deserializer (which does not contain + * type information). + */ + public abstract Object deserializeTypedFromArray(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException; + + /** + * Method called to let this type deserializer handle + * deserialization of "typed" object, when value itself + * is serialized as a scalar JSON value (something other + * than Array or Object), regardless of Java type. + * Method needs to figure out intended + * polymorphic type, locate {@link JsonDeserializer} to use, and + * call it with JSON data to deserializer (which does not contain + * type information). + */ + public abstract Object deserializeTypedFromScalar(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException; + + /** + * Method called to let this type deserializer handle + * deserialization of "typed" object, when value itself + * may have been serialized using any kind of JSON value + * (Array, Object, scalar). Should only be called if JSON + * serialization is polymorphic (not Java type); for example when + * using JSON node representation, or "untyped" Java object + * (which may be Map, Collection, wrapper/primitive etc). + */ + public abstract Object deserializeTypedFromAny(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException; + +} + \ No newline at end of file
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/TypeSerializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/TypeSerializer.java new file mode 100644 index 0000000..2c7598c --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/TypeSerializer.java
@@ -0,0 +1,163 @@ +package org.codehaus.jackson.map; + +import java.io.IOException; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.annotate.JsonTypeInfo; +import org.codehaus.jackson.map.jsontype.TypeIdResolver; + +/** + * Interface for serializing type information regarding instances of specified + * base type (super class), so that exact subtype can be properly deserialized + * later on. These instances are to be called by regular + * {@link org.codehaus.jackson.map.JsonSerializer}s using proper contextual + * calls, to add type information using mechanism type serializer was + * configured with. + * + * @since 1.5 + * @author tatus + */ +public abstract class TypeSerializer +{ + /* + /********************************************************** + /* Introspection + /********************************************************** + */ + + /** + * Accessor for type information inclusion method + * that serializer uses; indicates how type information + * is embedded in resulting JSON. + */ + public abstract JsonTypeInfo.As getTypeInclusion(); + + /** + * Name of property that contains type information, if + * property-based inclusion is used. + */ + public abstract String getPropertyName(); + + /** + * Accessor for object that handles conversions between + * types and matching type ids. + */ + public abstract TypeIdResolver getTypeIdResolver(); + + /* + /********************************************************** + /* Type serialization methods + /********************************************************** + */ + + /** + * Method called to write initial part of type information for given + * value, when it will be output as scalar JSON value (not as JSON + * Object or Array). + * This means that the context after call can not be that of JSON Object; + * it may be Array or root context. + * + * @param value Value that will be serialized, for which type information is + * to be written + * @param jgen Generator to use for writing type information + */ + public abstract void writeTypePrefixForScalar(Object value, JsonGenerator jgen) + throws IOException, JsonProcessingException; + + /** + * Method called to write initial part of type information for given + * value, when it will be output as JSON Object value (not as JSON + * Array or scalar). + * This means that context after call must be JSON Object, meaning that + * caller can then proceed to output field entries. + * + * @param value Value that will be serialized, for which type information is + * to be written + * @param jgen Generator to use for writing type information + */ + public abstract void writeTypePrefixForObject(Object value, JsonGenerator jgen) + throws IOException, JsonProcessingException; + + /** + * Method called to write initial part of type information for given + * value, when it will be output as JSON Array value (not as JSON + * Object or scalar). + * This means that context after call must be JSON Array, that is, there + * must be an open START_ARRAY to write contents in. + * + * @param value Value that will be serialized, for which type information is + * to be written + * @param jgen Generator to use for writing type information + */ + public abstract void writeTypePrefixForArray(Object value, JsonGenerator jgen) + throws IOException, JsonProcessingException; + + /** + * Method called after value has been serialized, to close any scopes opened + * by earlier matching call to {@link #writeTypePrefixForScalar}. + * Actual action to take may depend on various factors, but has to match with + * action {@link #writeTypePrefixForScalar} did (close array or object; or do nothing). + */ + public abstract void writeTypeSuffixForScalar(Object value, JsonGenerator jgen) + throws IOException, JsonProcessingException; + + /** + * Method called after value has been serialized, to close any scopes opened + * by earlier matching call to {@link #writeTypePrefixForObject}. + * It needs to write closing END_OBJECT marker, and any other decoration + * that needs to be matched. + */ + public abstract void writeTypeSuffixForObject(Object value, JsonGenerator jgen) + throws IOException, JsonProcessingException; + + /** + * Method called after value has been serialized, to close any scopes opened + * by earlier matching call to {@link #writeTypeSuffixForScalar}. + * It needs to write closing END_ARRAY marker, and any other decoration + * that needs to be matched. + */ + public abstract void writeTypeSuffixForArray(Object value, JsonGenerator jgen) + throws IOException, JsonProcessingException; + + /** + * Alternative version of the prefix-for-scalar method, which is given + * actual type to use (instead of using exact type of the value); typically + * a super type of actual value type + * + * @since 1.8 + */ + public void writeTypePrefixForScalar(Object value, JsonGenerator jgen, + Class<?> type) + throws IOException, JsonProcessingException + { + writeTypePrefixForScalar(value, jgen); + } + + /** + * Alternative version of the prefix-for-object method, which is given + * actual type to use (instead of using exact type of the value); typically + * a super type of actual value type + * + * @since 1.8 + */ + public void writeTypePrefixForObject(Object value, JsonGenerator jgen, + Class<?> type) + throws IOException, JsonProcessingException + { + writeTypePrefixForObject(value, jgen); + } + + /** + * Alternative version of the prefix-for-array method, which is given + * actual type to use (instead of using exact type of the value); typically + * a super type of actual value type + * + * @since 1.8 + */ + public void writeTypePrefixForArray(Object value, JsonGenerator jgen, + Class<?> type) + throws IOException, JsonProcessingException + { + writeTypePrefixForArray(value, jgen); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/annotate/JacksonInject.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/annotate/JacksonInject.java new file mode 100644 index 0000000..861f398 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/annotate/JacksonInject.java
@@ -0,0 +1,30 @@ +package org.codehaus.jackson.map.annotate; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.codehaus.jackson.annotate.JacksonAnnotation; + +/** + * Jackson-specific annotation used for indicating that value of + * annotated property will be "injected", i.e. set based on value + * configured by <code>ObjectMapper</code> (usually on per-call basis). + * Usually property is not deserialized from JSON, although it possible + * to have injected value as default and still allow optional override + * from JSON. + * + * @since 1.9 + */ +@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +@JacksonAnnotation +public @interface JacksonInject +{ + /** + * Logical id of the value to inject; if not specified (or specified + * as empty String), will use id based on declared type of property. + */ + public String value() default ""; +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/annotate/JacksonStdImpl.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/annotate/JacksonStdImpl.java new file mode 100644 index 0000000..1c74178 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/annotate/JacksonStdImpl.java
@@ -0,0 +1,25 @@ +package org.codehaus.jackson.map.annotate; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.codehaus.jackson.annotate.JacksonAnnotation; + +/** + * Marker interface used to indicate implementation classes + * (serializers, deserializers etc) that are standard ones Jackson + * uses; not custom ones that application has added. It can be + * added in cases where certain optimizations can be made if + * default instances are uses; for example when handling conversions + * of "natural" JSON types like Strings, booleans and numbers. + * + * @since 1.6 + */ +@Target({ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@JacksonAnnotation +public @interface JacksonStdImpl { + +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/annotate/JsonCachable.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/annotate/JsonCachable.java new file mode 100644 index 0000000..63d3aff --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/annotate/JsonCachable.java
@@ -0,0 +1,32 @@ +package org.codehaus.jackson.map.annotate; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.codehaus.jackson.annotate.JacksonAnnotation; + +/** + * Marker annotation used to denote whether given instance + * (currently only used with {@link org.codehaus.jackson.map.JsonDeserializer}) + * can be cached. + *<p> + * Default action to take in absence of annotation depends + * on object using annotation; with deserializers default is + * to assume instances are not cachable. + * + * @since 1.1 + */ +@Target({ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@JacksonAnnotation +public @interface JsonCachable +{ + /** + * Default value is true, giving semantics for parameterless tag instance + * such that empty instance indicates that instances of annotated class + * are indeed cachable. + */ + boolean value() default true; +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/annotate/JsonDeserialize.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/annotate/JsonDeserialize.java new file mode 100644 index 0000000..df7b41d --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/annotate/JsonDeserialize.java
@@ -0,0 +1,109 @@ +package org.codehaus.jackson.map.annotate; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.codehaus.jackson.annotate.JacksonAnnotation; +import org.codehaus.jackson.map.JsonDeserializer; +import org.codehaus.jackson.map.KeyDeserializer; + +/** + * Annotation use for configuring deserialization aspects, by attaching + * to "setter" methods or fields, or to value classes. + * When annotating value classes, configuration is used for instances + * of the value class but can be overridden by more specific annotations + * (ones that attach to methods or fields). + *<p> + * An example annotation would be: + *<pre> + * @JsonDeserialize(using=MySerializer.class, + * as=MyHashMap.class, + * keyAs=MyHashKey.class, + * contentAs=MyHashValue.class + * ) + *</pre> + *<p> + * NOTE: since version 1.2, annotation has also been applicable + * to (constructor) parameters + * + * @since 1.1 + */ +@Target({ElementType.METHOD, ElementType.FIELD, ElementType.TYPE, ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +@JacksonAnnotation +public @interface JsonDeserialize +{ + // // // Annotations for explicitly specifying deserializer + + /** + * Deserializer class to use for deserializing associated value. + * Depending on what is annotated, + * value is either an instance of annotated class (used globablly + * anywhere where class deserializer is needed); or only used for + * deserializing property access via a setter method. + */ + public Class<? extends JsonDeserializer<?>> using() + default JsonDeserializer.None.class; + + /** + * Deserializer class to use for deserializing contents (elements + * of a Collection/array, values of Maps) of annotated property. + * Can only be used on instances (methods, fields, constructors), + * and not value classes themselves. + * + * @since 1.3 + */ + public Class<? extends JsonDeserializer<?>> contentUsing() + default JsonDeserializer.None.class; + + /** + * Deserializer class to use for deserializing Map keys + * of annotated property. + * Can only be used on instances (methods, fields, constructors), + * and not value classes themselves. + * + * @since 1.3 + */ + public Class<? extends KeyDeserializer> keyUsing() + default KeyDeserializer.None.class; + + // // // Annotations for explicitly specifying deserialization type + // // // (which is used for choosing deserializer, if not explicitly + // // // specified + + /** + * Concrete type to deserialize values as, instead of type otherwise + * declared. Must be a subtype of declared type; otherwise an + * exception may be thrown by deserializer. + *<p> + * Bogus type {@link NoClass} can be used to indicate that declared + * type is used as is (i.e. this annotation property has no setting); + * this since annotation properties are not allowed to have null value. + *<p> + * Note: if {@link #using} is also used it has precedence + * (since it directly specified + * deserializer, whereas this would only be used to locate the + * deserializer) + * and value of this annotation property is ignored. + */ + public Class<?> as() default NoClass.class; + + /** + * Concrete type to deserialize keys of {@link java.util.Map} as, + * instead of type otherwise declared. + * Must be a subtype of declared type; otherwise an exception may be + * thrown by deserializer. + */ + public Class<?> keyAs() default NoClass.class; + + /** + * Concrete type to deserialize content (elements + * of a Collection/array, values of Maps) values as, + * instead of type otherwise declared. + * Must be a subtype of declared type; otherwise an exception may be + * thrown by deserializer. + */ + public Class<?> contentAs() default NoClass.class; +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/annotate/JsonFilter.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/annotate/JsonFilter.java new file mode 100644 index 0000000..2df068e --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/annotate/JsonFilter.java
@@ -0,0 +1,31 @@ +package org.codehaus.jackson.map.annotate; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.codehaus.jackson.annotate.JacksonAnnotation; + +/** + * Annotation used to indicate which logical filter is to be used + * for filtering out properties of type (class) annotated; + * association made by this annotation declaring ids of filters, + * and {@link org.codehaus.jackson.map.ObjectMapper} (or objects + * it delegates to) providing matching filters by id. + * Filters to use are of type + * {@link org.codehaus.jackson.map.ser.BeanPropertyFilter} and + * are registered through {@link org.codehaus.jackson.map.ObjectMapper} + * + * @since 1.7 + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@JacksonAnnotation +public @interface JsonFilter +{ + /** + * Id of filter to use; if empty String (""), no filter is to be used. + */ + public String value(); +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/annotate/JsonRootName.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/annotate/JsonRootName.java new file mode 100644 index 0000000..1056277 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/annotate/JsonRootName.java
@@ -0,0 +1,29 @@ +package org.codehaus.jackson.map.annotate; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.codehaus.jackson.annotate.JacksonAnnotation; + +/** + * Annotation similar to {@link javax.xml.bind.annotation.XmlRootElement}, + * used to indicate name to use for root-level wrapping, if wrapping is + * enabled. Annotation itself does not indicate that wrapping should + * be used; but if it is, name used for serialization should be name + * specified here, and deserializer will expect the name as well. + * + * @since 1.9.0 + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@JacksonAnnotation +public @interface JsonRootName +{ + /** + * Root name to use if root-level wrapping is enabled. + */ + public String value(); + +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/annotate/JsonSerialize.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/annotate/JsonSerialize.java new file mode 100644 index 0000000..b641770 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/annotate/JsonSerialize.java
@@ -0,0 +1,216 @@ +package org.codehaus.jackson.map.annotate; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.codehaus.jackson.annotate.JacksonAnnotation; +import org.codehaus.jackson.map.*; + +/** + * Annotation used for configuring serialization aspects, by attaching + * to "getter" methods or fields, or to value classes. + * When annotating value classes, configuration is used for instances + * of the value class but can be overridden by more specific annotations + * (ones that attach to methods or fields). + *<p> + * An example annotation would be: + *<pre> + * @JsonSerialize(using=MySerializer.class, + * as=MySubClass.class, + * include=JsonSerialize.Inclusion.NON_NULL, + * typing=JsonSerialize.Typing.STATIC + * ) + *</pre> + * (which would be redundant, since some properties block others: + * specifically, 'using' has precedence over 'as', which has precedence + * over 'typing' setting) + *<p> + * NOTE: since version 1.2, annotation has also been applicable + * to (constructor) parameters + * + * @since 1.1 + */ +@Target({ElementType.METHOD, ElementType.FIELD, ElementType.TYPE, ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +@JacksonAnnotation +public @interface JsonSerialize +{ + // // // Annotations for explicitly specifying deserializer + + /** + * Serializer class to use for + * serializing associated value. Depending on what is annotated, + * value is either an instance of annotated class (used globablly + * anywhere where class serializer is needed); or only used for + * serializing property access via a getter method. + */ + public Class<? extends JsonSerializer<?>> using() default JsonSerializer.None.class; + + /** + * Serializer class to use for serializing contents (elements + * of a Collection/array, values of Maps) of annotated property. + * Can only be used on properties (methods, fields, constructors), + * and not value classes themselves (as they are typically generic) + * + * @since 1.8 + */ + public Class<? extends JsonSerializer<?>> contentUsing() + default JsonSerializer.None.class; + + /** + * Serializer class to use for serializing Map keys + * of annotated property. + * Can only be used on properties (methods, fields, constructors), + * and not value classes themselves. + * + * @since 1.8 + */ + public Class<? extends JsonSerializer<?>> keyUsing() + default JsonSerializer.None.class; + + // // // Annotations for type handling, explicit declaration + // // // (type used for choosing deserializer, if not explicitly + // // // specified) + + /** + * Supertype (of declared type, which itself is supertype of runtime type) + * to use as type when locating serializer to use. + *<p> + * Bogus type {@link NoClass} can be used to indicate that declared + * type is used as is (i.e. this annotation property has no setting); + * this since annotation properties are not allowed to have null value. + *<p> + * Note: if {@link #using} is also used it has precedence + * (since it directly specifies + * serializer, whereas this would only be used to locate the + * serializer) + * and value of this annotation property is ignored. + */ + public Class<?> as() default NoClass.class; + + /** + * Concrete type to serialize keys of {@link java.util.Map} as, + * instead of type otherwise declared. + * Must be a supertype of declared type; otherwise an exception may be + * thrown by serializer. + */ + public Class<?> keyAs() default NoClass.class; + + /** + * Concrete type to serialize content value (elements + * of a Collection/array, values of Maps) as, + * instead of type otherwise declared. + * Must be a supertype of declared type; otherwise an exception may be + * thrown by serializer. + */ + public Class<?> contentAs() default NoClass.class; + + /** + * Whether type detection used is dynamic or static: that is, + * whether actual runtime type is used (dynamic), or just the + * declared type (static). + * + * @since 1.2 + */ + public Typing typing() default Typing.DYNAMIC; + + // // // Annotation(s) for inclusion criteria + + /** + * Which properties of annotated Bean are + * to be included in serialization (has no effect on other types + * like enums, primitives or collections). + * Choices are "all", "properties that have value other than null" + * and "properties that have non-default value" (i.e. default value + * being property setting for a Bean constructed with default no-arg + * constructor, often null). + * + */ + public Inclusion include() default Inclusion.ALWAYS; + + /* + /********************************************************** + /* Value enumerations needed + /********************************************************** + */ + + /** + * Enumeration used with {@link JsonSerialize#include} property + * to define which properties + * of Java Beans are to be included in serialization + * + * @since 1.1 + */ + public enum Inclusion + { + /** + * Value that indicates that properties are to be always included, + * independent of value + */ + ALWAYS, + + /** + * Value that indicates that only properties with non-null + * values are to be included. + */ + NON_NULL, + + /** + * Value that indicates that only properties that have values + * that differ from default settings (meaning values they have + * when Bean is constructed with its no-arguments constructor) + * are to be included. Value is generally not useful with + * {@link java.util.Map}s, since they have no default values; + * and if used, works same as {@link #ALWAYS}. + */ + NON_DEFAULT, + + /** + * Value that indicates that only properties that have values + * that values that are null or what is considered empty are + * not to be included. + * Emptiness is defined for following type: + *<ul> + * <li>For {@link java.util.Collection}s and {@link java.util.Map}s, + * method <code>isEmpty()</code> is called; + * </li> + * <li>For Java arrays, empty arrays are ones with length of 0 + * </li> + * <li>For Java {@link java.lang.String}s, <code>length()</code> is called, + * and return value of 0 indicates empty String (note that <code>String.isEmpty()</code> + * was added in Java 1.6 and as such can not be used by Jackson + * </li> + * <ul> + * For other types, non-null values are to be included. + * + * @since 1.9 + */ + NON_EMPTY + ; + } + + /** + * Enumeration used with {@link JsonSerialize#typing} property + * to define whether type detection is based on dynamic runtime + * type (DYNAMIC) or declared type (STATIC). + * + * @since 1.1 + */ + public enum Typing + { + /** + * Value that indicates that the actual dynamic runtime type is to + * be used. + */ + DYNAMIC, + + /** + * Value that indicates that the static declared type is to + * be used. + */ + STATIC + ; + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/annotate/JsonTypeIdResolver.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/annotate/JsonTypeIdResolver.java new file mode 100644 index 0000000..f209aab --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/annotate/JsonTypeIdResolver.java
@@ -0,0 +1,35 @@ +package org.codehaus.jackson.map.annotate; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.codehaus.jackson.annotate.JacksonAnnotation; +import org.codehaus.jackson.map.jsontype.TypeIdResolver; + +/** + * Annotation that can be used to plug a custom type identifier handler + * ({@link TypeIdResolver}) + * to be used by + * {@link org.codehaus.jackson.map.TypeSerializer}s + * and {@link org.codehaus.jackson.map.TypeDeserializer}s + * for converting between java types and type id included in JSON content. + * In simplest cases this can be a simple class with static mapping between + * type names and matching classes. + * + * @author tatu + * @since 1.5 + */ +@Target({ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@JacksonAnnotation +public @interface JsonTypeIdResolver +{ + /** + * Defines implementation class of {@link TypeIdResolver} to use for + * converting between external type id (type name) and actual + * type of object. + */ + public Class<? extends TypeIdResolver> value(); +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/annotate/JsonTypeResolver.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/annotate/JsonTypeResolver.java new file mode 100644 index 0000000..fd6ee4b --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/annotate/JsonTypeResolver.java
@@ -0,0 +1,28 @@ +package org.codehaus.jackson.map.annotate; + +import java.lang.annotation.*; + +import org.codehaus.jackson.annotate.JacksonAnnotation; +import org.codehaus.jackson.map.jsontype.TypeResolverBuilder; + +/** + * Annotation that can be used to explicitly define custom resolver + * used for handling serialization and deserialization of type information, + * needed for handling of polymorphic types (or sometimes just for linking + * abstract types to concrete types) + * + * @since 1.5 + */ +@Target({ElementType.TYPE}) +@Retention(RetentionPolicy.RUNTIME) +@JacksonAnnotation +public @interface JsonTypeResolver +{ + /** + * Defines implementation class of {@link TypeResolverBuilder} which is used to construct + * actual {@link org.codehaus.jackson.map.TypeDeserializer} and {@link org.codehaus.jackson.map.TypeDeserializer} + * instances that handle reading and writing addition type information needed to support polymorphic + * deserialization. + */ + public Class<? extends TypeResolverBuilder<?>> value(); +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/annotate/JsonValueInstantiator.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/annotate/JsonValueInstantiator.java new file mode 100644 index 0000000..80534a9 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/annotate/JsonValueInstantiator.java
@@ -0,0 +1,26 @@ +package org.codehaus.jackson.map.annotate; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.codehaus.jackson.annotate.JacksonAnnotation; +import org.codehaus.jackson.map.deser.ValueInstantiator; + +/** + * Annotation that can be used to indicate a {@link ValueInstantiator} to use + * for creating instances of specified type. + * + * @since 1.9 + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@JacksonAnnotation +public @interface JsonValueInstantiator +{ + /** + * @return {@link ValueInstantiator} to use for annotated type + */ + public Class<? extends ValueInstantiator> value(); +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/annotate/JsonView.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/annotate/JsonView.java new file mode 100644 index 0000000..2c9fdfa --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/annotate/JsonView.java
@@ -0,0 +1,37 @@ +package org.codehaus.jackson.map.annotate; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.codehaus.jackson.annotate.JacksonAnnotation; + +/** + * Annotation used for indicating view(s) that the property + * that is defined by method or field annotated is part of. + *<p> + * An example annotation would be: + *<pre> + * \@JsonView(BasicView.class) + *</pre> + * which would specify that property annotated would be included + * when processing (serializing, deserializing) View identified + * by <code>BasicView.class</code> (or its sub-class). + * If multiple View class identifiers are included, property will + * be part of all of them. + * + * @since 1.4 + */ + +@Target({ElementType.METHOD, ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +@JacksonAnnotation +public @interface JsonView { + /** + * View or views that annotated element is part of. Views are identified + * by classes, and use expected class inheritance relationship: child + * views contain all elements parent views have, for example. + */ + public Class<?>[] value() default { }; +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/annotate/NoClass.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/annotate/NoClass.java new file mode 100644 index 0000000..f3167f8 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/annotate/NoClass.java
@@ -0,0 +1,19 @@ +package org.codehaus.jackson.map.annotate; + +/** + * Marker class used with annotations to indicate "no class". This is + * a silly but necessary work-around -- annotations can not take nulls + * as either default or explicit values. Hence for class values we must + * explicitly use a bogus placeholder to denote equivalent of + * "no class" (for which 'null' is usually the natural choice). + *<p> + * Note before version 1.4, this marker class was under + * "org.codehaus.jackson.annotate". However, since it is only used + * by annotations in "org.codehaus.jackson.map.annotate" (and not externally + * exposed), it was moved to that package as of version 1.5. + */ +public final class NoClass +{ + private NoClass() { } +} +
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/annotate/package-info.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/annotate/package-info.java new file mode 100644 index 0000000..4aebeca --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/annotate/package-info.java
@@ -0,0 +1,5 @@ +/** + * Annotations that directly depend on Mapper classes (not just + * Jackson core) and are used for configuring Data Mapping functionality. + */ +package org.codehaus.jackson.map.annotate;
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/AbstractDeserializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/AbstractDeserializer.java new file mode 100644 index 0000000..3c785b8 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/AbstractDeserializer.java
@@ -0,0 +1,102 @@ +package org.codehaus.jackson.map.deser; + +import java.io.IOException; + +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.type.JavaType; + +/** + * Deserializer only used as placeholder for abstract types during polymorphic + * type handling deserialization. If so, there is no real deserializer associated + * with nominal type, just {@link TypeDeserializer}; and any calls that do not + * pass such resolver will result in an error. + * + * @author tatu + * + * @since 1.6 + */ +public class AbstractDeserializer + extends JsonDeserializer<Object> +{ + protected final JavaType _baseType; + + // support for "native" types, which require special care: + + protected final boolean _acceptString; + protected final boolean _acceptBoolean; + protected final boolean _acceptInt; + protected final boolean _acceptDouble; + + public AbstractDeserializer(JavaType bt) + { + _baseType = bt; + Class<?> cls = bt.getRawClass(); + _acceptString = cls.isAssignableFrom(String.class); + _acceptBoolean = (cls == Boolean.TYPE) || cls.isAssignableFrom(Boolean.class); + _acceptInt = (cls == Integer.TYPE) || cls.isAssignableFrom(Integer.class); + _acceptDouble = (cls == Double.TYPE) || cls.isAssignableFrom(Double.class); + } + + @Override + public Object deserializeWithType(JsonParser jp, DeserializationContext ctxt, + TypeDeserializer typeDeserializer) + throws IOException, JsonProcessingException + { + // First: support "natural" values (which are always serialized without type info!) + Object result = _deserializeIfNatural(jp, ctxt); + if (result != null) { + return result; + } + return typeDeserializer.deserializeTypedFromObject(jp, ctxt); + } + + @Override + public Object deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + // This method should never be called... + throw ctxt.instantiationException(_baseType.getRawClass(), "abstract types can only be instantiated with additional type information"); + } + + protected Object _deserializeIfNatural(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + /* As per [JACKSON-417], there is a chance we might be "natular" types + * (String, Boolean, Integer, Double), which do not include any type information... + * Care must be taken to only return this if return type matches, however. + * Finally, we may have to consider possibility of custom handlers for + * these values: but for now this should work ok. + */ + switch (jp.getCurrentToken()) { + case VALUE_STRING: + if (_acceptString) { + return jp.getText(); + } + break; + case VALUE_NUMBER_INT: + if (_acceptInt) { + return jp.getIntValue(); + } + break; + + case VALUE_NUMBER_FLOAT: + if (_acceptDouble) { + return Double.valueOf(jp.getDoubleValue()); + } + break; + case VALUE_TRUE: + if (_acceptBoolean) { + return Boolean.TRUE; + } + break; + case VALUE_FALSE: + if (_acceptBoolean) { + return Boolean.FALSE; + } + break; + } + return null; + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/ArrayDeserializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/ArrayDeserializer.java new file mode 100644 index 0000000..315760e --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/ArrayDeserializer.java
@@ -0,0 +1,28 @@ +package org.codehaus.jackson.map.deser; + +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.type.ArrayType; + +/** + * @deprecated Since 1.9, use {@link org.codehaus.jackson.map.deser.std.ObjectArrayDeserializer} instead. + */ +@Deprecated +public class ArrayDeserializer + extends org.codehaus.jackson.map.deser.std.ObjectArrayDeserializer +{ + /** + * @deprecated + */ + @Deprecated + public ArrayDeserializer(ArrayType arrayType, JsonDeserializer<Object> elemDeser) + { + this(arrayType, elemDeser, null); + } + + public ArrayDeserializer(ArrayType arrayType, JsonDeserializer<Object> elemDeser, + TypeDeserializer elemTypeDeser) + { + super(arrayType, elemDeser, elemTypeDeser); + } +} +
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/ArrayDeserializers.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/ArrayDeserializers.java new file mode 100644 index 0000000..8d46233 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/ArrayDeserializers.java
@@ -0,0 +1,11 @@ +package org.codehaus.jackson.map.deser; + +/** + * @deprecated Since 1.9, use {@link org.codehaus.jackson.map.deser.std.PrimitiveArrayDeserializers} instead. + */ +@Deprecated +public class ArrayDeserializers + extends org.codehaus.jackson.map.deser.std.PrimitiveArrayDeserializers +{ + private ArrayDeserializers() { super(); } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/BasicDeserializerFactory.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/BasicDeserializerFactory.java new file mode 100644 index 0000000..74e5c95 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/BasicDeserializerFactory.java
@@ -0,0 +1,895 @@ +package org.codehaus.jackson.map.deser; + +import java.util.*; +import java.util.concurrent.*; +import java.util.concurrent.atomic.AtomicReference; + +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.deser.std.AtomicReferenceDeserializer; +import org.codehaus.jackson.map.deser.std.CollectionDeserializer; +import org.codehaus.jackson.map.deser.std.EnumDeserializer; +import org.codehaus.jackson.map.deser.std.EnumMapDeserializer; +import org.codehaus.jackson.map.deser.std.EnumSetDeserializer; +import org.codehaus.jackson.map.deser.std.JsonNodeDeserializer; +import org.codehaus.jackson.map.deser.std.MapDeserializer; +import org.codehaus.jackson.map.deser.std.ObjectArrayDeserializer; +import org.codehaus.jackson.map.deser.std.PrimitiveArrayDeserializers; +import org.codehaus.jackson.map.deser.std.StdKeyDeserializers; +import org.codehaus.jackson.map.deser.std.StringCollectionDeserializer; +import org.codehaus.jackson.map.ext.OptionalHandlerFactory; +import org.codehaus.jackson.map.introspect.*; +import org.codehaus.jackson.map.jsontype.NamedType; +import org.codehaus.jackson.map.jsontype.TypeResolverBuilder; +import org.codehaus.jackson.map.type.*; +import org.codehaus.jackson.map.util.EnumResolver; +import org.codehaus.jackson.type.JavaType; + +/** + * Abstract factory base class that can provide deserializers for standard + * JDK classes, including collection classes and simple heuristics for + * "upcasting" commmon collection interface types + * (such as {@link java.util.Collection}). + *<p> + * Since all simple deserializers are eagerly instantiated, and there is + * no additional introspection or customizability of these types, + * this factory is stateless. + */ +public abstract class BasicDeserializerFactory + extends DeserializerFactory +{ + /** + * We will pre-create serializers for common non-structured + * (that is things other than Collection, Map or array) + * types. These need not go through factory. + */ + final static HashMap<ClassKey, JsonDeserializer<Object>> _simpleDeserializers = StdDeserializers.constructAll(); + + /** + * Set of available key deserializers is currently limited + * to standard types; and all known instances are storing + * in this map. + */ + final static HashMap<JavaType, KeyDeserializer> _keyDeserializers = StdKeyDeserializers.constructAll(); + + /* We do some defaulting for abstract Map classes and + * interfaces, to avoid having to use exact types or annotations in + * cases where the most common concrete Maps will do. + */ + @SuppressWarnings("rawtypes") + final static HashMap<String, Class<? extends Map>> _mapFallbacks = + new HashMap<String, Class<? extends Map>>(); + static { + _mapFallbacks.put(Map.class.getName(), LinkedHashMap.class); + _mapFallbacks.put(ConcurrentMap.class.getName(), ConcurrentHashMap.class); + _mapFallbacks.put(SortedMap.class.getName(), TreeMap.class); + + /* 11-Jan-2009, tatu: Let's see if we can still add support for + * JDK 1.6 interfaces, even if we run on 1.5. Just need to be + * more careful with typos, since compiler won't notice any + * problems... + */ + _mapFallbacks.put("java.util.NavigableMap", TreeMap.class); + try { + Class<?> key = Class.forName("java.util.concurrent.ConcurrentNavigableMap"); + Class<?> value = Class.forName("java.util.concurrent.ConcurrentSkipListMap"); + @SuppressWarnings("unchecked") + Class<? extends Map<?,?>> mapValue = (Class<? extends Map<?,?>>) value; + _mapFallbacks.put(key.getName(), mapValue); + } catch (ClassNotFoundException cnfe) { // occurs on 1.5 + } catch (SecurityException se) { + } + } + + /* We do some defaulting for abstract Collection classes and + * interfaces, to avoid having to use exact types or annotations in + * cases where the most common concrete Collection will do. + */ + @SuppressWarnings("rawtypes") + final static HashMap<String, Class<? extends Collection>> _collectionFallbacks = + new HashMap<String, Class<? extends Collection>>(); + static { + _collectionFallbacks.put(Collection.class.getName(), ArrayList.class); + _collectionFallbacks.put(List.class.getName(), ArrayList.class); + _collectionFallbacks.put(Set.class.getName(), HashSet.class); + _collectionFallbacks.put(SortedSet.class.getName(), TreeSet.class); + _collectionFallbacks.put(Queue.class.getName(), LinkedList.class); + + /* 11-Jan-2009, tatu: Let's see if we can still add support for + * JDK 1.6 interfaces, even if we run on 1.5. Just need to be + * more careful with typos, since compiler won't notice any + * problems... + */ + _collectionFallbacks.put("java.util.Deque", LinkedList.class); + _collectionFallbacks.put("java.util.NavigableSet", TreeSet.class); + } + + /** + * And finally, we have special array deserializers for primitive + * array types + */ + protected final static HashMap<JavaType,JsonDeserializer<Object>> _arrayDeserializers + = PrimitiveArrayDeserializers.getAll(); + + /** + * To support external/optional deserializers, we'll use this helper class + * (as per [JACKSON-386]) + */ + protected OptionalHandlerFactory optionalHandlers = OptionalHandlerFactory.instance; + + /* + /********************************************************** + /* Life cycle + /********************************************************** + */ + + protected BasicDeserializerFactory() { } + + // can't be implemented quite here + @Override + public abstract DeserializerFactory withConfig(DeserializerFactory.Config config); + + /* + /********************************************************** + /* Methods for sub-classes to override to provide + /* custom deserializers (since 1.7) + /********************************************************** + */ + + protected abstract JsonDeserializer<?> _findCustomArrayDeserializer(ArrayType type, DeserializationConfig config, + DeserializerProvider p, BeanProperty property, + TypeDeserializer elementTypeDeser, JsonDeserializer<?> elementDeser) + throws JsonMappingException; + + protected abstract JsonDeserializer<?> _findCustomCollectionDeserializer( + CollectionType type, DeserializationConfig config, + DeserializerProvider p, BasicBeanDescription beanDesc, BeanProperty property, + TypeDeserializer elementTypeDeser, JsonDeserializer<?> elementDeser) + throws JsonMappingException; + + protected abstract JsonDeserializer<?> _findCustomCollectionLikeDeserializer( + CollectionLikeType type, DeserializationConfig config, + DeserializerProvider p, BasicBeanDescription beanDesc, BeanProperty property, + TypeDeserializer elementTypeDeser, JsonDeserializer<?> elementDeser) + throws JsonMappingException; + + protected abstract JsonDeserializer<?> _findCustomEnumDeserializer(Class<?> type, + DeserializationConfig config, BasicBeanDescription beanDesc, BeanProperty property) + throws JsonMappingException; + + protected abstract JsonDeserializer<?> _findCustomMapDeserializer(MapType type, + DeserializationConfig config, + DeserializerProvider p, BasicBeanDescription beanDesc, BeanProperty property, + KeyDeserializer keyDeser, + TypeDeserializer elementTypeDeser, JsonDeserializer<?> elementDeser) + throws JsonMappingException; + + protected abstract JsonDeserializer<?> _findCustomMapLikeDeserializer(MapLikeType type, + DeserializationConfig config, + DeserializerProvider p, BasicBeanDescription beanDesc, BeanProperty property, + KeyDeserializer keyDeser, + TypeDeserializer elementTypeDeser, JsonDeserializer<?> elementDeser) + throws JsonMappingException; + + protected abstract JsonDeserializer<?> _findCustomTreeNodeDeserializer(Class<? extends JsonNode> type, + DeserializationConfig config, BeanProperty property) + throws JsonMappingException; + + /* + /********************************************************** + /* JsonDeserializerFactory impl (partial) + /********************************************************** + */ + + @Override + public abstract ValueInstantiator findValueInstantiator(DeserializationConfig config, + BasicBeanDescription beanDesc) + throws JsonMappingException; + + @Override + public abstract JavaType mapAbstractType(DeserializationConfig config, JavaType type) + throws JsonMappingException; + + @Override + public JsonDeserializer<?> createArrayDeserializer(DeserializationConfig config, DeserializerProvider p, + ArrayType type, BeanProperty property) + throws JsonMappingException + { + JavaType elemType = type.getContentType(); + + // Very first thing: is deserializer hard-coded for elements? + JsonDeserializer<Object> contentDeser = elemType.getValueHandler(); + if (contentDeser == null) { + // Maybe special array type, such as "primitive" arrays (int[] etc) + JsonDeserializer<?> deser = _arrayDeserializers.get(elemType); + if (deser != null) { + /* 23-Nov-2010, tatu: Although not commonly needed, ability to override + * deserializers for all types (including primitive arrays) is useful + * so let's allow this + */ + JsonDeserializer<?> custom = _findCustomArrayDeserializer(type, config, p, property, null, null); + if (custom != null) { + return custom; + } + return deser; + } + // If not, generic one: + if (elemType.isPrimitive()) { // sanity check + throw new IllegalArgumentException("Internal error: primitive type ("+type+") passed, no array deserializer found"); + } + } + // Then optional type info (1.5): if type has been resolved, we may already know type deserializer: + TypeDeserializer elemTypeDeser = elemType.getTypeHandler(); + // but if not, may still be possible to find: + if (elemTypeDeser == null) { + elemTypeDeser = findTypeDeserializer(config, elemType, property); + } + // 23-Nov-2010, tatu: Custom array deserializer? + JsonDeserializer<?> custom = _findCustomArrayDeserializer(type, config, p, property, elemTypeDeser, contentDeser); + if (custom != null) { + return custom; + } + + if (contentDeser == null) { + // 'null' -> arrays have no referring fields + contentDeser = p.findValueDeserializer(config, elemType, property); + } + return new ObjectArrayDeserializer(type, contentDeser, elemTypeDeser); + } + + @Override + public JsonDeserializer<?> createCollectionDeserializer(DeserializationConfig config, DeserializerProvider p, + CollectionType type, BeanProperty property) + throws JsonMappingException + { + // First: global defaulting: + type = (CollectionType) mapAbstractType(config, type); + + Class<?> collectionClass = type.getRawClass(); + BasicBeanDescription beanDesc = config.introspectForCreation(type); + // Explicit deserializer to use? (@JsonDeserialize.using) + JsonDeserializer<Object> deser = findDeserializerFromAnnotation(config, beanDesc.getClassInfo(), property); + if (deser != null) { + return deser; + } + // If not, any type modifiers? (@JsonDeserialize.as) + type = modifyTypeByAnnotation(config, beanDesc.getClassInfo(), type, null); + + JavaType contentType = type.getContentType(); + // Very first thing: is deserializer hard-coded for elements? + JsonDeserializer<Object> contentDeser = contentType.getValueHandler(); + + // Then optional type info (1.5): if type has been resolved, we may already know type deserializer: + TypeDeserializer contentTypeDeser = contentType.getTypeHandler(); + // but if not, may still be possible to find: + if (contentTypeDeser == null) { + contentTypeDeser = findTypeDeserializer(config, contentType, property); + } + + // 23-Nov-2010, tatu: Custom deserializer? + JsonDeserializer<?> custom = _findCustomCollectionDeserializer(type, config, p, beanDesc, property, + contentTypeDeser, contentDeser); + if (custom != null) { + return custom; + } + + if (contentDeser == null) { // not defined by annotation + // One special type: EnumSet: + if (EnumSet.class.isAssignableFrom(collectionClass)) { + return new EnumSetDeserializer(contentType.getRawClass(), + createEnumDeserializer(config, p, contentType, property)); + } + // But otherwise we can just use a generic value deserializer: + // 'null' -> collections have no referring fields + contentDeser = p.findValueDeserializer(config, contentType, property); + } + + /* One twist: if we are being asked to instantiate an interface or + * abstract Collection, we need to either find something that implements + * the thing, or give up. + * + * Note that we do NOT try to guess based on secondary interfaces + * here; that would probably not work correctly since casts would + * fail later on (as the primary type is not the interface we'd + * be implementing) + */ + if (type.isInterface() || type.isAbstract()) { + @SuppressWarnings({ "rawtypes" }) + Class<? extends Collection> fallback = _collectionFallbacks.get(collectionClass.getName()); + if (fallback == null) { + throw new IllegalArgumentException("Can not find a deserializer for non-concrete Collection type "+type); + } + collectionClass = fallback; + type = (CollectionType) config.constructSpecializedType(type, collectionClass); + // But if so, also need to re-check creators... + beanDesc = config.introspectForCreation(type); + } + ValueInstantiator inst = findValueInstantiator(config, beanDesc); + // 13-Dec-2010, tatu: Can use more optimal deserializer if content type is String, so: + if (contentType.getRawClass() == String.class) { + // no value type deserializer because Strings are one of natural/native types: + return new StringCollectionDeserializer(type, contentDeser, inst); + } + return new CollectionDeserializer(type, contentDeser, contentTypeDeser, inst); + } + + // Copied almost verbatim from "createCollectionDeserializer" -- should try to share more code + @Override + public JsonDeserializer<?> createCollectionLikeDeserializer(DeserializationConfig config, + DeserializerProvider p, CollectionLikeType type, BeanProperty property) + throws JsonMappingException + { + // First: global defaulting: + type = (CollectionLikeType) mapAbstractType(config, type); + + Class<?> collectionClass = type.getRawClass(); + BasicBeanDescription beanDesc = config.introspectClassAnnotations(collectionClass); + // Explicit deserializer to use? (@JsonDeserialize.using) + JsonDeserializer<Object> deser = findDeserializerFromAnnotation(config, beanDesc.getClassInfo(), property); + if (deser != null) { + return deser; + } + // If not, any type modifiers? (@JsonDeserialize.as) + type = modifyTypeByAnnotation(config, beanDesc.getClassInfo(), type, null); + + JavaType contentType = type.getContentType(); + // Very first thing: is deserializer hard-coded for elements? + JsonDeserializer<Object> contentDeser = contentType.getValueHandler(); + + // Then optional type info (1.5): if type has been resolved, we may already know type deserializer: + TypeDeserializer contentTypeDeser = contentType.getTypeHandler(); + // but if not, may still be possible to find: + if (contentTypeDeser == null) { + contentTypeDeser = findTypeDeserializer(config, contentType, property); + } + return _findCustomCollectionLikeDeserializer(type, config, p, beanDesc, property, + contentTypeDeser, contentDeser); + } + + @Override + public JsonDeserializer<?> createMapDeserializer(DeserializationConfig config, DeserializerProvider p, + MapType type, BeanProperty property) + throws JsonMappingException + { + // First: global defaulting: + type = (MapType) mapAbstractType(config, type); + + BasicBeanDescription beanDesc = config.introspectForCreation(type); + // Explicit deserializer to use? (@JsonDeserialize.using) + JsonDeserializer<Object> deser = findDeserializerFromAnnotation(config, beanDesc.getClassInfo(), property); + if (deser != null) { + return deser; + } + // If not, any type modifiers? (@JsonDeserialize.as) + type = modifyTypeByAnnotation(config, beanDesc.getClassInfo(), type, null); + JavaType keyType = type.getKeyType(); + JavaType contentType = type.getContentType(); + + // First: is there annotation-specified deserializer for values? + @SuppressWarnings("unchecked") + JsonDeserializer<Object> contentDeser = (JsonDeserializer<Object>) contentType.getValueHandler(); + + // Ok: need a key deserializer (null indicates 'default' here) + KeyDeserializer keyDes = (KeyDeserializer) keyType.getValueHandler(); + if (keyDes == null) { + keyDes = p.findKeyDeserializer(config, keyType, property); + } + // Then optional type info (1.5); either attached to type, or resolve separately: + TypeDeserializer contentTypeDeser = contentType.getTypeHandler(); + // but if not, may still be possible to find: + if (contentTypeDeser == null) { + contentTypeDeser = findTypeDeserializer(config, contentType, property); + } + + // 23-Nov-2010, tatu: Custom deserializer? + JsonDeserializer<?> custom = _findCustomMapDeserializer(type, config, p, beanDesc, property, + keyDes, contentTypeDeser, contentDeser); + + if (custom != null) { + return custom; + } + + if (contentDeser == null) { // nope... + // 'null' -> maps have no referring fields + contentDeser = p.findValueDeserializer(config, contentType, property); + } + /* Value handling is identical for all, + * but EnumMap requires special handling for keys + */ + Class<?> mapClass = type.getRawClass(); + if (EnumMap.class.isAssignableFrom(mapClass)) { + Class<?> kt = keyType.getRawClass(); + if (kt == null || !kt.isEnum()) { + throw new IllegalArgumentException("Can not construct EnumMap; generic (key) type not available"); + } + return new EnumMapDeserializer(keyType.getRawClass(), + createEnumDeserializer(config, p, keyType, property), + contentDeser); + } + + // Otherwise, generic handler works ok. + + /* But there is one more twist: if we are being asked to instantiate + * an interface or abstract Map, we need to either find something + * that implements the thing, or give up. + * + * Note that we do NOT try to guess based on secondary interfaces + * here; that would probably not work correctly since casts would + * fail later on (as the primary type is not the interface we'd + * be implementing) + */ + if (type.isInterface() || type.isAbstract()) { + @SuppressWarnings("rawtypes") + Class<? extends Map> fallback = _mapFallbacks.get(mapClass.getName()); + if (fallback == null) { + throw new IllegalArgumentException("Can not find a deserializer for non-concrete Map type "+type); + } + mapClass = fallback; + type = (MapType) config.constructSpecializedType(type, mapClass); + // But if so, also need to re-check creators... + beanDesc = config.introspectForCreation(type); + } + ValueInstantiator inst = findValueInstantiator(config, beanDesc); + MapDeserializer md = new MapDeserializer(type, inst, keyDes, contentDeser, contentTypeDeser); + md.setIgnorableProperties(config.getAnnotationIntrospector().findPropertiesToIgnore(beanDesc.getClassInfo())); + return md; + } + + // Copied almost verbatim from "createMapDeserializer" -- should try to share more code + @Override + public JsonDeserializer<?> createMapLikeDeserializer(DeserializationConfig config, + DeserializerProvider p, MapLikeType type, BeanProperty property) + throws JsonMappingException + { + // First: global defaulting: + type = (MapLikeType) mapAbstractType(config, type); + BasicBeanDescription beanDesc = config.introspectForCreation(type); + // Explicit deserializer to use? (@JsonDeserialize.using) + JsonDeserializer<Object> deser = findDeserializerFromAnnotation(config, beanDesc.getClassInfo(), property); + if (deser != null) { + return deser; + } + // If not, any type modifiers? (@JsonDeserialize.as) + type = modifyTypeByAnnotation(config, beanDesc.getClassInfo(), type, null); + JavaType keyType = type.getKeyType(); + JavaType contentType = type.getContentType(); + + // First: is there annotation-specified deserializer for values? + @SuppressWarnings("unchecked") + JsonDeserializer<Object> contentDeser = (JsonDeserializer<Object>) contentType.getValueHandler(); + + // Ok: need a key deserializer (null indicates 'default' here) + KeyDeserializer keyDes = (KeyDeserializer) keyType.getValueHandler(); + if (keyDes == null) { + keyDes = p.findKeyDeserializer(config, keyType, property); + } + // Then optional type info (1.5); either attached to type, or resolve separately: + TypeDeserializer contentTypeDeser = contentType.getTypeHandler(); + // but if not, may still be possible to find: + if (contentTypeDeser == null) { + contentTypeDeser = findTypeDeserializer(config, contentType, property); + } + return _findCustomMapLikeDeserializer(type, config, p, beanDesc, property, + keyDes, contentTypeDeser, contentDeser); + } + + /** + * Factory method for constructing serializers of {@link Enum} types. + */ + @Override + public JsonDeserializer<?> createEnumDeserializer(DeserializationConfig config, DeserializerProvider p, + JavaType type, BeanProperty property) + throws JsonMappingException + { + /* 18-Feb-2009, tatu: Must first check if we have a class annotation + * that should override default deserializer + */ + BasicBeanDescription beanDesc = config.introspectForCreation(type); + JsonDeserializer<?> des = findDeserializerFromAnnotation(config, beanDesc.getClassInfo(), property); + if (des != null) { + return des; + } + Class<?> enumClass = type.getRawClass(); + // 23-Nov-2010, tatu: Custom deserializer? + JsonDeserializer<?> custom = _findCustomEnumDeserializer(enumClass, config, beanDesc, property); + if (custom != null) { + return custom; + } + + // [JACKSON-193] May have @JsonCreator for static factory method: + for (AnnotatedMethod factory : beanDesc.getFactoryMethods()) { + if (config.getAnnotationIntrospector().hasCreatorAnnotation(factory)) { + int argCount = factory.getParameterCount(); + if (argCount == 1) { + Class<?> returnType = factory.getRawType(); + // usually should be class, but may be just plain Enum<?> (for Enum.valueOf()?) + if (returnType.isAssignableFrom(enumClass)) { + return EnumDeserializer.deserializerForCreator(config, enumClass, factory); + } + } + throw new IllegalArgumentException("Unsuitable method ("+factory+") decorated with @JsonCreator (for Enum type " + +enumClass.getName()+")"); + } + } + return new EnumDeserializer(constructEnumResolver(enumClass, config)); + } + + @Override + public JsonDeserializer<?> createTreeDeserializer(DeserializationConfig config, DeserializerProvider p, + JavaType nodeType, BeanProperty property) + throws JsonMappingException + { + @SuppressWarnings("unchecked") + Class<? extends JsonNode> nodeClass = (Class<? extends JsonNode>) nodeType.getRawClass(); + // 23-Nov-2010, tatu: Custom deserializer? + JsonDeserializer<?> custom = _findCustomTreeNodeDeserializer(nodeClass, config, property); + if (custom != null) { + return custom; + } + return JsonNodeDeserializer.getDeserializer(nodeClass); + } + + /** + * Method called by {@link BeanDeserializerFactory} to see if there might be a standard + * deserializer registered for given type. + * + * @since 1.8 + */ + @SuppressWarnings("unchecked") + protected JsonDeserializer<Object> findStdBeanDeserializer(DeserializationConfig config, + DeserializerProvider p, JavaType type, BeanProperty property) + throws JsonMappingException + { + Class<?> cls = type.getRawClass(); + // note: we do NOT check for custom deserializers here; that's for sub-class to do + JsonDeserializer<Object> deser = _simpleDeserializers.get(new ClassKey(cls)); + if (deser != null) { + return deser; + } + + // [JACKSON-283]: AtomicReference is a rather special type... + if (AtomicReference.class.isAssignableFrom(cls)) { + // Must find parameterization + TypeFactory tf = config.getTypeFactory(); + JavaType[] params = tf.findTypeParameters(type, AtomicReference.class); + JavaType referencedType; + if (params == null || params.length < 1) { // untyped (raw) + referencedType = TypeFactory.unknownType(); + } else { + referencedType = params[0]; + } + + JsonDeserializer<?> d2 = new AtomicReferenceDeserializer(referencedType, property); + return (JsonDeserializer<Object>)d2; + } + // [JACKSON-386]: External/optional type handlers are handled somewhat differently + JsonDeserializer<?> d = optionalHandlers.findDeserializer(type, config, p); + if (d != null) { + return (JsonDeserializer<Object>)d; + } + return null; + } + + @Override + public TypeDeserializer findTypeDeserializer(DeserializationConfig config, JavaType baseType, + BeanProperty property) + throws JsonMappingException + { + Class<?> cls = baseType.getRawClass(); + BasicBeanDescription bean = config.introspectClassAnnotations(cls); + AnnotatedClass ac = bean.getClassInfo(); + AnnotationIntrospector ai = config.getAnnotationIntrospector(); + TypeResolverBuilder<?> b = ai.findTypeResolver(config, ac, baseType); + + /* Ok: if there is no explicit type info handler, we may want to + * use a default. If so, config object knows what to use. + */ + Collection<NamedType> subtypes = null; + if (b == null) { + b = config.getDefaultTyper(baseType); + if (b == null) { + return null; + } + } else { + subtypes = config.getSubtypeResolver().collectAndResolveSubtypes(ac, config, ai); + } + // [JACKSON-505]: May need to figure out default implementation, if none found yet + // (note: check for abstract type is not 100% mandatory, more of an optimization) + if ((b.getDefaultImpl() == null) && baseType.isAbstract()) { + JavaType defaultType = mapAbstractType(config, baseType); + if (defaultType != null && defaultType.getRawClass() != baseType.getRawClass()) { + b = b.defaultImpl(defaultType.getRawClass()); + } + } + return b.buildTypeDeserializer(config, baseType, subtypes, property); + } + + /* + /********************************************************** + /* Extended API + /********************************************************** + */ + + /** + * Method called to create a type information deserializer for values of + * given non-container property, if one is needed. + * If not needed (no polymorphic handling configured for property), should return null. + *<p> + * Note that this method is only called for non-container bean properties, + * and not for values in container types or root values (or container properties) + * + * @param baseType Declared base type of the value to deserializer (actual + * deserializer type will be this type or its subtype) + * + * @return Type deserializer to use for given base type, if one is needed; null if not. + * + * @since 1.5 + */ + public TypeDeserializer findPropertyTypeDeserializer(DeserializationConfig config, JavaType baseType, + AnnotatedMember annotated, BeanProperty property) + throws JsonMappingException + { + AnnotationIntrospector ai = config.getAnnotationIntrospector(); + TypeResolverBuilder<?> b = ai.findPropertyTypeResolver(config, annotated, baseType); + // Defaulting: if no annotations on member, check value class + if (b == null) { + return findTypeDeserializer(config, baseType, property); + } + // but if annotations found, may need to resolve subtypes: + Collection<NamedType> subtypes = config.getSubtypeResolver().collectAndResolveSubtypes(annotated, config, ai); + return b.buildTypeDeserializer(config, baseType, subtypes, property); + } + + /** + * Method called to find and create a type information deserializer for values of + * given container (list, array, map) property, if one is needed. + * If not needed (no polymorphic handling configured for property), should return null. + *<p> + * Note that this method is only called for container bean properties, + * and not for values in container types or root values (or non-container properties) + * + * @param containerType Type of property; must be a container type + * @param propertyEntity Field or method that contains container property + * + * @since 1.5 + */ + public TypeDeserializer findPropertyContentTypeDeserializer(DeserializationConfig config, JavaType containerType, + AnnotatedMember propertyEntity, BeanProperty property) + throws JsonMappingException + { + AnnotationIntrospector ai = config.getAnnotationIntrospector(); + TypeResolverBuilder<?> b = ai.findPropertyContentTypeResolver(config, propertyEntity, containerType); + JavaType contentType = containerType.getContentType(); + // Defaulting: if no annotations on member, check class + if (b == null) { + return findTypeDeserializer(config, contentType, property); + } + // but if annotations found, may need to resolve subtypes: + Collection<NamedType> subtypes = config.getSubtypeResolver().collectAndResolveSubtypes(propertyEntity, config, ai); + return b.buildTypeDeserializer(config, contentType, subtypes, property); + } + + /* + /********************************************************** + /* Helper methods, value/content/key type introspection + /********************************************************** + */ + + /** + * Helper method called to check if a class or method + * has annotation that tells which class to use for deserialization. + * Returns null if no such annotation found. + */ + protected JsonDeserializer<Object> findDeserializerFromAnnotation(DeserializationConfig config, + Annotated ann, BeanProperty property) + throws JsonMappingException + { + Object deserDef = config.getAnnotationIntrospector().findDeserializer(ann); + if (deserDef != null) { + return _constructDeserializer(config, ann, property, deserDef); + } + return null; + } + + @SuppressWarnings("unchecked") + JsonDeserializer<Object> _constructDeserializer(DeserializationConfig config, Annotated ann, BeanProperty property, + Object deserDef) + throws JsonMappingException + { + if (deserDef instanceof JsonDeserializer) { + JsonDeserializer<Object> deser = (JsonDeserializer<Object>) deserDef; + // related to [JACKSON-569], need contextualization: + if (deser instanceof ContextualDeserializer<?>) { + deser = (JsonDeserializer<Object>)((ContextualDeserializer<?>) deser).createContextual(config, property); + } + return deser; + } + /* Alas, there's no way to force return type of "either class + * X or Y" -- need to throw an exception after the fact + */ + if (!(deserDef instanceof Class)) { + throw new IllegalStateException("AnnotationIntrospector returned deserializer definition of type "+deserDef.getClass().getName()+"; expected type JsonDeserializer or Class<JsonDeserializer> instead"); + } + Class<? extends JsonDeserializer<?>> deserClass = (Class<? extends JsonDeserializer<?>>) deserDef; + if (!JsonDeserializer.class.isAssignableFrom(deserClass)) { + throw new IllegalStateException("AnnotationIntrospector returned Class "+deserClass.getName()+"; expected Class<JsonDeserializer>"); + } + JsonDeserializer<Object> deser = config.deserializerInstance(ann, deserClass); + // related to [JACKSON-569], need contextualization: + if (deser instanceof ContextualDeserializer<?>) { + deser = (JsonDeserializer<Object>)((ContextualDeserializer<?>) deser).createContextual(config, property); + } + return deser; + } + + /** + * Method called to see if given method has annotations that indicate + * a more specific type than what the argument specifies. + * If annotations are present, they must specify compatible Class; + * instance of which can be assigned using the method. This means + * that the Class has to be raw class of type, or its sub-class + * (or, implementing class if original Class instance is an interface). + * + * @param a Method or field that the type is associated with + * @param type Type derived from the setter argument + * @param propName Name of property that refers to type, if any; null + * if no property information available (when modify type declaration + * of a class, for example) + * + * @return Original type if no annotations are present; or a more + * specific type derived from it if type annotation(s) was found + * + * @throws JsonMappingException if invalid annotation is found + */ + @SuppressWarnings({ "unchecked", "deprecation" }) + protected <T extends JavaType> T modifyTypeByAnnotation(DeserializationConfig config, + Annotated a, T type, String propName) + throws JsonMappingException + { + // first: let's check class for the instance itself: + AnnotationIntrospector intr = config.getAnnotationIntrospector(); + Class<?> subclass = intr.findDeserializationType(a, type, propName); + if (subclass != null) { + try { + type = (T) type.narrowBy(subclass); + } catch (IllegalArgumentException iae) { + throw new JsonMappingException("Failed to narrow type "+type+" with concrete-type annotation (value "+subclass.getName()+"), method '"+a.getName()+"': "+iae.getMessage(), null, iae); + } + } + + // then key class + if (type.isContainerType()) { + Class<?> keyClass = intr.findDeserializationKeyType(a, type.getKeyType(), propName); + if (keyClass != null) { + // illegal to use on non-Maps + if (!(type instanceof MapLikeType)) { + throw new JsonMappingException("Illegal key-type annotation: type "+type+" is not a Map(-like) type"); + } + try { + type = (T) ((MapLikeType) type).narrowKey(keyClass); + } catch (IllegalArgumentException iae) { + throw new JsonMappingException("Failed to narrow key type "+type+" with key-type annotation ("+keyClass.getName()+"): "+iae.getMessage(), null, iae); + } + } + JavaType keyType = type.getKeyType(); + /* 21-Mar-2011, tatu: ... and associated deserializer too (unless already assigned) + * (not 100% why or how, but this does seem to get called more than once, which + * is not good: for now, let's just avoid errors) + */ + if (keyType != null && keyType.getValueHandler() == null) { + Class<? extends KeyDeserializer> kdClass = intr.findKeyDeserializer(a); + if (kdClass != null && kdClass != KeyDeserializer.None.class) { + KeyDeserializer kd = config.keyDeserializerInstance(a, kdClass); + // !!! TODO: For 2.0, change to use this instead: + /* + type = (T) ((MapLikeType) type).withKeyValueHandler(kd); + keyType = type.getKeyType(); // just in case it's used below + */ + keyType.setValueHandler(kd); + } + } + + // and finally content class; only applicable to structured types + Class<?> cc = intr.findDeserializationContentType(a, type.getContentType(), propName); + if (cc != null) { + try { + type = (T) type.narrowContentsBy(cc); + } catch (IllegalArgumentException iae) { + throw new JsonMappingException("Failed to narrow content type "+type+" with content-type annotation ("+cc.getName()+"): "+iae.getMessage(), null, iae); + } + } + // ... as well as deserializer for contents: + JavaType contentType = type.getContentType(); + if (contentType.getValueHandler() == null) { // as with above, avoid resetting (which would trigger exception) + Class<? extends JsonDeserializer<?>> cdClass = intr.findContentDeserializer(a); + if (cdClass != null && cdClass != JsonDeserializer.None.class) { + JsonDeserializer<Object> cd = config.deserializerInstance(a, cdClass); + // !!! TODO: For 2.0, change to use this instead: + /* + type = (T) type.withContentValueHandler(cd); + */ + type.getContentType().setValueHandler(cd); + } + } + } + return type; + } + + /** + * Helper method used to resolve method return types and field + * types. The main trick here is that the containing bean may + * have type variable binding information (when deserializing + * using generic type passed as type reference), which is + * needed in some cases. + *<p> + * Starting with version 1.3, this method will also resolve instances + * of key and content deserializers if defined by annotations. + */ + @SuppressWarnings("deprecation") + protected JavaType resolveType(DeserializationConfig config, + BasicBeanDescription beanDesc, JavaType type, AnnotatedMember member, + BeanProperty property) + throws JsonMappingException + { + // [JACKSON-154]: Also need to handle keyUsing, contentUsing + if (type.isContainerType()) { + AnnotationIntrospector intr = config.getAnnotationIntrospector(); + JavaType keyType = type.getKeyType(); + if (keyType != null) { + Class<? extends KeyDeserializer> kdClass = intr.findKeyDeserializer(member); + if (kdClass != null && kdClass != KeyDeserializer.None.class) { + KeyDeserializer kd = config.keyDeserializerInstance(member, kdClass); + // !!! TODO: For 2.0, change to use this instead: + /* + type = ((MapLikeType) type).withKeyValueHandler(kd); + keyType = type.getKeyType(); // just in case it's used below + */ + keyType.setValueHandler(kd); + } + } + // and all container types have content types... + Class<? extends JsonDeserializer<?>> cdClass = intr.findContentDeserializer(member); + if (cdClass != null && cdClass != JsonDeserializer.None.class) { + JsonDeserializer<Object> cd = config.deserializerInstance(member, cdClass); + // !!! TODO: For 2.0, change to use this instead: + /* + type = type.withContentValueHandler(cd); + */ + type.getContentType().setValueHandler(cd); + } + /* 04-Feb-2010, tatu: Need to figure out JAXB annotations that indicate type + * information to use for polymorphic members; and specifically types for + * collection values (contents). + * ... but only applies to members (fields, methods), not classes + */ + if (member instanceof AnnotatedMember) { + TypeDeserializer contentTypeDeser = findPropertyContentTypeDeserializer(config, type, + (AnnotatedMember) member, property); + if (contentTypeDeser != null) { + type = type.withContentTypeHandler(contentTypeDeser); + } + } + } + TypeDeserializer valueTypeDeser; + + if (member instanceof AnnotatedMember) { // JAXB allows per-property annotations + valueTypeDeser = findPropertyTypeDeserializer(config, type, (AnnotatedMember) member, property); + } else { // classes just have Jackson annotations + // probably only occurs if 'property' is null anyway + valueTypeDeser = findTypeDeserializer(config, type, null); + } + if (valueTypeDeser != null) { + type = type.withTypeHandler(valueTypeDeser); + } + return type; + } + + protected EnumResolver<?> constructEnumResolver(Class<?> enumClass, DeserializationConfig config) + { + // [JACKSON-212]: may need to use Enum.toString() + if (config.isEnabled(DeserializationConfig.Feature.READ_ENUMS_USING_TO_STRING)) { + return EnumResolver.constructUnsafeUsingToString(enumClass); + } + return EnumResolver.constructUnsafe(enumClass, config.getAnnotationIntrospector()); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/BeanDeserializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/BeanDeserializer.java new file mode 100644 index 0000000..3e9630a --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/BeanDeserializer.java
@@ -0,0 +1,1541 @@ +package org.codehaus.jackson.map.deser; + +import java.io.IOException; +import java.lang.reflect.*; +import java.util.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.annotate.JsonTypeInfo; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.JsonCachable; +import org.codehaus.jackson.map.deser.impl.*; +import org.codehaus.jackson.map.deser.std.ContainerDeserializerBase; +import org.codehaus.jackson.map.deser.std.StdDeserializer; +import org.codehaus.jackson.map.introspect.AnnotatedClass; +import org.codehaus.jackson.map.introspect.AnnotatedMember; +import org.codehaus.jackson.map.introspect.AnnotatedWithParams; +import org.codehaus.jackson.map.type.ClassKey; +import org.codehaus.jackson.map.util.ClassUtil; +import org.codehaus.jackson.type.JavaType; +import org.codehaus.jackson.util.TokenBuffer; + +/** + * Deserializer class that can deserialize instances of + * arbitrary bean objects, usually from JSON Object structs, + * but possibly also from simple types like String values. + */ +@JsonCachable +/* Because of costs associated with constructing bean deserializers, + * they usually should be cached unlike other deserializer types. + * But more importantly, it is important to be able to cache + * bean serializers to handle cyclic references. + */ +public class BeanDeserializer + extends StdDeserializer<Object> + implements ResolvableDeserializer +{ + /* + /********************************************************** + /* Information regarding type being deserialized + /********************************************************** + */ + + /** + * Class for which deserializer is built; used for accessing + * annotations during resolution phase (see {@link #resolve}). + */ + final protected AnnotatedClass _forClass; + + /** + * Declared type of the bean this deserializer handles. + */ + final protected JavaType _beanType; + + /** + * Property that contains value to be deserialized using + * deserializer; mostly needed to find contextual annotations + * for subtypes. + * + * @since 1.7 + */ + final protected BeanProperty _property; + + /* + /********************************************************** + /* Construction configuration + /********************************************************** + */ + + /** + * Object that handles details of constructing initial + * bean value (to which bind data to), unless instance + * is passed (via updateValue()) + */ + protected final ValueInstantiator _valueInstantiator; + + /** + * Deserializer that is used iff delegate-based creator is + * to be used for deserializing from JSON Object. + */ + protected JsonDeserializer<Object> _delegateDeserializer; + + /** + * If the bean needs to be instantiated using constructor + * or factory method + * that takes one or more named properties as argument(s), + * this creator is used for instantiation. + */ + protected final PropertyBasedCreator _propertyBasedCreator; + + /** + * Flag that is set to mark "non-standard" cases; where either + * we use one of non-default creators, or there are unwrapped + * values to consider. + */ + protected boolean _nonStandardCreation; + + /* + /********************************************************** + /* Property information, setters + /********************************************************** + */ + + /** + * Mapping of property names to properties, built when all properties + * to use have been successfully resolved. + * + * @since 1.7 + */ + final protected BeanPropertyMap _beanProperties; + + /** + * List of {@link ValueInjector}s, if any injectable values are + * expected by the bean; otherwise null. + * This includes injectors used for injecting values via setters + * and fields, but not ones passed through constructor parameters. + * + * @since 1.9 + */ + final protected ValueInjector[] _injectables; + + /** + * Fallback setter used for handling any properties that are not + * mapped to regular setters. If setter is not null, it will be + * called once for each such property. + */ + protected SettableAnyProperty _anySetter; + + /** + * In addition to properties that are set, we will also keep + * track of recognized but ignorable properties: these will + * be skipped without errors or warnings. + */ + final protected HashSet<String> _ignorableProps; + + /** + * Flag that can be set to ignore and skip unknown properties. + * If set, will not throw an exception for unknown properties. + */ + final protected boolean _ignoreAllUnknown; + + /** + * We may also have one or more back reference fields (usually + * zero or one). + */ + final protected Map<String, SettableBeanProperty> _backRefs; + + /* + /********************************************************** + /* Related handlers + /********************************************************** + */ + + /** + * Lazily constructed map used to contain deserializers needed + * for polymorphic subtypes. + */ + protected HashMap<ClassKey, JsonDeserializer<Object>> _subDeserializers; + + /** + * If one of properties has "unwrapped" value, we need separate + * helper object + * + * @since 1.9 + */ + protected UnwrappedPropertyHandler _unwrappedPropertyHandler; + + /** + * Handler that we need iff any of properties uses external + * type id. + */ + protected ExternalTypeHandler _externalTypeIdHandler; + + /* + /********************************************************** + /* Life-cycle, construction, initialization + /********************************************************** + */ + + /** + * @deprecated (since 1.9) Use the constructor that takes {@link ValueInstantiator} instead + */ + @Deprecated + public BeanDeserializer(AnnotatedClass forClass, JavaType type, BeanProperty property, + CreatorCollector creators, + BeanPropertyMap properties, Map<String, SettableBeanProperty> backRefs, + HashSet<String> ignorableProps, boolean ignoreAllUnknown, + SettableAnyProperty anySetter) + { + this(forClass, type, property, + creators.constructValueInstantiator(null), + properties, backRefs, + ignorableProps, ignoreAllUnknown, + anySetter, null); + } + + /** + * @since 1.9 + */ + public BeanDeserializer(BeanDescription beanDesc, BeanProperty property, + ValueInstantiator valueInstantiator, + BeanPropertyMap properties, Map<String, SettableBeanProperty> backRefs, + HashSet<String> ignorableProps, boolean ignoreAllUnknown, + SettableAnyProperty anySetter, List<ValueInjector> injectables) + { + this(beanDesc.getClassInfo(), beanDesc.getType(), property, + valueInstantiator, + properties, backRefs, + ignorableProps, ignoreAllUnknown, + anySetter, injectables); + } + + /** + * @since 1.9 + */ + protected BeanDeserializer(AnnotatedClass forClass, JavaType type, BeanProperty property, + ValueInstantiator valueInstantiator, + BeanPropertyMap properties, Map<String, SettableBeanProperty> backRefs, + HashSet<String> ignorableProps, boolean ignoreAllUnknown, + SettableAnyProperty anySetter, List<ValueInjector> injectables) + { + super(type); + _forClass = forClass; + _beanType = type; + _property = property; + + _valueInstantiator = valueInstantiator; + if (valueInstantiator.canCreateFromObjectWith()) { + _propertyBasedCreator = new PropertyBasedCreator(valueInstantiator); + } else { + _propertyBasedCreator = null; + } + + _beanProperties = properties; + _backRefs = backRefs; + _ignorableProps = ignorableProps; + _ignoreAllUnknown = ignoreAllUnknown; + _anySetter = anySetter; + _injectables = (injectables == null || injectables.isEmpty()) ? null + : injectables.toArray(new ValueInjector[injectables.size()]); + + _nonStandardCreation = valueInstantiator.canCreateUsingDelegate() + || (_propertyBasedCreator != null) + || !valueInstantiator.canCreateUsingDefault() + || (_unwrappedPropertyHandler != null); + } + + /** + * Copy-constructor that can be used by sub-classes to allow + * copy-on-write styling copying of settings of an existing instance. + * + * @since 1.7 + */ + protected BeanDeserializer(BeanDeserializer src) + { + this(src, src._ignoreAllUnknown); + } + + /** + * @since 1.9 + */ + protected BeanDeserializer(BeanDeserializer src, boolean ignoreAllUnknown) + { + super(src._beanType); + + _forClass = src._forClass; + _beanType = src._beanType; + _property = src._property; + + _valueInstantiator = src._valueInstantiator; + _delegateDeserializer = src._delegateDeserializer; + _propertyBasedCreator = src._propertyBasedCreator; + + _beanProperties = src._beanProperties; + _backRefs = src._backRefs; + _ignorableProps = src._ignorableProps; + _ignoreAllUnknown = ignoreAllUnknown; + _anySetter = src._anySetter; + _injectables = src._injectables; + + _nonStandardCreation = src._nonStandardCreation; + _unwrappedPropertyHandler = src._unwrappedPropertyHandler; + } + + @Override + public JsonDeserializer<Object> unwrappingDeserializer() + { + /* bit kludgy but we don't want to accidentally change type; + * sub-classes MUST override this method to support unwrapped + * properties... + */ + if (getClass() != BeanDeserializer.class) { + return this; + } + /* main thing really is to just enforce ignoring of unknown + * properties; since there may be multiple unwrapped values + * and properties for all may be interleaved... + */ + return new BeanDeserializer(this, true); + } + + /* + /********************************************************** + /* Public accessors + /********************************************************** + */ + + public boolean hasProperty(String propertyName) { + return _beanProperties.find(propertyName) != null; + } + + /** + * Accessor for checking number of deserialized properties. + * + * @since 1.7 + */ + public int getPropertyCount() { + return _beanProperties.size(); + } + + public final Class<?> getBeanClass() { return _beanType.getRawClass(); } + + @Override public JavaType getValueType() { return _beanType; } + + /** + * + * @since 1.6 + */ + public Iterator<SettableBeanProperty> properties() + { + if (_beanProperties == null) { // since 1.7 + throw new IllegalStateException("Can only call before BeanDeserializer has been resolved"); + } + return _beanProperties.allProperties(); + } + + /** + * Method needed by {@link BeanDeserializerFactory} to properly link + * managed- and back-reference pairs. + */ + public SettableBeanProperty findBackReference(String logicalName) + { + if (_backRefs == null) { + return null; + } + return _backRefs.get(logicalName); + } + + /** + * @since 1.9 + */ + public ValueInstantiator getValueInstantiator() { + return _valueInstantiator; + } + + /* + /********************************************************** + /* Validation, post-processing + /********************************************************** + */ + + /** + * Method called to finalize setup of this deserializer, + * after deserializer itself has been registered. + * This is needed to handle recursive and transitive dependencies. + */ + @Override + public void resolve(DeserializationConfig config, DeserializerProvider provider) + throws JsonMappingException + { + Iterator<SettableBeanProperty> it = _beanProperties.allProperties(); + UnwrappedPropertyHandler unwrapped = null; + ExternalTypeHandler.Builder extTypes = null; + + while (it.hasNext()) { + SettableBeanProperty origProp = it.next(); + SettableBeanProperty prop = origProp; + // May already have deserializer from annotations, if so, skip: + if (!prop.hasValueDeserializer()) { + prop = prop.withValueDeserializer(findDeserializer(config, provider, prop.getType(), prop)); + } + // [JACKSON-235]: need to link managed references with matching back references + prop = _resolveManagedReferenceProperty(config, prop); + // [JACKSON-132]: support unwrapped values (via @JsonUnwrapped) + SettableBeanProperty u = _resolveUnwrappedProperty(config, prop); + if (u != null) { + prop = u; + if (unwrapped == null) { + unwrapped = new UnwrappedPropertyHandler(); + } + unwrapped.addProperty(prop); + } + // [JACKSON-594]: non-static inner classes too: + prop = _resolveInnerClassValuedProperty(config, prop); + if (prop != origProp) { + _beanProperties.replace(prop); + } + + /* one more thing: if this property uses "external property" type inclusion + * (see [JACKSON-453]), it needs different handling altogether + */ + if (prop.hasValueTypeDeserializer()) { + TypeDeserializer typeDeser = prop.getValueTypeDeserializer(); + if (typeDeser.getTypeInclusion() == JsonTypeInfo.As.EXTERNAL_PROPERTY) { + if (extTypes == null) { + extTypes = new ExternalTypeHandler.Builder(); + } + extTypes.addExternal(prop, typeDeser.getPropertyName()); + // In fact, remove from list of known properties to simplify later handling + _beanProperties.remove(prop); + } + } + } + + // Finally, "any setter" may also need to be resolved now + if (_anySetter != null && !_anySetter.hasValueDeserializer()) { + _anySetter = _anySetter.withValueDeserializer(findDeserializer(config, provider, _anySetter.getType(), _anySetter.getProperty())); + } + + // as well as delegate-based constructor: + if (_valueInstantiator.canCreateUsingDelegate()) { + JavaType delegateType = _valueInstantiator.getDelegateType(); + if (delegateType == null) { + throw new IllegalArgumentException("Invalid delegate-creator definition for "+_beanType + +": value instantiator ("+_valueInstantiator.getClass().getName() + +") returned true for 'canCreateUsingDelegate()', but null for 'getDelegateType()'"); + } + AnnotatedWithParams delegateCreator = _valueInstantiator.getDelegateCreator(); + // Need to create a temporary property to allow contextual deserializers: + BeanProperty.Std property = new BeanProperty.Std(null, + delegateType, _forClass.getAnnotations(), delegateCreator); + _delegateDeserializer = findDeserializer(config, provider, delegateType, property); + } + // or property-based one + // IMPORTANT: must access properties that _propertyBasedCreator has + if (_propertyBasedCreator != null) { + for (SettableBeanProperty prop : _propertyBasedCreator.getCreatorProperties()) { + if (!prop.hasValueDeserializer()) { + _propertyBasedCreator.assignDeserializer(prop, + findDeserializer(config, provider, prop.getType(), prop)); + } + } + } + if (extTypes != null) { + _externalTypeIdHandler = extTypes.build(); + // we consider this non-standard, to offline handling + _nonStandardCreation = true; + } + + _unwrappedPropertyHandler = unwrapped; + if (unwrapped != null) { // we consider this non-standard, to offline handling + _nonStandardCreation = true; + } + } + + /** + * Helper method called to see if given property is part of 'managed' property + * pair (managed + back reference), and if so, handle resolution details. + * + * @since 1.9 + */ + protected SettableBeanProperty _resolveManagedReferenceProperty(DeserializationConfig config, + SettableBeanProperty prop) + { + String refName = prop.getManagedReferenceName(); + if (refName == null) { + return prop; + } + JsonDeserializer<?> valueDeser = prop.getValueDeserializer(); + SettableBeanProperty backProp = null; + boolean isContainer = false; + if (valueDeser instanceof BeanDeserializer) { + backProp = ((BeanDeserializer) valueDeser).findBackReference(refName); + } else if (valueDeser instanceof ContainerDeserializerBase<?>) { + JsonDeserializer<?> contentDeser = ((ContainerDeserializerBase<?>) valueDeser).getContentDeserializer(); + if (!(contentDeser instanceof BeanDeserializer)) { + throw new IllegalArgumentException("Can not handle managed/back reference '"+refName + +"': value deserializer is of type ContainerDeserializerBase, but content type is not handled by a BeanDeserializer " + +" (instead it's of type "+contentDeser.getClass().getName()+")"); + } + backProp = ((BeanDeserializer) contentDeser).findBackReference(refName); + isContainer = true; + } else if (valueDeser instanceof AbstractDeserializer) { // [JACKSON-368]: not easy to fix, alas + throw new IllegalArgumentException("Can not handle managed/back reference for abstract types (property "+_beanType.getRawClass().getName()+"."+prop.getName()+")"); + } else { + throw new IllegalArgumentException("Can not handle managed/back reference '"+refName + +"': type for value deserializer is not BeanDeserializer or ContainerDeserializerBase, but " + +valueDeser.getClass().getName()); + } + if (backProp == null) { + throw new IllegalArgumentException("Can not handle managed/back reference '"+refName+"': no back reference property found from type " + +prop.getType()); + } + // also: verify that type is compatible + JavaType referredType = _beanType; + JavaType backRefType = backProp.getType(); + if (!backRefType.getRawClass().isAssignableFrom(referredType.getRawClass())) { + throw new IllegalArgumentException("Can not handle managed/back reference '"+refName+"': back reference type (" + +backRefType.getRawClass().getName()+") not compatible with managed type (" + +referredType.getRawClass().getName()+")"); + } + return new SettableBeanProperty.ManagedReferenceProperty(refName, prop, backProp, + _forClass.getAnnotations(), isContainer); + } + + /** + * Helper method called to see if given property might be so-called unwrapped + * property: these require special handling. + * + * @since 1.9 + */ + protected SettableBeanProperty _resolveUnwrappedProperty(DeserializationConfig config, + SettableBeanProperty prop) + { + AnnotatedMember am = prop.getMember(); + if (am != null && config.getAnnotationIntrospector().shouldUnwrapProperty(am) == Boolean.TRUE) { + JsonDeserializer<Object> orig = prop.getValueDeserializer(); + JsonDeserializer<Object> unwrapping = orig.unwrappingDeserializer(); + if (unwrapping != orig && unwrapping != null) { + // might be cleaner to create new instance; but difficult to do reliably, so: + return prop.withValueDeserializer(unwrapping); + } + } + return null; + } + + /** + * Helper method that will handle gruesome details of dealing with properties + * that have non-static inner class as value... + * + * @since 1.9 + */ + protected SettableBeanProperty _resolveInnerClassValuedProperty(DeserializationConfig config, + SettableBeanProperty prop) + { + /* Should we encounter a property that has non-static inner-class + * as value, we need to add some more magic to find the "hidden" constructor... + */ + JsonDeserializer<Object> deser = prop.getValueDeserializer(); + // ideally wouldn't rely on it being BeanDeserializer; but for now it'll have to do + if (deser instanceof BeanDeserializer) { + BeanDeserializer bd = (BeanDeserializer) deser; + ValueInstantiator vi = bd.getValueInstantiator(); + if (!vi.canCreateUsingDefault()) { // no default constructor + Class<?> valueClass = prop.getType().getRawClass(); + Class<?> enclosing = ClassUtil.getOuterClass(valueClass); + // and is inner class of the bean class... + if (enclosing != null && enclosing == _beanType.getRawClass()) { + for (Constructor<?> ctor : valueClass.getConstructors()) { + Class<?>[] paramTypes = ctor.getParameterTypes(); + if (paramTypes.length == 1 && paramTypes[0] == enclosing) { + if (config.isEnabled(DeserializationConfig.Feature.CAN_OVERRIDE_ACCESS_MODIFIERS)) { + ClassUtil.checkAndFixAccess(ctor); + } + return new SettableBeanProperty.InnerClassProperty(prop, ctor); + } + } + } + } + } + return prop; + } + + /* + /********************************************************** + /* JsonDeserializer implementation + /********************************************************** + */ + + /** + * Main deserialization method for bean-based objects (POJOs). + */ + @Override + public final Object deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + JsonToken t = jp.getCurrentToken(); + // common case first: + if (t == JsonToken.START_OBJECT) { + jp.nextToken(); + return deserializeFromObject(jp, ctxt); + } + // and then others, generally requiring use of @JsonCreator + switch (t) { + case VALUE_STRING: + return deserializeFromString(jp, ctxt); + case VALUE_NUMBER_INT: + return deserializeFromNumber(jp, ctxt); + case VALUE_NUMBER_FLOAT: + return deserializeFromDouble(jp, ctxt); + case VALUE_EMBEDDED_OBJECT: + return jp.getEmbeddedObject(); + case VALUE_TRUE: + case VALUE_FALSE: + return deserializeFromBoolean(jp, ctxt); + case START_ARRAY: + // these only work if there's a (delegating) creator... + return deserializeFromArray(jp, ctxt); + case FIELD_NAME: + case END_OBJECT: // added to resolve [JACKSON-319], possible related issues + return deserializeFromObject(jp, ctxt); + } + throw ctxt.mappingException(getBeanClass()); + } + + /** + * Secondary deserialization method, called in cases where POJO + * instance is created as part of deserialization, potentially + * after collecting some or all of the properties to set. + */ + @Override + public Object deserialize(JsonParser jp, DeserializationContext ctxt, Object bean) + throws IOException, JsonProcessingException + { + if (_injectables != null) { + injectValues(ctxt, bean); + } + if (_unwrappedPropertyHandler != null) { + return deserializeWithUnwrapped(jp, ctxt, bean); + } + if (_externalTypeIdHandler != null) { + return deserializeWithExternalTypeId(jp, ctxt, bean); + } + JsonToken t = jp.getCurrentToken(); + // 23-Mar-2010, tatu: In some cases, we start with full JSON object too... + if (t == JsonToken.START_OBJECT) { + t = jp.nextToken(); + } + for (; t == JsonToken.FIELD_NAME; t = jp.nextToken()) { + String propName = jp.getCurrentName(); + // Skip field name: + jp.nextToken(); + SettableBeanProperty prop = _beanProperties.find(propName); + + if (prop != null) { // normal case + try { + prop.deserializeAndSet(jp, ctxt, bean); + } catch (Exception e) { + wrapAndThrow(e, bean, propName, ctxt); + } + continue; + } + /* As per [JACKSON-313], things marked as ignorable should not be + * passed to any setter + */ + if (_ignorableProps != null && _ignorableProps.contains(propName)) { + jp.skipChildren(); + } else if (_anySetter != null) { + _anySetter.deserializeAndSet(jp, ctxt, bean, propName); + continue; + } else { + // Unknown: let's call handler method + handleUnknownProperty(jp, ctxt, bean, propName); + } + } + return bean; + } + + @Override + public Object deserializeWithType(JsonParser jp, DeserializationContext ctxt, + TypeDeserializer typeDeserializer) + throws IOException, JsonProcessingException + { + // In future could check current token... for now this should be enough: + return typeDeserializer.deserializeTypedFromObject(jp, ctxt); + } + + /* + /********************************************************** + /* Concrete deserialization methods + /********************************************************** + */ + + public Object deserializeFromObject(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + if (_nonStandardCreation) { + if (_unwrappedPropertyHandler != null) { + return deserializeWithUnwrapped(jp, ctxt); + } + if (_externalTypeIdHandler != null) { + return deserializeWithExternalTypeId(jp, ctxt); + } + return deserializeFromObjectUsingNonDefault(jp, ctxt); + } + + final Object bean = _valueInstantiator.createUsingDefault(); + if (_injectables != null) { + injectValues(ctxt, bean); + } + for (; jp.getCurrentToken() != JsonToken.END_OBJECT; jp.nextToken()) { + String propName = jp.getCurrentName(); + // Skip field name: + jp.nextToken(); + SettableBeanProperty prop = _beanProperties.find(propName); + if (prop != null) { // normal case + try { + prop.deserializeAndSet(jp, ctxt, bean); + } catch (Exception e) { + wrapAndThrow(e, bean, propName, ctxt); + } + continue; + } + _handleUnknown(jp, ctxt, bean, propName); + } + return bean; + } + + private final void _handleUnknown(JsonParser jp, DeserializationContext ctxt, + Object bean, String propName) + throws IOException, JsonProcessingException + { + /* As per [JACKSON-313], things marked as ignorable should not be + * passed to any setter + */ + if (_ignorableProps != null && _ignorableProps.contains(propName)) { + jp.skipChildren(); + } else if (_anySetter != null) { + try { + _anySetter.deserializeAndSet(jp, ctxt, bean, propName); + } catch (Exception e) { + wrapAndThrow(e, bean, propName, ctxt); + } + } else { + // Unknown: let's call handler method + handleUnknownProperty(jp, ctxt, bean, propName); + } + } + + /** + * @since 1.9 + */ + protected Object deserializeFromObjectUsingNonDefault(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + if (_delegateDeserializer != null) { + return _valueInstantiator.createUsingDelegate(_delegateDeserializer.deserialize(jp, ctxt)); + } + if (_propertyBasedCreator != null) { + return _deserializeUsingPropertyBased(jp, ctxt); + } + // should only occur for abstract types... + if (_beanType.isAbstract()) { + throw JsonMappingException.from(jp, "Can not instantiate abstract type "+_beanType + +" (need to add/enable type information?)"); + } + throw JsonMappingException.from(jp, "No suitable constructor found for type " + +_beanType+": can not instantiate from JSON object (need to add/enable type information?)"); + } + + public Object deserializeFromString(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + /* Bit complicated if we have delegating creator; may need to use it, + * or might not... + */ + if (_delegateDeserializer != null) { + if (!_valueInstantiator.canCreateFromString()) { + Object bean = _valueInstantiator.createUsingDelegate(_delegateDeserializer.deserialize(jp, ctxt)); + if (_injectables != null) { + injectValues(ctxt, bean); + } + return bean; + } + } + return _valueInstantiator.createFromString(jp.getText()); + } + + public Object deserializeFromNumber(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + switch (jp.getNumberType()) { + case INT: + if (_delegateDeserializer != null) { + if (!_valueInstantiator.canCreateFromInt()) { + Object bean = _valueInstantiator.createUsingDelegate(_delegateDeserializer.deserialize(jp, ctxt)); + if (_injectables != null) { + injectValues(ctxt, bean); + } + return bean; + } + } + return _valueInstantiator.createFromInt(jp.getIntValue()); + case LONG: + if (_delegateDeserializer != null) { + if (!_valueInstantiator.canCreateFromInt()) { + Object bean = _valueInstantiator.createUsingDelegate(_delegateDeserializer.deserialize(jp, ctxt)); + if (_injectables != null) { + injectValues(ctxt, bean); + } + return bean; + } + } + return _valueInstantiator.createFromLong(jp.getLongValue()); + } + // actually, could also be BigInteger, so: + if (_delegateDeserializer != null) { + Object bean = _valueInstantiator.createUsingDelegate(_delegateDeserializer.deserialize(jp, ctxt)); + if (_injectables != null) { + injectValues(ctxt, bean); + } + return bean; + } + throw ctxt.instantiationException(getBeanClass(), "no suitable creator method found to deserialize from JSON integer number"); + } + + /** + * Method called to deserialize POJO value from a JSON floating-point + * number. + * + * @since 1.9 + */ + public Object deserializeFromDouble(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + switch (jp.getNumberType()) { + case FLOAT: // no separate methods for taking float... + case DOUBLE: + if (_delegateDeserializer != null) { + if (!_valueInstantiator.canCreateFromDouble()) { + Object bean = _valueInstantiator.createUsingDelegate(_delegateDeserializer.deserialize(jp, ctxt)); + if (_injectables != null) { + injectValues(ctxt, bean); + } + return bean; + } + } + return _valueInstantiator.createFromDouble(jp.getDoubleValue()); + } + // actually, could also be BigDecimal, so: + if (_delegateDeserializer != null) { + return _valueInstantiator.createUsingDelegate(_delegateDeserializer.deserialize(jp, ctxt)); + } + throw ctxt.instantiationException(getBeanClass(), "no suitable creator method found to deserialize from JSON floating-point number"); + } + + /** + * Method called to deserialize POJO value from a JSON boolean + * value (true, false) + * + * @since 1.9 + */ + public Object deserializeFromBoolean(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + if (_delegateDeserializer != null) { + if (!_valueInstantiator.canCreateFromBoolean()) { + Object bean = _valueInstantiator.createUsingDelegate(_delegateDeserializer.deserialize(jp, ctxt)); + if (_injectables != null) { + injectValues(ctxt, bean); + } + return bean; + } + } + boolean value = (jp.getCurrentToken() == JsonToken.VALUE_TRUE); + return _valueInstantiator.createFromBoolean(value); + } + + /** + * @since 1.9 + */ + public Object deserializeFromArray(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + if (_delegateDeserializer != null) { + try { + Object bean = _valueInstantiator.createUsingDelegate(_delegateDeserializer.deserialize(jp, ctxt)); + if (_injectables != null) { + injectValues(ctxt, bean); + } + return bean; + } catch (Exception e) { + wrapInstantiationProblem(e, ctxt); + } + } + throw ctxt.mappingException(getBeanClass()); + } + + /** + * Method called to deserialize bean using "property-based creator": + * this means that a non-default constructor or factory method is + * called, and then possibly other setters. The trick is that + * values for creator method need to be buffered, first; and + * due to non-guaranteed ordering possibly some other properties + * as well. + * + * @since 1.2 + */ + protected final Object _deserializeUsingPropertyBased(final JsonParser jp, final DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + final PropertyBasedCreator creator = _propertyBasedCreator; + PropertyValueBuffer buffer = creator.startBuilding(jp, ctxt); + + // 04-Jan-2010, tatu: May need to collect unknown properties for polymorphic cases + TokenBuffer unknown = null; + + JsonToken t = jp.getCurrentToken(); + for (; t == JsonToken.FIELD_NAME; t = jp.nextToken()) { + String propName = jp.getCurrentName(); + jp.nextToken(); // to point to value + // creator property? + SettableBeanProperty creatorProp = creator.findCreatorProperty(propName); + if (creatorProp != null) { + // Last creator property to set? + Object value = creatorProp.deserialize(jp, ctxt); + if (buffer.assignParameter(creatorProp.getPropertyIndex(), value)) { + jp.nextToken(); // to move to following FIELD_NAME/END_OBJECT + Object bean; + try { + bean = creator.build(buffer); + } catch (Exception e) { + wrapAndThrow(e, _beanType.getRawClass(), propName, ctxt); + continue; // never gets here + } + // polymorphic? + if (bean.getClass() != _beanType.getRawClass()) { + return handlePolymorphic(jp, ctxt, bean, unknown); + } + if (unknown != null) { // nope, just extra unknown stuff... + bean = handleUnknownProperties(ctxt, bean, unknown); + } + // or just clean? + return deserialize(jp, ctxt, bean); + } + continue; + } + // regular property? needs buffering + SettableBeanProperty prop = _beanProperties.find(propName); + if (prop != null) { + buffer.bufferProperty(prop, prop.deserialize(jp, ctxt)); + continue; + } + /* As per [JACKSON-313], things marked as ignorable should not be + * passed to any setter + */ + if (_ignorableProps != null && _ignorableProps.contains(propName)) { + jp.skipChildren(); + continue; + } + // "any property"? + if (_anySetter != null) { + buffer.bufferAnyProperty(_anySetter, propName, _anySetter.deserialize(jp, ctxt)); + continue; + } + // Ok then, let's collect the whole field; name and value + if (unknown == null) { + unknown = new TokenBuffer(jp.getCodec()); + } + unknown.writeFieldName(propName); + unknown.copyCurrentStructure(jp); + } + + // We hit END_OBJECT, so: + Object bean; + try { + bean = creator.build(buffer); + } catch (Exception e) { + wrapInstantiationProblem(e, ctxt); + return null; // never gets here + } + if (unknown != null) { + // polymorphic? + if (bean.getClass() != _beanType.getRawClass()) { + return handlePolymorphic(null, ctxt, bean, unknown); + } + // no, just some extra unknown properties + return handleUnknownProperties(ctxt, bean, unknown); + } + return bean; + } + + /** + * Method called in cases where we may have polymorphic deserialization + * case: that is, type of Creator-constructed bean is not the type + * of deserializer itself. It should be a sub-class or implementation + * class; either way, we may have more specific deserializer to use + * for handling it. + * + * @param jp (optional) If not null, parser that has more properties to handle + * (in addition to buffered properties); if null, all properties are passed + * in buffer + */ + protected Object handlePolymorphic(JsonParser jp, DeserializationContext ctxt, + Object bean, TokenBuffer unknownTokens) + throws IOException, JsonProcessingException + { + // First things first: maybe there is a more specific deserializer available? + JsonDeserializer<Object> subDeser = _findSubclassDeserializer(ctxt, bean, unknownTokens); + if (subDeser != null) { + if (unknownTokens != null) { + // need to add END_OBJECT marker first + unknownTokens.writeEndObject(); + JsonParser p2 = unknownTokens.asParser(); + p2.nextToken(); // to get to first data field + bean = subDeser.deserialize(p2, ctxt, bean); + } + // Original parser may also have some leftovers + if (jp != null) { + bean = subDeser.deserialize(jp, ctxt, bean); + } + return bean; + } + // nope; need to use this deserializer. Unknowns we've seen so far? + if (unknownTokens != null) { + bean = handleUnknownProperties(ctxt, bean, unknownTokens); + } + // and/or things left to process via main parser? + if (jp != null) { + bean = deserialize(jp, ctxt, bean); + } + return bean; + } + + /* + /********************************************************** + /* Handling for cases where we have "unwrapped" values + /********************************************************** + */ + + /** + * Method called when there are declared "unwrapped" properties + * which need special handling + */ + protected Object deserializeWithUnwrapped(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + if (_delegateDeserializer != null) { + return _valueInstantiator.createUsingDelegate(_delegateDeserializer.deserialize(jp, ctxt)); + } + if (_propertyBasedCreator != null) { + return deserializeUsingPropertyBasedWithUnwrapped(jp, ctxt); + } + + TokenBuffer tokens = new TokenBuffer(jp.getCodec()); + tokens.writeStartObject(); + final Object bean = _valueInstantiator.createUsingDefault(); + + if (_injectables != null) { + injectValues(ctxt, bean); + } + + for (; jp.getCurrentToken() != JsonToken.END_OBJECT; jp.nextToken()) { + String propName = jp.getCurrentName(); + jp.nextToken(); + SettableBeanProperty prop = _beanProperties.find(propName); + if (prop != null) { // normal case + try { + prop.deserializeAndSet(jp, ctxt, bean); + } catch (Exception e) { + wrapAndThrow(e, bean, propName, ctxt); + } + continue; + } + // ignorable things should be ignored + if (_ignorableProps != null && _ignorableProps.contains(propName)) { + jp.skipChildren(); + continue; + } + // but... others should be passed to unwrapped property deserializers + tokens.writeFieldName(propName); + tokens.copyCurrentStructure(jp); + // how about any setter? We'll get copies but... + if (_anySetter != null) { + try { + _anySetter.deserializeAndSet(jp, ctxt, bean, propName); + } catch (Exception e) { + wrapAndThrow(e, bean, propName, ctxt); + } + continue; + } + } + tokens.writeEndObject(); + _unwrappedPropertyHandler.processUnwrapped(jp, ctxt, bean, tokens); + return bean; + } + + protected Object deserializeWithUnwrapped(JsonParser jp, DeserializationContext ctxt, Object bean) + throws IOException, JsonProcessingException + { + JsonToken t = jp.getCurrentToken(); + if (t == JsonToken.START_OBJECT) { + t = jp.nextToken(); + } + TokenBuffer tokens = new TokenBuffer(jp.getCodec()); + tokens.writeStartObject(); + for (; t == JsonToken.FIELD_NAME; t = jp.nextToken()) { + String propName = jp.getCurrentName(); + SettableBeanProperty prop = _beanProperties.find(propName); + jp.nextToken(); + if (prop != null) { // normal case + try { + prop.deserializeAndSet(jp, ctxt, bean); + } catch (Exception e) { + wrapAndThrow(e, bean, propName, ctxt); + } + continue; + } + if (_ignorableProps != null && _ignorableProps.contains(propName)) { + jp.skipChildren(); + continue; + } + // but... others should be passed to unwrapped property deserializers + tokens.writeFieldName(propName); + tokens.copyCurrentStructure(jp); + // how about any setter? We'll get copies but... + if (_anySetter != null) { + _anySetter.deserializeAndSet(jp, ctxt, bean, propName); + } + } + tokens.writeEndObject(); + _unwrappedPropertyHandler.processUnwrapped(jp, ctxt, bean, tokens); + return bean; + } + + protected Object deserializeUsingPropertyBasedWithUnwrapped(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + final PropertyBasedCreator creator = _propertyBasedCreator; + PropertyValueBuffer buffer = creator.startBuilding(jp, ctxt); + + TokenBuffer tokens = new TokenBuffer(jp.getCodec()); + tokens.writeStartObject(); + + JsonToken t = jp.getCurrentToken(); + for (; t == JsonToken.FIELD_NAME; t = jp.nextToken()) { + String propName = jp.getCurrentName(); + jp.nextToken(); // to point to value + // creator property? + SettableBeanProperty creatorProp = creator.findCreatorProperty(propName); + if (creatorProp != null) { + // Last creator property to set? + Object value = creatorProp.deserialize(jp, ctxt); + if (buffer.assignParameter(creatorProp.getPropertyIndex(), value)) { + t = jp.nextToken(); // to move to following FIELD_NAME/END_OBJECT + Object bean; + try { + bean = creator.build(buffer); + } catch (Exception e) { + wrapAndThrow(e, _beanType.getRawClass(), propName, ctxt); + continue; // never gets here + } + // if so, need to copy all remaining tokens into buffer + while (t == JsonToken.FIELD_NAME) { + jp.nextToken(); // to skip name + tokens.copyCurrentStructure(jp); + t = jp.nextToken(); + } + tokens.writeEndObject(); + if (bean.getClass() != _beanType.getRawClass()) { + // !!! 08-Jul-2011, tatu: Could probably support; but for now + // it's too complicated, so bail out + throw ctxt.mappingException("Can not create polymorphic instances with unwrapped values"); + } + return _unwrappedPropertyHandler.processUnwrapped(jp, ctxt, bean, tokens); + } + continue; + } + // regular property? needs buffering + SettableBeanProperty prop = _beanProperties.find(propName); + if (prop != null) { + buffer.bufferProperty(prop, prop.deserialize(jp, ctxt)); + continue; + } + /* As per [JACKSON-313], things marked as ignorable should not be + * passed to any setter + */ + if (_ignorableProps != null && _ignorableProps.contains(propName)) { + jp.skipChildren(); + continue; + } + tokens.writeFieldName(propName); + tokens.copyCurrentStructure(jp); + // "any property"? + if (_anySetter != null) { + buffer.bufferAnyProperty(_anySetter, propName, _anySetter.deserialize(jp, ctxt)); + } + } + + // We hit END_OBJECT, so: + Object bean; + try { + bean = creator.build(buffer); + } catch (Exception e) { + wrapInstantiationProblem(e, ctxt); + return null; // never gets here + } + return _unwrappedPropertyHandler.processUnwrapped(jp, ctxt, bean, tokens); + } + + /* + /********************************************************** + /* Handling for cases where we have property/-ies wth + /* external type id + /********************************************************** + */ + + protected Object deserializeWithExternalTypeId(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + if (_propertyBasedCreator != null) { + return deserializeUsingPropertyBasedWithExternalTypeId(jp, ctxt); + } + return deserializeWithExternalTypeId(jp, ctxt, _valueInstantiator.createUsingDefault()); + } + + protected Object deserializeWithExternalTypeId(JsonParser jp, DeserializationContext ctxt, + Object bean) + throws IOException, JsonProcessingException + { + final ExternalTypeHandler ext = _externalTypeIdHandler.start(); + for (; jp.getCurrentToken() != JsonToken.END_OBJECT; jp.nextToken()) { + String propName = jp.getCurrentName(); + jp.nextToken(); + SettableBeanProperty prop = _beanProperties.find(propName); + if (prop != null) { // normal case + // [JACKSON-831]: may have property AND be used as external type id: + if (jp.getCurrentToken().isScalarValue()) { + ext.handleTypePropertyValue(jp, ctxt, propName, bean); + } + try { + prop.deserializeAndSet(jp, ctxt, bean); + } catch (Exception e) { + wrapAndThrow(e, bean, propName, ctxt); + } + continue; + } + // ignorable things should be ignored + if (_ignorableProps != null && _ignorableProps.contains(propName)) { + jp.skipChildren(); + continue; + } + // but others are likely to be part of external type id thingy... + if (ext.handleToken(jp, ctxt, propName, bean)) { + continue; + } + // if not, the usual fallback handling: + if (_anySetter != null) { + try { + _anySetter.deserializeAndSet(jp, ctxt, bean, propName); + } catch (Exception e) { + wrapAndThrow(e, bean, propName, ctxt); + } + continue; + } else { + // Unknown: let's call handler method + handleUnknownProperty(jp, ctxt, bean, propName); + } + } + // and when we get this far, let's try finalizing the deal: + return ext.complete(jp, ctxt, bean); + } + + protected Object deserializeUsingPropertyBasedWithExternalTypeId(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + final ExternalTypeHandler ext = _externalTypeIdHandler.start(); + final PropertyBasedCreator creator = _propertyBasedCreator; + PropertyValueBuffer buffer = creator.startBuilding(jp, ctxt); + + TokenBuffer tokens = new TokenBuffer(jp.getCodec()); + tokens.writeStartObject(); + + JsonToken t = jp.getCurrentToken(); + for (; t == JsonToken.FIELD_NAME; t = jp.nextToken()) { + String propName = jp.getCurrentName(); + jp.nextToken(); // to point to value + // creator property? + SettableBeanProperty creatorProp = creator.findCreatorProperty(propName); + if (creatorProp != null) { + // Last creator property to set? + Object value = creatorProp.deserialize(jp, ctxt); + if (buffer.assignParameter(creatorProp.getPropertyIndex(), value)) { + t = jp.nextToken(); // to move to following FIELD_NAME/END_OBJECT + Object bean; + try { + bean = creator.build(buffer); + } catch (Exception e) { + wrapAndThrow(e, _beanType.getRawClass(), propName, ctxt); + continue; // never gets here + } + // if so, need to copy all remaining tokens into buffer + while (t == JsonToken.FIELD_NAME) { + jp.nextToken(); // to skip name + tokens.copyCurrentStructure(jp); + t = jp.nextToken(); + } + if (bean.getClass() != _beanType.getRawClass()) { + // !!! 08-Jul-2011, tatu: Could probably support; but for now + // it's too complicated, so bail out + throw ctxt.mappingException("Can not create polymorphic instances with unwrapped values"); + } + return ext.complete(jp, ctxt, bean); + } + continue; + } + // regular property? needs buffering + SettableBeanProperty prop = _beanProperties.find(propName); + if (prop != null) { + buffer.bufferProperty(prop, prop.deserialize(jp, ctxt)); + continue; + } + // external type id (or property that depends on it)? + if (ext.handleToken(jp, ctxt, propName, null)) { + continue; + } + /* As per [JACKSON-313], things marked as ignorable should not be + * passed to any setter + */ + if (_ignorableProps != null && _ignorableProps.contains(propName)) { + jp.skipChildren(); + continue; + } + // "any property"? + if (_anySetter != null) { + buffer.bufferAnyProperty(_anySetter, propName, _anySetter.deserialize(jp, ctxt)); + } + } + + // We hit END_OBJECT, so: + Object bean; + try { + bean = creator.build(buffer); + } catch (Exception e) { + wrapInstantiationProblem(e, ctxt); + return null; // never gets here + } + return ext.complete(jp, ctxt, bean); + } + + /* + /********************************************************** + /* Overridable helper methods + /********************************************************** + */ + + protected void injectValues(DeserializationContext ctxt, Object bean) + throws IOException, JsonProcessingException + { + for (ValueInjector injector : _injectables) { + injector.inject(ctxt, bean); + } + } + + /** + * Method called when a JSON property is encountered that has not matching + * setter, any-setter or field, and thus can not be assigned. + */ + @Override + protected void handleUnknownProperty(JsonParser jp, DeserializationContext ctxt, Object beanOrClass, String propName) + throws IOException, JsonProcessingException + { + /* 22-Aug-2010, tatu: Caller now mostly checks for ignorable properties, so + * following should not be necessary. However, "handleUnknownProperties()" seems + * to still possibly need it so it is left for now. + */ + // If registered as ignorable, skip + if (_ignoreAllUnknown || + (_ignorableProps != null && _ignorableProps.contains(propName))) { + jp.skipChildren(); + return; + } + /* Otherwise use default handling (call handler(s); if not + * handled, throw exception or skip depending on settings) + */ + super.handleUnknownProperty(jp, ctxt, beanOrClass, propName); + } + + /** + * Method called to handle set of one or more unknown properties, + * stored in their entirety in given {@link TokenBuffer} + * (as field entries, name and value). + */ + protected Object handleUnknownProperties(DeserializationContext ctxt, Object bean, TokenBuffer unknownTokens) + throws IOException, JsonProcessingException + { + // First: add closing END_OBJECT as marker + unknownTokens.writeEndObject(); + + // note: buffer does NOT have starting START_OBJECT + JsonParser bufferParser = unknownTokens.asParser(); + while (bufferParser.nextToken() != JsonToken.END_OBJECT) { + String propName = bufferParser.getCurrentName(); + // Unknown: let's call handler method + bufferParser.nextToken(); + handleUnknownProperty(bufferParser, ctxt, bean, propName); + } + return bean; + } + + /** + * Helper method called to (try to) locate deserializer for given sub-type of + * type that this deserializer handles. + */ + protected JsonDeserializer<Object> _findSubclassDeserializer(DeserializationContext ctxt, Object bean, TokenBuffer unknownTokens) + throws IOException, JsonProcessingException + { + JsonDeserializer<Object> subDeser; + + // First: maybe we have already created sub-type deserializer? + synchronized (this) { + subDeser = (_subDeserializers == null) ? null : _subDeserializers.get(new ClassKey(bean.getClass())); + } + if (subDeser != null) { + return subDeser; + } + // If not, maybe we can locate one. First, need provider + DeserializerProvider deserProv = ctxt.getDeserializerProvider(); + if (deserProv != null) { + JavaType type = ctxt.constructType(bean.getClass()); + /* 09-Dec-2010, tatu: Would be nice to know which property pointed to this + * bean... but, alas, no such information is retained, so: + */ + subDeser = deserProv.findValueDeserializer(ctxt.getConfig(), type, _property); + // Also, need to cache it + if (subDeser != null) { + synchronized (this) { + if (_subDeserializers == null) { + _subDeserializers = new HashMap<ClassKey,JsonDeserializer<Object>>();; + } + _subDeserializers.put(new ClassKey(bean.getClass()), subDeser); + } + } + } + return subDeser; + } + + /* + /********************************************************** + /* Helper methods for error reporting + /********************************************************** + */ + + /** + * Method that will modify caught exception (passed in as argument) + * as necessary to include reference information, and to ensure it + * is a subtype of {@link IOException}, or an unchecked exception. + *<p> + * Rules for wrapping and unwrapping are bit complicated; essentially: + *<ul> + * <li>Errors are to be passed as is (if uncovered via unwrapping) + * <li>"Plain" IOExceptions (ones that are not of type + * {@link JsonMappingException} are to be passed as is + *</ul> + */ + public void wrapAndThrow(Throwable t, Object bean, String fieldName, + DeserializationContext ctxt) + throws IOException + { + /* 05-Mar-2009, tatu: But one nasty edge is when we get + * StackOverflow: usually due to infinite loop. But that + * usually gets hidden within an InvocationTargetException... + */ + while (t instanceof InvocationTargetException && t.getCause() != null) { + t = t.getCause(); + } + // Errors and "plain" IOExceptions to be passed as is + if (t instanceof Error) { + throw (Error) t; + } + boolean wrap = (ctxt == null) || ctxt.isEnabled(DeserializationConfig.Feature.WRAP_EXCEPTIONS); + // Ditto for IOExceptions; except we may want to wrap mapping exceptions + if (t instanceof IOException) { + if (!wrap || !(t instanceof JsonMappingException)) { + throw (IOException) t; + } + } else if (!wrap) { // [JACKSON-407] -- allow disabling wrapping for unchecked exceptions + if (t instanceof RuntimeException) { + throw (RuntimeException) t; + } + } + // [JACKSON-55] Need to add reference information + throw JsonMappingException.wrapWithPath(t, bean, fieldName); + } + + public void wrapAndThrow(Throwable t, Object bean, int index, DeserializationContext ctxt) + throws IOException + { + while (t instanceof InvocationTargetException && t.getCause() != null) { + t = t.getCause(); + } + // Errors and "plain" IOExceptions to be passed as is + if (t instanceof Error) { + throw (Error) t; + } + boolean wrap = (ctxt == null) || ctxt.isEnabled(DeserializationConfig.Feature.WRAP_EXCEPTIONS); + // Ditto for IOExceptions; except we may want to wrap mapping exceptions + if (t instanceof IOException) { + if (!wrap || !(t instanceof JsonMappingException)) { + throw (IOException) t; + } + } else if (!wrap) { // [JACKSON-407] -- allow disabling wrapping for unchecked exceptions + if (t instanceof RuntimeException) { + throw (RuntimeException) t; + } + } + // [JACKSON-55] Need to add reference information + throw JsonMappingException.wrapWithPath(t, bean, index); + } + + protected void wrapInstantiationProblem(Throwable t, DeserializationContext ctxt) + throws IOException + { + while (t instanceof InvocationTargetException && t.getCause() != null) { + t = t.getCause(); + } + // Errors and "plain" IOExceptions to be passed as is + if (t instanceof Error) { + throw (Error) t; + } + boolean wrap = (ctxt == null) || ctxt.isEnabled(DeserializationConfig.Feature.WRAP_EXCEPTIONS); + if (t instanceof IOException) { + // Since we have no more information to add, let's not actually wrap.. + throw (IOException) t; + } else if (!wrap) { // [JACKSON-407] -- allow disabling wrapping for unchecked exceptions + if (t instanceof RuntimeException) { + throw (RuntimeException) t; + } + } + throw ctxt.instantiationException(_beanType.getRawClass(), t); + } + + /** + * @deprecated Since 1.7 use variant that takes {@link DeserializationContext} + */ + @Deprecated + public void wrapAndThrow(Throwable t, Object bean, String fieldName) + throws IOException + { + wrapAndThrow(t, bean, fieldName, null); + } + + /** + * @deprecated Since 1.7 use variant that takes {@link DeserializationContext} + */ + @Deprecated + public void wrapAndThrow(Throwable t, Object bean, int index) + throws IOException + { + wrapAndThrow(t, bean, index, null); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/BeanDeserializerBuilder.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/BeanDeserializerBuilder.java new file mode 100644 index 0000000..5c1030d --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/BeanDeserializerBuilder.java
@@ -0,0 +1,277 @@ +package org.codehaus.jackson.map.deser; + +import java.util.*; + +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.deser.impl.BeanPropertyMap; +import org.codehaus.jackson.map.deser.impl.ValueInjector; +import org.codehaus.jackson.map.introspect.AnnotatedMember; +import org.codehaus.jackson.map.introspect.BasicBeanDescription; +import org.codehaus.jackson.map.util.Annotations; +import org.codehaus.jackson.type.JavaType; + +/** + * Builder class used for aggregating deserialization information about + * a POJO, in order to build a {@link JsonDeserializer} for deserializing + * intances. + * + * @since 1.7 + */ +public class BeanDeserializerBuilder +{ + /* + /********************************************************** + /* General information about POJO + /********************************************************** + */ + + final protected BasicBeanDescription _beanDesc; + + /* + /********************************************************** + /* Accumulated information about properties + /********************************************************** + */ + + /** + * Properties to deserialize collected so far. + *<p> + * Note: since 1.9.1, LinkedHashMap has been used, since preservation + * of order is actually important for some use cases. + */ + final protected HashMap<String, SettableBeanProperty> _properties = new LinkedHashMap<String, SettableBeanProperty>(); + + /** + * Value injectors for deserialization + * + * @since 1.9 + */ + protected List<ValueInjector> _injectables; + + /** + * Back-reference properties this bean contains (if any) + */ + protected HashMap<String, SettableBeanProperty> _backRefProperties; + + /** + * Set of names of properties that are recognized but are to be ignored for deserialization + * purposes (meaning no exception is thrown, value is just skipped). + */ + protected HashSet<String> _ignorableProps; + + /** + * Object that will handle value instantiation for the bean type. + * + * @since 1.9 + */ + protected ValueInstantiator _valueInstantiator; + + /** + * Fallback setter used for handling any properties that are not + * mapped to regular setters. If setter is not null, it will be + * called once for each such property. + */ + protected SettableAnyProperty _anySetter; + + /** + * Flag that can be set to ignore and skip unknown properties. + * If set, will not throw an exception for unknown properties. + */ + protected boolean _ignoreAllUnknown; + + /* + /********************************************************** + /* Life-cycle: construction + /********************************************************** + */ + + public BeanDeserializerBuilder(BasicBeanDescription beanDesc) + { + _beanDesc = beanDesc; + } + + /** + * Copy constructor for sub-classes to use, when constructing + * custom builder instances + * + * @since 1.9 + */ + protected BeanDeserializerBuilder(BeanDeserializerBuilder src) + { + _beanDesc = src._beanDesc; + _anySetter = src._anySetter; + _ignoreAllUnknown = src._ignoreAllUnknown; + + // let's make copy of properties + _properties.putAll(src._properties); + _backRefProperties = _copy(src._backRefProperties); + // Hmmh. Should we create defensive copies here? For now, not yet + _ignorableProps = src._ignorableProps; + _valueInstantiator = src._valueInstantiator; + } + + private static HashMap<String, SettableBeanProperty> _copy(HashMap<String, SettableBeanProperty> src) + { + if (src == null) { + return null; + } + return new HashMap<String, SettableBeanProperty>(src); + } + + /* + /********************************************************** + /* Life-cycle: state modification (adders, setters) + /********************************************************** + */ + + /** + * Method for adding a new property or replacing a property. + */ + public void addOrReplaceProperty(SettableBeanProperty prop, boolean allowOverride) + { + _properties.put(prop.getName(), prop); + } + + /** + * Method to add a property setter. Will ensure that there is no + * unexpected override; if one is found will throw a + * {@link IllegalArgumentException}. + */ + public void addProperty(SettableBeanProperty prop) + { + SettableBeanProperty old = _properties.put(prop.getName(), prop); + if (old != null && old != prop) { // should never occur... + throw new IllegalArgumentException("Duplicate property '"+prop.getName()+"' for "+_beanDesc.getType()); + } + } + + /** + * Method called to add a property that represents so-called back reference; + * reference that "points back" to object that has forward reference to + * currently built bean. + */ + public void addBackReferenceProperty(String referenceName, SettableBeanProperty prop) + { + if (_backRefProperties == null) { + _backRefProperties = new HashMap<String, SettableBeanProperty>(4); + } + _backRefProperties.put(referenceName, prop); + // also: if we had property with same name, actually remove it + if (_properties != null) { + _properties.remove(prop.getName()); + } + } + + /** + * @since 1.9 + */ + public void addInjectable(String propertyName, JavaType propertyType, + Annotations contextAnnotations, AnnotatedMember member, + Object valueId) + { + if (_injectables == null) { + _injectables = new ArrayList<ValueInjector>(); + } + _injectables.add(new ValueInjector(propertyName, propertyType, + contextAnnotations, member, valueId)); + } + + /** + * Method that will add property name as one of properties that can + * be ignored if not recognized. + */ + public void addIgnorable(String propName) + { + if (_ignorableProps == null) { + _ignorableProps = new HashSet<String>(); + } + _ignorableProps.add(propName); + } + + /** + * Method called by deserializer factory, when a "creator property" + * (something that is passed via constructor- or factory method argument; + * instead of setter or field). + *<p> + * Default implementation does not do anything; we may need to revisit this + * decision if these properties need to be available through accessors. + * For now, however, we just have to ensure that we don't try to resolve + * types that masked setter/field has (see [JACKSON-700] for details). + * + * @since 1.9.2 + */ + public void addCreatorProperty(BeanPropertyDefinition propDef) + { + // do nothing + } + + public void setAnySetter(SettableAnyProperty s) + { + if (_anySetter != null && s != null) { + throw new IllegalStateException("_anySetter already set to non-null"); + } + _anySetter = s; + } + + public void setIgnoreUnknownProperties(boolean ignore) { + _ignoreAllUnknown = ignore; + } + + /** + * @since 1.9 + */ + public void setValueInstantiator(ValueInstantiator inst) { + _valueInstantiator = inst; + } + + /* + /********************************************************** + /* Public accessors + /********************************************************** + */ + + /** + * Method that allows accessing all properties that this + * builder currently contains. + *<p> + * Note that properties are returned in order that properties + * are ordered (explictly, or by rule), which is the serialization + * order. + * + * @since 1.8.3 + */ + public Iterator<SettableBeanProperty> getProperties() { + return _properties.values().iterator(); + } + + public boolean hasProperty(String propertyName) { + return _properties.containsKey(propertyName); + } + + public SettableBeanProperty removeProperty(String name) + { + return _properties.remove(name); + } + + /** + * @since 1.9 + */ + public ValueInstantiator getValueInstantiator() { + return _valueInstantiator; + } + + /* + /********************************************************** + /* Build method(s) + /********************************************************** + */ + + public JsonDeserializer<?> build(BeanProperty forProperty) + { + BeanPropertyMap propertyMap = new BeanPropertyMap(_properties.values()); + propertyMap.assignIndexes(); + return new BeanDeserializer(_beanDesc, forProperty, + _valueInstantiator, propertyMap, _backRefProperties, _ignorableProps, _ignoreAllUnknown, + _anySetter, _injectables); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/BeanDeserializerFactory.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/BeanDeserializerFactory.java new file mode 100644 index 0000000..620c9dc --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/BeanDeserializerFactory.java
@@ -0,0 +1,1476 @@ +package org.codehaus.jackson.map.deser; + +import java.util.*; + +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.deser.impl.CreatorCollector; +import org.codehaus.jackson.map.deser.impl.CreatorProperty; +import org.codehaus.jackson.map.deser.std.StdKeyDeserializers; +import org.codehaus.jackson.map.deser.std.ThrowableDeserializer; +import org.codehaus.jackson.map.introspect.*; +import org.codehaus.jackson.map.type.*; +import org.codehaus.jackson.map.util.ArrayBuilders; +import org.codehaus.jackson.map.util.ClassUtil; +import org.codehaus.jackson.map.util.EnumResolver; +import org.codehaus.jackson.type.JavaType; + +/** + * Concrete deserializer factory class that adds full Bean deserializer + * construction logic using class introspection. + *<p> + * Since there is no caching, this factory is stateless and a globally + * shared singleton instance ({@link #instance}) can be used by + * {@link DeserializerProvider}s). + */ +public class BeanDeserializerFactory + extends BasicDeserializerFactory +{ + /** + * Signature of <b>Throwable.initCause</b> method. + */ + private final static Class<?>[] INIT_CAUSE_PARAMS = new Class<?>[] { Throwable.class }; + + /* + /********************************************************** + /* Config class implementation + /********************************************************** + */ + + /** + * Standard configuration settings container class implementation. + * + * @since 1.7 + */ + public static class ConfigImpl extends Config + { + protected final static KeyDeserializers[] NO_KEY_DESERIALIZERS = new KeyDeserializers[0]; + protected final static BeanDeserializerModifier[] NO_MODIFIERS = new BeanDeserializerModifier[0]; + protected final static AbstractTypeResolver[] NO_ABSTRACT_TYPE_RESOLVERS = new AbstractTypeResolver[0]; + protected final static ValueInstantiators[] NO_VALUE_INSTANTIATORS = new ValueInstantiators[0]; + + /** + * List of providers for additional deserializers, checked before considering default + * basic or bean deserializers. + * + * @since 1.7 + */ + protected final Deserializers[] _additionalDeserializers; + + /** + * List of providers for additional key deserializers, checked before considering + * standard key deserializers. + * + * @since 1.7 + */ + protected final KeyDeserializers[] _additionalKeyDeserializers; + + /** + * List of modifiers that can change the way {@link BeanDeserializer} instances + * are configured and constructed. + */ + protected final BeanDeserializerModifier[] _modifiers; + + /** + * List of objects that may be able to resolve abstract types to + * concrete types. Used by functionality like "mr Bean" to materialize + * types as needed. + * + * @since 1.8 + */ + protected final AbstractTypeResolver[] _abstractTypeResolvers; + + /** + * List of objects that know how to create instances of POJO types; + * possibly using custom construction (non-annoted constructors; factory + * methods external to value type etc). + * Used to support objects that are created using non-standard methods; + * or to support post-constructor functionality. + * + * @since 1.9 + */ + protected final ValueInstantiators[] _valueInstantiators; + + /** + * Constructor for creating basic configuration with no additional + * handlers. + */ + public ConfigImpl() { + this(null, null, null, null, null); + } + + /** + * Copy-constructor that will create an instance that contains defined + * set of additional deserializer providers. + */ + protected ConfigImpl(Deserializers[] allAdditionalDeserializers, + KeyDeserializers[] allAdditionalKeyDeserializers, + BeanDeserializerModifier[] modifiers, + AbstractTypeResolver[] atr, + ValueInstantiators[] vi) + { + _additionalDeserializers = (allAdditionalDeserializers == null) ? + NO_DESERIALIZERS : allAdditionalDeserializers; + _additionalKeyDeserializers = (allAdditionalKeyDeserializers == null) ? + NO_KEY_DESERIALIZERS : allAdditionalKeyDeserializers; + _modifiers = (modifiers == null) ? NO_MODIFIERS : modifiers; + _abstractTypeResolvers = (atr == null) ? NO_ABSTRACT_TYPE_RESOLVERS : atr; + _valueInstantiators = (vi == null) ? NO_VALUE_INSTANTIATORS : vi; + } + + @Override + public Config withAdditionalDeserializers(Deserializers additional) + { + if (additional == null) { + throw new IllegalArgumentException("Can not pass null Deserializers"); + } + Deserializers[] all = ArrayBuilders.insertInListNoDup(_additionalDeserializers, additional); + return new ConfigImpl(all, _additionalKeyDeserializers, _modifiers, + _abstractTypeResolvers, _valueInstantiators); + } + + @Override + public Config withAdditionalKeyDeserializers(KeyDeserializers additional) + { + if (additional == null) { + throw new IllegalArgumentException("Can not pass null KeyDeserializers"); + } + KeyDeserializers[] all = ArrayBuilders.insertInListNoDup(_additionalKeyDeserializers, additional); + return new ConfigImpl(_additionalDeserializers, all, _modifiers, + _abstractTypeResolvers, _valueInstantiators); + } + + @Override + public Config withDeserializerModifier(BeanDeserializerModifier modifier) + { + if (modifier == null) { + throw new IllegalArgumentException("Can not pass null modifier"); + } + BeanDeserializerModifier[] all = ArrayBuilders.insertInListNoDup(_modifiers, modifier); + return new ConfigImpl(_additionalDeserializers, _additionalKeyDeserializers, all, + _abstractTypeResolvers, _valueInstantiators); + } + + @Override + public Config withAbstractTypeResolver(AbstractTypeResolver resolver) + { + if (resolver == null) { + throw new IllegalArgumentException("Can not pass null resolver"); + } + AbstractTypeResolver[] all = ArrayBuilders.insertInListNoDup(_abstractTypeResolvers, resolver); + return new ConfigImpl(_additionalDeserializers, _additionalKeyDeserializers, _modifiers, + all, _valueInstantiators); + } + + @Override + public Config withValueInstantiators(ValueInstantiators instantiators) + { + if (instantiators == null) { + throw new IllegalArgumentException("Can not pass null resolver"); + } + ValueInstantiators[] all = ArrayBuilders.insertInListNoDup(_valueInstantiators, instantiators); + return new ConfigImpl(_additionalDeserializers, _additionalKeyDeserializers, _modifiers, + _abstractTypeResolvers, all); + } + + @Override + public boolean hasDeserializers() { return _additionalDeserializers.length > 0; } + + @Override + public boolean hasKeyDeserializers() { return _additionalKeyDeserializers.length > 0; } + + @Override + public boolean hasDeserializerModifiers() { return _modifiers.length > 0; } + + @Override + public boolean hasAbstractTypeResolvers() { return _abstractTypeResolvers.length > 0; } + + @Override + public boolean hasValueInstantiators() { return _valueInstantiators.length > 0; } + + @Override + public Iterable<Deserializers> deserializers() { + return ArrayBuilders.arrayAsIterable(_additionalDeserializers); + } + + @Override + public Iterable<KeyDeserializers> keyDeserializers() { + return ArrayBuilders.arrayAsIterable(_additionalKeyDeserializers); + } + + @Override + public Iterable<BeanDeserializerModifier> deserializerModifiers() { + return ArrayBuilders.arrayAsIterable(_modifiers); + } + + @Override + public Iterable<AbstractTypeResolver> abstractTypeResolvers() { + return ArrayBuilders.arrayAsIterable(_abstractTypeResolvers); + } + + @Override + public Iterable<ValueInstantiators> valueInstantiators() { + return ArrayBuilders.arrayAsIterable(_valueInstantiators); + } + } + + /* + /********************************************************** + /* Life-cycle + /********************************************************** + */ + + /** + * Globally shareable thread-safe instance which has no additional custom deserializers + * registered + */ + public final static BeanDeserializerFactory instance = new BeanDeserializerFactory(null); + + /** + * Configuration settings for this factory; immutable instance (just like this + * factory), new version created via copy-constructor (fluent-style) + * + * @since 1.7 + */ + protected final Config _factoryConfig; + + @Deprecated + public BeanDeserializerFactory() { + this(null); + } + + /** + * @since 1.7 + */ + public BeanDeserializerFactory(DeserializerFactory.Config config) { + if (config == null) { + config = new ConfigImpl(); + } + _factoryConfig = config; + } + + @Override + public final Config getConfig() { + return _factoryConfig; + } + + /** + * Method used by module registration functionality, to construct a new bean + * deserializer factory + * with different configuration settings. + * + * @since 1.7 + */ + @Override + public DeserializerFactory withConfig(DeserializerFactory.Config config) + { + if (_factoryConfig == config) { + return this; + } + + /* 22-Nov-2010, tatu: Handling of subtypes is tricky if we do immutable-with-copy-ctor; + * and we pretty much have to here either choose between losing subtype instance + * when registering additional deserializers, or losing deserializers. + * Instead, let's actually just throw an error if this method is called when subtype + * has not properly overridden this method; this to indicate problem as soon as possible. + */ + if (getClass() != BeanDeserializerFactory.class) { + throw new IllegalStateException("Subtype of BeanDeserializerFactory ("+getClass().getName() + +") has not properly overridden method 'withAdditionalDeserializers': can not instantiate subtype with " + +"additional deserializer definitions"); + } + return new BeanDeserializerFactory(config); + } + + /* + /********************************************************** + /* Overrides for super-class methods used for finding + /* custom deserializers + /********************************************************** + */ + + @Override + public KeyDeserializer createKeyDeserializer(DeserializationConfig config, JavaType type, + BeanProperty property) + throws JsonMappingException + { + // First: possible custom deserializers + if (_factoryConfig.hasKeyDeserializers()) { + BasicBeanDescription beanDesc = config.introspectClassAnnotations(type.getRawClass()); + for (KeyDeserializers d : _factoryConfig.keyDeserializers()) { + KeyDeserializer deser = d.findKeyDeserializer(type, config, beanDesc, property); + if (deser != null) { + return deser; + } + } + } + // and if none found, standard ones: + // No serializer needed if it's plain old String, or Object/untyped + Class<?> raw = type.getRawClass(); + if (raw == String.class || raw == Object.class) { + return StdKeyDeserializers.constructStringKeyDeserializer(config, type); + } + // Most other keys are of limited number of static types + KeyDeserializer kdes = _keyDeserializers.get(type); + if (kdes != null) { + return kdes; + } + // And then other one-offs; first, Enum: + if (type.isEnumType()) { + return _createEnumKeyDeserializer(config, type, property); + } + // One more thing: can we find ctor(String) or valueOf(String)? + kdes = StdKeyDeserializers.findStringBasedKeyDeserializer(config, type); + return kdes; + } + + private KeyDeserializer _createEnumKeyDeserializer(DeserializationConfig config, JavaType type, + BeanProperty property) + throws JsonMappingException + { + BasicBeanDescription beanDesc = config.introspect(type); + Class<?> enumClass = type.getRawClass(); + EnumResolver<?> enumRes = constructEnumResolver(enumClass, config); + // [JACKSON-193] May have @JsonCreator for static factory method: + for (AnnotatedMethod factory : beanDesc.getFactoryMethods()) { + if (config.getAnnotationIntrospector().hasCreatorAnnotation(factory)) { + int argCount = factory.getParameterCount(); + if (argCount == 1) { + Class<?> returnType = factory.getRawType(); + // usually should be class, but may be just plain Enum<?> (for Enum.valueOf()?) + if (returnType.isAssignableFrom(enumClass)) { + // note: mostly copied from 'EnumDeserializer.deserializerForCreator(...)' + if (factory.getParameterType(0) != String.class) { + throw new IllegalArgumentException("Parameter #0 type for factory method ("+factory+") not suitable, must be java.lang.String"); + } + if (config.canOverrideAccessModifiers()) { + ClassUtil.checkAndFixAccess(factory.getMember()); + } + return StdKeyDeserializers.constructEnumKeyDeserializer(enumRes, factory); + } + } + throw new IllegalArgumentException("Unsuitable method ("+factory+") decorated with @JsonCreator (for Enum type " + +enumClass.getName()+")"); + } + } + // [JACKSON-749] Also, need to consider @JsonValue, if one found + return StdKeyDeserializers.constructEnumKeyDeserializer(enumRes); + } + + @Override + protected JsonDeserializer<?> _findCustomArrayDeserializer(ArrayType type, DeserializationConfig config, + DeserializerProvider provider, + BeanProperty property, + TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer) + throws JsonMappingException + { + for (Deserializers d : _factoryConfig.deserializers()) { + JsonDeserializer<?> deser = d.findArrayDeserializer(type, config, provider, property, + elementTypeDeserializer, elementDeserializer); + if (deser != null) { + return deser; + } + } + return null; + } + + @Override + protected JsonDeserializer<?> _findCustomCollectionDeserializer(CollectionType type, DeserializationConfig config, + DeserializerProvider provider, BasicBeanDescription beanDesc, + BeanProperty property, + TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer) + throws JsonMappingException + { + for (Deserializers d : _factoryConfig.deserializers()) { + JsonDeserializer<?> deser = d.findCollectionDeserializer(type, config, provider, beanDesc, property, + elementTypeDeserializer, elementDeserializer); + if (deser != null) { + return deser; + } + } + return null; + } + + @Override + protected JsonDeserializer<?> _findCustomCollectionLikeDeserializer(CollectionLikeType type, DeserializationConfig config, + DeserializerProvider provider, BasicBeanDescription beanDesc, + BeanProperty property, + TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer) + throws JsonMappingException + { + for (Deserializers d : _factoryConfig.deserializers()) { + JsonDeserializer<?> deser = d.findCollectionLikeDeserializer(type, config, provider, beanDesc, property, + elementTypeDeserializer, elementDeserializer); + if (deser != null) { + return deser; + } + } + return null; + } + + @Override + protected JsonDeserializer<?> _findCustomEnumDeserializer(Class<?> type, DeserializationConfig config, + BasicBeanDescription beanDesc, BeanProperty property) + throws JsonMappingException + { + for (Deserializers d : _factoryConfig.deserializers()) { + JsonDeserializer<?> deser = d.findEnumDeserializer(type, config, beanDesc, property); + if (deser != null) { + return deser; + } + } + return null; + } + + @Override + protected JsonDeserializer<?> _findCustomMapDeserializer(MapType type, + DeserializationConfig config, + DeserializerProvider provider, BasicBeanDescription beanDesc, BeanProperty property, + KeyDeserializer keyDeserializer, + TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer) + throws JsonMappingException + { + for (Deserializers d : _factoryConfig.deserializers()) { + JsonDeserializer<?> deser = d.findMapDeserializer(type, config, provider, beanDesc, property, + keyDeserializer, elementTypeDeserializer, elementDeserializer); + if (deser != null) { + return deser; + } + } + return null; + } + + @Override + protected JsonDeserializer<?> _findCustomMapLikeDeserializer(MapLikeType type, + DeserializationConfig config, + DeserializerProvider provider, BasicBeanDescription beanDesc, BeanProperty property, + KeyDeserializer keyDeserializer, + TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer) + throws JsonMappingException + { + for (Deserializers d : _factoryConfig.deserializers()) { + JsonDeserializer<?> deser = d.findMapLikeDeserializer(type, config, provider, beanDesc, property, + keyDeserializer, elementTypeDeserializer, elementDeserializer); + if (deser != null) { + return deser; + } + } + return null; + } + + @Override + protected JsonDeserializer<?> _findCustomTreeNodeDeserializer(Class<? extends JsonNode> type, + DeserializationConfig config, BeanProperty property) + throws JsonMappingException + { + for (Deserializers d : _factoryConfig.deserializers()) { + JsonDeserializer<?> deser = d.findTreeNodeDeserializer(type, config, property); + if (deser != null) { + return deser; + } + } + return null; + } + + // Note: NOT overriding, superclass has no matching method + @SuppressWarnings("unchecked") + protected JsonDeserializer<Object> _findCustomBeanDeserializer(JavaType type, DeserializationConfig config, + DeserializerProvider provider, BasicBeanDescription beanDesc, BeanProperty property) + throws JsonMappingException + { + for (Deserializers d : _factoryConfig.deserializers()) { + JsonDeserializer<?> deser = d.findBeanDeserializer(type, config, provider, beanDesc, property); + if (deser != null) { + return (JsonDeserializer<Object>) deser; + } + } + return null; + } + + /* + /********************************************************** + /* DeserializerFactory API implementation + /********************************************************** + */ + + /** + * Method that will find complete abstract type mapping for specified type, doing as + * many resolution steps as necessary. + */ + @Override + public JavaType mapAbstractType(DeserializationConfig config, JavaType type) + throws JsonMappingException + { + while (true) { + JavaType next = _mapAbstractType2(config, type); + if (next == null) { + return type; + } + /* Should not have to worry about cycles; but better verify since they will invariably + * occur... :-) + * (also: guard against invalid resolution to a non-related type) + */ + Class<?> prevCls = type.getRawClass(); + Class<?> nextCls = next.getRawClass(); + if ((prevCls == nextCls) || !prevCls.isAssignableFrom(nextCls)) { + throw new IllegalArgumentException("Invalid abstract type resolution from "+type+" to "+next+": latter is not a subtype of former"); + } + type = next; + } + } + + /** + * Value instantiator is created both based on creator annotations, + * and on optional externally provided instantiators (registered through + * module interface). + */ + @Override + public ValueInstantiator findValueInstantiator(DeserializationConfig config, + BasicBeanDescription beanDesc) + throws JsonMappingException + { + ValueInstantiator instantiator; + // [JACKSON-633] Check @JsonValueInstantiator before anything else + AnnotatedClass ac = beanDesc.getClassInfo(); + Object instDef = config.getAnnotationIntrospector().findValueInstantiator(ac); + if (instDef != null) { + if (instDef instanceof ValueInstantiator) { + instantiator = (ValueInstantiator) instDef; + } else { + if (!(instDef instanceof Class<?>)) { // sanity check + throw new IllegalStateException("Invalid value instantiator returned for type "+beanDesc+": neither a Class nor ValueInstantiator"); + } + Class<?> cls = (Class<?>) instDef; + if (!ValueInstantiator.class.isAssignableFrom(cls)) { + throw new IllegalStateException("Invalid instantiator Class<?> returned for type "+beanDesc+": " + +cls.getName()+" not a ValueInstantiator"); + } + @SuppressWarnings("unchecked") + Class<? extends ValueInstantiator> instClass = (Class<? extends ValueInstantiator>) cls; + instantiator = config.valueInstantiatorInstance(ac, (Class<? extends ValueInstantiator>)instClass); + } + } else { + instantiator = constructDefaultValueInstantiator(config, beanDesc); + } + + // finally: anyone want to modify ValueInstantiator? + if (_factoryConfig.hasValueInstantiators()) { + for (ValueInstantiators insts : _factoryConfig.valueInstantiators()) { + instantiator = insts.findValueInstantiator(config, beanDesc, instantiator); + // let's do sanity check; easier to spot buggy handlers + if (instantiator == null) { + throw new JsonMappingException("Broken registered ValueInstantiators (of type " + +insts.getClass().getName()+"): returned null ValueInstantiator"); + } + } + } + + return instantiator; + } + + /** + * Method that {@link DeserializerProvider}s call to create a new + * deserializer for types other than Collections, Maps, arrays and + * enums. + */ + @Override + public JsonDeserializer<Object> createBeanDeserializer(DeserializationConfig config, + DeserializerProvider p, JavaType type, BeanProperty property) + throws JsonMappingException + { + // First things first: abstract types may use defaulting: + if (type.isAbstract()) { + type = mapAbstractType(config, type); + } + + // First things first: maybe explicit definition via annotations? + BasicBeanDescription beanDesc = config.introspect(type); + JsonDeserializer<Object> ad = findDeserializerFromAnnotation(config, beanDesc.getClassInfo(), property); + if (ad != null) { + return ad; + } + // Or value annotation that indicates more specific type to use: + JavaType newType = modifyTypeByAnnotation(config, beanDesc.getClassInfo(), type, null); + if (newType.getRawClass() != type.getRawClass()) { + type = newType; + beanDesc = config.introspect(type); + } + // We may also have custom overrides: + JsonDeserializer<Object> custom = _findCustomBeanDeserializer(type, config, p, beanDesc, property); + if (custom != null) { + return custom; + } + /* One more thing to check: do we have an exception type + * (Throwable or its sub-classes)? If so, need slightly + * different handling. + */ + if (type.isThrowable()) { + return buildThrowableDeserializer(config, type, beanDesc, property); + } + /* Or, for abstract types, may have alternate means for resolution + * (defaulting, materialization) + */ + if (type.isAbstract()) { + // [JACKSON-41] (v1.6): Let's make it possible to materialize abstract types. + JavaType concreteType = materializeAbstractType(config, beanDesc); + if (concreteType != null) { + /* important: introspect actual implementation (abstract class or + * interface doesn't have constructors, for one) + */ + beanDesc = config.introspect(concreteType); + return buildBeanDeserializer(config, concreteType, beanDesc, property); + } + } + + // Otherwise, may want to check handlers for standard types, from superclass: + JsonDeserializer<Object> deser = findStdBeanDeserializer(config, p, type, property); + if (deser != null) { + return deser; + } + + // Otherwise: could the class be a Bean class? If not, bail out + if (!isPotentialBeanType(type.getRawClass())) { + return null; + } + // Use generic bean introspection to build deserializer + return buildBeanDeserializer(config, type, beanDesc, property); + } + + /** + * Method that will find abstract type mapping for specified type, doing a single + * lookup through registered abstract type resolvers; will not do recursive lookups. + */ + protected JavaType _mapAbstractType2(DeserializationConfig config, JavaType type) + throws JsonMappingException + { + Class<?> currClass = type.getRawClass(); + if (_factoryConfig.hasAbstractTypeResolvers()) { + for (AbstractTypeResolver resolver : _factoryConfig.abstractTypeResolvers()) { + JavaType concrete = resolver.findTypeMapping(config, type); + if (concrete != null && concrete.getRawClass() != currClass) { + return concrete; + } + } + } + return null; + } + + protected JavaType materializeAbstractType(DeserializationConfig config, + BasicBeanDescription beanDesc) + throws JsonMappingException + { + final JavaType abstractType = beanDesc.getType(); + + /* [JACKSON-502] (1.8): Now it is possible to have multiple resolvers too, + * as they are registered via module interface. + */ + for (AbstractTypeResolver r : _factoryConfig.abstractTypeResolvers()) { + JavaType concrete = r.resolveAbstractType(config, abstractType); + if (concrete != null) { + return concrete; + } + } + return null; + } + + /* + /********************************************************** + /* Public construction method beyond DeserializerFactory API: + /* can be called from outside as well as overridden by + /* sub-classes + /********************************************************** + */ + + /** + * Method that is to actually build a bean deserializer instance. + * All basic sanity checks have been done to know that what we have + * may be a valid bean type, and that there are no default simple + * deserializers. + */ + @SuppressWarnings("unchecked") + public JsonDeserializer<Object> buildBeanDeserializer(DeserializationConfig config, + JavaType type, BasicBeanDescription beanDesc, BeanProperty property) + throws JsonMappingException + { + // First: check what creators we can use, if any + ValueInstantiator valueInstantiator = findValueInstantiator(config, beanDesc); + // ... since often we have nothing to go on, if we have abstract type: + if (type.isAbstract()) { + if (!valueInstantiator.canInstantiate()) { + // and if so, need placeholder deserializer + return new AbstractDeserializer(type); + } + } + BeanDeserializerBuilder builder = constructBeanDeserializerBuilder(beanDesc); + builder.setValueInstantiator(valueInstantiator); + // And then setters for deserializing from JSON Object + addBeanProps(config, beanDesc, builder); + // managed/back reference fields/setters need special handling... first part + addReferenceProperties(config, beanDesc, builder); + addInjectables(config, beanDesc, builder); + + // [JACKSON-440]: update builder now that all information is in? + if (_factoryConfig.hasDeserializerModifiers()) { + for (BeanDeserializerModifier mod : _factoryConfig.deserializerModifiers()) { + builder = mod.updateBuilder(config, beanDesc, builder); + } + } + JsonDeserializer<?> deserializer = builder.build(property); + + // [JACKSON-440]: may have modifier(s) that wants to modify or replace serializer we just built: + if (_factoryConfig.hasDeserializerModifiers()) { + for (BeanDeserializerModifier mod : _factoryConfig.deserializerModifiers()) { + deserializer = mod.modifyDeserializer(config, beanDesc, deserializer); + } + } + return (JsonDeserializer<Object>) deserializer; + + } + + @SuppressWarnings("unchecked") + public JsonDeserializer<Object> buildThrowableDeserializer(DeserializationConfig config, + JavaType type, BasicBeanDescription beanDesc, BeanProperty property) + throws JsonMappingException + { + // first: construct like a regular bean deserializer... + BeanDeserializerBuilder builder = constructBeanDeserializerBuilder(beanDesc); + builder.setValueInstantiator(findValueInstantiator(config, beanDesc)); + + addBeanProps(config, beanDesc, builder); + // (and assume there won't be any back references) + + // But then let's decorate things a bit + /* To resolve [JACKSON-95], need to add "initCause" as setter + * for exceptions (sub-classes of Throwable). + */ + AnnotatedMethod am = beanDesc.findMethod("initCause", INIT_CAUSE_PARAMS); + if (am != null) { // should never be null + SettableBeanProperty prop = constructSettableProperty(config, beanDesc, "cause", am); + if (prop != null) { + /* 21-Aug-2011, tatus: We may actually have found 'cause' property + * to set (with new 1.9 code)... but let's replace it just in case, + * otherwise can end up with odd errors. + */ + builder.addOrReplaceProperty(prop, true); + } + } + + // And also need to ignore "localizedMessage" + builder.addIgnorable("localizedMessage"); + /* As well as "message": it will be passed via constructor, + * as there's no 'setMessage()' method + */ + builder.addIgnorable("message"); + // [JACKSON-794]: JDK 7 also added "getSuppressed", skip if we have such data: + builder.addIgnorable("suppressed"); + + // [JACKSON-440]: update builder now that all information is in? + if (_factoryConfig.hasDeserializerModifiers()) { + for (BeanDeserializerModifier mod : _factoryConfig.deserializerModifiers()) { + builder = mod.updateBuilder(config, beanDesc, builder); + } + } + JsonDeserializer<?> deserializer = builder.build(property); + + /* At this point it ought to be a BeanDeserializer; if not, must assume + * it's some other thing that can handle deserialization ok... + */ + if (deserializer instanceof BeanDeserializer) { + deserializer = new ThrowableDeserializer((BeanDeserializer) deserializer); + } + + // [JACKSON-440]: may have modifier(s) that wants to modify or replace serializer we just built: + if (_factoryConfig.hasDeserializerModifiers()) { + for (BeanDeserializerModifier mod : _factoryConfig.deserializerModifiers()) { + deserializer = mod.modifyDeserializer(config, beanDesc, deserializer); + } + } + return (JsonDeserializer<Object>) deserializer; + } + + /* + /********************************************************** + /* Helper methods for Bean deserializer construction, + /* overridable by sub-classes + /********************************************************** + */ + + /** + * Overridable method that constructs a {@link BeanDeserializerBuilder} + * which is used to accumulate information needed to create deserializer + * instance. + * + * @since 1.7 + */ + protected BeanDeserializerBuilder constructBeanDeserializerBuilder(BasicBeanDescription beanDesc) { + return new BeanDeserializerBuilder(beanDesc); + } + + /** + * Method that will construct standard default {@link ValueInstantiator} + * using annotations (like @JsonCreator) and visibility rules + * + * @since 1.9 + */ + protected ValueInstantiator constructDefaultValueInstantiator(DeserializationConfig config, + BasicBeanDescription beanDesc) + throws JsonMappingException + { + boolean fixAccess = config.isEnabled(DeserializationConfig.Feature.CAN_OVERRIDE_ACCESS_MODIFIERS); + CreatorCollector creators = new CreatorCollector(beanDesc, fixAccess); + AnnotationIntrospector intr = config.getAnnotationIntrospector(); + + // First, let's figure out constructor/factory-based instantiation + // 23-Jan-2010, tatus: but only for concrete types + if (beanDesc.getType().isConcrete()) { + AnnotatedConstructor defaultCtor = beanDesc.findDefaultConstructor(); + if (defaultCtor != null) { + if (fixAccess) { + ClassUtil.checkAndFixAccess(defaultCtor.getAnnotated()); + } + creators.setDefaultConstructor(defaultCtor); + } + } + + // need to construct suitable visibility checker: + VisibilityChecker<?> vchecker = config.getDefaultVisibilityChecker(); + vchecker = config.getAnnotationIntrospector().findAutoDetectVisibility(beanDesc.getClassInfo(), vchecker); + + /* Important: first add factory methods; then constructors, so + * latter can override former! + */ + _addDeserializerFactoryMethods(config, beanDesc, vchecker, intr, creators); + _addDeserializerConstructors(config, beanDesc, vchecker, intr, creators); + + return creators.constructValueInstantiator(config); + } + + protected void _addDeserializerConstructors + (DeserializationConfig config, BasicBeanDescription beanDesc, VisibilityChecker<?> vchecker, + AnnotationIntrospector intr, CreatorCollector creators) + throws JsonMappingException + { + for (AnnotatedConstructor ctor : beanDesc.getConstructors()) { + int argCount = ctor.getParameterCount(); + if (argCount < 1) { + continue; + } + boolean isCreator = intr.hasCreatorAnnotation(ctor); + boolean isVisible = vchecker.isCreatorVisible(ctor); + // some single-arg constructors (String, number) are auto-detected + if (argCount == 1) { + _handleSingleArgumentConstructor(config, beanDesc, vchecker, intr, creators, + ctor, isCreator, isVisible); + continue; + } + if (!isCreator && !isVisible) { + continue; + } + // [JACKSON-541] improved handling a bit so: + // 2 or more args; all params must have name annotations + // ... or @JacksonInject (or equivalent) + // But if it was auto-detected and there's no annotations, keep silent (was not meant to be a creator?) + boolean annotationFound = false; + /* [JACKSON-712] One more possibility; can have 1 or more injectables, and + * exactly one non-annotated parameter: if so, it's still delegating. + */ + AnnotatedParameter nonAnnotatedParam = null; + int namedCount = 0; + int injectCount = 0; + CreatorProperty[] properties = new CreatorProperty[argCount]; + for (int i = 0; i < argCount; ++i) { + AnnotatedParameter param = ctor.getParameter(i); + String name = (param == null) ? null : intr.findPropertyNameForParam(param); + Object injectId = intr.findInjectableValueId(param); + if (name != null && name.length() > 0) { + ++namedCount; + properties[i] = constructCreatorProperty(config, beanDesc, name, i, param, injectId); + } else if (injectId != null) { + ++injectCount; + properties[i] = constructCreatorProperty(config, beanDesc, name, i, param, injectId); + } else if (nonAnnotatedParam == null) { + nonAnnotatedParam = param; + } + } + + // Ok: if named or injectable, we have more work to do + if (isCreator || namedCount > 0 || injectCount > 0) { + // simple case; everything covered: + if ((namedCount + injectCount) == argCount) { + creators.addPropertyCreator(ctor, properties); + } else if ((namedCount == 0) && ((injectCount + 1) == argCount)) { + // secondary: all but one injectable, one un-annotated (un-named) + // [JACKSON-712] SHOULD support; but we won't yet (tricky to do, not impossible) + throw new IllegalArgumentException("Delegated constructor with Injectables not yet supported (see [JACKSON-712]) for " + +ctor); + } else { // otherwise, epic fail + throw new IllegalArgumentException("Argument #"+nonAnnotatedParam.getIndex()+" of constructor "+ctor+" has no property name annotation; must have name when multiple-paramater constructor annotated as Creator"); + } + } + if (annotationFound) { + creators.addPropertyCreator(ctor, properties); + } + } + } + + protected boolean _handleSingleArgumentConstructor(DeserializationConfig config, + BasicBeanDescription beanDesc, VisibilityChecker<?> vchecker, + AnnotationIntrospector intr, CreatorCollector creators, + AnnotatedConstructor ctor, boolean isCreator, boolean isVisible) + throws JsonMappingException + { + // note: if we do have parameter name, it'll be "property constructor": + AnnotatedParameter param = ctor.getParameter(0); + String name = intr.findPropertyNameForParam(param); + Object injectId = intr.findInjectableValueId(param); + + if ((injectId != null) || (name != null && name.length() > 0)) { // property-based + // We know there's a name and it's only 1 parameter. + CreatorProperty[] properties = new CreatorProperty[1]; + properties[0] = constructCreatorProperty(config, beanDesc, name, 0, param, injectId); + creators.addPropertyCreator(ctor, properties); + return true; + } + + // otherwise either 'simple' number, String, or general delegate: + Class<?> type = ctor.getParameterClass(0); + if (type == String.class) { + if (isCreator || isVisible) { + creators.addStringCreator(ctor); + } + return true; + } + if (type == int.class || type == Integer.class) { + if (isCreator || isVisible) { + creators.addIntCreator(ctor); + } + return true; + } + if (type == long.class || type == Long.class) { + if (isCreator || isVisible) { + creators.addLongCreator(ctor); + } + return true; + } + if (type == double.class || type == Double.class) { + if (isCreator || isVisible) { + creators.addDoubleCreator(ctor); + } + return true; + } + + // Delegating Creator ok iff it has @JsonCreator (etc) + if (isCreator) { + creators.addDelegatingCreator(ctor); + return true; + } + return false; + } + + protected void _addDeserializerFactoryMethods + (DeserializationConfig config, BasicBeanDescription beanDesc, VisibilityChecker<?> vchecker, + AnnotationIntrospector intr, CreatorCollector creators) + throws JsonMappingException + { + + for (AnnotatedMethod factory : beanDesc.getFactoryMethods()) { + int argCount = factory.getParameterCount(); + if (argCount < 1) { + continue; + } + boolean isCreator = intr.hasCreatorAnnotation(factory); + // some single-arg factory methods (String, number) are auto-detected + if (argCount == 1) { + AnnotatedParameter param = factory.getParameter(0); + String name = intr.findPropertyNameForParam(param); + Object injectId = intr.findInjectableValueId(param); + + if ((injectId == null) && (name == null || name.length() == 0)) { // not property based + _handleSingleArgumentFactory(config, beanDesc, vchecker, intr, creators, + factory, isCreator); + // otherwise just ignored + continue; + } + // fall through if there's name + } else { + // more than 2 args, must be @JsonCreator + if (!intr.hasCreatorAnnotation(factory)) { + continue; + } + } + // 1 or more args; all params must have name annotations + CreatorProperty[] properties = new CreatorProperty[argCount]; + for (int i = 0; i < argCount; ++i) { + AnnotatedParameter param = factory.getParameter(i); + String name = intr.findPropertyNameForParam(param); + Object injectableId = intr.findInjectableValueId(param); + // At this point, name annotation is NOT optional + if ((name == null || name.length() == 0) && (injectableId == null)) { + throw new IllegalArgumentException("Argument #"+i+" of factory method "+factory+" has no property name annotation; must have when multiple-paramater static method annotated as Creator"); + } + properties[i] = constructCreatorProperty(config, beanDesc, name, i, param, injectableId); + } + creators.addPropertyCreator(factory, properties); + } + } + + protected boolean _handleSingleArgumentFactory(DeserializationConfig config, + BasicBeanDescription beanDesc, VisibilityChecker<?> vchecker, + AnnotationIntrospector intr, CreatorCollector creators, + AnnotatedMethod factory, boolean isCreator) + throws JsonMappingException + { + Class<?> type = factory.getParameterClass(0); + + if (type == String.class) { + if (isCreator || vchecker.isCreatorVisible(factory)) { + creators.addStringCreator(factory); + } + return true; + } + if (type == int.class || type == Integer.class) { + if (isCreator || vchecker.isCreatorVisible(factory)) { + creators.addIntCreator(factory); + } + return true; + } + if (type == long.class || type == Long.class) { + if (isCreator || vchecker.isCreatorVisible(factory)) { + creators.addLongCreator(factory); + } + return true; + } + if (type == double.class || type == Double.class) { + if (isCreator || vchecker.isCreatorVisible(factory)) { + creators.addDoubleCreator(factory); + } + return true; + } + if (type == boolean.class || type == Boolean.class) { + if (isCreator || vchecker.isCreatorVisible(factory)) { + creators.addBooleanCreator(factory); + } + return true; + } + if (intr.hasCreatorAnnotation(factory)) { + creators.addDelegatingCreator(factory); + return true; + } + return false; + } + + /** + * Method that will construct a property object that represents + * a logical property passed via Creator (constructor or static + * factory method) + */ + protected CreatorProperty constructCreatorProperty(DeserializationConfig config, + BasicBeanDescription beanDesc, String name, int index, + AnnotatedParameter param, + Object injectableValueId) + throws JsonMappingException + { + JavaType t0 = config.getTypeFactory().constructType(param.getParameterType(), beanDesc.bindingsForBeanType()); + BeanProperty.Std property = new BeanProperty.Std(name, t0, beanDesc.getClassAnnotations(), param); + JavaType type = resolveType(config, beanDesc, t0, param, property); + if (type != t0) { + property = property.withType(type); + } + // Is there an annotation that specifies exact deserializer? + JsonDeserializer<Object> deser = findDeserializerFromAnnotation(config, param, property); + // If yes, we are mostly done: + type = modifyTypeByAnnotation(config, param, type, name); + + // Type deserializer: either comes from property (and already resolved) + TypeDeserializer typeDeser = (TypeDeserializer) type.getTypeHandler(); + // or if not, based on type being referenced: + if (typeDeser == null) { + typeDeser = findTypeDeserializer(config, type, property); + } + CreatorProperty prop = new CreatorProperty(name, type, typeDeser, + beanDesc.getClassAnnotations(), param, index, injectableValueId); + if (deser != null) { + prop = prop.withValueDeserializer(deser); + } + return prop; + } + + /** + * Method called to figure out settable properties for the + * bean deserializer to use. + *<p> + * Note: designed to be overridable, and effort is made to keep interface + * similar between versions. + */ + protected void addBeanProps(DeserializationConfig config, + BasicBeanDescription beanDesc, BeanDeserializerBuilder builder) + throws JsonMappingException + { + List<BeanPropertyDefinition> props = beanDesc.findProperties(); + // Things specified as "ok to ignore"? [JACKSON-77] + AnnotationIntrospector intr = config.getAnnotationIntrospector(); + boolean ignoreAny = false; + { + Boolean B = intr.findIgnoreUnknownProperties(beanDesc.getClassInfo()); + if (B != null) { + ignoreAny = B.booleanValue(); + builder.setIgnoreUnknownProperties(ignoreAny); + } + } + // Or explicit/implicit definitions? + Set<String> ignored = ArrayBuilders.arrayToSet(intr.findPropertiesToIgnore(beanDesc.getClassInfo())); + for (String propName : ignored) { + builder.addIgnorable(propName); + } + AnnotatedMethod anySetter = beanDesc.findAnySetter(); + // Implicit ones via @JsonIgnore and equivalent? + /* 26-Dec-2011, tatu: As per [JACKSON-744], it probably does NOT make + * sense to consider ignorable, esp. now that both getters and setters + * can induce ignoral. + */ + { + Collection<String> ignored2 = (anySetter == null) ? + beanDesc.getIgnoredPropertyNames() : beanDesc.getIgnoredPropertyNamesForDeser(); + if (ignored2 != null) { + for (String propName : ignored2) { + // allow ignoral of similarly named JSON property, but do not force; + // latter means NOT adding this to 'ignored': + builder.addIgnorable(propName); + } + } + } + HashMap<Class<?>,Boolean> ignoredTypes = new HashMap<Class<?>,Boolean>(); + + // These are all valid setters, but we do need to introspect bit more + for (BeanPropertyDefinition property : props) { + String name = property.getName(); + if (ignored.contains(name)) { // explicit ignoral using @JsonIgnoreProperties needs to block entries + continue; + } + /* [JACKSON-700] If property as passed via constructor parameter, we must + * handle things in special way. Not sure what is the most optimal way... + * for now, let's just call a (new) method in builder, which does nothing. + */ + if (property.hasConstructorParameter()) { + // but let's call a method just to allow custom builders to be aware... + builder.addCreatorProperty(property); + continue; + } + // primary: have a setter? + if (property.hasSetter()) { + AnnotatedMethod setter = property.getSetter(); + // [JACKSON-429] Some types are declared as ignorable as well + Class<?> type = setter.getParameterClass(0); + if (isIgnorableType(config, beanDesc, type, ignoredTypes)) { + // important: make ignorable, to avoid errors if value is actually seen + builder.addIgnorable(name); + continue; + } + SettableBeanProperty prop = constructSettableProperty(config, beanDesc, name, setter); + if (prop != null) { + builder.addProperty(prop); + } + continue; + } + if (property.hasField()) { + AnnotatedField field = property.getField(); + // [JACKSON-429] Some types are declared as ignorable as well + Class<?> type = field.getRawType(); + if (isIgnorableType(config, beanDesc, type, ignoredTypes)) { + // important: make ignorable, to avoid errors if value is actually seen + builder.addIgnorable(name); + continue; + } + SettableBeanProperty prop = constructSettableProperty(config, beanDesc, name, field); + if (prop != null) { + builder.addProperty(prop); + } + } + } + // Also, do we have a fallback "any" setter? + if (anySetter != null) { + builder.setAnySetter(constructAnySetter(config, beanDesc, anySetter)); + } + + /* As per [JACKSON-88], may also need to consider getters + * for Map/Collection properties + */ + /* also, as per [JACKSON-328], should not override fields (or actual setters), + * thus these are added AFTER adding fields + */ + if (config.isEnabled(DeserializationConfig.Feature.USE_GETTERS_AS_SETTERS)) { + /* Hmmh. We have to assume that 'use getters as setters' also + * implies 'yes, do auto-detect these getters'? (if not, we'd + * need to add AUTO_DETECT_GETTERS to deser config too, not + * just ser config) + */ + for (BeanPropertyDefinition property : props) { + if (property.hasGetter()) { + String name = property.getName(); + if (builder.hasProperty(name) || ignored.contains(name)) { + continue; + } + AnnotatedMethod getter = property.getGetter(); + // should only consider Collections and Maps, for now? + Class<?> rt = getter.getRawType(); + if (Collection.class.isAssignableFrom(rt) || Map.class.isAssignableFrom(rt)) { + if (!ignored.contains(name) && !builder.hasProperty(name)) { + builder.addProperty(constructSetterlessProperty(config, beanDesc, name, getter)); + } + } + } + } + } + } + + /** + * Method that will find if bean has any managed- or back-reference properties, + * and if so add them to bean, to be linked during resolution phase. + * + * @since 1.6 + */ + protected void addReferenceProperties(DeserializationConfig config, + BasicBeanDescription beanDesc, BeanDeserializerBuilder builder) + throws JsonMappingException + { + // and then back references, not necessarily found as regular properties + Map<String,AnnotatedMember> refs = beanDesc.findBackReferenceProperties(); + if (refs != null) { + for (Map.Entry<String, AnnotatedMember> en : refs.entrySet()) { + String name = en.getKey(); + AnnotatedMember m = en.getValue(); + if (m instanceof AnnotatedMethod) { + builder.addBackReferenceProperty(name, constructSettableProperty( + config, beanDesc, m.getName(), (AnnotatedMethod) m)); + } else { + builder.addBackReferenceProperty(name, constructSettableProperty( + config, beanDesc, m.getName(), (AnnotatedField) m)); + } + } + } + } + + /** + * Method called locate all members used for value injection (if any), + * constructor {@link org.codehaus.jackson.map.deser.impl.ValueInjector} instances, and add them to builder. + * + * @since 1.9 + */ + protected void addInjectables(DeserializationConfig config, + BasicBeanDescription beanDesc, BeanDeserializerBuilder builder) + throws JsonMappingException + { + Map<Object, AnnotatedMember> raw = beanDesc.findInjectables(); + if (raw != null) { + boolean fixAccess = config.isEnabled(DeserializationConfig.Feature.CAN_OVERRIDE_ACCESS_MODIFIERS); + for (Map.Entry<Object, AnnotatedMember> entry : raw.entrySet()) { + AnnotatedMember m = entry.getValue(); + if (fixAccess) { + m.fixAccess(); // to ensure we can call it + } + builder.addInjectable(m.getName(), beanDesc.resolveType(m.getGenericType()), + beanDesc.getClassAnnotations(), m, entry.getKey()); + } + } + } + + /** + * Method called to construct fallback {@link SettableAnyProperty} + * for handling unknown bean properties, given a method that + * has been designated as such setter. + */ + protected SettableAnyProperty constructAnySetter(DeserializationConfig config, + BasicBeanDescription beanDesc, AnnotatedMethod setter) + throws JsonMappingException + { + if (config.isEnabled(DeserializationConfig.Feature.CAN_OVERRIDE_ACCESS_MODIFIERS)) { + setter.fixAccess(); // to ensure we can call it + } + // we know it's a 2-arg method, second arg is the value + JavaType type = beanDesc.bindingsForBeanType().resolveType(setter.getParameterType(1)); + BeanProperty.Std property = new BeanProperty.Std(setter.getName(), type, beanDesc.getClassAnnotations(), setter); + type = resolveType(config, beanDesc, type, setter, property); + + /* AnySetter can be annotated with @JsonClass (etc) just like a + * regular setter... so let's see if those are used. + * Returns null if no annotations, in which case binding will + * be done at a later point. + */ + JsonDeserializer<Object> deser = findDeserializerFromAnnotation(config, setter, property); + if (deser != null) { + return new SettableAnyProperty(property, setter, type, deser); + } + /* Otherwise, method may specify more specific (sub-)class for + * value (no need to check if explicit deser was specified): + */ + type = modifyTypeByAnnotation(config, setter, type, property.getName()); + return new SettableAnyProperty(property, setter, type, null); + } + + /** + * Method that will construct a regular bean property setter using + * the given setter method. + * + * @param setter Method to use to set property value; or null if none. + * Null only for "setterless" properties + * + * @return Property constructed, if any; or null to indicate that + * there should be no property based on given definitions. + */ + protected SettableBeanProperty constructSettableProperty(DeserializationConfig config, + BasicBeanDescription beanDesc, String name, + AnnotatedMethod setter) + throws JsonMappingException + { + // need to ensure method is callable (for non-public) + if (config.isEnabled(DeserializationConfig.Feature.CAN_OVERRIDE_ACCESS_MODIFIERS)) { + setter.fixAccess(); + } + + // note: this works since we know there's exactly one argument for methods + JavaType t0 = beanDesc.bindingsForBeanType().resolveType(setter.getParameterType(0)); + BeanProperty.Std property = new BeanProperty.Std(name, t0, beanDesc.getClassAnnotations(), setter); + JavaType type = resolveType(config, beanDesc, t0, setter, property); + // did type change? + if (type != t0) { + property = property.withType(type); + } + + /* First: does the Method specify the deserializer to use? + * If so, let's use it. + */ + JsonDeserializer<Object> propDeser = findDeserializerFromAnnotation(config, setter, property); + type = modifyTypeByAnnotation(config, setter, type, name); + TypeDeserializer typeDeser = type.getTypeHandler(); + SettableBeanProperty prop = new SettableBeanProperty.MethodProperty(name, type, typeDeser, + beanDesc.getClassAnnotations(), setter); + if (propDeser != null) { + prop = prop.withValueDeserializer(propDeser); + } + // [JACKSON-235]: need to retain name of managed forward references: + AnnotationIntrospector.ReferenceProperty ref = config.getAnnotationIntrospector().findReferenceType(setter); + if (ref != null && ref.isManagedReference()) { + prop.setManagedReferenceName(ref.getName()); + } + return prop; + } + + protected SettableBeanProperty constructSettableProperty(DeserializationConfig config, + BasicBeanDescription beanDesc, String name, AnnotatedField field) + throws JsonMappingException + { + // need to ensure method is callable (for non-public) + if (config.isEnabled(DeserializationConfig.Feature.CAN_OVERRIDE_ACCESS_MODIFIERS)) { + field.fixAccess(); + } + JavaType t0 = beanDesc.bindingsForBeanType().resolveType(field.getGenericType()); + BeanProperty.Std property = new BeanProperty.Std(name, t0, beanDesc.getClassAnnotations(), field); + JavaType type = resolveType(config, beanDesc, t0, field, property); + // did type change? + if (type != t0) { + property = property.withType(type); + } + /* First: does the Method specify the deserializer to use? + * If so, let's use it. + */ + JsonDeserializer<Object> propDeser = findDeserializerFromAnnotation(config, field, property); + type = modifyTypeByAnnotation(config, field, type, name); + TypeDeserializer typeDeser = type.getTypeHandler(); + SettableBeanProperty prop = new SettableBeanProperty.FieldProperty(name, type, typeDeser, + beanDesc.getClassAnnotations(), field); + if (propDeser != null) { + prop = prop.withValueDeserializer(propDeser); + } + // [JACKSON-235]: need to retain name of managed forward references: + AnnotationIntrospector.ReferenceProperty ref = config.getAnnotationIntrospector().findReferenceType(field); + if (ref != null && ref.isManagedReference()) { + prop.setManagedReferenceName(ref.getName()); + } + return prop; + } + + /** + * Method that will construct a regular bean property setter using + * the given setter method. + * + * @param getter Method to use to get property value to modify, null if + * none. Non-null for "setterless" properties. + */ + protected SettableBeanProperty constructSetterlessProperty(DeserializationConfig config, + BasicBeanDescription beanDesc, String name, AnnotatedMethod getter) + throws JsonMappingException + { + // need to ensure it is callable now: + if (config.isEnabled(DeserializationConfig.Feature.CAN_OVERRIDE_ACCESS_MODIFIERS)) { + getter.fixAccess(); + } + + JavaType type = getter.getType(beanDesc.bindingsForBeanType()); + /* First: does the Method specify the deserializer to use? + * If so, let's use it. + */ + BeanProperty.Std property = new BeanProperty.Std(name, type, beanDesc.getClassAnnotations(), getter); + // @TODO: create BeanProperty to pass? + JsonDeserializer<Object> propDeser = findDeserializerFromAnnotation(config, getter, property); + type = modifyTypeByAnnotation(config, getter, type, name); + TypeDeserializer typeDeser = type.getTypeHandler(); + SettableBeanProperty prop = new SettableBeanProperty.SetterlessProperty(name, type, typeDeser, + beanDesc.getClassAnnotations(), getter); + if (propDeser != null) { + prop = prop.withValueDeserializer(propDeser); + } + return prop; + } + + /* + /********************************************************** + /* Helper methods for Bean deserializer, other + /********************************************************** + */ + + /** + * Helper method used to skip processing for types that we know + * can not be (i.e. are never consider to be) beans: + * things like primitives, Arrays, Enums, and proxy types. + *<p> + * Note that usually we shouldn't really be getting these sort of + * types anyway; but better safe than sorry. + */ + protected boolean isPotentialBeanType(Class<?> type) + { + String typeStr = ClassUtil.canBeABeanType(type); + if (typeStr != null) { + throw new IllegalArgumentException("Can not deserialize Class "+type.getName()+" (of type "+typeStr+") as a Bean"); + } + if (ClassUtil.isProxyType(type)) { + throw new IllegalArgumentException("Can not deserialize Proxy class "+type.getName()+" as a Bean"); + } + /* also: can't deserialize some local classes: static are ok; in-method not; + * and with [JACKSON-594], other non-static inner classes are ok + */ + typeStr = ClassUtil.isLocalType(type, true); + if (typeStr != null) { + throw new IllegalArgumentException("Can not deserialize Class "+type.getName()+" (of type "+typeStr+") as a Bean"); + } + return true; + } + + /** + * Helper method that will check whether given raw type is marked as always ignorable + * (for purpose of ignoring properties with type) + */ + protected boolean isIgnorableType(DeserializationConfig config, BasicBeanDescription beanDesc, + Class<?> type, Map<Class<?>,Boolean> ignoredTypes) + { + Boolean status = ignoredTypes.get(type); + if (status == null) { + BasicBeanDescription desc = config.introspectClassAnnotations(type); + status = config.getAnnotationIntrospector().isIgnorableType(desc.getClassInfo()); + // We default to 'false', ie. not ignorable + if (status == null) { + status = Boolean.FALSE; + } + } + return status; + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/BeanDeserializerModifier.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/BeanDeserializerModifier.java new file mode 100644 index 0000000..69c0dab --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/BeanDeserializerModifier.java
@@ -0,0 +1,58 @@ +package org.codehaus.jackson.map.deser; + +import org.codehaus.jackson.map.DeserializationConfig; +import org.codehaus.jackson.map.JsonDeserializer; +import org.codehaus.jackson.map.deser.BeanDeserializer; +import org.codehaus.jackson.map.deser.BeanDeserializerFactory; +import org.codehaus.jackson.map.introspect.BasicBeanDescription; + +/** + * Abstract class that defines API for objects that can be registered (for {@link BeanDeserializerFactory} + * to participate in constructing {@link BeanDeserializer} instances. + * This is typically done by modules that want alter some aspects of deserialization + * process; and is preferable to sub-classing of {@link BeanDeserializerFactory}. + *<p> + * Sequence in which callback methods are called is as follows: + * <li>updateBuilder is called once all initial pieces for building deserializer + * have been collected + * </li> + * <li><code>modifyDeserializer</code> is called after deserializer has been built + * by {@link BeanDeserializerBuilder} + * but before it is returned to be used + * </li> + * </ol> + *<p> + * Default method implementations are "no-op"s, meaning that methods are implemented + * but have no effect; this is mostly so that new methods can be added in later + * versions. + * + * @since 1.7 + */ +public abstract class BeanDeserializerModifier +{ + /** + * Method called by {@link BeanDeserializerFactory} when it has collected + * basic information such as tentative list of properties to deserialize. + * + * Implementations may choose to modify state of builder (to affect deserializer being + * built), or even completely replace it (if they want to build different kind of + * deserializer). Typically changes mostly concern set of properties to deserialize. + */ + public BeanDeserializerBuilder updateBuilder(DeserializationConfig config, + BasicBeanDescription beanDesc, BeanDeserializerBuilder builder) { + return builder; + } + + /** + * Method called by {@link BeanDeserializerFactory} after constructing default + * bean deserializer instance with properties collected and ordered earlier. + * Implementations can modify or replace given deserializer and return deserializer + * to use. Note that although initial deserializer being passed is of type + * {@link BeanDeserializer}, modifiers may return deserializers of other types; + * and this is why implementations must check for type before casting. + */ + public JsonDeserializer<?> modifyDeserializer(DeserializationConfig config, + BasicBeanDescription beanDesc, JsonDeserializer<?> deserializer) { + return deserializer; + } +} \ No newline at end of file
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/CollectionDeserializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/CollectionDeserializer.java new file mode 100644 index 0000000..8c64490 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/CollectionDeserializer.java
@@ -0,0 +1,47 @@ +package org.codehaus.jackson.map.deser; + +import java.lang.reflect.Constructor; +import java.util.*; + +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.type.JavaType; + +/** + * @deprecated Since 1.9, use {@link org.codehaus.jackson.map.deser.std.ContainerDeserializerBase} instead. + */ +@Deprecated +public class CollectionDeserializer + extends org.codehaus.jackson.map.deser.std.CollectionDeserializer +{ + /** + * @deprecated Since 1.9, use variant that takes ValueInstantiator + */ + @SuppressWarnings("deprecation") + @Deprecated + public CollectionDeserializer(JavaType collectionType, JsonDeserializer<Object> valueDeser, + TypeDeserializer valueTypeDeser, + Constructor<Collection<Object>> defCtor) + { + super(collectionType, valueDeser, valueTypeDeser, defCtor); + } + + /** + * @since 1.9 + */ + public CollectionDeserializer(JavaType collectionType, JsonDeserializer<Object> valueDeser, + TypeDeserializer valueTypeDeser, ValueInstantiator valueInstantiator) + { + super(collectionType, valueDeser, valueTypeDeser, valueInstantiator); + } + + /** + * Copy-constructor that can be used by sub-classes to allow + * copy-on-write styling copying of settings of an existing instance. + * + * @since 1.9 + */ + protected CollectionDeserializer(CollectionDeserializer src) + { + super(src); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/ContainerDeserializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/ContainerDeserializer.java new file mode 100644 index 0000000..e653406 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/ContainerDeserializer.java
@@ -0,0 +1,14 @@ +package org.codehaus.jackson.map.deser; + +/** + * @deprecated Since 1.9, use {@link org.codehaus.jackson.map.deser.std.ContainerDeserializerBase} instead. + */ +@Deprecated +public abstract class ContainerDeserializer<T> + extends org.codehaus.jackson.map.deser.std.ContainerDeserializerBase<T> +{ + protected ContainerDeserializer(Class<?> selfType) + { + super(selfType); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/CustomDeserializerFactory.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/CustomDeserializerFactory.java new file mode 100644 index 0000000..4a8e040 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/CustomDeserializerFactory.java
@@ -0,0 +1,227 @@ +package org.codehaus.jackson.map.deser; + +import java.util.*; + +import org.codehaus.jackson.type.JavaType; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.type.*; + +/** + * Deserializer factory implementation that allows for configuring + * mapping between types and deserializers to use, by using + * multiple types of overrides. Existing mappings established by + * {@link BeanDeserializerFactory} (and its super class, + * {@link BasicDeserializerFactory}) are used if no overrides are + * defined. + *<p> + * Unlike base deserializer factories, this factory is stateful because + * of configuration settings. It is thread-safe, however, as long as + * all configuration as done before using the factory -- a single + * instance can be shared between providers and mappers. + *<p> + * Configurations currently available are: + *<ul> + * <li>Ability to define explicit mappings between simple non-generic + * classes/interfaces and deserializers to use for deserializing + * instance of these classes. Mappings are one-to-one (i.e. there is + * no "generic" variant for handling sub- or super-classes/interfaces). + * </li> + *</ul> + *<p> + * The way custom deserializer factory instances are hooked to + * {@link ObjectMapper} is usually by constructing an instance of + * {@link DeserializerProvider} (most commonly + * {@link StdDeserializerProvider}) with custom deserializer factory, + * and setting {@link ObjectMapper} to use it. + * + * @deprecated Starting with 1.7, functionality of this class has been + * implemented both in base {@link SerializerFactory} (see methods + * like {@link SerializerFactory#withAdditionalSerializers(Serializers)}) + * and through new Module API. As such, this class is not the best way + * to add custom functionality, and will likely be removed from 2.0 release + */ +@Deprecated +public class CustomDeserializerFactory + extends BeanDeserializerFactory +{ + /* + /********************************************************** + /* Configuration, direct/special mappings + /********************************************************** + */ + + /** + * Direct mappings that are used for exact class and interface type + * matches. + */ + protected HashMap<ClassKey,JsonDeserializer<Object>> _directClassMappings = null; + + /* + /********************************************************** + /* Configuration: mappings that define "mix-in annotations" + /********************************************************** + */ + + /** + * Mapping that defines how to apply mix-in annotations: key is + * the type to received additional annotations, and value is the + * type that has annotations to "mix in". + *<p> + * Annotations associated with the value classes will be used to + * override annotations of the key class, associated with the + * same field or method. They can be further masked by sub-classes: + * you can think of it as injecting annotations between the target + * class and its sub-classes (or interfaces) + * + * @since 1.2 + */ + protected HashMap<ClassKey,Class<?>> _mixInAnnotations; + + /* + /********************************************************** + /* Life-cycle, constructors + /********************************************************** + */ + + public CustomDeserializerFactory() { + this(null); + } + + protected CustomDeserializerFactory(Config config) + { + super(config); + } + + @Override + public DeserializerFactory withConfig(Config config) + { + // See super-class method for reasons for this check... + if (getClass() != CustomDeserializerFactory.class) { + throw new IllegalStateException("Subtype of CustomDeserializerFactory ("+getClass().getName() + +") has not properly overridden method 'withAdditionalDeserializers': can not instantiate subtype with " + +"additional deserializer definitions"); + } + return new CustomDeserializerFactory(config); + } + + /* + /********************************************************** + /* Configuration: type-to-serializer mappings + /********************************************************** + */ + + /** + * Method used to add a mapping for specific type -- and only that + * type -- to use specified deserializer. + * This means that binding is not used for sub-types. + *<p> + * Note that both class and interfaces can be mapped, since the type + * is derived from method declarations; and hence may be abstract types + * and interfaces. This is different from custom serialization where + * only class types can be directly mapped. + * + * @param forClass Class to deserialize using specific deserializer. + * @param deser Deserializer to use for the class. Declared type for + * deserializer may be more specific (sub-class) than declared class + * to map, since that will still be compatible (deserializer produces + * sub-class which is assignable to field/method) + */ + @SuppressWarnings("unchecked") + public <T> void addSpecificMapping(Class<T> forClass, JsonDeserializer<? extends T> deser) + { + ClassKey key = new ClassKey(forClass); + if (_directClassMappings == null) { + _directClassMappings = new HashMap<ClassKey,JsonDeserializer<Object>>(); + } + _directClassMappings.put(key, (JsonDeserializer<Object>)deser); + } + + /** + * Method to use for adding mix-in annotations that Class + * <code>classWithMixIns</code> contains into class + * <code>destinationClass</code>. Mixing in is done when introspecting + * class annotations and properties. + * Annotations from <code>classWithMixIns</code> (and its supertypes) + * will <b>override</b> + * anything <code>destinationClass</code> (and its super-types) + * has already. + * + * @param destinationClass Class to modify by adding annotations + * @param classWithMixIns Class that contains annotations to add + * + * @since 1.2 + */ + public void addMixInAnnotationMapping(Class<?> destinationClass, + Class<?> classWithMixIns) + { + if (_mixInAnnotations == null) { + _mixInAnnotations = new HashMap<ClassKey,Class<?>>(); + } + _mixInAnnotations.put(new ClassKey(destinationClass), classWithMixIns); + } + + /* + /********************************************************** + /* DeserializerFactory API + /********************************************************** + */ + + @Override + public JsonDeserializer<Object> createBeanDeserializer(DeserializationConfig config, DeserializerProvider p, + JavaType type, BeanProperty property) + throws JsonMappingException + { + Class<?> cls = type.getRawClass(); + ClassKey key = new ClassKey(cls); + + // Do we have a match? + if (_directClassMappings != null) { + JsonDeserializer<Object> deser = _directClassMappings.get(key); + if (deser != null) { + return deser; + } + } + // If not, let super class do its job + return super.createBeanDeserializer(config, p, type, property); + } + + @Override + public JsonDeserializer<?> createArrayDeserializer(DeserializationConfig config, DeserializerProvider p, + ArrayType type, BeanProperty property) + throws JsonMappingException + { + ClassKey key = new ClassKey(type.getRawClass()); + if (_directClassMappings != null) { + JsonDeserializer<Object> deser = _directClassMappings.get(key); + if (deser != null) { + return deser; + } + } + return super.createArrayDeserializer(config, p, type, property); + } + + //public JsonDeserializer<?> createCollectionDeserializer(...) throws JsonMappingException + + @Override + public JsonDeserializer<?> createEnumDeserializer(DeserializationConfig config, DeserializerProvider p, + JavaType enumType, BeanProperty property) + throws JsonMappingException + { + /* Enums can't extend anything; must be a direct + * match, if anything: + * (theoretically they can implement interfaces, but that seems irrelevant) + */ + if (_directClassMappings != null) { + ClassKey key = new ClassKey(enumType.getRawClass()); + JsonDeserializer<?> deser = _directClassMappings.get(key); + if (deser != null) { + return deser; + } + } + return super.createEnumDeserializer(config, p, enumType, property); + } + + //public JsonDeserializer<?> createMapDeserializer(...) throws JsonMappingException + + //public JsonDeserializer<?> createTreeDeserializer(...) throws JsonMappingException +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/DateDeserializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/DateDeserializer.java new file mode 100644 index 0000000..0a4c6d8 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/DateDeserializer.java
@@ -0,0 +1,9 @@ +package org.codehaus.jackson.map.deser; + +/** + * @deprecated Since 1.9, use {@link org.codehaus.jackson.map.deser.std.JsonNodeDeserializer} instead. + */ +@Deprecated +public class DateDeserializer + extends org.codehaus.jackson.map.deser.std.DateDeserializer +{ }
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/EnumDeserializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/EnumDeserializer.java new file mode 100644 index 0000000..f79d6ef --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/EnumDeserializer.java
@@ -0,0 +1,15 @@ +package org.codehaus.jackson.map.deser; + +import org.codehaus.jackson.map.util.EnumResolver; + +/** + * @deprecated Since 1.9, use {@link org.codehaus.jackson.map.deser.std.EnumDeserializer} instead. + */ +@Deprecated +public class EnumDeserializer + extends org.codehaus.jackson.map.deser.std.EnumDeserializer +{ + public EnumDeserializer(EnumResolver<?> res) { + super(res); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/EnumResolver.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/EnumResolver.java new file mode 100644 index 0000000..913a9b3 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/EnumResolver.java
@@ -0,0 +1,17 @@ +package org.codehaus.jackson.map.deser; + +import java.util.HashMap; + +/** + * @deprecated Since 1.9, use {@link org.codehaus.jackson.map.util.EnumResolver} instead. + */ +@Deprecated +public final class EnumResolver<T extends Enum<T>> + extends org.codehaus.jackson.map.util.EnumResolver<T> +{ + private EnumResolver(Class<T> enumClass, T[] enums, HashMap<String, T> map) { + super(enumClass, enums, map); + } +} + +
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/FromStringDeserializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/FromStringDeserializer.java new file mode 100644 index 0000000..10ac40f --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/FromStringDeserializer.java
@@ -0,0 +1,13 @@ +package org.codehaus.jackson.map.deser; + +/** + * @deprecated Since 1.9, use {@link org.codehaus.jackson.map.deser.std.FromStringDeserializer} instead. + */ +@Deprecated +public abstract class FromStringDeserializer<T> + extends org.codehaus.jackson.map.deser.std.FromStringDeserializer<T> +{ + protected FromStringDeserializer(Class<?> vc) { + super(vc); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/JsonNodeDeserializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/JsonNodeDeserializer.java new file mode 100644 index 0000000..4fccd39 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/JsonNodeDeserializer.java
@@ -0,0 +1,54 @@ +package org.codehaus.jackson.map.deser; + +import java.io.IOException; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.node.*; + +/** + * @deprecated Since 1.9, use {@link org.codehaus.jackson.map.deser.std.JsonNodeDeserializer} instead. + */ +@Deprecated +public class JsonNodeDeserializer + extends org.codehaus.jackson.map.deser.std.JsonNodeDeserializer +{ + /** + * Singleton instance of generic deserializer for {@link JsonNode}. + * + * @deprecated Use {@link #getDeserializer} accessor instead: will be removed from 2.0 + */ + @Deprecated + public final static JsonNodeDeserializer instance = new JsonNodeDeserializer(); + + /** + * @deprecated since 1.9.0 + */ + @Deprecated + protected final ObjectNode deserializeObject(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + return deserializeObject(jp, ctxt, ctxt.getNodeFactory()); + } + + /** + * @deprecated since 1.9.0 + */ + @Deprecated + protected final ArrayNode deserializeArray(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + return deserializeArray(jp, ctxt, ctxt.getNodeFactory()); + } + + /** + * @deprecated since 1.9.0 + */ + @Deprecated + protected final JsonNode deserializeAny(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + return deserializeAny(jp, ctxt, ctxt.getNodeFactory()); + } + +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/MapDeserializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/MapDeserializer.java new file mode 100644 index 0000000..187e58c --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/MapDeserializer.java
@@ -0,0 +1,44 @@ +package org.codehaus.jackson.map.deser; + +import java.lang.reflect.Constructor; +import java.util.Map; + +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.type.JavaType; + +/** + * @deprecated Since 1.9, use {@link org.codehaus.jackson.map.deser.std.MapDeserializer} instead. + */ +@Deprecated +public class MapDeserializer + extends org.codehaus.jackson.map.deser.std.MapDeserializer +{ + /** + * @deprecated Since 1.9, use variant that takes ValueInstantiator + */ + @SuppressWarnings("deprecation") + @Deprecated + public MapDeserializer(JavaType mapType, Constructor<Map<Object,Object>> defCtor, + KeyDeserializer keyDeser, JsonDeserializer<Object> valueDeser, + TypeDeserializer valueTypeDeser) + { + super(mapType, defCtor, keyDeser, valueDeser, valueTypeDeser); + } + + public MapDeserializer(JavaType mapType, ValueInstantiator valueInstantiator, + KeyDeserializer keyDeser, JsonDeserializer<Object> valueDeser, + TypeDeserializer valueTypeDeser) + { + super(mapType, valueInstantiator, keyDeser, valueDeser, valueTypeDeser); + } + + /** + * Copy-constructor that can be used by sub-classes to allow + * copy-on-write styling copying of settings of an existing instance. + * + * @since 1.9 + */ + protected MapDeserializer(MapDeserializer src) { + super(src); + } +} \ No newline at end of file
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/SettableAnyProperty.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/SettableAnyProperty.java new file mode 100644 index 0000000..25a3483 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/SettableAnyProperty.java
@@ -0,0 +1,177 @@ +package org.codehaus.jackson.map.deser; + +import java.io.IOException; +import java.lang.reflect.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.BeanProperty; +import org.codehaus.jackson.map.DeserializationContext; +import org.codehaus.jackson.map.JsonDeserializer; +import org.codehaus.jackson.map.JsonMappingException; +import org.codehaus.jackson.map.introspect.AnnotatedMethod; +import org.codehaus.jackson.type.JavaType; + +/** + * Class that represents a "wildcard" set method which can be used + * to generically set values of otherwise unmapped (aka "unknown") + * properties read from Json content. + *<p> + * !!! Note: might make sense to refactor to share some code + * with {@link SettableBeanProperty}? + */ +public final class SettableAnyProperty +{ + /** + * Method used for setting "any" properties, along with annotation + * information. Retained to allow contextualization of any properties. + * + * @since 1.7 + */ + final protected BeanProperty _property; + + /** + * Physical JDK object used for assigning properties. + */ + final protected Method _setter; + + final protected JavaType _type; + + protected JsonDeserializer<Object> _valueDeserializer; + + /* + /********************************************************** + /* Life-cycle + /********************************************************** + */ + + /** + * @deprecated Since 1.9 - use variant that takes deserializer + */ + @Deprecated + public SettableAnyProperty(BeanProperty property, AnnotatedMethod setter, JavaType type) { + this(property, setter, type, null); + } + + public SettableAnyProperty(BeanProperty property, AnnotatedMethod setter, JavaType type, + JsonDeserializer<Object> valueDeser) { + this(property, setter.getAnnotated(), type, valueDeser); + } + + public SettableAnyProperty(BeanProperty property, Method rawSetter, JavaType type, + JsonDeserializer<Object> valueDeser) { + _property = property; + _type = type; + _setter = rawSetter; + _valueDeserializer = valueDeser; + } + + public SettableAnyProperty withValueDeserializer(JsonDeserializer<Object> deser) { + return new SettableAnyProperty(_property, _setter, _type, deser); + } + + /** + * @deprecated Since 1.9 - construct with deserializer + */ + @Deprecated + public void setValueDeserializer(JsonDeserializer<Object> deser) + { + if (_valueDeserializer != null) { // sanity check + throw new IllegalStateException("Already had assigned deserializer for SettableAnyProperty"); + } + _valueDeserializer = deser; + } + + /* + /********************************************************** + /* Public API, accessors + /********************************************************** + */ + + public BeanProperty getProperty() { return _property; } + + public boolean hasValueDeserializer() { return (_valueDeserializer != null); } + + public JavaType getType() { return _type; } + + /* + /********************************************************** + /* Public API, deserialization + /********************************************************** + */ + + /** + * Method called to deserialize appropriate value, given parser (and + * context), and set it using appropriate method (a setter method). + */ + public final void deserializeAndSet(JsonParser jp, DeserializationContext ctxt, + Object instance, String propName) + throws IOException, JsonProcessingException + { + set(instance, propName, deserialize(jp, ctxt)); + } + + public final Object deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + JsonToken t = jp.getCurrentToken(); + if (t == JsonToken.VALUE_NULL) { + return null; + } + return _valueDeserializer.deserialize(jp, ctxt); + } + + public final void set(Object instance, String propName, Object value) + throws IOException + { + try { + _setter.invoke(instance, propName, value); + } catch (Exception e) { + _throwAsIOE(e, propName, value); + } + } + + /* + /********************************************************** + /* Helper methods + /********************************************************** + */ + + /** + * @param e Exception to re-throw or wrap + * @param propName Name of property (from Json input) to set + * @param value Value of the property + */ + protected void _throwAsIOE(Exception e, String propName, Object value) + throws IOException + { + if (e instanceof IllegalArgumentException) { + String actType = (value == null) ? "[NULL]" : value.getClass().getName(); + StringBuilder msg = new StringBuilder("Problem deserializing \"any\" property '").append(propName); + msg.append("' of class "+getClassName()+" (expected type: ").append(_type); + msg.append("; actual type: ").append(actType).append(")"); + String origMsg = e.getMessage(); + if (origMsg != null) { + msg.append(", problem: ").append(origMsg); + } else { + msg.append(" (no error message provided)"); + } + throw new JsonMappingException(msg.toString(), null, e); + } + if (e instanceof IOException) { + throw (IOException) e; + } + if (e instanceof RuntimeException) { + throw (RuntimeException) e; + } + // let's wrap the innermost problem + Throwable t = e; + while (t.getCause() != null) { + t = t.getCause(); + } + throw new JsonMappingException(t.getMessage(), null, t); + } + + private String getClassName() { return _setter.getDeclaringClass().getName(); } + + @Override public String toString() { return "[any property on class "+getClassName()+"]"; } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/SettableBeanProperty.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/SettableBeanProperty.java new file mode 100644 index 0000000..e477b5c --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/SettableBeanProperty.java
@@ -0,0 +1,827 @@ +package org.codehaus.jackson.map.deser; + +import java.io.IOException; +import java.lang.annotation.Annotation; +import java.lang.reflect.*; +import java.util.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.introspect.AnnotatedField; +import org.codehaus.jackson.map.introspect.AnnotatedMember; +import org.codehaus.jackson.map.introspect.AnnotatedMethod; +import org.codehaus.jackson.map.util.Annotations; +import org.codehaus.jackson.map.util.ClassUtil; +import org.codehaus.jackson.type.JavaType; +import org.codehaus.jackson.util.InternCache; + +/** + * Base class for settable properties of a bean: contains + * both type and name definitions, and reflection-based set functionality. + * Concrete sub-classes implement details, so that both field- and + * setter-backed properties can be handled + */ +public abstract class SettableBeanProperty + implements BeanProperty // since 1.7 +{ + /** + * Logical name of the property (often but not always derived + * from the setter method name) + */ + protected final String _propName; + + /** + * Base type for property; may be a supertype of actual value. + */ + protected final JavaType _type; + + /** + * Class that contains this property (either class that declares + * the property or one of its subclasses), class that is + * deserialized using deserializer that contains this property. + */ + protected final Annotations _contextAnnotations; + + /** + * Deserializer used for handling property value. + */ + protected JsonDeserializer<Object> _valueDeserializer; + + /** + * If value will contain type information (to support + * polymorphic handling), this is the type deserializer + * used to handle type resolution. + */ + protected TypeDeserializer _valueTypeDeserializer; + + /** + * Object used to figure out value to be used when 'null' literal is encountered in JSON. + * For most types simply Java null, but for primitive types must + * be a non-null value (like Integer.valueOf(0) for int). + * + * @since 1.7 + */ + protected NullProvider _nullProvider; + + /** + * If property represents a managed (forward) reference + * (see [JACKSON-235]), we will need name of reference for + * later linking. + */ + protected String _managedReferenceName; + + /** + * Index of property (within all property of a bean); assigned + * when all properties have been collected. Order of entries + * is arbitrary, but once indexes are assigned they are not + * changed. + * + * @since 1.7 + */ + protected int _propertyIndex = -1; + + /* + /********************************************************** + /* Life-cycle (construct & configure) + /********************************************************** + */ + + protected SettableBeanProperty(String propName, JavaType type, TypeDeserializer typeDeser, + Annotations contextAnnotations) + { + /* 09-Jan-2009, tatu: Intern()ing makes sense since Jackson parsed + * field names are (usually) interned too, hence lookups will be faster. + */ + // 23-Oct-2009, tatu: should this be disabled wrt [JACKSON-180]? + if (propName == null || propName.length() == 0) { + _propName = ""; + } else { + _propName = InternCache.instance.intern(propName); + } + _type = type; + _contextAnnotations = contextAnnotations; + _valueTypeDeserializer = typeDeser; + } + + /** + * Basic copy-constructor for sub-classes to use. + * + * @since 1.9 + */ + protected SettableBeanProperty(SettableBeanProperty src) + { + _propName = src._propName; + _type = src._type; + _contextAnnotations = src._contextAnnotations; + _valueDeserializer = src._valueDeserializer; + _valueTypeDeserializer = src._valueTypeDeserializer; + _nullProvider = src._nullProvider; + _managedReferenceName = src._managedReferenceName; + _propertyIndex = src._propertyIndex; + } + + /** + * Copy-with-deserializer-change constructor for sub-classes to use. + * + * @since 1.9 + */ + protected SettableBeanProperty(SettableBeanProperty src, JsonDeserializer<Object> deser) + { + _propName = src._propName; + _type = src._type; + _contextAnnotations = src._contextAnnotations; + _valueTypeDeserializer = src._valueTypeDeserializer; + _managedReferenceName = src._managedReferenceName; + _propertyIndex = src._propertyIndex; + + _valueDeserializer = deser; + if (deser == null) { + _nullProvider = null; + } else { + Object nvl = deser.getNullValue(); + _nullProvider = (nvl == null) ? null : new NullProvider(_type, nvl); + } + } + + @Deprecated + public void setValueDeserializer(JsonDeserializer<Object> deser) + { + if (_valueDeserializer != null) { // sanity check + throw new IllegalStateException("Already had assigned deserializer for property '"+getName()+"' (class "+getDeclaringClass().getName()+")"); + } + _valueDeserializer = deser; + Object nvl = _valueDeserializer.getNullValue(); + _nullProvider = (nvl == null) ? null : new NullProvider(_type, nvl); + } + + /** + * @since 1.9 + */ + public abstract SettableBeanProperty withValueDeserializer(JsonDeserializer<Object> deser); + + public void setManagedReferenceName(String n) { + _managedReferenceName = n; + } + + /** + * Method used to assign index for property. + * + * @since 1.7 + */ + public void assignIndex(int index) { + if (_propertyIndex != -1) { + throw new IllegalStateException("Property '"+getName()+"' already had index ("+_propertyIndex+"), trying to assign "+index); + } + _propertyIndex = index; + } + + /* + /********************************************************** + /* BeanProperty impl + /********************************************************** + */ + + @Override + public final String getName() { return _propName; } + + @Override + public JavaType getType() { return _type; } + + @Override + public abstract <A extends Annotation> A getAnnotation(Class<A> acls); + + @Override + public abstract AnnotatedMember getMember(); + + @Override + public <A extends Annotation> A getContextAnnotation(Class<A> acls) { + return _contextAnnotations.get(acls); + } + + /* + /********************************************************** + /* Accessors + /********************************************************** + */ + + protected final Class<?> getDeclaringClass() { + return getMember().getDeclaringClass(); + } + + /** + * @deprecated Since 1.7, use {@link #getName} instead. + */ + @Deprecated + public String getPropertyName() { return _propName; } + + public String getManagedReferenceName() { return _managedReferenceName; } + + public boolean hasValueDeserializer() { return (_valueDeserializer != null); } + + /** + * @since 1.9 + */ + public boolean hasValueTypeDeserializer() { return (_valueTypeDeserializer != null); } + + /** + * @since 1.9 + */ + public JsonDeserializer<Object> getValueDeserializer() { return _valueDeserializer; } + + /** + * @since 1.9 + */ + public TypeDeserializer getValueTypeDeserializer() { return _valueTypeDeserializer; } + + /** + * Method for accessing unique index of this property; indexes are + * assigned once all properties of a {@link BeanDeserializer} have + * been collected. + * + * @return Index of this property + * + * @since 1.7 Although note that it was misspelled as "getProperytIndex"; fixed in 1.9 + */ + public int getPropertyIndex() { return _propertyIndex; } + + /** + * @deprecated Since 1.9: use {@link #getPropertyIndex} instead + */ + @Deprecated + public int getProperytIndex() { return getPropertyIndex(); } + + /** + * Accessor for id of injectable value, if this bean property supports + * value injection. + * + * @since 1.9 + */ + public Object getInjectableValueId() { return null; } + + /* + /********************************************************** + /* Public API + /********************************************************** + */ + + /** + * Method called to deserialize appropriate value, given parser (and + * context), and set it using appropriate mechanism. + * Pre-condition is that passed parser must point to the first token + * that should be consumed to produce the value (the only value for + * scalars, multiple for Objects and Arrays). + */ + public abstract void deserializeAndSet(JsonParser jp, DeserializationContext ctxt, + Object instance) + throws IOException, JsonProcessingException; + + public abstract void set(Object instance, Object value) + throws IOException; + + /** + * This method is needed by some specialized bean deserializers, + * and also called by some {@link #deserializeAndSet} implementations. + *<p> + * Pre-condition is that passed parser must point to the first token + * that should be consumed to produce the value (the only value for + * scalars, multiple for Objects and Arrays). + */ + public final Object deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + JsonToken t = jp.getCurrentToken(); + if (t == JsonToken.VALUE_NULL) { + return (_nullProvider == null) ? null : _nullProvider.nullValue(ctxt); + } + if (_valueTypeDeserializer != null) { + return _valueDeserializer.deserializeWithType(jp, ctxt, _valueTypeDeserializer); + } + return _valueDeserializer.deserialize(jp, ctxt); + } + + /* + /********************************************************** + /* Helper methods + /********************************************************** + */ + + /** + * Method that takes in exception of any type, and casts or wraps it + * to an IOException or its subclass. + */ + protected void _throwAsIOE(Exception e, Object value) + throws IOException + { + if (e instanceof IllegalArgumentException) { + String actType = (value == null) ? "[NULL]" : value.getClass().getName(); + StringBuilder msg = new StringBuilder("Problem deserializing property '").append(getPropertyName()); + msg.append("' (expected type: ").append(getType()); + msg.append("; actual type: ").append(actType).append(")"); + String origMsg = e.getMessage(); + if (origMsg != null) { + msg.append(", problem: ").append(origMsg); + } else { + msg.append(" (no error message provided)"); + } + throw new JsonMappingException(msg.toString(), null, e); + } + _throwAsIOE(e); + } + + protected IOException _throwAsIOE(Exception e) + throws IOException + { + if (e instanceof IOException) { + throw (IOException) e; + } + if (e instanceof RuntimeException) { + throw (RuntimeException) e; + } + // let's wrap the innermost problem + Throwable th = e; + while (th.getCause() != null) { + th = th.getCause(); + } + throw new JsonMappingException(th.getMessage(), null, th); + } + + @Override public String toString() { return "[property '"+getName()+"']"; } + + /* + /********************************************************** + /* Implementation classes + /********************************************************** + */ + + /** + * This concrete sub-class implements property that is set + * using regular "setter" method. + */ + public final static class MethodProperty + extends SettableBeanProperty + { + protected final AnnotatedMethod _annotated; + + /** + * Setter method for modifying property value; used for + * "regular" method-accessible properties. + */ + protected final Method _setter; + + public MethodProperty(String name, JavaType type, TypeDeserializer typeDeser, + Annotations contextAnnotations, AnnotatedMethod method) + { + super(name, type, typeDeser, contextAnnotations); + _annotated = method; + _setter = method.getAnnotated(); + } + + protected MethodProperty(MethodProperty src, JsonDeserializer<Object> deser) { + super(src, deser); + _annotated = src._annotated; + _setter = src._setter; + } + + @Override + public MethodProperty withValueDeserializer(JsonDeserializer<Object> deser) { + return new MethodProperty(this, deser); + } + + /* + /********************************************************** + /* BeanProperty impl + /********************************************************** + */ + + @Override + public <A extends Annotation> A getAnnotation(Class<A> acls) { + return _annotated.getAnnotation(acls); + } + + @Override public AnnotatedMember getMember() { return _annotated; } + + /* + /********************************************************** + /* Overridden methods + /********************************************************** + */ + + @Override + public void deserializeAndSet(JsonParser jp, DeserializationContext ctxt, + Object instance) + throws IOException, JsonProcessingException + { + set(instance, deserialize(jp, ctxt)); + } + + @Override + public final void set(Object instance, Object value) + throws IOException + { + try { + _setter.invoke(instance, value); + } catch (Exception e) { + _throwAsIOE(e, value); + } + } + } + + /** + * This concrete sub-class implements Collection or Map property that is + * indirectly by getting the property value and directly modifying it. + */ + public final static class SetterlessProperty + extends SettableBeanProperty + { + protected final AnnotatedMethod _annotated; + + /** + * Get method for accessing property value used to access property + * (of Collection or Map type) to modify. + */ + protected final Method _getter; + + public SetterlessProperty(String name, JavaType type, TypeDeserializer typeDeser, + Annotations contextAnnotations, AnnotatedMethod method) + { + super(name, type, typeDeser, contextAnnotations); + _annotated = method; + _getter = method.getAnnotated(); + } + + protected SetterlessProperty(SetterlessProperty src, JsonDeserializer<Object> deser) { + super(src, deser); + _annotated = src._annotated; + _getter = src._getter; + } + + @Override + public SetterlessProperty withValueDeserializer(JsonDeserializer<Object> deser) { + return new SetterlessProperty(this, deser); + } + + /* + /********************************************************** + /* BeanProperty impl + /********************************************************** + */ + + @Override + public <A extends Annotation> A getAnnotation(Class<A> acls) { + return _annotated.getAnnotation(acls); + } + + @Override public AnnotatedMember getMember() { return _annotated; } + + /* + /********************************************************** + /* Overridden methods + /********************************************************** + */ + + @Override + public final void deserializeAndSet(JsonParser jp, DeserializationContext ctxt, + Object instance) + throws IOException, JsonProcessingException + { + JsonToken t = jp.getCurrentToken(); + if (t == JsonToken.VALUE_NULL) { + /* Hmmh. Is this a problem? We won't be setting anything, so it's + * equivalent of empty Collection/Map in this case + */ + return; + } + + // Ok: then, need to fetch Collection/Map to modify: + Object toModify; + try { + toModify = _getter.invoke(instance); + } catch (Exception e) { + _throwAsIOE(e); + return; // never gets here + } + /* Note: null won't work, since we can't then inject anything + * in. At least that's not good in common case. However, + * theoretically the case where we get JSON null might + * be compatible. If so, implementation could be changed. + */ + if (toModify == null) { + throw new JsonMappingException("Problem deserializing 'setterless' property '"+getName()+"': get method returned null"); + } + _valueDeserializer.deserialize(jp, ctxt, toModify); + } + + @Override + public final void set(Object instance, Object value) + throws IOException + { + throw new UnsupportedOperationException("Should never call 'set' on setterless property"); + } + } + + /** + * This concrete sub-class implements property that is set + * directly assigning to a Field. + */ + public final static class FieldProperty + extends SettableBeanProperty + { + protected final AnnotatedField _annotated; + + /** + * Actual field to set when deserializing this property. + */ + protected final Field _field; + + public FieldProperty(String name, JavaType type, TypeDeserializer typeDeser, + Annotations contextAnnotations, AnnotatedField field) + { + super(name, type, typeDeser, contextAnnotations); + _annotated = field; + _field = field.getAnnotated(); + } + + protected FieldProperty(FieldProperty src, JsonDeserializer<Object> deser) { + super(src, deser); + _annotated = src._annotated; + _field = src._field; + } + + @Override + public FieldProperty withValueDeserializer(JsonDeserializer<Object> deser) { + return new FieldProperty(this, deser); + } + + /* + /********************************************************** + /* BeanProperty impl + /********************************************************** + */ + + @Override + public <A extends Annotation> A getAnnotation(Class<A> acls) { + return _annotated.getAnnotation(acls); + } + + @Override public AnnotatedMember getMember() { return _annotated; } + + /* + /********************************************************** + /* Overridden methods + /********************************************************** + */ + + @Override + public void deserializeAndSet(JsonParser jp, DeserializationContext ctxt, + Object instance) + throws IOException, JsonProcessingException + { + set(instance, deserialize(jp, ctxt)); + } + + @Override + public final void set(Object instance, Object value) + throws IOException + { + try { + _field.set(instance, value); + } catch (Exception e) { + _throwAsIOE(e, value); + } + } + } + + /** + * Wrapper property that is used to handle managed (forward) properties + * (see [JACKSON-235] for more information). Basically just need to + * delegate first to actual forward property, and + * + * @author tatu + */ + public final static class ManagedReferenceProperty + extends SettableBeanProperty + { + protected final String _referenceName; + + /** + * Flag that indicates whether property to handle is a container type + * (array, Collection, Map) or not. + */ + protected final boolean _isContainer; + + protected final SettableBeanProperty _managedProperty; + + protected final SettableBeanProperty _backProperty; + + public ManagedReferenceProperty(String refName, + SettableBeanProperty forward, SettableBeanProperty backward, + Annotations contextAnnotations, + boolean isContainer) + { + super(forward.getName(), forward.getType(), forward._valueTypeDeserializer, + contextAnnotations); + _referenceName = refName; + _managedProperty = forward; + _backProperty = backward; + _isContainer = isContainer; + } + + protected ManagedReferenceProperty(ManagedReferenceProperty src, JsonDeserializer<Object> deser) + { + super(src, deser); + _referenceName = src._referenceName; + _isContainer = src._isContainer; + _managedProperty = src._managedProperty; + _backProperty = src._backProperty; + } + + @Override + public ManagedReferenceProperty withValueDeserializer(JsonDeserializer<Object> deser) { + return new ManagedReferenceProperty(this, deser); + } + + /* + /********************************************************** + /* BeanProperty impl + /********************************************************** + */ + + @Override + public <A extends Annotation> A getAnnotation(Class<A> acls) { + return _managedProperty.getAnnotation(acls); + } + + @Override public AnnotatedMember getMember() { return _managedProperty.getMember(); } + + /* + /********************************************************** + /* Overridden methods + /********************************************************** + */ + + @Override + public void deserializeAndSet(JsonParser jp, DeserializationContext ctxt, + Object instance) + throws IOException, JsonProcessingException + { + set(instance, _managedProperty.deserialize(jp, ctxt)); + } + + @Override + public final void set(Object instance, Object value) + throws IOException + { + _managedProperty.set(instance, value); + /* And then back reference, if (and only if!) we actually have a non-null + * reference + */ + if (value != null) { + if (_isContainer) { // ok, this gets ugly... but has to do for now + if (value instanceof Object[]) { + for (Object ob : (Object[]) value) { + if (ob != null) { + _backProperty.set(ob, instance); + } + } + } else if (value instanceof Collection<?>) { + for (Object ob : (Collection<?>) value) { + if (ob != null) { + _backProperty.set(ob, instance); + } + } + } else if (value instanceof Map<?,?>) { + for (Object ob : ((Map<?,?>) value).values()) { + if (ob != null) { + _backProperty.set(ob, instance); + } + } + } else { + throw new IllegalStateException("Unsupported container type ("+value.getClass().getName() + +") when resolving reference '"+_referenceName+"'"); + } + } else { + _backProperty.set(value, instance); + } + } + } + } + + /** + * This sub-class is used to handle special case of value being a + * non-static inner class. If so, we will have to use a special + * alternative for default constructor; but otherwise can delegate + * to regular implementation. + * + * @since 1.9 + */ + public final static class InnerClassProperty + extends SettableBeanProperty + { + /** + * Actual property that we use after value construction. + */ + protected final SettableBeanProperty _delegate; + + /** + * Single-arg constructor we use for value instantiation. + */ + protected final Constructor<?> _creator; + + public InnerClassProperty(SettableBeanProperty delegate, + Constructor<?> ctor) + { + super(delegate); + _delegate = delegate; + _creator = ctor; + } + + protected InnerClassProperty(InnerClassProperty src, JsonDeserializer<Object> deser) + { + super(src, deser); + _delegate = src._delegate.withValueDeserializer(deser); + _creator = src._creator; + } + + @Override + public InnerClassProperty withValueDeserializer(JsonDeserializer<Object> deser) { + return new InnerClassProperty(this, deser); + } + + // // // BeanProperty impl + + @Override + public <A extends Annotation> A getAnnotation(Class<A> acls) { + return _delegate.getAnnotation(acls); + } + + @Override public AnnotatedMember getMember() { return _delegate.getMember(); } + + // // // Overridden methods + + @Override + public void deserializeAndSet(JsonParser jp, DeserializationContext ctxt, + Object bean) + throws IOException, JsonProcessingException + { + // mostly copied from super class impl: + JsonToken t = jp.getCurrentToken(); + Object value; + if (t == JsonToken.VALUE_NULL) { + value = (_nullProvider == null) ? null : _nullProvider.nullValue(ctxt); + } else if (_valueTypeDeserializer != null) { + value = _valueDeserializer.deserializeWithType(jp, ctxt, _valueTypeDeserializer); + } else { // the usual case + try { + value = _creator.newInstance(bean); + } catch (Exception e) { + ClassUtil.unwrapAndThrowAsIAE(e, "Failed to instantiate class "+_creator.getDeclaringClass().getName()+", problem: "+e.getMessage()); + value = null; + } + _valueDeserializer.deserialize(jp, ctxt, value); + } + set(bean, value); + } + + @Override + public final void set(Object instance, Object value) throws IOException + { + _delegate.set(instance, value); + } + } + + /* + /********************************************************** + /* Other helper classes + /********************************************************** + */ + + /** + * To support [JACKSON-420] we need bit more indirection; this is used to produce + * artificial failure for primitives that don't accept JSON null as value. + */ + protected final static class NullProvider + { + private final Object _nullValue; + + private final boolean _isPrimitive; + + private final Class<?> _rawType; + + protected NullProvider(JavaType type, Object nullValue) + { + _nullValue = nullValue; + // [JACKSON-420] + _isPrimitive = type.isPrimitive(); + _rawType = type.getRawClass(); + } + + public Object nullValue(DeserializationContext ctxt) throws JsonProcessingException + { + if (_isPrimitive && ctxt.isEnabled(DeserializationConfig.Feature.FAIL_ON_NULL_FOR_PRIMITIVES)) { + throw ctxt.mappingException("Can not map JSON null into type "+_rawType.getName() + +" (set DeserializationConfig.Feature.FAIL_ON_NULL_FOR_PRIMITIVES to 'false' to allow)"); + } + return _nullValue; + } + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/StdDeserializationContext.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/StdDeserializationContext.java new file mode 100644 index 0000000..970ac14 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/StdDeserializationContext.java
@@ -0,0 +1,326 @@ +package org.codehaus.jackson.map.deser; + +import java.io.IOException; +import java.text.DateFormat; +import java.text.ParseException; +import java.util.*; + +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.JsonToken; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.exc.UnrecognizedPropertyException; +import org.codehaus.jackson.map.util.ArrayBuilders; +import org.codehaus.jackson.map.util.ClassUtil; +import org.codehaus.jackson.map.util.LinkedNode; +import org.codehaus.jackson.map.util.ObjectBuffer; +import org.codehaus.jackson.type.JavaType; + +/** + * Default implementation of {@link DeserializationContext}. + */ +public class StdDeserializationContext + extends DeserializationContext +{ + /** + * Let's limit length of error messages, for cases where underlying data + * may be very large -- no point in spamming logs with megs of meaningless + * data. + */ + final static int MAX_ERROR_STR_LEN = 500; + + // // // Configuration + + /** + * Currently active parser used for deserialization. + * May be different from the outermost parser + * when content is buffered. + */ + protected JsonParser _parser; + + /** + * @since 1.5 + */ + protected final DeserializerProvider _deserProvider; + + /** + * @since 1.9 + */ + protected final InjectableValues _injectableValues; + + // // // Helper object recycling + + protected ArrayBuilders _arrayBuilders; + + protected ObjectBuffer _objectBuffer; + + protected DateFormat _dateFormat; + + /* + /********************************************************** + /* Life-cycle + /********************************************************** + */ + + public StdDeserializationContext(DeserializationConfig config, JsonParser jp, + DeserializerProvider prov, InjectableValues injectableValues) + { + super(config); + _parser = jp; + _deserProvider = prov; + _injectableValues = injectableValues; + } + + /* + /********************************************************** + /* Public API, accessors + /********************************************************** + */ + + @Override + public DeserializerProvider getDeserializerProvider() { + return _deserProvider; + } + + /** + * Method for accessing the currently active parser. + * May be different from the outermost parser + * when content is buffered. + *<p> + * Use of this method is discouraged: if code has direct access + * to the active parser, that should be used instead. + */ + @Override + public JsonParser getParser() { return _parser; } + + @Override + public Object findInjectableValue(Object valueId, + BeanProperty forProperty, Object beanInstance) + { + if (_injectableValues == null) { + throw new IllegalStateException("No 'injectableValues' configured, can not inject value with id ["+valueId+"]"); + } + return _injectableValues.findInjectableValue(valueId, this, forProperty, beanInstance); + } + + /* + /********************************************************** + /* Public API, helper object recycling + /********************************************************** + */ + + @Override + public final ObjectBuffer leaseObjectBuffer() + { + ObjectBuffer buf = _objectBuffer; + if (buf == null) { + buf = new ObjectBuffer(); + } else { + _objectBuffer = null; + } + return buf; + } + + @Override + public final void returnObjectBuffer(ObjectBuffer buf) + { + /* Already have a reusable buffer? Let's retain bigger one + * (or if equal, favor newer one, shorter life-cycle) + */ + if (_objectBuffer == null + || buf.initialCapacity() >= _objectBuffer.initialCapacity()) { + _objectBuffer = buf; + } + } + + @Override + public final ArrayBuilders getArrayBuilders() + { + if (_arrayBuilders == null) { + _arrayBuilders = new ArrayBuilders(); + } + return _arrayBuilders; + } + + /* + /********************************************************** + /* Parsing methods that may use reusable/recyclable objects + /********************************************************** + */ + + @Override + public Date parseDate(String dateStr) + throws IllegalArgumentException + { + try { + return getDateFormat().parse(dateStr); + } catch (ParseException pex) { + throw new IllegalArgumentException(pex.getMessage()); + } + } + + @Override + public Calendar constructCalendar(Date d) + { + /* 08-Jan-2008, tatu: not optimal, but should work for the + * most part; let's revise as needed. + */ + Calendar c = Calendar.getInstance(); + c.setTime(d); + return c; + } + /* + /********************************************************** + /* Public API, problem handling, reporting + /********************************************************** + */ + + /** + * Method deserializers can call to inform configured {@link DeserializationProblemHandler}s + * of an unrecognized property. + * + * @since 1.5 + */ + @Override + public boolean handleUnknownProperty(JsonParser jp, JsonDeserializer<?> deser, Object instanceOrClass, String propName) + throws IOException, JsonProcessingException + { + LinkedNode<DeserializationProblemHandler> h = _config.getProblemHandlers(); + if (h != null) { + /* 04-Jan-2009, tatu: Ugh. Need to mess with currently active parser + * since parser is not explicitly passed to handler... that was a mistake + */ + JsonParser oldParser = _parser; + _parser = jp; + try { + while (h != null) { + // Can bail out if it's handled + if (h.value().handleUnknownProperty(this, deser, instanceOrClass, propName)) { + return true; + } + h = h.next(); + } + } finally { + _parser = oldParser; + } + } + return false; + } + + @Override + public JsonMappingException mappingException(Class<?> targetClass) { + return mappingException(targetClass, _parser.getCurrentToken()); + } + + @Override + public JsonMappingException mappingException(Class<?> targetClass, JsonToken token) + { + String clsName = _calcName(targetClass); + return JsonMappingException.from(_parser, "Can not deserialize instance of "+clsName+" out of "+token+" token"); + } + + @Override + public JsonMappingException instantiationException(Class<?> instClass, Throwable t) + { + return JsonMappingException.from(_parser, + "Can not construct instance of "+instClass.getName()+", problem: "+t.getMessage(), + t); + } + + @Override + public JsonMappingException instantiationException(Class<?> instClass, String msg) + { + return JsonMappingException.from(_parser, "Can not construct instance of "+instClass.getName()+", problem: "+msg); + } + + /** + * Method that will construct an exception suitable for throwing when + * some String values are acceptable, but the one encountered is not + */ + @Override + public JsonMappingException weirdStringException(Class<?> instClass, String msg) + { + return JsonMappingException.from(_parser, "Can not construct instance of "+instClass.getName()+" from String value '"+_valueDesc()+"': "+msg); + } + + @Override + public JsonMappingException weirdNumberException(Class<?> instClass, String msg) + { + return JsonMappingException.from(_parser, "Can not construct instance of "+instClass.getName()+" from number value ("+_valueDesc()+"): "+msg); + } + + @Override + public JsonMappingException weirdKeyException(Class<?> keyClass, String keyValue, String msg) + { + return JsonMappingException.from(_parser, "Can not construct Map key of type "+keyClass.getName()+" from String \""+_desc(keyValue)+"\": "+msg); + } + + @Override + public JsonMappingException wrongTokenException(JsonParser jp, JsonToken expToken, String msg) + { + return JsonMappingException.from(jp, "Unexpected token ("+jp.getCurrentToken()+"), expected "+expToken+": "+msg); + } + + @Override + public JsonMappingException unknownFieldException(Object instanceOrClass, String fieldName) + { + return UnrecognizedPropertyException.from(_parser, instanceOrClass, fieldName); + } + + @Override + public JsonMappingException unknownTypeException(JavaType type, String id) + { + return JsonMappingException.from(_parser, "Could not resolve type id '"+id+"' into a subtype of "+type); + } + + /* + /********************************************************** + /* Overridable internal methods + /********************************************************** + */ + + protected DateFormat getDateFormat() + { + if (_dateFormat == null) { + // must create a clone since Formats are not thread-safe: + _dateFormat = (DateFormat)_config.getDateFormat().clone(); + } + return _dateFormat; + } + + protected String determineClassName(Object instance) + { + return ClassUtil.getClassDescription(instance); + } + + /* + /********************************************************** + /* Other internal methods + /********************************************************** + */ + + protected String _calcName(Class<?> cls) + { + if (cls.isArray()) { + return _calcName(cls.getComponentType())+"[]"; + } + return cls.getName(); + } + + protected String _valueDesc() + { + try { + return _desc(_parser.getText()); + } catch (Exception e) { + return "[N/A]"; + } + } + protected String _desc(String desc) + { + // !!! should we quote it? (in case there are control chars, linefeeds) + if (desc.length() > MAX_ERROR_STR_LEN) { + desc = desc.substring(0, MAX_ERROR_STR_LEN) + "]...[" + desc.substring(desc.length() - MAX_ERROR_STR_LEN); + } + return desc; + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/StdDeserializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/StdDeserializer.java new file mode 100644 index 0000000..7eea5d4 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/StdDeserializer.java
@@ -0,0 +1,94 @@ +package org.codehaus.jackson.map.deser; + +import java.io.IOException; + +import org.codehaus.jackson.Base64Variants; +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.JsonToken; +import org.codehaus.jackson.map.DeserializationContext; +import org.codehaus.jackson.map.TypeDeserializer; +import org.codehaus.jackson.map.annotate.JacksonStdImpl; +import org.codehaus.jackson.map.deser.std.StdScalarDeserializer; +import org.codehaus.jackson.type.JavaType; + +/** + * @deprecated Since 1.9, use {@link org.codehaus.jackson.map.deser.std.StdDeserializer} instead. + */ +@Deprecated +public abstract class StdDeserializer<T> + extends org.codehaus.jackson.map.deser.std.StdDeserializer<T> +{ + protected StdDeserializer(Class<?> vc) { + super(vc); + } + + protected StdDeserializer(JavaType valueType) { + super(valueType); + } + + /* + /********************************************************** + /* Deprecated inner classes + /********************************************************** + */ + + /** + * @deprecated Since 1.9 use {@link org.codehaus.jackson.map.deser.std.ClassDeserializer} instead. + */ + @Deprecated + @JacksonStdImpl + public class ClassDeserializer extends org.codehaus.jackson.map.deser.std.ClassDeserializer { } + + /** + * @deprecated Since 1.9 use {@link org.codehaus.jackson.map.deser.std.CalendarDeserializer} instead. + */ + @Deprecated + @JacksonStdImpl + public class CalendarDeserializer extends org.codehaus.jackson.map.deser.std.CalendarDeserializer { } + + /** + * @deprecated Since 1.9 use {@link org.codehaus.jackson.map.deser.std.StringDeserializer} instead. + */ + @Deprecated + @JacksonStdImpl + public final static class StringDeserializer + extends StdScalarDeserializer<String> + { + public StringDeserializer() { super(String.class); } + + @Override + public String deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + JsonToken curr = jp.getCurrentToken(); + if (curr == JsonToken.VALUE_STRING) { + return jp.getText(); + } + if (curr == JsonToken.VALUE_EMBEDDED_OBJECT) { + Object ob = jp.getEmbeddedObject(); + if (ob == null) { + return null; + } + if (ob instanceof byte[]) { + return Base64Variants.getDefaultVariant().encode((byte[]) ob, false); + } + return ob.toString(); + } + if (curr.isScalarValue()) { + return jp.getText(); + } + throw ctxt.mappingException(_valueClass, curr); + } + + @SuppressWarnings("deprecation") + @Override + public String deserializeWithType(JsonParser jp, DeserializationContext ctxt, + TypeDeserializer typeDeserializer) + throws IOException, JsonProcessingException + { + return deserialize(jp, ctxt); + } + } + +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/StdDeserializerProvider.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/StdDeserializerProvider.java new file mode 100644 index 0000000..6fc6c2c --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/StdDeserializerProvider.java
@@ -0,0 +1,474 @@ +package org.codehaus.jackson.map.deser; + +import java.io.IOException; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; + +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.io.SerializedString; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.deser.BeanDeserializer; +import org.codehaus.jackson.map.introspect.AnnotatedClass; +import org.codehaus.jackson.map.type.*; +import org.codehaus.jackson.map.util.ClassUtil; +import org.codehaus.jackson.map.util.RootNameLookup; +import org.codehaus.jackson.type.JavaType; + +/** + * Default {@link DeserializerProvider} implementation. + * Handles low-level caching (non-root) aspects of deserializer + * handling; all construction details are delegated to configured + * {@link DeserializerFactory} instance that the provider owns. + */ +public class StdDeserializerProvider + extends DeserializerProvider +{ + /* + /********************************************************** + /* Caching + /********************************************************** + */ + + /** + * We will also cache some dynamically constructed deserializers; + * specifically, ones that are expensive to construct. + * This currently means bean and Enum deserializers; array, List and Map + * deserializers will not be cached. + *<p> + * Given that we don't expect much concurrency for additions + * (should very quickly converge to zero after startup), let's + * explicitly define a low concurrency setting. + */ + final protected ConcurrentHashMap<JavaType, JsonDeserializer<Object>> _cachedDeserializers + = new ConcurrentHashMap<JavaType, JsonDeserializer<Object>>(64, 0.75f, 2); + + /** + * During deserializer construction process we may need to keep track of partially + * completed deserializers, to resolve cyclic dependencies. This is the + * map used for storing deserializers before they are fully complete. + */ + final protected HashMap<JavaType, JsonDeserializer<Object>> _incompleteDeserializers + = new HashMap<JavaType, JsonDeserializer<Object>>(8); + + final protected RootNameLookup _rootNames; + + /* + /********************************************************** + /* Configuration + /********************************************************** + */ + + /** + * Factory responsible for constructing actual deserializers, if not + * one of pre-configured types. + */ + protected DeserializerFactory _factory; + + /* + /********************************************************** + /* Life-cycle + /********************************************************** + */ + + /** + * Default constructor. Equivalent to calling + *<pre> + * new StdDeserializerProvider(BeanDeserializerFactory.instance); + *</pre> + */ + public StdDeserializerProvider() { this(BeanDeserializerFactory.instance); } + + public StdDeserializerProvider(DeserializerFactory f) { + _factory = f; + _rootNames = new RootNameLookup(); + } + + @Override + public DeserializerProvider withAdditionalDeserializers(Deserializers d) { + return withFactory(_factory.withAdditionalDeserializers(d)); + } + + @Override + public DeserializerProvider withAdditionalKeyDeserializers(KeyDeserializers d) { + return withFactory(_factory.withAdditionalKeyDeserializers(d)); + } + + @Override + public DeserializerProvider withDeserializerModifier(BeanDeserializerModifier modifier) { + return withFactory(_factory.withDeserializerModifier(modifier)); + } + + @Override + public DeserializerProvider withAbstractTypeResolver(AbstractTypeResolver resolver) { + return withFactory(_factory.withAbstractTypeResolver(resolver)); + } + + @Override + public DeserializerProvider withValueInstantiators(ValueInstantiators instantiators) { + return withFactory(_factory.withValueInstantiators(instantiators)); + } + + @Override + public StdDeserializerProvider withFactory(DeserializerFactory factory) { + // sanity-check to try to prevent hard-to-debug problems; sub-classes MUST override this method + if (this.getClass() != StdDeserializerProvider.class) { + throw new IllegalStateException("DeserializerProvider of type " + +this.getClass().getName()+" does not override 'withFactory()' method"); + } + return new StdDeserializerProvider(factory); + } + + /* + /********************************************************** + /* Abstract methods impls + /********************************************************** + */ + + @Override + public JavaType mapAbstractType(DeserializationConfig config, JavaType type) + throws JsonMappingException + { + return _factory.mapAbstractType(config, type); + } + + @Override + public SerializedString findExpectedRootName(DeserializationConfig config, JavaType type) + throws JsonMappingException + { + return _rootNames.findRootName(type, config); + } + + @SuppressWarnings("unchecked") + @Override + public JsonDeserializer<Object> findValueDeserializer(DeserializationConfig config, + JavaType propertyType, BeanProperty property) + throws JsonMappingException + { + JsonDeserializer<Object> deser = _findCachedDeserializer(propertyType); + if (deser != null) { + // [JACKSON-385]: need to support contextualization: + if (deser instanceof ContextualDeserializer<?>) { + JsonDeserializer<?> d = ((ContextualDeserializer<?>) deser).createContextual(config, property); + deser = (JsonDeserializer<Object>) d; + } + return deser; + } + // If not, need to request factory to construct (or recycle) + deser = _createAndCacheValueDeserializer(config, propertyType, property); + if (deser == null) { + /* Should we let caller handle it? Let's have a helper method + * decide it; can throw an exception, or return a valid + * deserializer + */ + deser = _handleUnknownValueDeserializer(propertyType); + } + // [JACKSON-385]: need to support contextualization: + if (deser instanceof ContextualDeserializer<?>) { + JsonDeserializer<?> d = ((ContextualDeserializer<?>) deser).createContextual(config, property); + deser = (JsonDeserializer<Object>) d; + } + return deser; + } + + @Override + public JsonDeserializer<Object> findTypedValueDeserializer(DeserializationConfig config, + JavaType type, BeanProperty property) + throws JsonMappingException + { + JsonDeserializer<Object> deser = findValueDeserializer(config, type, property); + TypeDeserializer typeDeser = _factory.findTypeDeserializer(config, type, property); + if (typeDeser != null) { + return new WrappedDeserializer(typeDeser, deser); + } + return deser; + } + + @Override + public KeyDeserializer findKeyDeserializer(DeserializationConfig config, + JavaType type, BeanProperty property) + throws JsonMappingException + { + KeyDeserializer kd = _factory.createKeyDeserializer(config, type, property); + // One more thing: contextuality + if (kd instanceof ContextualKeyDeserializer) { + kd = ((ContextualKeyDeserializer) kd).createContextual(config, property); + } + if (kd == null) { // if none found, need to use a placeholder that'll fail + return _handleUnknownKeyDeserializer(type); + } + return kd; + } + + /** + * Method that can be called to find out whether a deserializer can + * be found for given type + */ + @Override + public boolean hasValueDeserializerFor(DeserializationConfig config, JavaType type) + { + /* Note: mostly copied from findValueDeserializer, except for + * handling of unknown types + */ + JsonDeserializer<Object> deser = _findCachedDeserializer(type); + if (deser == null) { + try { + deser = _createAndCacheValueDeserializer(config, type, null); + } catch (Exception e) { + return false; + } + } + return (deser != null); + } + + @Override + public int cachedDeserializersCount() { + return _cachedDeserializers.size(); + } + + /** + * Method that will drop all dynamically constructed deserializers (ones that + * are counted as result value for {@link #cachedDeserializersCount}). + * This can be used to remove memory usage (in case some deserializers are + * only used once or so), or to force re-construction of deserializers after + * configuration changes for mapper than owns the provider. + * + * @since 1.4 + */ + @Override + public void flushCachedDeserializers() { + _cachedDeserializers.clear(); + } + + /* + /********************************************************** + /* Overridable helper methods + /********************************************************** + */ + + protected JsonDeserializer<Object> _findCachedDeserializer(JavaType type) + { + if (type == null) { + throw new IllegalArgumentException(); + } + return _cachedDeserializers.get(type); + } + + /** + * Method that will try to create a deserializer for given type, + * and resolve and cache it if necessary + * + * @param config Configuration + * @param type Type of property to deserializer + * @param property Property (field, setter, ctor arg) to use deserializer for + */ + protected JsonDeserializer<Object>_createAndCacheValueDeserializer(DeserializationConfig config, + JavaType type, BeanProperty property) + throws JsonMappingException + { + /* Only one thread to construct deserializers at any given point in time; + * limitations necessary to ensure that only completely initialized ones + * are visible and used. + */ + synchronized (_incompleteDeserializers) { + // Ok, then: could it be that due to a race condition, deserializer can now be found? + JsonDeserializer<Object> deser = _findCachedDeserializer(type); + if (deser != null) { + return deser; + } + int count = _incompleteDeserializers.size(); + // Or perhaps being resolved right now? + if (count > 0) { + deser = _incompleteDeserializers.get(type); + if (deser != null) { + return deser; + } + } + // Nope: need to create and possibly cache + try { + return _createAndCache2(config, type, property); + } finally { + // also: any deserializers that have been created are complete by now + if (count == 0 && _incompleteDeserializers.size() > 0) { + _incompleteDeserializers.clear(); + } + } + } + } + + /** + * Method that handles actual construction (via factory) and caching (both + * intermediate and eventual) + */ + protected JsonDeserializer<Object> _createAndCache2(DeserializationConfig config, JavaType type, + BeanProperty property) + throws JsonMappingException + { + JsonDeserializer<Object> deser; + try { + deser = _createDeserializer(config, type, property); + } catch (IllegalArgumentException iae) { + /* We better only expose checked exceptions, since those + * are what caller is expected to handle + */ + throw new JsonMappingException(iae.getMessage(), null, iae); + } + if (deser == null) { + return null; + } + /* cache resulting deserializer? always true for "plain" BeanDeserializer + * (but can be re-defined for sub-classes by using @JsonCachable!) + */ + // 08-Jun-2010, tatu: Related to [JACKSON-296], need to avoid caching MapSerializers... so: + boolean isResolvable = (deser instanceof ResolvableDeserializer); + boolean addToCache = (deser.getClass() == BeanDeserializer.class); + if (!addToCache) { + // 14-Feb-2011, tatu: As per [JACKSON-487], try fully blocking annotation access: + if (config.isEnabled(DeserializationConfig.Feature.USE_ANNOTATIONS)) { + AnnotationIntrospector aintr = config.getAnnotationIntrospector(); + // note: pass 'null' to prevent mix-ins from being used + AnnotatedClass ac = AnnotatedClass.construct(deser.getClass(), aintr, null); + Boolean cacheAnn = aintr.findCachability(ac); + if (cacheAnn != null) { + addToCache = cacheAnn.booleanValue(); + } + } + } + /* we will temporarily hold on to all created deserializers (to + * handle cyclic references, and possibly reuse non-cached + * deserializers (list, map)) + */ + /* 07-Jun-2010, tatu: Danger: [JACKSON-296] was caused by accidental + * resolution of a reference -- couple of ways to prevent this; + * either not add Lists or Maps, or clear references eagerly. + * Let's actually do both; since both seem reasonable. + */ + /* Need to resolve? Mostly done for bean deserializers; required for + * resolving cyclic references. + */ + if (isResolvable) { + _incompleteDeserializers.put(type, deser); + _resolveDeserializer(config, (ResolvableDeserializer)deser); + _incompleteDeserializers.remove(type); + } + if (addToCache) { + _cachedDeserializers.put(type, deser); + } + return deser; + } + + /* Refactored so we can isolate the casts that require suppression + * of type-safety warnings. + */ + @SuppressWarnings("unchecked") + protected JsonDeserializer<Object> _createDeserializer(DeserializationConfig config, + JavaType type, BeanProperty property) + throws JsonMappingException + { + if (type.isEnumType()) { + return (JsonDeserializer<Object>) _factory.createEnumDeserializer(config, this, type, property); + } + if (type.isContainerType()) { + if (type.isArrayType()) { + return (JsonDeserializer<Object>)_factory.createArrayDeserializer(config, this, + (ArrayType) type, property); + } + if (type.isMapLikeType()) { + MapLikeType mlt = (MapLikeType) type; + if (mlt.isTrueMapType()) { + return (JsonDeserializer<Object>)_factory.createMapDeserializer(config, this, + (MapType) mlt, property); + } + return (JsonDeserializer<Object>)_factory.createMapLikeDeserializer(config, this, + mlt, property); + } + if (type.isCollectionLikeType()) { + CollectionLikeType clt = (CollectionLikeType) type; + if (clt.isTrueCollectionType()) { + return (JsonDeserializer<Object>)_factory.createCollectionDeserializer(config, this, + (CollectionType) clt, property); + } + return (JsonDeserializer<Object>)_factory.createCollectionLikeDeserializer(config, this, + clt, property); + } + } + + // 02-Mar-2009, tatu: Let's consider JsonNode to be a type of its own + if (JsonNode.class.isAssignableFrom(type.getRawClass())) { + return (JsonDeserializer<Object>)_factory.createTreeDeserializer(config, this, type, property); + } + return (JsonDeserializer<Object>)_factory.createBeanDeserializer(config, this, type, property); + } + + protected void _resolveDeserializer(DeserializationConfig config, ResolvableDeserializer ser) + throws JsonMappingException + { + ser.resolve(config, this); + } + + /* + /********************************************************** + /* Overridable error reporting methods + /********************************************************** + */ + + protected JsonDeserializer<Object> _handleUnknownValueDeserializer(JavaType type) + throws JsonMappingException + { + // Let's try to figure out the reason, to give better error + Class<?> rawClass = type.getRawClass(); + if (!ClassUtil.isConcrete(rawClass)) { + throw new JsonMappingException("Can not find a Value deserializer for abstract type "+type); + } + throw new JsonMappingException("Can not find a Value deserializer for type "+type); + } + + protected KeyDeserializer _handleUnknownKeyDeserializer(JavaType type) + throws JsonMappingException + { + throw new JsonMappingException("Can not find a (Map) Key deserializer for type "+type); + } + + /* + /********************************************************** + /* Helper classes + /********************************************************** + */ + + /** + * Simple deserializer that will call configured type deserializer, passing + * in configured data deserializer, and exposing it all as a simple + * deserializer. + */ + protected final static class WrappedDeserializer + extends JsonDeserializer<Object> + { + final TypeDeserializer _typeDeserializer; + final JsonDeserializer<Object> _deserializer; + + public WrappedDeserializer(TypeDeserializer typeDeser, JsonDeserializer<Object> deser) + { + super(); + _typeDeserializer = typeDeser; + _deserializer = deser; + } + + @Override + public Object deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + return _deserializer.deserializeWithType(jp, ctxt, _typeDeserializer); + } + + @Override + public Object deserializeWithType(JsonParser jp, DeserializationContext ctxt, + TypeDeserializer typeDeserializer) + throws IOException, JsonProcessingException + { + // should never happen? (if it can, could call on that object) + throw new IllegalStateException("Type-wrapped deserializer's deserializeWithType should never get called"); + } + } + +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/StdDeserializers.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/StdDeserializers.java new file mode 100644 index 0000000..c3b828d --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/StdDeserializers.java
@@ -0,0 +1,119 @@ +package org.codehaus.jackson.map.deser; + +import java.util.*; + +import org.codehaus.jackson.map.JsonDeserializer; +import org.codehaus.jackson.map.deser.std.AtomicBooleanDeserializer; +import org.codehaus.jackson.map.deser.std.CalendarDeserializer; +import org.codehaus.jackson.map.deser.std.ClassDeserializer; +import org.codehaus.jackson.map.deser.std.DateDeserializer; +import org.codehaus.jackson.map.deser.std.FromStringDeserializer; +import org.codehaus.jackson.map.deser.std.JavaTypeDeserializer; +import org.codehaus.jackson.map.deser.std.StdDeserializer; +import org.codehaus.jackson.map.deser.std.StringDeserializer; +import org.codehaus.jackson.map.deser.std.TimestampDeserializer; +import org.codehaus.jackson.map.deser.std.TokenBufferDeserializer; +import org.codehaus.jackson.map.deser.std.UntypedObjectDeserializer; +import org.codehaus.jackson.map.type.*; + +/** + * Helper class used to contain simple/well-known deserializers for core JDK types. + *<p> + * Note: as of Jackson 1.9, we use type-erased class for registering, since + * some types may come either as type-erased or typed (for example, + * <code>java.lang.Class</code>). + */ +class StdDeserializers +{ + final HashMap<ClassKey, JsonDeserializer<Object>> _deserializers + = new HashMap<ClassKey, JsonDeserializer<Object>>(); + + private StdDeserializers() + { + // First, add the fall-back "untyped" deserializer: + add(new UntypedObjectDeserializer()); + + // Then String and String-like converters: + StdDeserializer<?> strDeser = new StringDeserializer(); + add(strDeser, String.class); + add(strDeser, CharSequence.class); + add(new ClassDeserializer()); + + // Then primitive-wrappers (simple): + add(new StdDeserializer.BooleanDeserializer(Boolean.class, null)); + add(new StdDeserializer.ByteDeserializer(Byte.class, null)); + add(new StdDeserializer.ShortDeserializer(Short.class, null)); + add(new StdDeserializer.CharacterDeserializer(Character.class, null)); + add(new StdDeserializer.IntegerDeserializer(Integer.class, null)); + add(new StdDeserializer.LongDeserializer(Long.class, null)); + add(new StdDeserializer.FloatDeserializer(Float.class, null)); + add(new StdDeserializer.DoubleDeserializer(Double.class, null)); + + /* And actual primitives: difference is the way nulls are to be + * handled... + */ + add(new StdDeserializer.BooleanDeserializer(Boolean.TYPE, Boolean.FALSE)); + add(new StdDeserializer.ByteDeserializer(Byte.TYPE, Byte.valueOf((byte)(0)))); + add(new StdDeserializer.ShortDeserializer(Short.TYPE, Short.valueOf((short)0))); + add(new StdDeserializer.CharacterDeserializer(Character.TYPE, Character.valueOf('\0'))); + add(new StdDeserializer.IntegerDeserializer(Integer.TYPE, Integer.valueOf(0))); + add(new StdDeserializer.LongDeserializer(Long.TYPE, Long.valueOf(0L))); + add(new StdDeserializer.FloatDeserializer(Float.TYPE, Float.valueOf(0.0f))); + add(new StdDeserializer.DoubleDeserializer(Double.TYPE, Double.valueOf(0.0))); + + // and related + add(new StdDeserializer.NumberDeserializer()); + add(new StdDeserializer.BigDecimalDeserializer()); + add(new StdDeserializer.BigIntegerDeserializer()); + + add(new CalendarDeserializer()); + add(new DateDeserializer()); + /* 24-Jan-2010, tatu: When including type information, we may + * know that we specifically need GregorianCalendar... + */ + add(new CalendarDeserializer(GregorianCalendar.class), + GregorianCalendar.class); + add(new StdDeserializer.SqlDateDeserializer()); + add(new TimestampDeserializer()); + + // From-string deserializers: + for (StdDeserializer<?> deser : FromStringDeserializer.all()) { + add(deser); + } + + // And finally some odds and ends + + // to deserialize Throwable, need stack trace elements: + add(new StdDeserializer.StackTraceElementDeserializer()); + + // [JACKSON-283] need to support atomic types, too + // (note: AtomicInteger/Long work due to single-arg constructor) + add(new AtomicBooleanDeserializer()); + + // including some core Jackson types: + add(new TokenBufferDeserializer()); + add(new JavaTypeDeserializer()); + } + + /** + * Public accessor to deserializers for core types. + */ + public static HashMap<ClassKey, JsonDeserializer<Object>> constructAll() + { + return new StdDeserializers()._deserializers; + } + + private void add(StdDeserializer<?> stdDeser) + { + add(stdDeser, stdDeser.getValueClass()); + } + + private void add(StdDeserializer<?> stdDeser, Class<?> valueClass) + { + // must do some unfortunate casting here... + @SuppressWarnings("unchecked") + JsonDeserializer<Object> deser = (JsonDeserializer<Object>) stdDeser; + // Not super clean, but default TypeFactory does work here: + _deserializers.put(new ClassKey(valueClass), deser); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/StdKeyDeserializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/StdKeyDeserializer.java new file mode 100644 index 0000000..6071f65 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/StdKeyDeserializer.java
@@ -0,0 +1,12 @@ +package org.codehaus.jackson.map.deser; + +/** + * @deprecated Since 1.9, use {@link org.codehaus.jackson.map.deser.std.StdKeyDeserializer} instead. + */ +@Deprecated +public abstract class StdKeyDeserializer + extends org.codehaus.jackson.map.deser.std.StdKeyDeserializer +{ + protected StdKeyDeserializer(Class<?> cls) { super(cls); } +} +
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/StdKeyDeserializers.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/StdKeyDeserializers.java new file mode 100644 index 0000000..a9063ce --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/StdKeyDeserializers.java
@@ -0,0 +1,11 @@ +package org.codehaus.jackson.map.deser; + +/** + * @deprecated Since 1.9, use {@link org.codehaus.jackson.map.deser.std.StdKeyDeserializers} instead. + */ +@Deprecated +class StdKeyDeserializers + extends org.codehaus.jackson.map.deser.std.StdKeyDeserializers +{ + protected StdKeyDeserializers() { super(); } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/StdScalarDeserializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/StdScalarDeserializer.java new file mode 100644 index 0000000..b8ff702 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/StdScalarDeserializer.java
@@ -0,0 +1,13 @@ +package org.codehaus.jackson.map.deser; + +/** + * @deprecated Since 1.9, use {@link org.codehaus.jackson.map.deser.std.StdScalarDeserializer} instead. + */ +@Deprecated +public abstract class StdScalarDeserializer<T> + extends org.codehaus.jackson.map.deser.std.StdDeserializer<T> +{ + protected StdScalarDeserializer(Class<?> vc) { + super(vc); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/ThrowableDeserializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/ThrowableDeserializer.java new file mode 100644 index 0000000..4418894 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/ThrowableDeserializer.java
@@ -0,0 +1,13 @@ +package org.codehaus.jackson.map.deser; + +/** + * @deprecated Since 1.9, use {@link org.codehaus.jackson.map.deser.std.ThrowableDeserializer} instead. + */ +@Deprecated +public class ThrowableDeserializer + extends org.codehaus.jackson.map.deser.std.ThrowableDeserializer +{ + public ThrowableDeserializer(BeanDeserializer baseDeserializer) { + super(baseDeserializer); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/UntypedObjectDeserializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/UntypedObjectDeserializer.java new file mode 100644 index 0000000..5eb115e --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/UntypedObjectDeserializer.java
@@ -0,0 +1,9 @@ +package org.codehaus.jackson.map.deser; + +/** + * @deprecated Since 1.9, use {@link org.codehaus.jackson.map.deser.std.UntypedObjectDeserializer} instead. + */ +@Deprecated +public class UntypedObjectDeserializer + extends org.codehaus.jackson.map.deser.std.UntypedObjectDeserializer +{ }
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/ValueInstantiator.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/ValueInstantiator.java new file mode 100644 index 0000000..0f587d0 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/ValueInstantiator.java
@@ -0,0 +1,280 @@ +package org.codehaus.jackson.map.deser; + +import java.io.IOException; + +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.map.JsonMappingException; +import org.codehaus.jackson.map.introspect.AnnotatedWithParams; +import org.codehaus.jackson.type.JavaType; + +/** + * Class that defines simple API implemented by objects that create value + * instances. Some or all of properties of value instances may + * be initialized by instantiator, rest being populated by deserializer, + * to which value instance is passed. + * Since different kinds of JSON values (structured and scalar) + * may be bound to Java values, in some cases instantiator + * fully defines resulting value; this is the case when JSON value + * is a scalar value (String, number, boolean). + *<p> + * Note that this type is not parameterized (even though it would seemingly + * make sense), because such type information can not be use effectively + * during runtime: access is always using either wildcard type, or just + * basic {@link java.lang.Object}; and so adding type parameter seems + * like unnecessary extra work. + *<p> + * Actual implementations are strongly recommended to be based on + * {@link org.codehaus.jackson.map.deser.std.StdValueInstantiator} + * which implements all methods, and as such will be compatible + * across versions even if new methods were added to this interface. + * + * @since 1.9 + */ +public abstract class ValueInstantiator +{ + /* + /********************************************************** + /* Metadata accessors + /********************************************************** + */ + + /** + * Method that returns description of the value type this instantiator + * handles. Used for error messages, diagnostics. + */ + public abstract String getValueTypeDesc(); + + /** + * Method that will return true if any of <code>canCreateXxx</code> method + * returns true: that is, if there is any way that an instance could + * be created. + */ + public boolean canInstantiate() { + return + canCreateUsingDefault() + || canCreateUsingDelegate() + || canCreateFromObjectWith() + || canCreateFromString() + || canCreateFromInt() + || canCreateFromLong() + || canCreateFromDouble() + || canCreateFromBoolean() + ; + } + + /** + * Method that can be called to check whether a String-based creator + * is available for this instantiator + */ + public boolean canCreateFromString() { + return false; + } + + /** + * Method that can be called to check whether an integer (int, Integer) based + * creator is available to use (to call {@link #createFromInt}). + */ + public boolean canCreateFromInt() { + return false; + } + + /** + * Method that can be called to check whether a long (long, Long) based + * creator is available to use (to call {@link #createFromLong}). + */ + public boolean canCreateFromLong() { + return false; + } + + /** + * Method that can be called to check whether a double (double / Double) based + * creator is available to use (to call {@link #createFromDouble}). + */ + public boolean canCreateFromDouble() { + return false; + } + + /** + * Method that can be called to check whether a double (boolean / Boolean) based + * creator is available to use (to call {@link #createFromDouble}). + */ + public boolean canCreateFromBoolean() { + return false; + } + + /** + * Method that can be called to check whether a default creator (constructor, + * or no-arg static factory method) + * is available for this instantiator + */ + public boolean canCreateUsingDefault() { + return getDefaultCreator() != null; + } + + /** + * Method that can be called to check whether a delegate-based creator (single-arg + * constructor or factory method) + * is available for this instantiator + */ + public boolean canCreateUsingDelegate() { + return getDelegateType() != null; + } + + /** + * Method that can be called to check whether a property-based creator + * (argument-taking constructor or factory method) + * is available to instantiate values from JSON Object + */ + public boolean canCreateFromObjectWith() { + return false; + } + + /** + * Method called to determine types of instantiation arguments + * to use when creating instances with creator arguments + * (when {@link #canCreateFromObjectWith()} returns true). + * These arguments are bound from JSON, using specified + * property types to locate deserializers. + *<p> + * NOTE: all properties will be of type + * {@link org.codehaus.jackson.map.deser.impl.CreatorProperty}. + */ + public SettableBeanProperty[] getFromObjectArguments() { + return null; + } + + /** + * Method that can be used to determine what is the type of delegate + * type to use, if any; if no delegates are used, will return null. + * If non-null type is returned, deserializer will bind JSON into + * specified type (using standard deserializer for that type), and + * pass that to instantiator. + */ + public JavaType getDelegateType() { + return null; + } + + /* + /********************************************************** + /* Instantiation methods for JSON Object + /********************************************************** + */ + + /** + * Method called to create value instance from a JSON value when + * no data needs to passed to creator (constructor, factory method); + * typically this will call the default constructor of the value object. + * It will only be used if more specific creator methods are not + * applicable; hence "default". + *<p> + * This method is called if {@link #getFromObjectArguments} returns + * null or empty List. + */ + public Object createUsingDefault() + throws IOException, JsonProcessingException { + throw new JsonMappingException("Can not instantiate value of type " + +getValueTypeDesc()+"; no default creator found"); + } + + /** + * Method called to create value instance from JSON Object when + * instantiation arguments are passed; this is done, for example when passing information + * specified with "Creator" annotations. + *<p> + * This method is called if {@link #getFromObjectArguments} returns + * a non-empty List of arguments. + */ + public Object createFromObjectWith(Object[] args) + throws IOException, JsonProcessingException { + throw new JsonMappingException("Can not instantiate value of type " + +getValueTypeDesc()+" with arguments"); + } + + /** + * Method to called to create value instance from JSON Object using + * an intermediate "delegate" value to pass to createor method + */ + public Object createUsingDelegate(Object delegate) + throws IOException, JsonProcessingException + { + throw new JsonMappingException("Can not instantiate value of type " + +getValueTypeDesc()+" using delegate"); + } + + /* + /********************************************************** + /* Instantiation methods for JSON scalar types + /* (String, Number, Boolean) + /********************************************************** + */ + + public Object createFromString(String value) throws IOException, JsonProcessingException { + throw new JsonMappingException("Can not instantiate value of type " + +getValueTypeDesc()+" from JSON String"); + } + + public Object createFromInt(int value) throws IOException, JsonProcessingException { + throw new JsonMappingException("Can not instantiate value of type " + +getValueTypeDesc()+" from JSON int number"); + } + + public Object createFromLong(long value) throws IOException, JsonProcessingException { + throw new JsonMappingException("Can not instantiate value of type " + +getValueTypeDesc()+" from JSON long number"); + } + + public Object createFromDouble(double value) throws IOException, JsonProcessingException { + throw new JsonMappingException("Can not instantiate value of type " + +getValueTypeDesc()+" from JSON floating-point number"); + } + + public Object createFromBoolean(boolean value) throws IOException, JsonProcessingException { + throw new JsonMappingException("Can not instantiate value of type " + +getValueTypeDesc()+" from JSON boolean value"); + } + + /* + /********************************************************** + /* Accessors for underlying creator objects (optional) + /********************************************************** + */ + + /** + * Method that can be called to try to access member (constructor, + * static factory method) that is used as the "default creator" + * (creator that is called without arguments; typically default + * [zero-argument] constructor of the type). + * Note that implementations not required to return actual object + * they use (or, they may use some other instantiation) method. + * That is, even if {@link #canCreateUsingDefault()} returns true, + * this method may return null . + */ + public AnnotatedWithParams getDefaultCreator() { + return null; + } + + /** + * Method that can be called to try to access member (constructor, + * static factory method) that is used as the "delegate creator". + * Note that implementations not required to return actual object + * they use (or, they may use some other instantiation) method. + * That is, even if {@link #canCreateUsingDelegate()} returns true, + * this method may return null . + */ + public AnnotatedWithParams getDelegateCreator() { + return null; + } + + /** + * Method that can be called to try to access member (constructor, + * static factory method) that is used as the "non-default creator" + * (constructor or factory method that takes one or more arguments). + * Note that implementations not required to return actual object + * they use (or, they may use some other instantiation) method. + * That is, even if {@link #canCreateFromObjectWith()} returns true, + * this method may return null . + */ + public AnnotatedWithParams getWithArgsCreator() { + return null; + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/ValueInstantiators.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/ValueInstantiators.java new file mode 100644 index 0000000..0c84916 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/ValueInstantiators.java
@@ -0,0 +1,52 @@ +package org.codehaus.jackson.map.deser; + +import org.codehaus.jackson.map.*; + +/** + * Interface for providers of {@link ValueInstantiator} instances. + * Implemented when an object wants to provide custom value instantiators, + * usually to support custom value types with alternate constructors, or + * which need specified post-processing after construction but before + * binding data. + * + * @since 1.9 + */ +public interface ValueInstantiators +{ + /** + * Method called to find the {@link ValueInstantiator} to use for creating + * instances of specified type during deserialization. + * Note that a default value instantiator is always created first and passed; + * if an implementation does not want to modify or replace it, it has to return + * passed instance as is (returning null is an error) + * + * @param config Deserialization configuration in use + * @param beanDesc Additional information about POJO type to be instantiated: + * description will always be of type + * {@link org.codehaus.jackson.map.introspect.BasicBeanDescription} (that is, + * safe to cast to this more specific type) + * @param defaultInstantiator Instantiator that will be used if no changes are made; + * passed to allow custom instances to use annotation-provided information + * (note, however, that earlier {@link ValueInstantiators} may have changed it to + * a custom instantiator already) + * + * @return Instantiator to use; either <code>defaultInstantiator</code> that was passed, + * or a custom variant; can not be null. + */ + public ValueInstantiator findValueInstantiator(DeserializationConfig config, + BeanDescription beanDesc, ValueInstantiator defaultInstantiator); + + /** + * Basic "NOP" implementation that can be used as the base class for custom implementations. + * Safer to extend (instead of implementing {@link ValueInstantiators}) in case later + * Jackson versions add new methods in base interface. + */ + public static class Base implements ValueInstantiators + { + @Override + public ValueInstantiator findValueInstantiator(DeserializationConfig config, + BeanDescription beanDesc, ValueInstantiator defaultInstantiator) { + return defaultInstantiator; + } + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/impl/BeanPropertyMap.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/impl/BeanPropertyMap.java new file mode 100644 index 0000000..fb5c23a --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/impl/BeanPropertyMap.java
@@ -0,0 +1,257 @@ +package org.codehaus.jackson.map.deser.impl; + +import java.util.*; + +import org.codehaus.jackson.map.deser.SettableBeanProperty; + +/** + * Helper class used for storing mapping from property name to + * {@link SettableBeanProperty} instances. + *<p> + * Note that this class is used instead of generic {@link java.util.HashMap} + * is performance: although default implementation is very good for generic + * use cases, it can still be streamlined a bit for specific use case + * we have. + * + * @since 1.7 + */ +public final class BeanPropertyMap +{ + private final Bucket[] _buckets; + + private final int _hashMask; + + private final int _size; + + public BeanPropertyMap(Collection<SettableBeanProperty> properties) + { + _size = properties.size(); + int bucketCount = findSize(_size); + _hashMask = bucketCount-1; + Bucket[] buckets = new Bucket[bucketCount]; + for (SettableBeanProperty property : properties) { + String key = property.getName(); + int index = key.hashCode() & _hashMask; + buckets[index] = new Bucket(buckets[index], key, property); + } + _buckets = buckets; + } + + public void assignIndexes() + { + // order is arbitrary, but stable: + int index = 0; + for (Bucket bucket : _buckets) { + while (bucket != null) { + bucket.value.assignIndex(index++); + bucket = bucket.next; + } + } + } + + private final static int findSize(int size) + { + // For small enough results (32 or less), we'll require <= 50% fill rate; otherwise 80% + int needed = (size <= 32) ? (size + size) : (size + (size >> 2)); + int result = 2; + while (result < needed) { + result += result; + } + return result; + } + + /* + /********************************************************** + /* Public API + /********************************************************** + */ + + public int size() { return _size; } + + /** + * Accessor for traversing over all contained properties. + */ + public Iterator<SettableBeanProperty> allProperties() { + return new IteratorImpl(_buckets); + } + + public SettableBeanProperty find(String key) + { + int index = key.hashCode() & _hashMask; + Bucket bucket = _buckets[index]; + // Let's unroll first lookup since that is null or match in 90+% cases + if (bucket == null) { + return null; + } + // Primarily we do just identity comparison as keys should be interned + if (bucket.key == key) { + return bucket.value; + } + while ((bucket = bucket.next) != null) { + if (bucket.key == key) { + return bucket.value; + } + } + // Do we need fallback for non-interned Strings? + return _findWithEquals(key, index); + } + + /** + * Specialized method that can be used to replace an existing entry + * (note: entry MUST exist; otherwise exception is thrown) with + * specified replacement. + */ + public void replace(SettableBeanProperty property) + { + String name = property.getName(); + int index = name.hashCode() & (_buckets.length-1); + + /* This is bit tricky just because buckets themselves + * are immutable, so we need to recreate the chain. Fine. + */ + Bucket tail = null; + boolean found = false; + + + for (Bucket bucket = _buckets[index]; bucket != null; bucket = bucket.next) { + // match to remove? + if (!found && bucket.key.equals(name)) { + found = true; + } else { + tail = new Bucket(tail, bucket.key, bucket.value); + } + } + // Not finding specified entry is error, so: + if (!found) { + throw new NoSuchElementException("No entry '"+property+"' found, can't replace"); + } + /* So let's attach replacement in front: useful also because + * it allows replacement even when iterating over entries + */ + _buckets[index] = new Bucket(tail, name, property); + } + + /** + * Specialized method for removing specified existing entry. + * NOTE: entry MUST exist, otherwise an exception is thrown. + * + * @since 1.9 + */ + public void remove(SettableBeanProperty property) + { + // Mostly this is the same as code with 'replace', just bit simpler... + String name = property.getName(); + int index = name.hashCode() & (_buckets.length-1); + Bucket tail = null; + boolean found = false; + // slightly complex just because chain is immutable, must recreate + for (Bucket bucket = _buckets[index]; bucket != null; bucket = bucket.next) { + // match to remove? + if (!found && bucket.key.equals(name)) { + found = true; + } else { + tail = new Bucket(tail, bucket.key, bucket.value); + } + } + if (!found) { // must be found + throw new NoSuchElementException("No entry '"+property+"' found, can't remove"); + } + _buckets[index] = tail; + } + + /* + /********************************************************** + /* Helper methods + /********************************************************** + */ + + private SettableBeanProperty _findWithEquals(String key, int index) + { + Bucket bucket = _buckets[index]; + while (bucket != null) { + if (key.equals(bucket.key)) { + return bucket.value; + } + bucket = bucket.next; + } + return null; + } + + /* + /********************************************************** + /* Helper beans + /********************************************************** + */ + + private final static class Bucket + { + public final Bucket next; + public final String key; + public final SettableBeanProperty value; + + public Bucket(Bucket next, String key, SettableBeanProperty value) + { + this.next = next; + this.key = key; + this.value = value; + } + } + + private final static class IteratorImpl implements Iterator<SettableBeanProperty> + { + /** + * Buckets of the map + */ + private final Bucket[] _buckets; + + /** + * Bucket that contains next value to return (if any); null if nothing more to iterate + */ + private Bucket _currentBucket; + + /** + * Index of the next bucket in bucket array to check. + */ + private int _nextBucketIndex; + + public IteratorImpl(Bucket[] buckets) { + _buckets = buckets; + // need to initialize to point to first entry... + int i = 0; + for (int len = _buckets.length; i < len; ) { + Bucket b = _buckets[i++]; + if (b != null) { + _currentBucket = b; + break; + } + } + _nextBucketIndex = i; + } + + @Override + public boolean hasNext() { + return _currentBucket != null; + } + + @Override + public SettableBeanProperty next() + { + Bucket curr = _currentBucket; + if (curr == null) { // sanity check + throw new NoSuchElementException(); + } + // need to advance, too + Bucket b = curr.next; + while (b == null && _nextBucketIndex < _buckets.length) { + b = _buckets[_nextBucketIndex++]; + } + _currentBucket = b; + return curr.value; + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/impl/CreatorCollector.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/impl/CreatorCollector.java new file mode 100644 index 0000000..8252d79 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/impl/CreatorCollector.java
@@ -0,0 +1,147 @@ +package org.codehaus.jackson.map.deser.impl; + +import java.lang.reflect.Member; +import java.util.*; + +import org.codehaus.jackson.map.DeserializationConfig; +import org.codehaus.jackson.map.deser.ValueInstantiator; +import org.codehaus.jackson.map.deser.std.StdValueInstantiator; +import org.codehaus.jackson.map.introspect.*; +import org.codehaus.jackson.map.type.TypeBindings; +import org.codehaus.jackson.map.util.ClassUtil; +import org.codehaus.jackson.type.JavaType; + +/** + * Container class for storing information on creators (based on annotations, + * visibility), to be able to build actual instantiator later on. + */ +public class CreatorCollector +{ + /// Type of bean being created + final BasicBeanDescription _beanDesc; + + final boolean _canFixAccess; + + protected AnnotatedConstructor _defaultConstructor; + + protected AnnotatedWithParams _stringCreator, _intCreator, _longCreator; + protected AnnotatedWithParams _doubleCreator, _booleanCreator; + + protected AnnotatedWithParams _delegateCreator; + + protected AnnotatedWithParams _propertyBasedCreator; + protected CreatorProperty[] _propertyBasedArgs = null; + + /* + /********************************************************** + /* Life-cycle + /********************************************************** + */ + + public CreatorCollector(BasicBeanDescription beanDesc, boolean canFixAccess) + { + _beanDesc = beanDesc; + _canFixAccess = canFixAccess; + } + + /** + * @since 1.9.0 + */ + public ValueInstantiator constructValueInstantiator(DeserializationConfig config) + { + StdValueInstantiator inst = new StdValueInstantiator(config, _beanDesc.getType()); + + JavaType delegateType; + + if (_delegateCreator == null) { + delegateType = null; + } else { + TypeBindings bindings = _beanDesc.bindingsForBeanType(); + delegateType = bindings.resolveType(_delegateCreator.getParameterType(0)); + } + + inst.configureFromObjectSettings(_defaultConstructor, + _delegateCreator, delegateType, + _propertyBasedCreator, _propertyBasedArgs); + inst.configureFromStringCreator(_stringCreator); + inst.configureFromIntCreator(_intCreator); + inst.configureFromLongCreator(_longCreator); + inst.configureFromDoubleCreator(_doubleCreator); + inst.configureFromBooleanCreator(_booleanCreator); + return inst; + } + + /* + /********************************************************** + /* Setters + /********************************************************** + */ + + public void setDefaultConstructor(AnnotatedConstructor ctor) { + _defaultConstructor = ctor; + } + + public void addStringCreator(AnnotatedWithParams creator) { + _stringCreator = verifyNonDup(creator, _stringCreator, "String"); + } + public void addIntCreator(AnnotatedWithParams creator) { + _intCreator = verifyNonDup(creator, _intCreator, "int"); + } + public void addLongCreator(AnnotatedWithParams creator) { + _longCreator = verifyNonDup(creator, _longCreator, "long"); + } + public void addDoubleCreator(AnnotatedWithParams creator) { + _doubleCreator = verifyNonDup(creator, _doubleCreator, "double"); + } + public void addBooleanCreator(AnnotatedWithParams creator) { + _booleanCreator = verifyNonDup(creator, _booleanCreator, "boolean"); + } + + public void addDelegatingCreator(AnnotatedWithParams creator) { + _delegateCreator = verifyNonDup(creator, _delegateCreator, "delegate"); + } + + public void addPropertyCreator(AnnotatedWithParams creator, CreatorProperty[] properties) + { + _propertyBasedCreator = verifyNonDup(creator, _propertyBasedCreator, "property-based"); + // [JACKSON-470] Better ensure we have no duplicate names either... + if (properties.length > 1) { + HashMap<String,Integer> names = new HashMap<String,Integer>(); + for (int i = 0, len = properties.length; i < len; ++i) { + String name = properties[i].getName(); + /* [Issue-13]: Need to consider Injectables, which may not have + * a name at all, and need to be skipped + */ + if (name.length() == 0 && properties[i].getInjectableValueId() != null) { + continue; + } + Integer old = names.put(name, Integer.valueOf(i)); + if (old != null) { + throw new IllegalArgumentException("Duplicate creator property \""+name+"\" (index "+old+" vs "+i+")"); + } + } + } + _propertyBasedArgs = properties; + } + + /* + /********************************************************** + /* Helper methods + /********************************************************** + */ + + protected AnnotatedWithParams verifyNonDup(AnnotatedWithParams newOne, AnnotatedWithParams oldOne, + String type) + { + if (oldOne != null) { + // important: ok to override factory with constructor; but not within same type, so: + if (oldOne.getClass() == newOne.getClass()) { + throw new IllegalArgumentException("Conflicting "+type+" creators: already had "+oldOne+", encountered "+newOne); + } + } + if (_canFixAccess) { + ClassUtil.checkAndFixAccess((Member) newOne.getAnnotated()); + } + return newOne; + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/impl/CreatorProperty.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/impl/CreatorProperty.java new file mode 100644 index 0000000..9025931 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/impl/CreatorProperty.java
@@ -0,0 +1,152 @@ +package org.codehaus.jackson.map.deser.impl; + +import java.io.IOException; +import java.lang.annotation.Annotation; + +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.map.DeserializationContext; +import org.codehaus.jackson.map.JsonDeserializer; +import org.codehaus.jackson.map.TypeDeserializer; +import org.codehaus.jackson.map.deser.SettableBeanProperty; +import org.codehaus.jackson.map.introspect.AnnotatedMember; +import org.codehaus.jackson.map.introspect.AnnotatedParameter; +import org.codehaus.jackson.map.util.Annotations; +import org.codehaus.jackson.type.JavaType; + +/** + * This concrete sub-class implements property that is passed + * via Creator (constructor or static factory method). + * It is not a full-featured implementation in that its set method + * should never be called -- instead, value must separately passed. + *<p> + * Note on injectable values (1.9): unlike with other mutators, where + * deserializer and injecting are separate, here we deal the two as related + * things. This is necessary to add proper priority, as well as to simplify + * coordination. + *<p> + * Note that this class was moved in Jackson 1.9 + * from being a static sub-class of "org.codehaus.jackson.map.deser.SettableBeanProperty" + * into separate class, to make it easier to use it for custom creators. + */ +public class CreatorProperty + extends SettableBeanProperty +{ + /** + * Placeholder that represents constructor parameter, when it is created + * from actual constructor. + * May be null when a synthetic instance is created. + */ + protected final AnnotatedParameter _annotated; + + /** + * Id of value to inject, if value injection should be used for this parameter + * (in addition to, or instead of, regular deserialization). + * + * @since 1.9 + */ + protected final Object _injectableValueId; + + /** + * @param name Name of the logical property + * @param type Type of the property, used to find deserializer + * @param typeDeser Type deserializer to use for handling polymorphic type + * information, if one is needed + * @param contextAnnotations Contextual annotations (usually by class that + * declares creator [constructor, factory method] that includes + * this property) + * @param param Representation of property, constructor or factory + * method parameter; used for accessing annotations of the property + */ + public CreatorProperty(String name, JavaType type, TypeDeserializer typeDeser, + Annotations contextAnnotations, AnnotatedParameter param, + int index, Object injectableValueId) + { + super(name, type, typeDeser, contextAnnotations); + _annotated = param; + _propertyIndex = index; + _injectableValueId = injectableValueId; + } + + protected CreatorProperty(CreatorProperty src, JsonDeserializer<Object> deser) { + super(src, deser); + _annotated = src._annotated; + _injectableValueId = src._injectableValueId; + } + + @Override + public CreatorProperty withValueDeserializer(JsonDeserializer<Object> deser) { + return new CreatorProperty(this, deser); + } + + /** + * Method that can be called to locate value to be injected for this + * property, if it is configured for this. + * + * @since 1.9 + */ + public Object findInjectableValue(DeserializationContext context, Object beanInstance) + { + if (_injectableValueId == null) { + throw new IllegalStateException("Property '"+getName() + +"' (type "+getClass().getName()+") has no injectable value id configured"); + } + return context.findInjectableValue(_injectableValueId, this, beanInstance); + } + + /** + * Method to find value to inject, and inject it to this property. + * + * @since 1.9 + */ + public void inject(DeserializationContext context, Object beanInstance) + throws IOException + { + set(beanInstance, findInjectableValue(context, beanInstance)); + } + + /* + /********************************************************** + /* BeanProperty impl + /********************************************************** + */ + + @Override + public <A extends Annotation> A getAnnotation(Class<A> acls) { + if (_annotated == null) { + return null; + } + return _annotated.getAnnotation(acls); + } + + @Override public AnnotatedMember getMember() { return _annotated; } + + /* + /********************************************************** + /* Overridden methods + /********************************************************** + */ + + @Override + public void deserializeAndSet(JsonParser jp, DeserializationContext ctxt, + Object instance) + throws IOException, JsonProcessingException + { + set(instance, deserialize(jp, ctxt)); + } + + @Override + public void set(Object instance, Object value) + throws IOException + { + /* Hmmmh. Should we return quietly (NOP), or error? + * For now, let's just bail out without fuss. + */ + //throw new IllegalStateException("Method should never be called on a "+getClass().getName()); + } + + @Override + public Object getInjectableValueId() { + return _injectableValueId; + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/impl/ExternalTypeHandler.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/impl/ExternalTypeHandler.java new file mode 100644 index 0000000..335ff2c --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/impl/ExternalTypeHandler.java
@@ -0,0 +1,205 @@ +package org.codehaus.jackson.map.deser.impl; + +import java.io.IOException; +import java.util.*; + +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.map.DeserializationContext; +import org.codehaus.jackson.map.deser.SettableBeanProperty; +import org.codehaus.jackson.util.TokenBuffer; + +/** + * Helper class that is used to flatten JSON structure when using + * "external type id" (see {@link org.codehaus.jackson.annotate.JsonTypeInfo.As#EXTERNAL_PROPERTY}). + * This is needed to store temporary state and buffer tokens, as the structure is + * rearranged a bit so that actual type deserializer can resolve type and + * finalize deserialization. + * + * @since 1.9 + */ +public class ExternalTypeHandler +{ + private final ExtTypedProperty[] _properties; + private final HashMap<String, Integer> _nameToPropertyIndex; + + private final String[] _typeIds; + private final TokenBuffer[] _tokens; + + protected ExternalTypeHandler(ExtTypedProperty[] properties, + HashMap<String, Integer> nameToPropertyIndex, + String[] typeIds, TokenBuffer[] tokens) + { + _properties = properties; + _nameToPropertyIndex = nameToPropertyIndex; + _typeIds = typeIds; + _tokens = tokens; + } + + protected ExternalTypeHandler(ExternalTypeHandler h) + { + _properties = h._properties; + _nameToPropertyIndex = h._nameToPropertyIndex; + int len = _properties.length; + _typeIds = new String[len]; + _tokens = new TokenBuffer[len]; + } + + public ExternalTypeHandler start() { + return new ExternalTypeHandler(this); + } + + /** + * Method called to see if given property/value pair is an external type + * id; and if so handle it. This is <b>only</b> to be called in case + * containing POJO has similarly named property as the external type id; + * otherwise {@link #handleToken} should be called instead. + */ + public boolean handleTypePropertyValue(JsonParser jp, DeserializationContext ctxt, + String propName, Object bean) + throws IOException, JsonProcessingException + { + Integer I = _nameToPropertyIndex.get(propName); + if (I == null) { + return false; + } + int index = I.intValue(); + ExtTypedProperty prop = _properties[index]; + if (!prop.hasTypePropertyName(propName)) { + return false; + } + _typeIds[index] = jp.getText(); + // note: can NOT skip child values (should always be String anyway) + boolean canDeserialize = (bean != null) && (_tokens[index] != null); + // Minor optimization: deserialize properties as soon as we have all we need: + if (canDeserialize) { + _deserialize(jp, ctxt, bean, index); + // clear stored data, to avoid deserializing+setting twice: + _typeIds[index] = null; + _tokens[index] = null; + } + return true; + } + + /** + * Method called to ask handler to handle + */ + public boolean handleToken(JsonParser jp, DeserializationContext ctxt, + String propName, Object bean) + throws IOException, JsonProcessingException + { + Integer I = _nameToPropertyIndex.get(propName); + if (I == null) { + return false; + } + int index = I.intValue(); + ExtTypedProperty prop = _properties[index]; + boolean canDeserialize; + if (prop.hasTypePropertyName(propName)) { + _typeIds[index] = jp.getText(); + jp.skipChildren(); + canDeserialize = (bean != null) && (_tokens[index] != null); + } else { + TokenBuffer tokens = new TokenBuffer(jp.getCodec()); + tokens.copyCurrentStructure(jp); + _tokens[index] = tokens; + canDeserialize = (bean != null) && (_typeIds[index] != null); + } + /* Minor optimization: let's deserialize properties as soon as + * we have all pertinent information: + */ + if (canDeserialize) { + _deserialize(jp, ctxt, bean, index); + // clear stored data, to avoid deserializing+setting twice: + _typeIds[index] = null; + _tokens[index] = null; + } + return true; + } + + public Object complete(JsonParser jp, DeserializationContext ctxt, Object bean) + throws IOException, JsonProcessingException + { + for (int i = 0, len = _properties.length; i < len; ++i) { + if (_typeIds[i] == null) { + // let's allow missing both type and property (may already have been set, too) + if (_tokens[i] == null) { + continue; + } + // but not just one + throw ctxt.mappingException("Missing external type id property '"+_properties[i].getTypePropertyName()+"'"); + } else if (_tokens[i] == null) { + SettableBeanProperty prop = _properties[i].getProperty(); + throw ctxt.mappingException("Missing property '"+prop.getName()+"' for external type id '"+_properties[i].getTypePropertyName()); + } + _deserialize(jp, ctxt, bean, i); + } + return bean; + } + + protected final void _deserialize(JsonParser jp, DeserializationContext ctxt, Object bean, int index) + throws IOException, JsonProcessingException + { + /* Ok: time to mix type id, value; and we will actually use "wrapper-array" + * style to ensure we can handle all kinds of JSON constructs. + */ + TokenBuffer merged = new TokenBuffer(jp.getCodec()); + merged.writeStartArray(); + merged.writeString(_typeIds[index]); + JsonParser p2 = _tokens[index].asParser(jp); + p2.nextToken(); + merged.copyCurrentStructure(p2); + merged.writeEndArray(); + // needs to point to START_OBJECT (or whatever first token is) + p2 = merged.asParser(jp); + p2.nextToken(); + _properties[index].getProperty().deserializeAndSet(p2, ctxt, bean); + } + + /* + /********************************************************** + /* Helper classes + /********************************************************** + */ + + public static class Builder + { + private final ArrayList<ExtTypedProperty> _properties = new ArrayList<ExtTypedProperty>(); + private final HashMap<String, Integer> _nameToPropertyIndex = new HashMap<String, Integer>(); + + public void addExternal(SettableBeanProperty property, String extPropName) + { + Integer index = _properties.size(); + _properties.add(new ExtTypedProperty(property, extPropName)); + _nameToPropertyIndex.put(property.getName(), index); + _nameToPropertyIndex.put(extPropName, index); + } + + public ExternalTypeHandler build() { + return new ExternalTypeHandler(_properties.toArray(new ExtTypedProperty[_properties.size()]), + _nameToPropertyIndex, null, null); + } + } + + private final static class ExtTypedProperty + { + private final SettableBeanProperty _property; + private final String _typePropertyName; + + public ExtTypedProperty(SettableBeanProperty property, String typePropertyName) + { + _property = property; + _typePropertyName = typePropertyName; + } + + public boolean hasTypePropertyName(String n) { + return n.equals(_typePropertyName); + } + + public String getTypePropertyName() { return _typePropertyName; } + + public SettableBeanProperty getProperty() { + return _property; + } + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/impl/PropertyBasedCreator.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/impl/PropertyBasedCreator.java new file mode 100644 index 0000000..63708e7 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/impl/PropertyBasedCreator.java
@@ -0,0 +1,125 @@ +package org.codehaus.jackson.map.deser.impl; + +import java.io.IOException; +import java.util.Collection; +import java.util.HashMap; + +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.map.DeserializationContext; +import org.codehaus.jackson.map.JsonDeserializer; +import org.codehaus.jackson.map.deser.SettableBeanProperty; +import org.codehaus.jackson.map.deser.ValueInstantiator; +import org.codehaus.jackson.map.util.ClassUtil; + +/** + * Object that is used to collect arguments for non-default creator + * (non-default-constructor, or argument-taking factory method) + * before creator can be called. + * Since ordering of JSON properties is not guaranteed, this may + * require buffering of values other than ones being passed to + * creator. + */ +public final class PropertyBasedCreator +{ + protected final ValueInstantiator _valueInstantiator; + + /** + * Map that contains property objects for either constructor or factory + * method (whichever one is null: one property for each + * parameter for that one), keyed by logical property name + */ + protected final HashMap<String, SettableBeanProperty> _properties; + + /** + * Number of properties: usually same as size of {@link #_properties}, + * but not necessarily, when we have unnamed injectable properties. + */ + protected final int _propertyCount; + + /** + * If some property values must always have a non-null value (like + * primitive types do), this array contains such default values. + */ + protected Object[] _defaultValues; + + /** + * Array that contains properties that expect value to inject, if any; + * null if no injectable values are expected. + * + * @since 1.9 + */ + protected final SettableBeanProperty[] _propertiesWithInjectables; + + public PropertyBasedCreator(ValueInstantiator valueInstantiator) + { + _valueInstantiator = valueInstantiator; + _properties = new HashMap<String, SettableBeanProperty>(); + // [JACKSON-372]: primitive types need extra care + Object[] defValues = null; + SettableBeanProperty[] creatorProps = valueInstantiator.getFromObjectArguments(); + SettableBeanProperty[] propertiesWithInjectables = null; + final int len = creatorProps.length; + _propertyCount = len; + for (int i = 0; i < len; ++i) { + SettableBeanProperty prop = creatorProps[i]; + _properties.put(prop.getName(), prop); + if (prop.getType().isPrimitive()) { + if (defValues == null) { + defValues = new Object[len]; + } + defValues[i] = ClassUtil.defaultValue(prop.getType().getRawClass()); + } + Object injectableValueId = prop.getInjectableValueId(); + if (injectableValueId != null) { + if (propertiesWithInjectables == null) { + propertiesWithInjectables = new SettableBeanProperty[len]; + } + propertiesWithInjectables[i] = prop; + } + } + _defaultValues = defValues; + _propertiesWithInjectables = propertiesWithInjectables; + } + + public Collection<SettableBeanProperty> getCreatorProperties() { + return _properties.values(); + } + + public SettableBeanProperty findCreatorProperty(String name) { + return _properties.get(name); + } + + public void assignDeserializer(SettableBeanProperty prop, JsonDeserializer<Object> deser) { + prop = prop.withValueDeserializer(deser); + _properties.put(prop.getName(), prop); + Object nullValue = deser.getNullValue(); + if (nullValue != null) { + if (_defaultValues == null) { + _defaultValues = new Object[_properties.size()]; + } + _defaultValues[prop.getPropertyIndex()] = nullValue; + } + } + + /** + * Method called when starting to build a bean instance. + */ + public PropertyValueBuffer startBuilding(JsonParser jp, DeserializationContext ctxt) + { + PropertyValueBuffer buffer = new PropertyValueBuffer(jp, ctxt, _propertyCount); + if (_propertiesWithInjectables != null) { + buffer.inject(_propertiesWithInjectables); + } + return buffer; + } + + public Object build(PropertyValueBuffer buffer) throws IOException + { + Object bean = _valueInstantiator.createFromObjectWith(buffer.getParameters(_defaultValues)); + // Anything buffered? + for (PropertyValue pv = buffer.buffered(); pv != null; pv = pv.next) { + pv.assign(bean); + } + return bean; + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/impl/PropertyValue.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/impl/PropertyValue.java new file mode 100644 index 0000000..b4aa6a7 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/impl/PropertyValue.java
@@ -0,0 +1,116 @@ +package org.codehaus.jackson.map.deser.impl; + +import java.io.IOException; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.map.deser.SettableAnyProperty; +import org.codehaus.jackson.map.deser.SettableBeanProperty; + +/** + * Base class for property values that need to be buffered during + * deserialization. + */ +public abstract class PropertyValue +{ + public final PropertyValue next; + + /** + * Value to assign when POJO has been instantiated. + */ + public final Object value; + + protected PropertyValue(PropertyValue next, Object value) + { + this.next = next; + this.value = value; + } + + /** + * Method called to assign stored value of this property to specified + * bean instance + */ + public abstract void assign(Object bean) + throws IOException, JsonProcessingException; + + /* + /********************************************************** + /* Concrete property value classes + /********************************************************** + */ + + /** + * Property value that used when assigning value to property using + * a setter method or direct field access. + */ + final static class Regular + extends PropertyValue + { + final SettableBeanProperty _property; + + public Regular(PropertyValue next, Object value, + SettableBeanProperty prop) + { + super(next, value); + _property = prop; + } + + @Override + public void assign(Object bean) + throws IOException, JsonProcessingException + { + _property.set(bean, value); + } + } + + /** + * Property value type used when storing entries to be added + * to a POJO using "any setter" (method that takes name and + * value arguments, allowing setting multiple different + * properties using single method). + */ + final static class Any + extends PropertyValue + { + final SettableAnyProperty _property; + final String _propertyName; + + public Any(PropertyValue next, Object value, + SettableAnyProperty prop, + String propName) + { + super(next, value); + _property = prop; + _propertyName = propName; + } + + @Override + public void assign(Object bean) + throws IOException, JsonProcessingException + { + _property.set(bean, _propertyName, value); + } + } + + /** + * Property value type used when storing entries to be added + * to a Map. + */ + final static class Map + extends PropertyValue + { + final Object _key; + + public Map(PropertyValue next, Object value, Object key) + { + super(next, value); + _key = key; + } + + @SuppressWarnings("unchecked") + @Override + public void assign(Object bean) + throws IOException, JsonProcessingException + { + ((java.util.Map<Object,Object>) bean).put(_key, value); + } + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/impl/PropertyValueBuffer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/impl/PropertyValueBuffer.java new file mode 100644 index 0000000..eee535d --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/impl/PropertyValueBuffer.java
@@ -0,0 +1,102 @@ +package org.codehaus.jackson.map.deser.impl; + +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.map.DeserializationContext; +import org.codehaus.jackson.map.deser.SettableAnyProperty; +import org.codehaus.jackson.map.deser.SettableBeanProperty; + +/** + * Simple container used for temporarily buffering a set of + * <code>PropertyValue</code>s. + * Using during construction of beans (and Maps) that use Creators, + * and hence need buffering before instance (that will have properties + * to assign values to) is constructed. + */ +public final class PropertyValueBuffer +{ + final JsonParser _parser; + final DeserializationContext _context; + + /** + * Buffer used for storing creator parameters for constructing + * instance + */ + final Object[] _creatorParameters; + + /** + * Number of creator parameters we are still missing. + *<p> + * NOTE: assumes there are no duplicates, for now. + */ + private int _paramsNeeded; + + /** + * If we get non-creator parameters before or between + * creator parameters, those need to be buffered. Buffer + * is just a simple linked list + */ + private PropertyValue _buffered; + + public PropertyValueBuffer(JsonParser jp, DeserializationContext ctxt, int paramCount) + { + _parser = jp; + _context = ctxt; + _paramsNeeded = paramCount; + _creatorParameters = new Object[paramCount]; + } + + public void inject(SettableBeanProperty[] injectableProperties) + { + for (int i = 0, len = injectableProperties.length; i < len; ++i) { + SettableBeanProperty prop = injectableProperties[i]; + if (prop != null) { + // null since there is no POJO yet + _creatorParameters[i] = _context.findInjectableValue(prop.getInjectableValueId(), + prop, null); + } + } + } + + /** + * @param defaults If any of parameters requires nulls to be replaced with a non-null + * object (usually primitive types), this is a non-null array that has such replacement + * values (and nulls for cases where nulls are ok) + */ + protected final Object[] getParameters(Object[] defaults) + { + if (defaults != null) { + for (int i = 0, len = _creatorParameters.length; i < len; ++i) { + if (_creatorParameters[i] == null) { + Object value = defaults[i]; + if (value != null) { + _creatorParameters[i] = value; + } + } + } + } + return _creatorParameters; + } + + protected PropertyValue buffered() { return _buffered; } + + /** + * @return True if we have received all creator parameters + */ + public boolean assignParameter(int index, Object value) { + _creatorParameters[index] = value; + return --_paramsNeeded <= 0; + } + + public void bufferProperty(SettableBeanProperty prop, Object value) { + _buffered = new PropertyValue.Regular(_buffered, value, prop); + } + + public void bufferAnyProperty(SettableAnyProperty prop, String propName, Object value) { + _buffered = new PropertyValue.Any(_buffered, value, prop, propName); + } + + public void bufferMapProperty(Object key, Object value) { + _buffered = new PropertyValue.Map(_buffered, value, key); + } +} +
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/impl/UnwrappedPropertyHandler.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/impl/UnwrappedPropertyHandler.java new file mode 100644 index 0000000..18a1f06 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/impl/UnwrappedPropertyHandler.java
@@ -0,0 +1,41 @@ +package org.codehaus.jackson.map.deser.impl; + +import java.io.IOException; +import java.util.*; + +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.map.DeserializationContext; +import org.codehaus.jackson.map.deser.SettableBeanProperty; +import org.codehaus.jackson.util.TokenBuffer; + +/** + * Object that is responsible for handling acrobatics related to + * deserializing "unwrapped" values; sets of properties that are + * embedded (inlined) as properties of parent JSON object. + * + * @since 1.9 + */ +public class UnwrappedPropertyHandler +{ + protected final ArrayList<SettableBeanProperty> _properties = new ArrayList<SettableBeanProperty>(); + + public UnwrappedPropertyHandler() { } + + public void addProperty(SettableBeanProperty property) { + _properties.add(property); + } + + public Object processUnwrapped(JsonParser originalParser, DeserializationContext ctxt, Object bean, + TokenBuffer buffered) + throws IOException, JsonProcessingException + { + for (int i = 0, len = _properties.size(); i < len; ++i) { + SettableBeanProperty prop = _properties.get(i); + JsonParser jp = buffered.asParser(); + jp.nextToken(); + prop.deserializeAndSet(jp, ctxt, bean); + } + return bean; + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/impl/ValueInjector.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/impl/ValueInjector.java new file mode 100644 index 0000000..19162db --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/impl/ValueInjector.java
@@ -0,0 +1,45 @@ +package org.codehaus.jackson.map.deser.impl; + +import java.io.IOException; + +import org.codehaus.jackson.map.BeanProperty; +import org.codehaus.jackson.map.DeserializationContext; +import org.codehaus.jackson.map.introspect.AnnotatedMember; +import org.codehaus.jackson.map.util.Annotations; +import org.codehaus.jackson.type.JavaType; + +/** + * Class that encapsulates details of value injection that occurs before + * deserialization of a POJO. Details include information needed to find + * injectable value (logical id) as well as method used for assigning + * value (setter or field) + * + * @since 1.9 + */ +public class ValueInjector + extends BeanProperty.Std +{ + /** + * Identifier used for looking up value to inject + */ + protected final Object _valueId; + + public ValueInjector(String propertyName, JavaType type, + Annotations contextAnnotations, AnnotatedMember mutator, + Object valueId) + { + super(propertyName, type, contextAnnotations, mutator); + _valueId = valueId; + } + + public Object findValue(DeserializationContext context, Object beanInstance) + { + return context.findInjectableValue(_valueId, this, beanInstance); + } + + public void inject(DeserializationContext context, Object beanInstance) + throws IOException + { + _member.setValue(beanInstance, findValue(context, beanInstance)); + } +} \ No newline at end of file
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/impl/package-info.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/impl/package-info.java new file mode 100644 index 0000000..96b104e --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/impl/package-info.java
@@ -0,0 +1,9 @@ +/** + * Contains those implementation classes of deserialization part of + * data binding that are not considered part of public or semi-public + * interfaces. Use of these classes by non-core classes is discouraged, + * although occasionally this may be necessary. + * Note that backwards-compatibility of these classes is not guaranteed + * between minor releases (but is between patch releases). + */ +package org.codehaus.jackson.map.deser.impl;
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/package-info.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/package-info.java new file mode 100644 index 0000000..3314c50 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/package-info.java
@@ -0,0 +1,5 @@ +/** + * Contains implementation classes of deserialization part of + * data binding. + */ +package org.codehaus.jackson.map.deser;
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/AtomicBooleanDeserializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/AtomicBooleanDeserializer.java new file mode 100644 index 0000000..74bae98 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/AtomicBooleanDeserializer.java
@@ -0,0 +1,22 @@ +package org.codehaus.jackson.map.deser.std; + +import java.io.IOException; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.map.DeserializationContext; + +public class AtomicBooleanDeserializer + extends StdScalarDeserializer<AtomicBoolean> +{ + public AtomicBooleanDeserializer() { super(AtomicBoolean.class); } + + @Override + public AtomicBoolean deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + // 16-Dec-2010, tatu: Should we actually convert null to null AtomicBoolean? + return new AtomicBoolean(_parseBooleanPrimitive(jp, ctxt)); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/AtomicReferenceDeserializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/AtomicReferenceDeserializer.java new file mode 100644 index 0000000..88426e8 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/AtomicReferenceDeserializer.java
@@ -0,0 +1,47 @@ +package org.codehaus.jackson.map.deser.std; + +import java.io.IOException; +import java.util.concurrent.atomic.AtomicReference; + +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.type.JavaType; + +public class AtomicReferenceDeserializer + extends StdScalarDeserializer<AtomicReference<?>> + implements ResolvableDeserializer +{ + /** + * Type of value that we reference + */ + protected final JavaType _referencedType; + + protected final BeanProperty _property; + + protected JsonDeserializer<?> _valueDeserializer; + + /** + * @param referencedType Parameterization of this reference + */ + public AtomicReferenceDeserializer(JavaType referencedType, BeanProperty property) + { + super(AtomicReference.class); + _referencedType = referencedType; + _property = property; + } + + @Override + public AtomicReference<?> deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + return new AtomicReference<Object>(_valueDeserializer.deserialize(jp, ctxt)); + } + + @Override + public void resolve(DeserializationConfig config, DeserializerProvider provider) + throws JsonMappingException + { + _valueDeserializer = provider.findValueDeserializer(config, _referencedType, _property); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/CalendarDeserializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/CalendarDeserializer.java new file mode 100644 index 0000000..7a97e36 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/CalendarDeserializer.java
@@ -0,0 +1,47 @@ +package org.codehaus.jackson.map.deser.std; + +import java.io.IOException; +import java.util.Calendar; +import java.util.Date; + +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.map.DeserializationContext; +import org.codehaus.jackson.map.annotate.JacksonStdImpl; + +@JacksonStdImpl +public class CalendarDeserializer + extends StdScalarDeserializer<Calendar> +{ + /** + * We may know actual expected type; if so, it will be + * used for instantiation. + */ + protected final Class<? extends Calendar> _calendarClass; + + public CalendarDeserializer() { this(null); } + public CalendarDeserializer(Class<? extends Calendar> cc) { + super(Calendar.class); + _calendarClass = cc; + } + + @Override + public Calendar deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + Date d = _parseDate(jp, ctxt); + if (d == null) { + return null; + } + if (_calendarClass == null) { + return ctxt.constructCalendar(d); + } + try { + Calendar c = _calendarClass.newInstance(); + c.setTimeInMillis(d.getTime()); + return c; + } catch (Exception e) { + throw ctxt.instantiationException(_calendarClass, e); + } + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/ClassDeserializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/ClassDeserializer.java new file mode 100644 index 0000000..8c62e74 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/ClassDeserializer.java
@@ -0,0 +1,49 @@ +package org.codehaus.jackson.map.deser.std; + +import java.io.IOException; + +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.JsonToken; +import org.codehaus.jackson.map.DeserializationContext; +import org.codehaus.jackson.map.annotate.JacksonStdImpl; + +/** + * + * @since 1.9 (renamed from 'org.codehaus.jackson.map.deser.StdDeserializer#ClassDeserializer') + */ +@JacksonStdImpl +public class ClassDeserializer + extends StdScalarDeserializer<Class<?>> +{ + public ClassDeserializer() { super(Class.class); } + + @Override + public Class<?> deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + JsonToken curr = jp.getCurrentToken(); + // Currently will only accept if given simple class name + if (curr == JsonToken.VALUE_STRING) { + String className = jp.getText(); + // [JACKSON-597]: support primitive types (and void) + if (className.indexOf('.') < 0) { + if ("int".equals(className)) return Integer.TYPE; + if ("long".equals(className)) return Long.TYPE; + if ("float".equals(className)) return Float.TYPE; + if ("double".equals(className)) return Double.TYPE; + if ("boolean".equals(className)) return Boolean.TYPE; + if ("byte".equals(className)) return Byte.TYPE; + if ("char".equals(className)) return Character.TYPE; + if ("short".equals(className)) return Short.TYPE; + if ("void".equals(className)) return Void.TYPE; + } + try { + return Class.forName(jp.getText()); + } catch (ClassNotFoundException e) { + throw ctxt.instantiationException(_valueClass, e); + } + } + throw ctxt.mappingException(_valueClass, curr); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/CollectionDeserializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/CollectionDeserializer.java new file mode 100644 index 0000000..7a6c39a --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/CollectionDeserializer.java
@@ -0,0 +1,265 @@ +package org.codehaus.jackson.map.deser.std; + +import java.io.IOException; +import java.lang.reflect.Constructor; +import java.util.*; + +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.JsonToken; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.JacksonStdImpl; +import org.codehaus.jackson.map.deser.ValueInstantiator; +import org.codehaus.jackson.map.deser.std.ContainerDeserializerBase; +import org.codehaus.jackson.map.deser.std.StdValueInstantiator; +import org.codehaus.jackson.map.introspect.AnnotatedConstructor; +import org.codehaus.jackson.map.introspect.AnnotatedWithParams; +import org.codehaus.jackson.type.JavaType; + +/** + * Basic serializer that can take JSON "Array" structure and + * construct a {@link java.util.Collection} instance, with typed contents. + *<p> + * Note: for untyped content (one indicated by passing Object.class + * as the type), {@link UntypedObjectDeserializer} is used instead. + * It can also construct {@link java.util.List}s, but not with specific + * POJO types, only other containers and primitives/wrappers. + * + * @since 1.9 (renamed from 'org.codehaus.jackson.map.deser.CollectionDeserializer) + */ +@JacksonStdImpl +public class CollectionDeserializer + extends ContainerDeserializerBase<Collection<Object>> + implements ResolvableDeserializer +{ + // // Configuration + + protected final JavaType _collectionType; + + /** + * Value deserializer. + */ + protected final JsonDeserializer<Object> _valueDeserializer; + + /** + * If element instances have polymorphic type information, this + * is the type deserializer that can handle it + */ + protected final TypeDeserializer _valueTypeDeserializer; + + // // Instance construction settings: + + /** + * @since 1.9 + */ + protected final ValueInstantiator _valueInstantiator; + + /** + * Deserializer that is used iff delegate-based creator is + * to be used for deserializing from JSON Object. + */ + protected JsonDeserializer<Object> _delegateDeserializer; + + // NOTE: no PropertyBasedCreator, as JSON Arrays have no properties + + /* + /********************************************************** + /* Life-cycle + /********************************************************** + */ + + /** + * @deprecated Since 1.9, use variant that takes ValueInstantiator + */ + @Deprecated + protected CollectionDeserializer(JavaType collectionType, JsonDeserializer<Object> valueDeser, + TypeDeserializer valueTypeDeser, + Constructor<Collection<Object>> defCtor) + { + super(collectionType.getRawClass()); + _collectionType = collectionType; + _valueDeserializer = valueDeser; + _valueTypeDeserializer = valueTypeDeser; + // not super-clean, but has to do... + StdValueInstantiator inst = new StdValueInstantiator(null, collectionType); + if (defCtor != null) { + AnnotatedConstructor aCtor = new AnnotatedConstructor(defCtor, + null, null); + inst.configureFromObjectSettings(aCtor, null, null, null, null); + } + _valueInstantiator = inst; + } + + /** + * @since 1.9 + */ + public CollectionDeserializer(JavaType collectionType, JsonDeserializer<Object> valueDeser, + TypeDeserializer valueTypeDeser, ValueInstantiator valueInstantiator) + { + super(collectionType.getRawClass()); + _collectionType = collectionType; + _valueDeserializer = valueDeser; + _valueTypeDeserializer = valueTypeDeser; + _valueInstantiator = valueInstantiator; + } + + /** + * Copy-constructor that can be used by sub-classes to allow + * copy-on-write styling copying of settings of an existing instance. + * + * @since 1.9 + */ + protected CollectionDeserializer(CollectionDeserializer src) + { + super(src._valueClass); + _collectionType = src._collectionType; + _valueDeserializer = src._valueDeserializer; + _valueTypeDeserializer = src._valueTypeDeserializer; + _valueInstantiator = src._valueInstantiator; + _delegateDeserializer = src._delegateDeserializer; + } + + /* + /********************************************************** + /* Validation, post-processing (ResolvableDeserializer) + /********************************************************** + */ + + /** + * Method called to finalize setup of this deserializer, + * after deserializer itself has been registered. This + * is needed to handle recursive and transitive dependencies. + */ + @Override + public void resolve(DeserializationConfig config, DeserializerProvider provider) + throws JsonMappingException + { + // May need to resolve types for delegate-based creators: + if (_valueInstantiator.canCreateUsingDelegate()) { + JavaType delegateType = _valueInstantiator.getDelegateType(); + if (delegateType == null) { + throw new IllegalArgumentException("Invalid delegate-creator definition for "+_collectionType + +": value instantiator ("+_valueInstantiator.getClass().getName() + +") returned true for 'canCreateUsingDelegate()', but null for 'getDelegateType()'"); + } + AnnotatedWithParams delegateCreator = _valueInstantiator.getDelegateCreator(); + // Need to create a temporary property to allow contextual deserializers: + // Note: unlike BeanDeserializer, we don't have an AnnotatedClass around; hence no annotations passed + BeanProperty.Std property = new BeanProperty.Std(null, + delegateType, null, delegateCreator); + _delegateDeserializer = findDeserializer(config, provider, delegateType, property); + } + } + + /* + /********************************************************** + /* ContainerDeserializerBase API + /********************************************************** + */ + + @Override + public JavaType getContentType() { + return _collectionType.getContentType(); + } + + @Override + public JsonDeserializer<Object> getContentDeserializer() { + return _valueDeserializer; + } + + /* + /********************************************************** + /* JsonDeserializer API + /********************************************************** + */ + + @SuppressWarnings("unchecked") + @Override + public Collection<Object> deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + if (_delegateDeserializer != null) { + return (Collection<Object>) _valueInstantiator.createUsingDelegate(_delegateDeserializer.deserialize(jp, ctxt)); + } + /* [JACKSON-620]: empty String may be ok; bit tricky to check, however, since + * there is also possibility of "auto-wrapping" of single-element arrays. + * Hence we only accept empty String here. + */ + if (jp.getCurrentToken() == JsonToken.VALUE_STRING) { + String str = jp.getText(); + if (str.length() == 0) { + return (Collection<Object>) _valueInstantiator.createFromString(str); + } + } + return deserialize(jp, ctxt, (Collection<Object>) _valueInstantiator.createUsingDefault()); + } + + @Override + public Collection<Object> deserialize(JsonParser jp, DeserializationContext ctxt, + Collection<Object> result) + throws IOException, JsonProcessingException + { + // Ok: must point to START_ARRAY (or equivalent) + if (!jp.isExpectedStartArrayToken()) { + return handleNonArray(jp, ctxt, result); + } + + JsonDeserializer<Object> valueDes = _valueDeserializer; + JsonToken t; + final TypeDeserializer typeDeser = _valueTypeDeserializer; + + while ((t = jp.nextToken()) != JsonToken.END_ARRAY) { + Object value; + + if (t == JsonToken.VALUE_NULL) { + value = null; + } else if (typeDeser == null) { + value = valueDes.deserialize(jp, ctxt); + } else { + value = valueDes.deserializeWithType(jp, ctxt, typeDeser); + } + result.add(value); + } + return result; + } + + @Override + public Object deserializeWithType(JsonParser jp, DeserializationContext ctxt, + TypeDeserializer typeDeserializer) + throws IOException, JsonProcessingException + { + // In future could check current token... for now this should be enough: + return typeDeserializer.deserializeTypedFromArray(jp, ctxt); + } + + /** + * Helper method called when current token is no START_ARRAY. Will either + * throw an exception, or try to handle value as if member of implicit + * array, depending on configuration. + */ + private final Collection<Object> handleNonArray(JsonParser jp, DeserializationContext ctxt, + Collection<Object> result) + throws IOException, JsonProcessingException + { + // [JACKSON-526]: implicit arrays from single values? + if (!ctxt.isEnabled(DeserializationConfig.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY)) { + throw ctxt.mappingException(_collectionType.getRawClass()); + } + JsonDeserializer<Object> valueDes = _valueDeserializer; + final TypeDeserializer typeDeser = _valueTypeDeserializer; + JsonToken t = jp.getCurrentToken(); + + Object value; + + if (t == JsonToken.VALUE_NULL) { + value = null; + } else if (typeDeser == null) { + value = valueDes.deserialize(jp, ctxt); + } else { + value = valueDes.deserializeWithType(jp, ctxt, typeDeser); + } + result.add(value); + return result; + } + +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/ContainerDeserializerBase.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/ContainerDeserializerBase.java new file mode 100644 index 0000000..9dde0a6 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/ContainerDeserializerBase.java
@@ -0,0 +1,37 @@ +package org.codehaus.jackson.map.deser.std; + +import org.codehaus.jackson.map.JsonDeserializer; +import org.codehaus.jackson.type.JavaType; + +/** + * Intermediate base deserializer class that adds more shared accessor + * so that other classes can access information about contained (value) + * types + * + * @since 1.9 (renamed from 'org.codehaus.jackson.map.deser.ContainerDeserializer') + */ +public abstract class ContainerDeserializerBase<T> + extends StdDeserializer<T> +{ + protected ContainerDeserializerBase(Class<?> selfType) + { + super(selfType); + } + + /* + /********************************************************** + /* Extended API + /********************************************************** + */ + + /** + * Accessor for declared type of contained value elements; either exact + * type, or one of its supertypes. + */ + public abstract JavaType getContentType(); + + /** + * Accesor for deserializer use for deserializing content values. + */ + public abstract JsonDeserializer<Object> getContentDeserializer(); +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/DateDeserializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/DateDeserializer.java new file mode 100644 index 0000000..94135ce --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/DateDeserializer.java
@@ -0,0 +1,30 @@ +package org.codehaus.jackson.map.deser.std; + +import java.io.IOException; +import java.util.Date; + +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.map.DeserializationContext; + +/** + * Simple deserializer for handling {@link java.util.Date} values. + *<p> + * One way to customize Date formats accepted is to override method + * {@link DeserializationContext#parseDate} that this basic + * deserializer calls. + * + * @since 1.9 (moved from higher-level package) + */ +public class DateDeserializer + extends StdScalarDeserializer<Date> +{ + public DateDeserializer() { super(Date.class); } + + @Override + public java.util.Date deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + return _parseDate(jp, ctxt); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/EnumDeserializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/EnumDeserializer.java new file mode 100644 index 0000000..fdd6226 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/EnumDeserializer.java
@@ -0,0 +1,154 @@ +package org.codehaus.jackson.map.deser.std; + +import java.io.IOException; +import java.lang.reflect.Method; + +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.JsonToken; +import org.codehaus.jackson.map.DeserializationConfig; +import org.codehaus.jackson.map.JsonDeserializer; +import org.codehaus.jackson.map.DeserializationContext; +import org.codehaus.jackson.map.annotate.JsonCachable; +import org.codehaus.jackson.map.introspect.AnnotatedMethod; +import org.codehaus.jackson.map.util.ClassUtil; +import org.codehaus.jackson.map.util.EnumResolver; + +/** + * Deserializer class that can deserialize instances of + * specified Enum class from Strings and Integers. + * + * @since 1.9 (moved from higher-level package) + */ +@JsonCachable +public class EnumDeserializer + extends StdScalarDeserializer<Enum<?>> +{ + protected final EnumResolver<?> _resolver; + + public EnumDeserializer(EnumResolver<?> res) + { + super(Enum.class); + _resolver = res; + } + + /** + * Factory method used when Enum instances are to be deserialized + * using a creator (static factory method) + * + * @return Deserializer based on given factory method, if type was suitable; + * null if type can not be used + */ + public static JsonDeserializer<?> deserializerForCreator(DeserializationConfig config, + Class<?> enumClass, AnnotatedMethod factory) + { + // note: caller has verified there's just one arg; but we must verify its type + Class<?> raw = factory.getParameterClass(0); + if (raw == String.class) { + raw = null; + } else if (raw == Integer.TYPE || raw == Integer.class) { + raw = Integer.class; + } else if (raw == Long.TYPE || raw == Long.class) { + raw = Long.class; + } else { + throw new IllegalArgumentException("Parameter #0 type for factory method ("+factory + +") not suitable, must be java.lang.String or int/Integer/long/Long"); + } + if (config.isEnabled(DeserializationConfig.Feature.CAN_OVERRIDE_ACCESS_MODIFIERS)) { + ClassUtil.checkAndFixAccess(factory.getMember()); + } + return new FactoryBasedDeserializer(enumClass, factory, raw); + } + + /* + /********************************************************** + /* Default JsonDeserializer implementation + /********************************************************** + */ + + @Override + public Enum<?> deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + JsonToken curr = jp.getCurrentToken(); + + // Usually should just get string value; but in some cases FIELD_NAME (enum as key) + if (curr == JsonToken.VALUE_STRING || curr == JsonToken.FIELD_NAME) { + String name = jp.getText(); + Enum<?> result = _resolver.findEnum(name); + if (result == null) { + throw ctxt.weirdStringException(_resolver.getEnumClass(), "value not one of declared Enum instance names"); + } + return result; + } + // But let's consider int acceptable as well (if within ordinal range) + if (curr == JsonToken.VALUE_NUMBER_INT) { + /* ... unless told not to do that. :-) + * (as per [JACKSON-412] + */ + if (ctxt.isEnabled(DeserializationConfig.Feature.FAIL_ON_NUMBERS_FOR_ENUMS)) { + throw ctxt.mappingException("Not allowed to deserialize Enum value out of JSON number (disable DeserializationConfig.Feature.FAIL_ON_NUMBERS_FOR_ENUMS to allow)"); + } + + int index = jp.getIntValue(); + Enum<?> result = _resolver.getEnum(index); + if (result == null) { + throw ctxt.weirdNumberException(_resolver.getEnumClass(), "index value outside legal index range [0.."+_resolver.lastValidIndex()+"]"); + } + return result; + } + throw ctxt.mappingException(_resolver.getEnumClass()); + } + + /* + /********************************************************** + /* Default JsonDeserializer implementation + /********************************************************** + */ + + /** + * Deserializer that uses a single-String static factory method + * for locating Enum values by String id. + */ + protected static class FactoryBasedDeserializer + extends StdScalarDeserializer<Object> + { + protected final Class<?> _enumClass; + + // Marker type; null if String expected; otherwise numeric wrapper + protected final Class<?> _inputType; + protected final Method _factory; + + public FactoryBasedDeserializer(Class<?> cls, AnnotatedMethod f, + Class<?> inputType) + { + super(Enum.class); + _enumClass = cls; + _factory = f.getAnnotated(); + _inputType = inputType; + } + + @Override + public Object deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + // couple of accepted types... + Object value; + if (_inputType == null) { + value = jp.getText(); + } else if (_inputType == Integer.class) { + value = Integer.valueOf(jp.getValueAsInt()); + } else if (_inputType == Long.class) { + value = Long.valueOf(jp.getValueAsLong()); + } else { + throw ctxt.mappingException(_enumClass); + } + try { + return _factory.invoke(_enumClass, value); + } catch (Exception e) { + ClassUtil.unwrapAndThrowAsIAE(e); + } + return null; + } + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/EnumMapDeserializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/EnumMapDeserializer.java new file mode 100644 index 0000000..1996a63 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/EnumMapDeserializer.java
@@ -0,0 +1,90 @@ +package org.codehaus.jackson.map.deser.std; + +import java.io.IOException; +import java.util.*; + +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.JsonToken; +import org.codehaus.jackson.map.JsonDeserializer; +import org.codehaus.jackson.map.DeserializationContext; +import org.codehaus.jackson.map.TypeDeserializer; +import org.codehaus.jackson.map.deser.std.StdDeserializer; +import org.codehaus.jackson.map.util.EnumResolver; + +/** + * + * <p> + * Note: casting within this class is all messed up -- just could not figure out a way + * to properly deal with recursive definition of "EnumMap<K extends Enum<K>, V> + * + * @author tsaloranta + * + * @since 1.9 (renamed from 'org.codehaus.jackson.map.deser.EnumMapDeserializer') + */ +@SuppressWarnings({ "unchecked", "rawtypes" }) +public class EnumMapDeserializer + extends StdDeserializer<EnumMap<?,?>> +{ + protected final Class<?> _enumClass; + + protected final JsonDeserializer<Enum<?>> _keyDeserializer; + + protected final JsonDeserializer<Object> _valueDeserializer; + + @Deprecated + public EnumMapDeserializer(EnumResolver<?> enumRes, JsonDeserializer<Object> valueDeser) + { + this(enumRes.getEnumClass(), new EnumDeserializer(enumRes), valueDeser); + } + + public EnumMapDeserializer(Class<?> enumClass, JsonDeserializer<?> keyDeserializer, + JsonDeserializer<Object> valueDeser) + { + super(EnumMap.class); + _enumClass = enumClass; + _keyDeserializer = (JsonDeserializer<Enum<?>>) keyDeserializer; + _valueDeserializer = valueDeser; + } + + @Override + public EnumMap<?,?> deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + // Ok: must point to START_OBJECT + if (jp.getCurrentToken() != JsonToken.START_OBJECT) { + throw ctxt.mappingException(EnumMap.class); + } + EnumMap result = constructMap(); + + while ((jp.nextToken()) != JsonToken.END_OBJECT) { + Enum<?> key = _keyDeserializer.deserialize(jp, ctxt); + if (key == null) { + throw ctxt.weirdStringException(_enumClass, "value not one of declared Enum instance names"); + } + // And then the value... + JsonToken t = jp.nextToken(); + /* note: MUST check for nulls separately: deserializers will + * not handle them (and maybe fail or return bogus data) + */ + Object value = (t == JsonToken.VALUE_NULL) ? + null : _valueDeserializer.deserialize(jp, ctxt); + result.put(key, value); + } + return result; + } + + @Override + public Object deserializeWithType(JsonParser jp, DeserializationContext ctxt, + TypeDeserializer typeDeserializer) + throws IOException, JsonProcessingException + { + // In future could check current token... for now this should be enough: + return typeDeserializer.deserializeTypedFromObject(jp, ctxt); + } + + private EnumMap<?,?> constructMap() + { + return new EnumMap(_enumClass); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/EnumSetDeserializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/EnumSetDeserializer.java new file mode 100644 index 0000000..76dba4e --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/EnumSetDeserializer.java
@@ -0,0 +1,89 @@ +package org.codehaus.jackson.map.deser.std; + +import java.io.IOException; +import java.util.*; + +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.JsonToken; +import org.codehaus.jackson.map.DeserializationContext; +import org.codehaus.jackson.map.JsonDeserializer; +import org.codehaus.jackson.map.TypeDeserializer; +import org.codehaus.jackson.map.util.EnumResolver; + +/** + * + * <p> + * Note: casting within this class is all messed up -- just could not figure out a way + * to properly deal with recursive definition of "EnumSet<K extends Enum<K>, V> + * + * @author tsaloranta + * + * @since 1.9 (moved from higher-level package) + */ +@SuppressWarnings("rawtypes") +public class EnumSetDeserializer + extends StdDeserializer<EnumSet<?>> +{ + protected final Class<Enum> _enumClass; + + protected final JsonDeserializer<Enum<?>> _enumDeserializer; + + @SuppressWarnings("unchecked" ) + public EnumSetDeserializer(EnumResolver enumRes) + { + // fugly, but what we can we do... + this((Class<Enum>) ((Class<?>) enumRes.getEnumClass()), + new EnumDeserializer(enumRes)); + } + + @SuppressWarnings("unchecked" ) + public EnumSetDeserializer(Class<?> enumClass, JsonDeserializer<?> deser) + { + super(EnumSet.class); + _enumClass = (Class<Enum>) enumClass; + _enumDeserializer = (JsonDeserializer<Enum<?>>) deser; + } + + @SuppressWarnings("unchecked") + @Override + public EnumSet<?> deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + // Ok: must point to START_ARRAY (or equivalent) + if (!jp.isExpectedStartArrayToken()) { + throw ctxt.mappingException(EnumSet.class); + } + EnumSet result = constructSet(); + JsonToken t; + + while ((t = jp.nextToken()) != JsonToken.END_ARRAY) { + /* What to do with nulls? Fail or ignore? Fail, for now + * (note: would fail if we passed it to EnumDeserializer, too, + * but in general nulls should never be passed to non-container + * deserializers) + */ + if (t == JsonToken.VALUE_NULL) { + throw ctxt.mappingException(_enumClass); + } + Enum<?> value = _enumDeserializer.deserialize(jp, ctxt); + result.add(value); + } + return result; + } + + @Override + public Object deserializeWithType(JsonParser jp, DeserializationContext ctxt, + TypeDeserializer typeDeserializer) + throws IOException, JsonProcessingException + { + return typeDeserializer.deserializeTypedFromArray(jp, ctxt); + } + + @SuppressWarnings("unchecked") + private EnumSet constructSet() + { + // superbly ugly... but apparently necessary + return EnumSet.noneOf(_enumClass); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/FromStringDeserializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/FromStringDeserializer.java new file mode 100644 index 0000000..ce53dfc --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/FromStringDeserializer.java
@@ -0,0 +1,265 @@ +package org.codehaus.jackson.map.deser.std; + +import java.io.*; +import java.net.InetAddress; +import java.net.URI; +import java.net.URL; +import java.nio.charset.Charset; +import java.util.*; +import java.util.regex.Pattern; + +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.JsonToken; +import org.codehaus.jackson.map.DeserializationContext; + +/** + * Base class for simple deserializer which only accept JSON String + * values as the source. + * + * @since 1.9 (moved from higher-level package) + */ +public abstract class FromStringDeserializer<T> + extends StdScalarDeserializer<T> +{ + protected FromStringDeserializer(Class<?> vc) { + super(vc); + } + + public static Iterable<FromStringDeserializer<?>>all() + { + ArrayList<FromStringDeserializer<?>> all = new ArrayList<FromStringDeserializer<?>>(); + + all.add(new UUIDDeserializer()); + all.add(new URLDeserializer()); + all.add(new URIDeserializer()); + all.add(new CurrencyDeserializer()); + all.add(new PatternDeserializer()); + // since 1.7: + all.add(new LocaleDeserializer()); + // 1.8: + all.add(new InetAddressDeserializer()); + all.add(new TimeZoneDeserializer()); + // 1.9 + all.add(new CharsetDeserializer()); + + return all; + } + + @SuppressWarnings("unchecked") + @Override + public final T deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + if (jp.getCurrentToken() == JsonToken.VALUE_STRING) { + String text = jp.getText().trim(); + // 15-Oct-2010, tatu: Empty String usually means null, so + if (text.length() == 0) { + return null; + } + try { + T result = _deserialize(text, ctxt); + if (result != null) { + return result; + } + } catch (IllegalArgumentException iae) { + // nothing to do here, yet? We'll fail anyway + } + throw ctxt.weirdStringException(_valueClass, "not a valid textual representation"); + } + if (jp.getCurrentToken() == JsonToken.VALUE_EMBEDDED_OBJECT) { + // Trivial cases; null to null, instance of type itself returned as is + Object ob = jp.getEmbeddedObject(); + if (ob == null) { + return null; + } + if (_valueClass.isAssignableFrom(ob.getClass())) { + return (T) ob; + } + return _deserializeEmbedded(ob, ctxt); + } + throw ctxt.mappingException(_valueClass); + } + + protected abstract T _deserialize(String value, DeserializationContext ctxt) + throws IOException, JsonProcessingException; + + protected T _deserializeEmbedded(Object ob, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + // default impl: error out + throw ctxt.mappingException("Don't know how to convert embedded Object of type " + +ob.getClass().getName()+" into "+_valueClass.getName()); + } + + /* + /********************************************************** + /* Then concrete implementations + /********************************************************** + */ + + public static class UUIDDeserializer + extends FromStringDeserializer<UUID> + { + public UUIDDeserializer() { super(UUID.class); } + + @Override + protected UUID _deserialize(String value, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + return UUID.fromString(value); + } + + @Override + protected UUID _deserializeEmbedded(Object ob, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + if (ob instanceof byte[]) { + byte[] bytes = (byte[]) ob; + if (bytes.length != 16) { + ctxt.mappingException("Can only construct UUIDs from 16 byte arrays; got "+bytes.length+" bytes"); + } + // clumsy, but should work for now... + DataInputStream in = new DataInputStream(new ByteArrayInputStream(bytes)); + long l1 = in.readLong(); + long l2 = in.readLong(); + return new UUID(l1, l2); + } + super._deserializeEmbedded(ob, ctxt); + return null; // never gets here + } + } + + public static class URLDeserializer + extends FromStringDeserializer<URL> + { + public URLDeserializer() { super(URL.class); } + + @Override + protected URL _deserialize(String value, DeserializationContext ctxt) + throws IOException + { + return new URL(value); + } + } + + public static class URIDeserializer + extends FromStringDeserializer<URI> + { + public URIDeserializer() { super(URI.class); } + + @Override + protected URI _deserialize(String value, DeserializationContext ctxt) + throws IllegalArgumentException + { + return URI.create(value); + } + } + + public static class CurrencyDeserializer + extends FromStringDeserializer<Currency> + { + public CurrencyDeserializer() { super(Currency.class); } + + @Override + protected Currency _deserialize(String value, DeserializationContext ctxt) + throws IllegalArgumentException + { + // will throw IAE if unknown: + return Currency.getInstance(value); + } + } + + public static class PatternDeserializer + extends FromStringDeserializer<Pattern> + { + public PatternDeserializer() { super(Pattern.class); } + + @Override + protected Pattern _deserialize(String value, DeserializationContext ctxt) + throws IllegalArgumentException + { + // will throw IAE (or its subclass) if malformed + return Pattern.compile(value); + } + } + + /** + * Kept protected as it's not meant to be extensible at this point + * + * @since 1.7 + */ + protected static class LocaleDeserializer + extends FromStringDeserializer<Locale> + { + public LocaleDeserializer() { super(Locale.class); } + + @Override + protected Locale _deserialize(String value, DeserializationContext ctxt) + throws IOException + { + int ix = value.indexOf('_'); + if (ix < 0) { // single argument + return new Locale(value); + } + String first = value.substring(0, ix); + value = value.substring(ix+1); + ix = value.indexOf('_'); + if (ix < 0) { // two pieces + return new Locale(first, value); + } + String second = value.substring(0, ix); + return new Locale(first, second, value.substring(ix+1)); + } + } + + /** + * As per [JACKSON-484], also need special handling for InetAddress... + * + * @since 1.7.4 + */ + protected static class InetAddressDeserializer + extends FromStringDeserializer<InetAddress> + { + public InetAddressDeserializer() { super(InetAddress.class); } + + @Override + protected InetAddress _deserialize(String value, DeserializationContext ctxt) + throws IOException + { + return InetAddress.getByName(value); + } + } + + // [JACKSON-789] (since 1.9.5) + protected static class CharsetDeserializer + extends FromStringDeserializer<Charset> + { + public CharsetDeserializer() { super(Charset.class); } + + @Override + protected Charset _deserialize(String value, DeserializationContext ctxt) + throws IOException + { + return Charset.forName(value); + } + } + + /** + * As per [JACKSON-522], also need special handling for InetAddress... + * + * @since 1.7.4 + */ + protected static class TimeZoneDeserializer + extends FromStringDeserializer<TimeZone> + { + public TimeZoneDeserializer() { super(TimeZone.class); } + + @Override + protected TimeZone _deserialize(String value, DeserializationContext ctxt) + throws IOException + { + return TimeZone.getTimeZone(value); + } + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/JavaTypeDeserializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/JavaTypeDeserializer.java new file mode 100644 index 0000000..09a8548 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/JavaTypeDeserializer.java
@@ -0,0 +1,38 @@ +package org.codehaus.jackson.map.deser.std; + +import java.io.IOException; + +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.JsonToken; +import org.codehaus.jackson.map.DeserializationContext; +import org.codehaus.jackson.type.JavaType; + +/** + * @since 1.9 + */ +public class JavaTypeDeserializer + extends StdScalarDeserializer<JavaType> +{ + public JavaTypeDeserializer() { super(JavaType.class); } + + @Override + public JavaType deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + JsonToken curr = jp.getCurrentToken(); + // Usually should just get string value: + if (curr == JsonToken.VALUE_STRING) { + String str = jp.getText().trim(); + if (str.length() == 0) { + return getEmptyValue(); + } + return ctxt.getTypeFactory().constructFromCanonical(str); + } + // or occasionally just embedded object maybe + if (curr == JsonToken.VALUE_EMBEDDED_OBJECT) { + return (JavaType) jp.getEmbeddedObject(); + } + throw ctxt.mappingException(_valueClass); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/JsonNodeDeserializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/JsonNodeDeserializer.java new file mode 100644 index 0000000..eabb1d6 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/JsonNodeDeserializer.java
@@ -0,0 +1,314 @@ +package org.codehaus.jackson.map.deser.std; + +import java.io.IOException; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.node.*; + +/** + * Deserializer that can build instances of {@link JsonNode} from any + * JSON content, using appropriate {@link JsonNode} type. + * + * @since 1.9 (moved from higher-level package) + */ +public class JsonNodeDeserializer + extends BaseNodeDeserializer<JsonNode> +{ + /** + * Singleton instance of generic deserializer for {@link JsonNode}. + * Only used for types other than JSON Object and Array. + */ + private final static JsonNodeDeserializer instance = new JsonNodeDeserializer(); + + protected JsonNodeDeserializer() { super(JsonNode.class); } + + /** + * Factory method for accessing deserializer for specific node type + */ + public static JsonDeserializer<? extends JsonNode> getDeserializer(Class<?> nodeClass) + { + if (nodeClass == ObjectNode.class) { + return ObjectDeserializer.getInstance(); + } + if (nodeClass == ArrayNode.class) { + return ArrayDeserializer.getInstance(); + } + // For others, generic one works fine + return instance; + } + + /* + /********************************************************** + /* Actual deserializer implementations + /********************************************************** + */ + + /** + * Implementation that will produce types of any JSON nodes; not just one + * deserializer is registered to handle (in case of more specialized handler). + * Overridden by typed sub-classes for more thorough checking + */ + @Override + public JsonNode deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + switch (jp.getCurrentToken()) { + case START_OBJECT: + return deserializeObject(jp, ctxt, ctxt.getNodeFactory()); + case START_ARRAY: + return deserializeArray(jp, ctxt, ctxt.getNodeFactory()); + default: + return deserializeAny(jp, ctxt, ctxt.getNodeFactory()); + } + } + + /* + /********************************************************** + /* Specific instances for more accurate types + /********************************************************** + */ + + final static class ObjectDeserializer + extends BaseNodeDeserializer<ObjectNode> + { + protected final static ObjectDeserializer _instance = new ObjectDeserializer(); + + protected ObjectDeserializer() { + super(ObjectNode.class); + } + + public static ObjectDeserializer getInstance() { return _instance; } + + @Override + public ObjectNode deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + if (jp.getCurrentToken() == JsonToken.START_OBJECT) { + jp.nextToken(); + return deserializeObject(jp, ctxt, ctxt.getNodeFactory()); + } + if (jp.getCurrentToken() == JsonToken.FIELD_NAME) { + return deserializeObject(jp, ctxt, ctxt.getNodeFactory()); + } + throw ctxt.mappingException(ObjectNode.class); + } + } + + final static class ArrayDeserializer + extends BaseNodeDeserializer<ArrayNode> + { + protected final static ArrayDeserializer _instance = new ArrayDeserializer(); + + protected ArrayDeserializer() { + super(ArrayNode.class); + } + + public static ArrayDeserializer getInstance() { return _instance; } + + @Override + public ArrayNode deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + if (jp.isExpectedStartArrayToken()) { + return deserializeArray(jp, ctxt, ctxt.getNodeFactory()); + } + throw ctxt.mappingException(ArrayNode.class); + } + } +} + +/** + * Base class for all actual {@link JsonNode} deserializer + * implementations + */ +abstract class BaseNodeDeserializer<N extends JsonNode> + extends StdDeserializer<N> +{ + public BaseNodeDeserializer(Class<N> nodeClass) + { + super(nodeClass); + } + + @Override + public Object deserializeWithType(JsonParser jp, DeserializationContext ctxt, + TypeDeserializer typeDeserializer) + throws IOException, JsonProcessingException + { + /* Output can be as JSON Object, Array or scalar: no way to know + * a priori. So: + */ + return typeDeserializer.deserializeTypedFromAny(jp, ctxt); + } + + /* + /********************************************************** + /* Overridable methods + /********************************************************** + */ + + protected void _reportProblem(JsonParser jp, String msg) + throws JsonMappingException + { + throw new JsonMappingException(msg, jp.getTokenLocation()); + } + + /** + * Method called when there is a duplicate value for a field. + * By default we don't care, and the last value is used. + * Can be overridden to provide alternate handling, such as throwing + * an exception, or choosing different strategy for combining values + * or choosing which one to keep. + * + * @param fieldName Name of the field for which duplicate value was found + * @param objectNode Object node that contains values + * @param oldValue Value that existed for the object node before newValue + * was added + * @param newValue Newly added value just added to the object node + */ + protected void _handleDuplicateField(String fieldName, ObjectNode objectNode, + JsonNode oldValue, JsonNode newValue) + throws JsonProcessingException + { + // By default, we don't do anything + ; + } + + /* + /********************************************************** + /* Helper methods + /********************************************************** + */ + + protected final ObjectNode deserializeObject(JsonParser jp, DeserializationContext ctxt, + final JsonNodeFactory nodeFactory) + throws IOException, JsonProcessingException + { + ObjectNode node = nodeFactory.objectNode(); + JsonToken t = jp.getCurrentToken(); + if (t == JsonToken.START_OBJECT) { + t = jp.nextToken(); + } + for (; t == JsonToken.FIELD_NAME; t = jp.nextToken()) { + String fieldName = jp.getCurrentName(); + JsonNode value; + switch (jp.nextToken()) { + case START_OBJECT: + value = deserializeObject(jp, ctxt, nodeFactory); + break; + case START_ARRAY: + value = deserializeArray(jp, ctxt, nodeFactory); + break; + case VALUE_STRING: + value = nodeFactory.textNode(jp.getText()); + break; + default: + value = deserializeAny(jp, ctxt, nodeFactory); + } + JsonNode old = node.put(fieldName, value); + if (old != null) { + _handleDuplicateField(fieldName, node, old, value); + } + } + return node; + } + + protected final ArrayNode deserializeArray(JsonParser jp, DeserializationContext ctxt, + final JsonNodeFactory nodeFactory) + throws IOException, JsonProcessingException + { + ArrayNode node = nodeFactory.arrayNode(); + while (true) { + switch (jp.nextToken()) { + case START_OBJECT: + node.add(deserializeObject(jp, ctxt, nodeFactory)); + break; + case START_ARRAY: + node.add(deserializeArray(jp, ctxt, nodeFactory)); + break; + case END_ARRAY: + return node; + case VALUE_STRING: + node.add(nodeFactory.textNode(jp.getText())); + break; + default: + node.add(deserializeAny(jp, ctxt, nodeFactory)); + break; + } + } + } + + protected final JsonNode deserializeAny(JsonParser jp, DeserializationContext ctxt, + final JsonNodeFactory nodeFactory) + throws IOException, JsonProcessingException + { + switch (jp.getCurrentToken()) { + case START_OBJECT: + return deserializeObject(jp, ctxt, nodeFactory); + + case START_ARRAY: + return deserializeArray(jp, ctxt, nodeFactory); + + case FIELD_NAME: + return deserializeObject(jp, ctxt, nodeFactory); + + case VALUE_EMBEDDED_OBJECT: + // [JACKSON-796] + { + Object ob = jp.getEmbeddedObject(); + if (ob == null) { // should this occur? + return nodeFactory.nullNode(); + } + Class<?> type = ob.getClass(); + if (type == byte[].class) { // most common special case + return nodeFactory.binaryNode((byte[]) ob); + } + // any other special handling needed? + return nodeFactory.POJONode(ob); + } + + case VALUE_STRING: + return nodeFactory.textNode(jp.getText()); + + case VALUE_NUMBER_INT: + { + JsonParser.NumberType nt = jp.getNumberType(); + if (nt == JsonParser.NumberType.BIG_INTEGER + || ctxt.isEnabled(DeserializationConfig.Feature.USE_BIG_INTEGER_FOR_INTS)) { + return nodeFactory.numberNode(jp.getBigIntegerValue()); + } + if (nt == JsonParser.NumberType.INT) { + return nodeFactory.numberNode(jp.getIntValue()); + } + return nodeFactory.numberNode(jp.getLongValue()); + } + + case VALUE_NUMBER_FLOAT: + { + JsonParser.NumberType nt = jp.getNumberType(); + if (nt == JsonParser.NumberType.BIG_DECIMAL + || ctxt.isEnabled(DeserializationConfig.Feature.USE_BIG_DECIMAL_FOR_FLOATS)) { + return nodeFactory.numberNode(jp.getDecimalValue()); + } + return nodeFactory.numberNode(jp.getDoubleValue()); + } + + case VALUE_TRUE: + return nodeFactory.booleanNode(true); + + case VALUE_FALSE: + return nodeFactory.booleanNode(false); + + case VALUE_NULL: + return nodeFactory.nullNode(); + + // These states can not be mapped; input stream is + // off by an event or two + + //case END_OBJECT: + //case END_ARRAY: + default: + throw ctxt.mappingException(getValueClass()); + } + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/MapDeserializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/MapDeserializer.java new file mode 100644 index 0000000..ee71967 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/MapDeserializer.java
@@ -0,0 +1,412 @@ +package org.codehaus.jackson.map.deser.std; + +import java.io.IOException; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.util.*; + +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.JsonToken; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.JacksonStdImpl; +import org.codehaus.jackson.map.deser.SettableBeanProperty; +import org.codehaus.jackson.map.deser.ValueInstantiator; +import org.codehaus.jackson.map.deser.impl.PropertyBasedCreator; +import org.codehaus.jackson.map.deser.impl.PropertyValueBuffer; +import org.codehaus.jackson.map.deser.std.ContainerDeserializerBase; +import org.codehaus.jackson.map.deser.std.StdValueInstantiator; +import org.codehaus.jackson.map.introspect.AnnotatedConstructor; +import org.codehaus.jackson.map.introspect.AnnotatedWithParams; +import org.codehaus.jackson.map.util.ArrayBuilders; +import org.codehaus.jackson.type.JavaType; + +/** + * Basic serializer that can take Json "Object" structure and + * construct a {@link java.util.Map} instance, with typed contents. + *<p> + * Note: for untyped content (one indicated by passing Object.class + * as the type), {@link UntypedObjectDeserializer} is used instead. + * It can also construct {@link java.util.Map}s, but not with specific + * POJO types, only other containers and primitives/wrappers. + */ +@JacksonStdImpl +public class MapDeserializer + extends ContainerDeserializerBase<Map<Object,Object>> + implements ResolvableDeserializer +{ + // // Configuration: typing, deserializers + + protected final JavaType _mapType; + + /** + * Key deserializer used, if not null. If null, String from JSON + * content is used as is. + */ + protected final KeyDeserializer _keyDeserializer; + + /** + * Value deserializer. + */ + protected final JsonDeserializer<Object> _valueDeserializer; + + /** + * If value instances have polymorphic type information, this + * is the type deserializer that can handle it + */ + protected final TypeDeserializer _valueTypeDeserializer; + + // // Instance construction settings: + + /** + * @since 1.9 + */ + protected final ValueInstantiator _valueInstantiator; + + /** + * @since 1.9 + */ + protected final boolean _hasDefaultCreator; + + /** + * If the Map is to be instantiated using non-default constructor + * or factory method + * that takes one or more named properties as argument(s), + * this creator is used for instantiation. + */ + protected PropertyBasedCreator _propertyBasedCreator; + + /** + * Deserializer that is used iff delegate-based creator is + * to be used for deserializing from JSON Object. + */ + protected JsonDeserializer<Object> _delegateDeserializer; + + // // Any properties to ignore if seen? + + protected HashSet<String> _ignorableProperties; + + /* + /********************************************************** + /* Life-cycle + /********************************************************** + */ + + /** + * @deprecated Since 1.9, use variant that takes ValueInstantiator + */ + @Deprecated + protected MapDeserializer(JavaType mapType, Constructor<Map<Object,Object>> defCtor, + KeyDeserializer keyDeser, JsonDeserializer<Object> valueDeser, + TypeDeserializer valueTypeDeser) + { + super(Map.class); + _mapType = mapType; + _keyDeserializer = keyDeser; + _valueDeserializer = valueDeser; + _valueTypeDeserializer = valueTypeDeser; + // not super-clean, but has to do... + StdValueInstantiator inst = new StdValueInstantiator(null, mapType); + if (defCtor != null) { + AnnotatedConstructor aCtor = new AnnotatedConstructor(defCtor, + null, null); + inst.configureFromObjectSettings(aCtor, null, null, null, null); + } + _hasDefaultCreator = (defCtor != null); + _valueInstantiator = inst; + } + + public MapDeserializer(JavaType mapType, ValueInstantiator valueInstantiator, + KeyDeserializer keyDeser, JsonDeserializer<Object> valueDeser, + TypeDeserializer valueTypeDeser) + { + super(Map.class); + _mapType = mapType; + _keyDeserializer = keyDeser; + _valueDeserializer = valueDeser; + _valueTypeDeserializer = valueTypeDeser; + _valueInstantiator = valueInstantiator; + if (valueInstantiator.canCreateFromObjectWith()) { + _propertyBasedCreator = new PropertyBasedCreator(valueInstantiator); + } else { + _propertyBasedCreator = null; + } + _hasDefaultCreator = valueInstantiator.canCreateUsingDefault(); + } + + /** + * Copy-constructor that can be used by sub-classes to allow + * copy-on-write styling copying of settings of an existing instance. + * + * @since 1.9 + */ + protected MapDeserializer(MapDeserializer src) + { + super(src._valueClass); + _mapType = src._mapType; + _keyDeserializer = src._keyDeserializer; + _valueDeserializer = src._valueDeserializer; + _valueTypeDeserializer = src._valueTypeDeserializer; + _valueInstantiator = src._valueInstantiator; + _propertyBasedCreator = src._propertyBasedCreator; + _delegateDeserializer = src._delegateDeserializer; + _hasDefaultCreator = src._hasDefaultCreator; + // should we make a copy here? + _ignorableProperties = src._ignorableProperties; + } + + public void setIgnorableProperties(String[] ignorable) + { + _ignorableProperties = (ignorable == null || ignorable.length == 0) ? + null : ArrayBuilders.arrayToSet(ignorable); + } + + /* + /********************************************************** + /* Validation, post-processing (ResolvableDeserializer) + /********************************************************** + */ + + /** + * Method called to finalize setup of this deserializer, + * after deserializer itself has been registered. This + * is needed to handle recursive and transitive dependencies. + */ + @Override + public void resolve(DeserializationConfig config, DeserializerProvider provider) + throws JsonMappingException + { + // May need to resolve types for delegate- and/or property-based creators: + if (_valueInstantiator.canCreateUsingDelegate()) { + JavaType delegateType = _valueInstantiator.getDelegateType(); + if (delegateType == null) { + throw new IllegalArgumentException("Invalid delegate-creator definition for "+_mapType + +": value instantiator ("+_valueInstantiator.getClass().getName() + +") returned true for 'canCreateUsingDelegate()', but null for 'getDelegateType()'"); + } + AnnotatedWithParams delegateCreator = _valueInstantiator.getDelegateCreator(); + // Need to create a temporary property to allow contextual deserializers: + // Note: unlike BeanDeserializer, we don't have an AnnotatedClass around; hence no annotations passed + BeanProperty.Std property = new BeanProperty.Std(null, + delegateType, null, delegateCreator); + _delegateDeserializer = findDeserializer(config, provider, delegateType, property); + } + if (_propertyBasedCreator != null) { + for (SettableBeanProperty prop : _propertyBasedCreator.getCreatorProperties()) { + if (!prop.hasValueDeserializer()) { + _propertyBasedCreator.assignDeserializer(prop, findDeserializer(config, provider, prop.getType(), prop)); + } + } + } + } + + /* + /********************************************************** + /* ContainerDeserializerBase API + /********************************************************** + */ + + @Override + public JavaType getContentType() { + return _mapType.getContentType(); + } + + @Override + public JsonDeserializer<Object> getContentDeserializer() { + return _valueDeserializer; + } + + /* + /********************************************************** + /* JsonDeserializer API + /********************************************************** + */ + + @Override + @SuppressWarnings("unchecked") + public Map<Object,Object> deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + if (_propertyBasedCreator != null) { + return _deserializeUsingCreator(jp, ctxt); + } + if (_delegateDeserializer != null) { + return (Map<Object,Object>) _valueInstantiator.createUsingDelegate(_delegateDeserializer.deserialize(jp, ctxt)); + } + if (!_hasDefaultCreator) { + throw ctxt.instantiationException(getMapClass(), "No default constructor found"); + } + // Ok: must point to START_OBJECT, FIELD_NAME or END_OBJECT + JsonToken t = jp.getCurrentToken(); + if (t != JsonToken.START_OBJECT && t != JsonToken.FIELD_NAME && t != JsonToken.END_OBJECT) { + // [JACKSON-620] (empty) String may be ok however: + if (t == JsonToken.VALUE_STRING) { + return (Map<Object,Object>) _valueInstantiator.createFromString(jp.getText()); + } + throw ctxt.mappingException(getMapClass()); + } + final Map<Object,Object> result = (Map<Object,Object>) _valueInstantiator.createUsingDefault(); + _readAndBind(jp, ctxt, result); + return result; + } + + @Override + public Map<Object,Object> deserialize(JsonParser jp, DeserializationContext ctxt, + Map<Object,Object> result) + throws IOException, JsonProcessingException + { + // Ok: must point to START_OBJECT or FIELD_NAME + JsonToken t = jp.getCurrentToken(); + if (t != JsonToken.START_OBJECT && t != JsonToken.FIELD_NAME) { + throw ctxt.mappingException(getMapClass()); + } + _readAndBind(jp, ctxt, result); + return result; + } + + @Override + public Object deserializeWithType(JsonParser jp, DeserializationContext ctxt, + TypeDeserializer typeDeserializer) + throws IOException, JsonProcessingException + { + // In future could check current token... for now this should be enough: + return typeDeserializer.deserializeTypedFromObject(jp, ctxt); + } + + /* + /********************************************************** + /* Other public accessors + /********************************************************** + */ + + @SuppressWarnings("unchecked") + public final Class<?> getMapClass() { return (Class<Map<Object,Object>>) _mapType.getRawClass(); } + + @Override public JavaType getValueType() { return _mapType; } + + /* + /********************************************************** + /* Internal methods + /********************************************************** + */ + + protected final void _readAndBind(JsonParser jp, DeserializationContext ctxt, + Map<Object,Object> result) + throws IOException, JsonProcessingException + { + JsonToken t = jp.getCurrentToken(); + if (t == JsonToken.START_OBJECT) { + t = jp.nextToken(); + } + final KeyDeserializer keyDes = _keyDeserializer; + final JsonDeserializer<Object> valueDes = _valueDeserializer; + final TypeDeserializer typeDeser = _valueTypeDeserializer; + for (; t == JsonToken.FIELD_NAME; t = jp.nextToken()) { + // Must point to field name + String fieldName = jp.getCurrentName(); + Object key = keyDes.deserializeKey(fieldName, ctxt); + // And then the value... + t = jp.nextToken(); + if (_ignorableProperties != null && _ignorableProperties.contains(fieldName)) { + jp.skipChildren(); + continue; + } + // Note: must handle null explicitly here; value deserializers won't + Object value; + if (t == JsonToken.VALUE_NULL) { + value = null; + } else if (typeDeser == null) { + value = valueDes.deserialize(jp, ctxt); + } else { + value = valueDes.deserializeWithType(jp, ctxt, typeDeser); + } + /* !!! 23-Dec-2008, tatu: should there be an option to verify + * that there are no duplicate field names? (and/or what + * to do, keep-first or keep-last) + */ + result.put(key, value); + } + } + + @SuppressWarnings("unchecked") + public Map<Object,Object> _deserializeUsingCreator(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + final PropertyBasedCreator creator = _propertyBasedCreator; + PropertyValueBuffer buffer = creator.startBuilding(jp, ctxt); + + JsonToken t = jp.getCurrentToken(); + if (t == JsonToken.START_OBJECT) { + t = jp.nextToken(); + } + final JsonDeserializer<Object> valueDes = _valueDeserializer; + final TypeDeserializer typeDeser = _valueTypeDeserializer; + for (; t == JsonToken.FIELD_NAME; t = jp.nextToken()) { + String propName = jp.getCurrentName(); + t = jp.nextToken(); // to get to value + if (_ignorableProperties != null && _ignorableProperties.contains(propName)) { + jp.skipChildren(); // and skip it (in case of array/object) + continue; + } + // creator property? + SettableBeanProperty prop = creator.findCreatorProperty(propName); + if (prop != null) { + // Last property to set? + Object value = prop.deserialize(jp, ctxt); + if (buffer.assignParameter(prop.getPropertyIndex(), value)) { + jp.nextToken(); + Map<Object,Object> result; + try { + result = (Map<Object,Object>)creator.build(buffer); + } catch (Exception e) { + wrapAndThrow(e, _mapType.getRawClass()); + return null; + } + _readAndBind(jp, ctxt, result); + return result; + } + continue; + } + // other property? needs buffering + String fieldName = jp.getCurrentName(); + Object key = _keyDeserializer.deserializeKey(fieldName, ctxt); + Object value; + if (t == JsonToken.VALUE_NULL) { + value = null; + } else if (typeDeser == null) { + value = valueDes.deserialize(jp, ctxt); + } else { + value = valueDes.deserializeWithType(jp, ctxt, typeDeser); + } + buffer.bufferMapProperty(key, value); + } + // end of JSON object? + // if so, can just construct and leave... + try { + return (Map<Object,Object>)creator.build(buffer); + } catch (Exception e) { + wrapAndThrow(e, _mapType.getRawClass()); + return null; + } + } + + // note: copied form BeanDeserializer; should try to share somehow... + protected void wrapAndThrow(Throwable t, Object ref) + throws IOException + { + // to handle StackOverflow: + while (t instanceof InvocationTargetException && t.getCause() != null) { + t = t.getCause(); + } + // Errors and "plain" IOExceptions to be passed as is + if (t instanceof Error) { + throw (Error) t; + } + // ... except for mapping exceptions + if (t instanceof IOException && !(t instanceof JsonMappingException)) { + throw (IOException) t; + } + throw JsonMappingException.wrapWithPath(t, ref, null); + } + +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/ObjectArrayDeserializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/ObjectArrayDeserializer.java new file mode 100644 index 0000000..2960c9b --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/ObjectArrayDeserializer.java
@@ -0,0 +1,201 @@ +package org.codehaus.jackson.map.deser.std; + +import java.io.IOException; +import java.lang.reflect.Array; + +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.JsonToken; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.JacksonStdImpl; +import org.codehaus.jackson.map.type.ArrayType; +import org.codehaus.jackson.map.util.ObjectBuffer; +import org.codehaus.jackson.type.JavaType; + +/** + * Basic serializer that can serialize non-primitive arrays. + */ +@JacksonStdImpl +public class ObjectArrayDeserializer + extends ContainerDeserializerBase<Object[]> +{ + // // Configuration + + protected final JavaType _arrayType; + + /** + * Flag that indicates whether the component type is Object or not. + * Used for minor optimization when constructing result. + */ + protected final boolean _untyped; + + /** + * Type of contained elements: needed for constructing actual + * result array + */ + protected final Class<?> _elementClass; + + /** + * Element deserializer + */ + protected final JsonDeserializer<Object> _elementDeserializer; + + /** + * If element instances have polymorphic type information, this + * is the type deserializer that can handle it + */ + protected final TypeDeserializer _elementTypeDeserializer; + + public ObjectArrayDeserializer(ArrayType arrayType, JsonDeserializer<Object> elemDeser, + TypeDeserializer elemTypeDeser) + { + super(Object[].class); + _arrayType = arrayType; + _elementClass = arrayType.getContentType().getRawClass(); + _untyped = (_elementClass == Object.class); + _elementDeserializer = elemDeser; + _elementTypeDeserializer = elemTypeDeser; + } + + /* + /********************************************************** + /* ContainerDeserializerBase API + /********************************************************** + */ + + @Override + public JavaType getContentType() { + return _arrayType.getContentType(); + } + + @Override + public JsonDeserializer<Object> getContentDeserializer() { + return _elementDeserializer; + } + + /* + /********************************************************** + /* JsonDeserializer API + /********************************************************** + */ + + @Override + public Object[] deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + // Ok: must point to START_ARRAY (or equivalent) + if (!jp.isExpectedStartArrayToken()) { + return handleNonArray(jp, ctxt); + } + + final ObjectBuffer buffer = ctxt.leaseObjectBuffer(); + Object[] chunk = buffer.resetAndStart(); + int ix = 0; + JsonToken t; + final TypeDeserializer typeDeser = _elementTypeDeserializer; + + while ((t = jp.nextToken()) != JsonToken.END_ARRAY) { + // Note: must handle null explicitly here; value deserializers won't + Object value; + + if (t == JsonToken.VALUE_NULL) { + value = null; + } else if (typeDeser == null) { + value = _elementDeserializer.deserialize(jp, ctxt); + } else { + value = _elementDeserializer.deserializeWithType(jp, ctxt, typeDeser); + } + if (ix >= chunk.length) { + chunk = buffer.appendCompletedChunk(chunk); + ix = 0; + } + chunk[ix++] = value; + } + + Object[] result; + + if (_untyped) { + result = buffer.completeAndClearBuffer(chunk, ix); + } else { + result = buffer.completeAndClearBuffer(chunk, ix, _elementClass); + } + ctxt.returnObjectBuffer(buffer); + return result; + } + + @Override + public Object[] deserializeWithType(JsonParser jp, DeserializationContext ctxt, + TypeDeserializer typeDeserializer) + throws IOException, JsonProcessingException + { + /* Should there be separate handling for base64 stuff? + * for now this should be enough: + */ + return (Object[]) typeDeserializer.deserializeTypedFromArray(jp, ctxt); + } + + /* + /********************************************************** + /* Internal methods + /********************************************************** + */ + + protected Byte[] deserializeFromBase64(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + // First same as what PrimitiveArrayDeserializers.ByteDeser does: + byte[] b = jp.getBinaryValue(ctxt.getBase64Variant()); + // But then need to convert to wrappers + Byte[] result = new Byte[b.length]; + for (int i = 0, len = b.length; i < len; ++i) { + result[i] = Byte.valueOf(b[i]); + } + return result; + } + + private final Object[] handleNonArray(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + // [JACKSON-620] Empty String can become null... + if ((jp.getCurrentToken() == JsonToken.VALUE_STRING) + && ctxt.isEnabled(DeserializationConfig.Feature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT)) { + String str = jp.getText(); + if (str.length() == 0) { + return null; + } + } + + // Can we do implicit coercion to a single-element array still? + if (!ctxt.isEnabled(DeserializationConfig.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY)) { + /* 04-Oct-2009, tatu: One exception; byte arrays are generally + * serialized as base64, so that should be handled + */ + if (jp.getCurrentToken() == JsonToken.VALUE_STRING + && _elementClass == Byte.class) { + return deserializeFromBase64(jp, ctxt); + } + throw ctxt.mappingException(_arrayType.getRawClass()); + } + JsonToken t = jp.getCurrentToken(); + Object value; + + if (t == JsonToken.VALUE_NULL) { + value = null; + } else if (_elementTypeDeserializer == null) { + value = _elementDeserializer.deserialize(jp, ctxt); + } else { + value = _elementDeserializer.deserializeWithType(jp, ctxt, _elementTypeDeserializer); + } + // Ok: bit tricky, since we may want T[], not just Object[] + Object[] result; + + if (_untyped) { + result = new Object[1]; + } else { + result = (Object[]) Array.newInstance(_elementClass, 1); + } + result[0] = value; + return result; + } +} +
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/PrimitiveArrayDeserializers.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/PrimitiveArrayDeserializers.java new file mode 100644 index 0000000..9945bec --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/PrimitiveArrayDeserializers.java
@@ -0,0 +1,583 @@ +package org.codehaus.jackson.map.deser.std; + +import java.io.IOException; +import java.util.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.JacksonStdImpl; +import org.codehaus.jackson.map.type.*; +import org.codehaus.jackson.map.util.ArrayBuilders; +import org.codehaus.jackson.map.util.ObjectBuffer; +import org.codehaus.jackson.type.JavaType; + +/** + * Container for deserializers used for instantiating "primitive arrays", + * arrays that contain non-object java primitive types. + * + * @since 1.9 (renamed from 'org.codehaus.jackson.map.deser.ArrayDeserilizers) + */ +public class PrimitiveArrayDeserializers +{ + HashMap<JavaType,JsonDeserializer<Object>> _allDeserializers; + + final static PrimitiveArrayDeserializers instance = new PrimitiveArrayDeserializers(); + + protected PrimitiveArrayDeserializers() + { + _allDeserializers = new HashMap<JavaType,JsonDeserializer<Object>>(); + // note: we'll use component type as key, not array type + add(boolean.class, new BooleanDeser()); + + /* ByteDeser is bit special, as it has 2 separate modes of operation; + * one for String input (-> base64 input), the other for + * numeric input + */ + add(byte.class, new ByteDeser()); + add(short.class, new ShortDeser()); + add(int.class, new IntDeser()); + add(long.class, new LongDeser()); + + add(float.class, new FloatDeser()); + add(double.class, new DoubleDeser()); + + add(String.class, new StringDeser()); + /* also: char[] is most likely only used with Strings; doesn't + * seem to make sense to transfer as numbers + */ + add(char.class, new CharDeser()); + } + + public static HashMap<JavaType,JsonDeserializer<Object>> getAll() + { + return instance._allDeserializers; + } + + @SuppressWarnings("unchecked") + private void add(Class<?> cls, JsonDeserializer<?> deser) + { + /* Not super clean to use default TypeFactory in general, but + * since primitive array types can't be modified for anything + * useful, this should be ok: + */ + _allDeserializers.put(TypeFactory.defaultInstance().constructType(cls), + (JsonDeserializer<Object>) deser); + } + + public Object deserializeWithType(JsonParser jp, DeserializationContext ctxt, + TypeDeserializer typeDeserializer) + throws IOException, JsonProcessingException + { + /* Should there be separate handling for base64 stuff? + * for now this should be enough: + */ + return typeDeserializer.deserializeTypedFromArray(jp, ctxt); + } + + /* + /******************************************************** + /* Intermediate base class + /******************************************************** + */ + + /** + * Intermediate base class for primitive array deserializers + */ + static abstract class Base<T> extends StdDeserializer<T> + { + protected Base(Class<T> cls) { + super(cls); + } + + @Override + public Object deserializeWithType(JsonParser jp, DeserializationContext ctxt, + TypeDeserializer typeDeserializer) + throws IOException, JsonProcessingException + { + return typeDeserializer.deserializeTypedFromArray(jp, ctxt); + } + } + + /* + /******************************************************** + /* Actual deserializers: efficient String[], char[] deserializers + /******************************************************** + */ + + @JacksonStdImpl + final static class StringDeser + extends Base<String[]> + { + public StringDeser() { super(String[].class); } + + @Override + public String[] deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + // Ok: must point to START_ARRAY (or equivalent) + if (!jp.isExpectedStartArrayToken()) { + return handleNonArray(jp, ctxt); + } + final ObjectBuffer buffer = ctxt.leaseObjectBuffer(); + Object[] chunk = buffer.resetAndStart(); + int ix = 0; + JsonToken t; + + while ((t = jp.nextToken()) != JsonToken.END_ARRAY) { + // Ok: no need to convert Strings, but must recognize nulls + String value = (t == JsonToken.VALUE_NULL) ? null : jp.getText(); + if (ix >= chunk.length) { + chunk = buffer.appendCompletedChunk(chunk); + ix = 0; + } + chunk[ix++] = value; + } + String[] result = buffer.completeAndClearBuffer(chunk, ix, String.class); + ctxt.returnObjectBuffer(buffer); + return result; + } + + private final String[] handleNonArray(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + // [JACKSON-526]: implicit arrays from single values? + if (!ctxt.isEnabled(DeserializationConfig.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY)) { + // [JACKSON-620] Empty String can become null... + if ((jp.getCurrentToken() == JsonToken.VALUE_STRING) + && ctxt.isEnabled(DeserializationConfig.Feature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT)) { + String str = jp.getText(); + if (str.length() == 0) { + return null; + } + } + throw ctxt.mappingException(_valueClass); + } + return new String[] { (jp.getCurrentToken() == JsonToken.VALUE_NULL) ? null : jp.getText() }; + } + } + + @JacksonStdImpl + final static class CharDeser + extends Base<char[]> + { + public CharDeser() { super(char[].class); } + + @Override + public char[] deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + /* Won't take arrays, must get a String (could also + * convert other tokens to Strings... but let's not bother + * yet, doesn't seem to make sense) + */ + JsonToken t = jp.getCurrentToken(); + if (t == JsonToken.VALUE_STRING) { + // note: can NOT return shared internal buffer, must copy: + char[] buffer = jp.getTextCharacters(); + int offset = jp.getTextOffset(); + int len = jp.getTextLength(); + + char[] result = new char[len]; + System.arraycopy(buffer, offset, result, 0, len); + return result; + } + if (jp.isExpectedStartArrayToken()) { + // Let's actually build as a String, then get chars + StringBuilder sb = new StringBuilder(64); + while ((t = jp.nextToken()) != JsonToken.END_ARRAY) { + if (t != JsonToken.VALUE_STRING) { + throw ctxt.mappingException(Character.TYPE); + } + String str = jp.getText(); + if (str.length() != 1) { + throw JsonMappingException.from(jp, "Can not convert a JSON String of length "+str.length()+" into a char element of char array"); + } + sb.append(str.charAt(0)); + } + return sb.toString().toCharArray(); + } + // or, maybe an embedded object? + if (t == JsonToken.VALUE_EMBEDDED_OBJECT) { + Object ob = jp.getEmbeddedObject(); + if (ob == null) return null; + if (ob instanceof char[]) { + return (char[]) ob; + } + if (ob instanceof String) { + return ((String) ob).toCharArray(); + } + // 04-Feb-2011, tatu: byte[] can be converted; assuming base64 is wanted + if (ob instanceof byte[]) { + return Base64Variants.getDefaultVariant().encode((byte[]) ob, false).toCharArray(); + } + // not recognized, just fall through + } + throw ctxt.mappingException(_valueClass); + } + } + + /* + /******************************************************** + /* Actual deserializers: primivate array desers + /******************************************************** + */ + + @JacksonStdImpl + final static class BooleanDeser + extends Base<boolean[]> + { + public BooleanDeser() { super(boolean[].class); } + + @Override + public boolean[] deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + if (!jp.isExpectedStartArrayToken()) { + return handleNonArray(jp, ctxt); + } + ArrayBuilders.BooleanBuilder builder = ctxt.getArrayBuilders().getBooleanBuilder(); + boolean[] chunk = builder.resetAndStart(); + int ix = 0; + + while (jp.nextToken() != JsonToken.END_ARRAY) { + // whether we should allow truncating conversions? + boolean value = _parseBooleanPrimitive(jp, ctxt); + if (ix >= chunk.length) { + chunk = builder.appendCompletedChunk(chunk, ix); + ix = 0; + } + chunk[ix++] = value; + } + return builder.completeAndClearBuffer(chunk, ix); + } + + private final boolean[] handleNonArray(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + // [JACKSON-620] Empty String can become null... + if ((jp.getCurrentToken() == JsonToken.VALUE_STRING) + && ctxt.isEnabled(DeserializationConfig.Feature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT)) { + if (jp.getText().length() == 0) { + return null; + } + } + if (!ctxt.isEnabled(DeserializationConfig.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY)) { + throw ctxt.mappingException(_valueClass); + } + return new boolean[] { _parseBooleanPrimitive(jp, ctxt) }; + } + } + + /** + * When dealing with byte arrays we have one more alternative (compared + * to int/long/shorts): base64 encoded data. + */ + @JacksonStdImpl + final static class ByteDeser + extends Base<byte[]> + { + public ByteDeser() { super(byte[].class); } + + @Override + public byte[] deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + JsonToken t = jp.getCurrentToken(); + + // Most likely case: base64 encoded String? + if (t == JsonToken.VALUE_STRING) { + return jp.getBinaryValue(ctxt.getBase64Variant()); + } + // 31-Dec-2009, tatu: Also may be hidden as embedded Object + if (t == JsonToken.VALUE_EMBEDDED_OBJECT) { + Object ob = jp.getEmbeddedObject(); + if (ob == null) return null; + if (ob instanceof byte[]) { + return (byte[]) ob; + } + } + if (!jp.isExpectedStartArrayToken()) { + return handleNonArray(jp, ctxt); + } + ArrayBuilders.ByteBuilder builder = ctxt.getArrayBuilders().getByteBuilder(); + byte[] chunk = builder.resetAndStart(); + int ix = 0; + + while ((t = jp.nextToken()) != JsonToken.END_ARRAY) { + // whether we should allow truncating conversions? + byte value; + if (t == JsonToken.VALUE_NUMBER_INT || t == JsonToken.VALUE_NUMBER_FLOAT) { + // should we catch overflow exceptions? + value = jp.getByteValue(); + } else { + // [JACKSON-79]: should probably accept nulls as 0 + if (t != JsonToken.VALUE_NULL) { + throw ctxt.mappingException(_valueClass.getComponentType()); + } + value = (byte) 0; + } + if (ix >= chunk.length) { + chunk = builder.appendCompletedChunk(chunk, ix); + ix = 0; + } + chunk[ix++] = value; + } + return builder.completeAndClearBuffer(chunk, ix); + } + + private final byte[] handleNonArray(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + // [JACKSON-620] Empty String can become null... + if ((jp.getCurrentToken() == JsonToken.VALUE_STRING) + && ctxt.isEnabled(DeserializationConfig.Feature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT)) { + if (jp.getText().length() == 0) { + return null; + } + } + if (!ctxt.isEnabled(DeserializationConfig.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY)) { + throw ctxt.mappingException(_valueClass); + } + byte value; + JsonToken t = jp.getCurrentToken(); + if (t == JsonToken.VALUE_NUMBER_INT || t == JsonToken.VALUE_NUMBER_FLOAT) { + // should we catch overflow exceptions? + value = jp.getByteValue(); + } else { + // [JACKSON-79]: should probably accept nulls as 'false' + if (t != JsonToken.VALUE_NULL) { + throw ctxt.mappingException(_valueClass.getComponentType()); + } + value = (byte) 0; + } + return new byte[] { value }; + } + } + + @JacksonStdImpl + final static class ShortDeser + extends Base<short[]> + { + public ShortDeser() { super(short[].class); } + + @Override + public short[] deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + if (!jp.isExpectedStartArrayToken()) { + return handleNonArray(jp, ctxt); + } + ArrayBuilders.ShortBuilder builder = ctxt.getArrayBuilders().getShortBuilder(); + short[] chunk = builder.resetAndStart(); + int ix = 0; + + while (jp.nextToken() != JsonToken.END_ARRAY) { + short value = _parseShortPrimitive(jp, ctxt); + if (ix >= chunk.length) { + chunk = builder.appendCompletedChunk(chunk, ix); + ix = 0; + } + chunk[ix++] = value; + } + return builder.completeAndClearBuffer(chunk, ix); + } + + private final short[] handleNonArray(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + // [JACKSON-620] Empty String can become null... + if ((jp.getCurrentToken() == JsonToken.VALUE_STRING) + && ctxt.isEnabled(DeserializationConfig.Feature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT)) { + if (jp.getText().length() == 0) { + return null; + } + } + if (!ctxt.isEnabled(DeserializationConfig.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY)) { + throw ctxt.mappingException(_valueClass); + } + return new short[] { _parseShortPrimitive(jp, ctxt) }; + } + } + + @JacksonStdImpl + final static class IntDeser + extends Base<int[]> + { + public IntDeser() { super(int[].class); } + + @Override + public int[] deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + if (!jp.isExpectedStartArrayToken()) { + return handleNonArray(jp, ctxt); + } + ArrayBuilders.IntBuilder builder = ctxt.getArrayBuilders().getIntBuilder(); + int[] chunk = builder.resetAndStart(); + int ix = 0; + + while (jp.nextToken() != JsonToken.END_ARRAY) { + // whether we should allow truncating conversions? + int value = _parseIntPrimitive(jp, ctxt); + if (ix >= chunk.length) { + chunk = builder.appendCompletedChunk(chunk, ix); + ix = 0; + } + chunk[ix++] = value; + } + return builder.completeAndClearBuffer(chunk, ix); + } + + private final int[] handleNonArray(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + // [JACKSON-620] Empty String can become null... + if ((jp.getCurrentToken() == JsonToken.VALUE_STRING) + && ctxt.isEnabled(DeserializationConfig.Feature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT)) { + if (jp.getText().length() == 0) { + return null; + } + } + if (!ctxt.isEnabled(DeserializationConfig.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY)) { + throw ctxt.mappingException(_valueClass); + } + return new int[] { _parseIntPrimitive(jp, ctxt) }; + } + } + + @JacksonStdImpl + final static class LongDeser + extends Base<long[]> + { + public LongDeser() { super(long[].class); } + + @Override + public long[] deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + if (!jp.isExpectedStartArrayToken()) { + return handleNonArray(jp, ctxt); + } + ArrayBuilders.LongBuilder builder = ctxt.getArrayBuilders().getLongBuilder(); + long[] chunk = builder.resetAndStart(); + int ix = 0; + + while (jp.nextToken() != JsonToken.END_ARRAY) { + long value = _parseLongPrimitive(jp, ctxt); + if (ix >= chunk.length) { + chunk = builder.appendCompletedChunk(chunk, ix); + ix = 0; + } + chunk[ix++] = value; + } + return builder.completeAndClearBuffer(chunk, ix); + } + + private final long[] handleNonArray(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + // [JACKSON-620] Empty String can become null... + if ((jp.getCurrentToken() == JsonToken.VALUE_STRING) + && ctxt.isEnabled(DeserializationConfig.Feature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT)) { + if (jp.getText().length() == 0) { + return null; + } + } + if (!ctxt.isEnabled(DeserializationConfig.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY)) { + throw ctxt.mappingException(_valueClass); + } + return new long[] { _parseLongPrimitive(jp, ctxt) }; + } + } + + @JacksonStdImpl + final static class FloatDeser + extends Base<float[]> + { + public FloatDeser() { super(float[].class); } + + @Override + public float[] deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + if (!jp.isExpectedStartArrayToken()) { + return handleNonArray(jp, ctxt); + } + ArrayBuilders.FloatBuilder builder = ctxt.getArrayBuilders().getFloatBuilder(); + float[] chunk = builder.resetAndStart(); + int ix = 0; + + while (jp.nextToken() != JsonToken.END_ARRAY) { + // whether we should allow truncating conversions? + float value = _parseFloatPrimitive(jp, ctxt); + if (ix >= chunk.length) { + chunk = builder.appendCompletedChunk(chunk, ix); + ix = 0; + } + chunk[ix++] = value; + } + return builder.completeAndClearBuffer(chunk, ix); + } + + private final float[] handleNonArray(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + // [JACKSON-620] Empty String can become null... + if ((jp.getCurrentToken() == JsonToken.VALUE_STRING) + && ctxt.isEnabled(DeserializationConfig.Feature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT)) { + if (jp.getText().length() == 0) { + return null; + } + } + if (!ctxt.isEnabled(DeserializationConfig.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY)) { + throw ctxt.mappingException(_valueClass); + } + return new float[] { _parseFloatPrimitive(jp, ctxt) }; + } + } + + @JacksonStdImpl + final static class DoubleDeser + extends Base<double[]> + { + public DoubleDeser() { super(double[].class); } + + @Override + public double[] deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + if (!jp.isExpectedStartArrayToken()) { + return handleNonArray(jp, ctxt); + } + ArrayBuilders.DoubleBuilder builder = ctxt.getArrayBuilders().getDoubleBuilder(); + double[] chunk = builder.resetAndStart(); + int ix = 0; + + while (jp.nextToken() != JsonToken.END_ARRAY) { + double value = _parseDoublePrimitive(jp, ctxt); + if (ix >= chunk.length) { + chunk = builder.appendCompletedChunk(chunk, ix); + ix = 0; + } + chunk[ix++] = value; + } + return builder.completeAndClearBuffer(chunk, ix); + } + + private final double[] handleNonArray(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + // [JACKSON-620] Empty String can become null... + if ((jp.getCurrentToken() == JsonToken.VALUE_STRING) + && ctxt.isEnabled(DeserializationConfig.Feature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT)) { + if (jp.getText().length() == 0) { + return null; + } + } + if (!ctxt.isEnabled(DeserializationConfig.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY)) { + throw ctxt.mappingException(_valueClass); + } + return new double[] { _parseDoublePrimitive(jp, ctxt) }; + } + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/StdDeserializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/StdDeserializer.java new file mode 100644 index 0000000..fa0aacf --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/StdDeserializer.java
@@ -0,0 +1,1137 @@ +package org.codehaus.jackson.map.deser.std; + +import java.io.IOException; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.*; + +import org.codehaus.jackson.JsonParser.NumberType; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.JsonToken; +import org.codehaus.jackson.io.NumberInput; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.JacksonStdImpl; +import org.codehaus.jackson.type.JavaType; + +/** + * Base class for common deserializers. Contains shared + * base functionality for dealing with primitive values, such + * as (re)parsing from String. + * + * @since 1.9 (moved from higher-level package) + */ +public abstract class StdDeserializer<T> + extends JsonDeserializer<T> +{ + /** + * Type of values this deserializer handles: sometimes + * exact types, other time most specific supertype of + * types deserializer handles (which may be as generic + * as {@link Object} in some case) + */ + final protected Class<?> _valueClass; + + protected StdDeserializer(Class<?> vc) { + _valueClass = vc; + } + + protected StdDeserializer(JavaType valueType) { + _valueClass = (valueType == null) ? null : valueType.getRawClass(); + } + + /* + /********************************************************** + /* Extended API + /********************************************************** + */ + + public Class<?> getValueClass() { return _valueClass; } + + /** + * Exact structured type deserializer handles, if known. + *<p> + * Default implementation just returns null. + */ + public JavaType getValueType() { return null; } + + /** + * Method that can be called to determine if given deserializer is the default + * deserializer Jackson uses; as opposed to a custom deserializer installed by + * a module or calling application. Determination is done using + * {@link JacksonStdImpl} annotation on deserializer class. + * + * @since 1.7 + */ + protected boolean isDefaultSerializer(JsonDeserializer<?> deserializer) + { + return (deserializer != null && deserializer.getClass().getAnnotation(JacksonStdImpl.class) != null); + } + + /* + /********************************************************** + /* Partial JsonDeserializer implementation + /********************************************************** + */ + + /** + * Base implementation that does not assume specific type + * inclusion mechanism. Sub-classes are expected to override + * this method if they are to handle type information. + */ + @Override + public Object deserializeWithType(JsonParser jp, DeserializationContext ctxt, + TypeDeserializer typeDeserializer) + throws IOException, JsonProcessingException + { + return typeDeserializer.deserializeTypedFromAny(jp, ctxt); + } + + /* + /********************************************************** + /* Helper methods for sub-classes, parsing + /********************************************************** + */ + + protected final boolean _parseBooleanPrimitive(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + JsonToken t = jp.getCurrentToken(); + if (t == JsonToken.VALUE_TRUE) { + return true; + } + if (t == JsonToken.VALUE_FALSE) { + return false; + } + if (t == JsonToken.VALUE_NULL) { + return false; + } + // [JACKSON-78]: should accept ints too, (0 == false, otherwise true) + if (t == JsonToken.VALUE_NUMBER_INT) { + // 11-Jan-2012, tatus: May be outside of int... + if (jp.getNumberType() == NumberType.INT) { + return (jp.getIntValue() != 0); + } + return _parseBooleanFromNumber(jp, ctxt); + } + // And finally, let's allow Strings to be converted too + if (t == JsonToken.VALUE_STRING) { + String text = jp.getText().trim(); + if ("true".equals(text)) { + return true; + } + if ("false".equals(text) || text.length() == 0) { + return Boolean.FALSE; + } + throw ctxt.weirdStringException(_valueClass, "only \"true\" or \"false\" recognized"); + } + // Otherwise, no can do: + throw ctxt.mappingException(_valueClass, t); + } + + protected final Boolean _parseBoolean(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + JsonToken t = jp.getCurrentToken(); + if (t == JsonToken.VALUE_TRUE) { + return Boolean.TRUE; + } + if (t == JsonToken.VALUE_FALSE) { + return Boolean.FALSE; + } + // [JACKSON-78]: should accept ints too, (0 == false, otherwise true) + if (t == JsonToken.VALUE_NUMBER_INT) { + // 11-Jan-2012, tatus: May be outside of int... + if (jp.getNumberType() == NumberType.INT) { + return (jp.getIntValue() == 0) ? Boolean.FALSE : Boolean.TRUE; + } + return Boolean.valueOf(_parseBooleanFromNumber(jp, ctxt)); + } + if (t == JsonToken.VALUE_NULL) { + return (Boolean) getNullValue(); + } + // And finally, let's allow Strings to be converted too + if (t == JsonToken.VALUE_STRING) { + String text = jp.getText().trim(); + if ("true".equals(text)) { + return Boolean.TRUE; + } + if ("false".equals(text)) { + return Boolean.FALSE; + } + if (text.length() == 0) { + return (Boolean) getEmptyValue(); + } + throw ctxt.weirdStringException(_valueClass, "only \"true\" or \"false\" recognized"); + } + // Otherwise, no can do: + throw ctxt.mappingException(_valueClass, t); + } + + protected final boolean _parseBooleanFromNumber(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + if (jp.getNumberType() == NumberType.LONG) { + return (jp.getLongValue() == 0L) ? Boolean.FALSE : Boolean.TRUE; + } + // no really good logic; let's actually resort to textual comparison + String str = jp.getText(); + if ("0.0".equals(str) || "0".equals(str)) { + return Boolean.FALSE; + } + return Boolean.TRUE; + } + + protected Byte _parseByte(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + JsonToken t = jp.getCurrentToken(); + if (t == JsonToken.VALUE_NUMBER_INT || t == JsonToken.VALUE_NUMBER_FLOAT) { // coercing should work too + return jp.getByteValue(); + } + if (t == JsonToken.VALUE_STRING) { // let's do implicit re-parse + String text = jp.getText().trim(); + int value; + try { + int len = text.length(); + if (len == 0) { + return (Byte) getEmptyValue(); + } + value = NumberInput.parseInt(text); + } catch (IllegalArgumentException iae) { + throw ctxt.weirdStringException(_valueClass, "not a valid Byte value"); + } + // So far so good: but does it fit? + // as per [JACKSON-804], allow range up to 255, inclusive + if (value < Byte.MIN_VALUE || value > 255) { + throw ctxt.weirdStringException(_valueClass, "overflow, value can not be represented as 8-bit value"); + } + return Byte.valueOf((byte) value); + } + if (t == JsonToken.VALUE_NULL) { + return (Byte) getNullValue(); + } + throw ctxt.mappingException(_valueClass, t); + } + + protected Short _parseShort(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + JsonToken t = jp.getCurrentToken(); + if (t == JsonToken.VALUE_NUMBER_INT || t == JsonToken.VALUE_NUMBER_FLOAT) { // coercing should work too + return jp.getShortValue(); + } + if (t == JsonToken.VALUE_STRING) { // let's do implicit re-parse + String text = jp.getText().trim(); + int value; + try { + int len = text.length(); + if (len == 0) { + return (Short) getEmptyValue(); + } + value = NumberInput.parseInt(text); + } catch (IllegalArgumentException iae) { + throw ctxt.weirdStringException(_valueClass, "not a valid Short value"); + } + // So far so good: but does it fit? + if (value < Short.MIN_VALUE || value > Short.MAX_VALUE) { + throw ctxt.weirdStringException(_valueClass, "overflow, value can not be represented as 16-bit value"); + } + return Short.valueOf((short) value); + } + if (t == JsonToken.VALUE_NULL) { + return (Short) getNullValue(); + } + throw ctxt.mappingException(_valueClass, t); + } + + protected final short _parseShortPrimitive(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + int value = _parseIntPrimitive(jp, ctxt); + // So far so good: but does it fit? + if (value < Short.MIN_VALUE || value > Short.MAX_VALUE) { + throw ctxt.weirdStringException(_valueClass, "overflow, value can not be represented as 16-bit value"); + } + return (short) value; + } + + protected final int _parseIntPrimitive(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + JsonToken t = jp.getCurrentToken(); + + // Int works as is, coercing fine as well + if (t == JsonToken.VALUE_NUMBER_INT || t == JsonToken.VALUE_NUMBER_FLOAT) { // coercing should work too + return jp.getIntValue(); + } + if (t == JsonToken.VALUE_STRING) { // let's do implicit re-parse + /* 31-Dec-2009, tatus: Should improve handling of overflow + * values... but this'll have to do for now + */ + String text = jp.getText().trim(); + try { + int len = text.length(); + if (len > 9) { + long l = Long.parseLong(text); + if (l < Integer.MIN_VALUE || l > Integer.MAX_VALUE) { + throw ctxt.weirdStringException(_valueClass, + "Overflow: numeric value ("+text+") out of range of int ("+Integer.MIN_VALUE+" - "+Integer.MAX_VALUE+")"); + } + return (int) l; + } + if (len == 0) { + return 0; + } + return NumberInput.parseInt(text); + } catch (IllegalArgumentException iae) { + throw ctxt.weirdStringException(_valueClass, "not a valid int value"); + } + } + if (t == JsonToken.VALUE_NULL) { + return 0; + } + // Otherwise, no can do: + throw ctxt.mappingException(_valueClass, t); + } + + protected final Integer _parseInteger(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + JsonToken t = jp.getCurrentToken(); + if (t == JsonToken.VALUE_NUMBER_INT || t == JsonToken.VALUE_NUMBER_FLOAT) { // coercing should work too + return Integer.valueOf(jp.getIntValue()); + } + if (t == JsonToken.VALUE_STRING) { // let's do implicit re-parse + String text = jp.getText().trim(); + try { + int len = text.length(); + if (len > 9) { + long l = Long.parseLong(text); + if (l < Integer.MIN_VALUE || l > Integer.MAX_VALUE) { + throw ctxt.weirdStringException(_valueClass, + "Overflow: numeric value ("+text+") out of range of Integer ("+Integer.MIN_VALUE+" - "+Integer.MAX_VALUE+")"); + } + return Integer.valueOf((int) l); + } + if (len == 0) { + return (Integer) getEmptyValue(); + } + return Integer.valueOf(NumberInput.parseInt(text)); + } catch (IllegalArgumentException iae) { + throw ctxt.weirdStringException(_valueClass, "not a valid Integer value"); + } + } + if (t == JsonToken.VALUE_NULL) { + return (Integer) getNullValue(); + } + // Otherwise, no can do: + throw ctxt.mappingException(_valueClass, t); + } + + protected final Long _parseLong(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + JsonToken t = jp.getCurrentToken(); + + // it should be ok to coerce (although may fail, too) + if (t == JsonToken.VALUE_NUMBER_INT || t == JsonToken.VALUE_NUMBER_FLOAT) { + return jp.getLongValue(); + } + // let's allow Strings to be converted too + if (t == JsonToken.VALUE_STRING) { + // !!! 05-Jan-2009, tatu: Should we try to limit value space, JDK is too lenient? + String text = jp.getText().trim(); + if (text.length() == 0) { + return (Long) getEmptyValue(); + } + try { + return Long.valueOf(NumberInput.parseLong(text)); + } catch (IllegalArgumentException iae) { } + throw ctxt.weirdStringException(_valueClass, "not a valid Long value"); + } + if (t == JsonToken.VALUE_NULL) { + return (Long) getNullValue(); + } + // Otherwise, no can do: + throw ctxt.mappingException(_valueClass, t); + } + + protected final long _parseLongPrimitive(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + JsonToken t = jp.getCurrentToken(); + if (t == JsonToken.VALUE_NUMBER_INT || t == JsonToken.VALUE_NUMBER_FLOAT) { + return jp.getLongValue(); + } + if (t == JsonToken.VALUE_STRING) { + String text = jp.getText().trim(); + if (text.length() == 0) { + return 0L; + } + try { + return NumberInput.parseLong(text); + } catch (IllegalArgumentException iae) { } + throw ctxt.weirdStringException(_valueClass, "not a valid long value"); + } + if (t == JsonToken.VALUE_NULL) { + return 0L; + } + throw ctxt.mappingException(_valueClass, t); + } + + protected final Float _parseFloat(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + // We accept couple of different types; obvious ones first: + JsonToken t = jp.getCurrentToken(); + + if (t == JsonToken.VALUE_NUMBER_INT || t == JsonToken.VALUE_NUMBER_FLOAT) { // coercing should work too + return jp.getFloatValue(); + } + // And finally, let's allow Strings to be converted too + if (t == JsonToken.VALUE_STRING) { + String text = jp.getText().trim(); + if (text.length() == 0) { + return (Float) getEmptyValue(); + } + switch (text.charAt(0)) { + case 'I': + if ("Infinity".equals(text) || "INF".equals(text)) { + return Float.POSITIVE_INFINITY; + } + break; + case 'N': + if ("NaN".equals(text)) { + return Float.NaN; + } + break; + case '-': + if ("-Infinity".equals(text) || "-INF".equals(text)) { + return Float.NEGATIVE_INFINITY; + } + break; + } + try { + return Float.parseFloat(text); + } catch (IllegalArgumentException iae) { } + throw ctxt.weirdStringException(_valueClass, "not a valid Float value"); + } + if (t == JsonToken.VALUE_NULL) { + return (Float) getNullValue(); + } + // Otherwise, no can do: + throw ctxt.mappingException(_valueClass, t); + } + + protected final float _parseFloatPrimitive(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + JsonToken t = jp.getCurrentToken(); + + if (t == JsonToken.VALUE_NUMBER_INT || t == JsonToken.VALUE_NUMBER_FLOAT) { // coercing should work too + return jp.getFloatValue(); + } + if (t == JsonToken.VALUE_STRING) { + String text = jp.getText().trim(); + if (text.length() == 0) { + return 0.0f; + } + switch (text.charAt(0)) { + case 'I': + if ("Infinity".equals(text) || "INF".equals(text)) { + return Float.POSITIVE_INFINITY; + } + break; + case 'N': + if ("NaN".equals(text)) { + return Float.NaN; + } + break; + case '-': + if ("-Infinity".equals(text) || "-INF".equals(text)) { + return Float.NEGATIVE_INFINITY; + } + break; + } + try { + return Float.parseFloat(text); + } catch (IllegalArgumentException iae) { } + throw ctxt.weirdStringException(_valueClass, "not a valid float value"); + } + if (t == JsonToken.VALUE_NULL) { + return 0.0f; + } + // Otherwise, no can do: + throw ctxt.mappingException(_valueClass, t); + } + + protected final Double _parseDouble(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + JsonToken t = jp.getCurrentToken(); + + if (t == JsonToken.VALUE_NUMBER_INT || t == JsonToken.VALUE_NUMBER_FLOAT) { // coercing should work too + return jp.getDoubleValue(); + } + if (t == JsonToken.VALUE_STRING) { + String text = jp.getText().trim(); + if (text.length() == 0) { + return (Double) getEmptyValue(); + } + switch (text.charAt(0)) { + case 'I': + if ("Infinity".equals(text) || "INF".equals(text)) { + return Double.POSITIVE_INFINITY; + } + break; + case 'N': + if ("NaN".equals(text)) { + return Double.NaN; + } + break; + case '-': + if ("-Infinity".equals(text) || "-INF".equals(text)) { + return Double.NEGATIVE_INFINITY; + } + break; + } + try { + return parseDouble(text); + } catch (IllegalArgumentException iae) { } + throw ctxt.weirdStringException(_valueClass, "not a valid Double value"); + } + if (t == JsonToken.VALUE_NULL) { + return (Double) getNullValue(); + } + // Otherwise, no can do: + throw ctxt.mappingException(_valueClass, t); + } + + protected final double _parseDoublePrimitive(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + // We accept couple of different types; obvious ones first: + JsonToken t = jp.getCurrentToken(); + + if (t == JsonToken.VALUE_NUMBER_INT || t == JsonToken.VALUE_NUMBER_FLOAT) { // coercing should work too + return jp.getDoubleValue(); + } + // And finally, let's allow Strings to be converted too + if (t == JsonToken.VALUE_STRING) { + String text = jp.getText().trim(); + if (text.length() == 0) { + return 0.0; + } + switch (text.charAt(0)) { + case 'I': + if ("Infinity".equals(text) || "INF".equals(text)) { + return Double.POSITIVE_INFINITY; + } + break; + case 'N': + if ("NaN".equals(text)) { + return Double.NaN; + } + break; + case '-': + if ("-Infinity".equals(text) || "-INF".equals(text)) { + return Double.NEGATIVE_INFINITY; + } + break; + } + try { + return parseDouble(text); + } catch (IllegalArgumentException iae) { } + throw ctxt.weirdStringException(_valueClass, "not a valid double value"); + } + if (t == JsonToken.VALUE_NULL) { + return 0.0; + } + // Otherwise, no can do: + throw ctxt.mappingException(_valueClass, t); + } + + + protected java.util.Date _parseDate(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + JsonToken t = jp.getCurrentToken(); + if (t == JsonToken.VALUE_NUMBER_INT) { + return new java.util.Date(jp.getLongValue()); + } + if (t == JsonToken.VALUE_NULL) { + return (java.util.Date) getNullValue(); + } + if (t == JsonToken.VALUE_STRING) { + try { + /* As per [JACKSON-203], take empty Strings to mean + * null + */ + String str = jp.getText().trim(); + if (str.length() == 0) { + return (Date) getEmptyValue(); + } + return ctxt.parseDate(str); + } catch (IllegalArgumentException iae) { + throw ctxt.weirdStringException(_valueClass, "not a valid representation (error: "+iae.getMessage()+")"); + } + } + throw ctxt.mappingException(_valueClass, t); + } + + /** + * Helper method for encapsulating calls to low-level double value parsing; single place + * just because we need a work-around that must be applied to all calls. + *<p> + * Note: copied from <code>org.codehaus.jackson.io.NumberUtil</code> (to avoid dependency to + * version 1.8; except for String constants, but that gets compiled in bytecode here) + */ + protected final static double parseDouble(String numStr) throws NumberFormatException + { + // [JACKSON-486]: avoid some nasty float representations... but should it be MIN_NORMAL or MIN_VALUE? + if (NumberInput.NASTY_SMALL_DOUBLE.equals(numStr)) { + return Double.MIN_NORMAL; + } + return Double.parseDouble(numStr); + } + + /* + /**************************************************** + /* Helper methods for sub-classes, resolving dependencies + /**************************************************** + */ + + /** + * Helper method used to locate deserializers for properties the + * type this deserializer handles contains (usually for properties of + * bean types) + * + * @param config Active deserialization configuration + * @param provider Deserializer provider to use for actually finding deserializer(s) + * @param type Type of property to deserialize + * @param property Actual property object (field, method, constuctor parameter) used + * for passing deserialized values; provided so deserializer can be contextualized if necessary (since 1.7) + */ + protected JsonDeserializer<Object> findDeserializer(DeserializationConfig config, DeserializerProvider provider, + JavaType type, BeanProperty property) + throws JsonMappingException + { + JsonDeserializer<Object> deser = provider.findValueDeserializer(config, type, property); + return deser; + } + + /* + /********************************************************** + /* Helper methods for sub-classes, problem reporting + /********************************************************** + */ + + /** + * Method called to deal with a property that did not map to a known + * Bean property. Method can deal with the problem as it sees fit (ignore, + * throw exception); but if it does return, it has to skip the matching + * Json content parser has. + *<p> + * NOTE: method signature was changed in version 1.5; explicit JsonParser + * <b>must</b> be passed since it may be something other than what + * context has. Prior versions did not include the first parameter. + * + * @param jp Parser that points to value of the unknown property + * @param ctxt Context for deserialization; allows access to the parser, + * error reporting functionality + * @param instanceOrClass Instance that is being populated by this + * deserializer, or if not known, Class that would be instantiated. + * If null, will assume type is what {@link #getValueClass} returns. + * @param propName Name of the property that can not be mapped + */ + protected void handleUnknownProperty(JsonParser jp, DeserializationContext ctxt, Object instanceOrClass, String propName) + throws IOException, JsonProcessingException + { + if (instanceOrClass == null) { + instanceOrClass = getValueClass(); + } + // Maybe we have configured handler(s) to take care of it? + if (ctxt.handleUnknownProperty(jp, this, instanceOrClass, propName)) { + return; + } + // Nope, not handled. Potentially that's a problem... + reportUnknownProperty(ctxt, instanceOrClass, propName); + + /* If we get this far, need to skip now; we point to first token of + * value (START_xxx for structured, or the value token for others) + */ + jp.skipChildren(); + } + + protected void reportUnknownProperty(DeserializationContext ctxt, + Object instanceOrClass, String fieldName) + throws IOException, JsonProcessingException + { + // throw exception if that's what we are expected to do + if (ctxt.isEnabled(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES)) { + throw ctxt.unknownFieldException(instanceOrClass, fieldName); + } + // ... or if not, just ignore + } + + + /* + /********************************************************** + /* Then one intermediate base class for things that have + /* both primitive and wrapper types + /********************************************************** + */ + + protected abstract static class PrimitiveOrWrapperDeserializer<T> + extends StdScalarDeserializer<T> + { + final T _nullValue; + + protected PrimitiveOrWrapperDeserializer(Class<T> vc, T nvl) + { + super(vc); + _nullValue = nvl; + } + + @Override + public final T getNullValue() { + return _nullValue; + } + } + + /* + /********************************************************** + /* Then primitive/wrapper types + /********************************************************** + */ + + @JacksonStdImpl + public final static class BooleanDeserializer + extends PrimitiveOrWrapperDeserializer<Boolean> + { + public BooleanDeserializer(Class<Boolean> cls, Boolean nvl) + { + super(cls, nvl); + } + + @Override + public Boolean deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + return _parseBoolean(jp, ctxt); + } + + // 1.6: since we can never have type info ("natural type"; String, Boolean, Integer, Double): + // (is it an error to even call this version?) + @Override + public Boolean deserializeWithType(JsonParser jp, DeserializationContext ctxt, + TypeDeserializer typeDeserializer) + throws IOException, JsonProcessingException + { + return _parseBoolean(jp, ctxt); + } + } + + @JacksonStdImpl + public final static class ByteDeserializer + extends PrimitiveOrWrapperDeserializer<Byte> + { + public ByteDeserializer(Class<Byte> cls, Byte nvl) + { + super(cls, nvl); + } + + @Override + public Byte deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + return _parseByte(jp, ctxt); + } + } + + @JacksonStdImpl + public final static class ShortDeserializer + extends PrimitiveOrWrapperDeserializer<Short> + { + public ShortDeserializer(Class<Short> cls, Short nvl) + { + super(cls, nvl); + } + + @Override + public Short deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + return _parseShort(jp, ctxt); + } + } + + @JacksonStdImpl + public final static class CharacterDeserializer + extends PrimitiveOrWrapperDeserializer<Character> + { + public CharacterDeserializer(Class<Character> cls, Character nvl) + { + super(cls, nvl); + } + + @Override + public Character deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + JsonToken t = jp.getCurrentToken(); + int value; + + if (t == JsonToken.VALUE_NUMBER_INT) { // ok iff ascii value + value = jp.getIntValue(); + if (value >= 0 && value <= 0xFFFF) { + return Character.valueOf((char) value); + } + } else if (t == JsonToken.VALUE_STRING) { // this is the usual type + // But does it have to be exactly one char? + String text = jp.getText(); + if (text.length() == 1) { + return Character.valueOf(text.charAt(0)); + } + // actually, empty should become null? + if (text.length() == 0) { + return (Character) getEmptyValue(); + } + } + throw ctxt.mappingException(_valueClass, t); + } + } + + @JacksonStdImpl + public final static class IntegerDeserializer + extends PrimitiveOrWrapperDeserializer<Integer> + { + public IntegerDeserializer(Class<Integer> cls, Integer nvl) + { + super(cls, nvl); + } + + @Override + public Integer deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + return _parseInteger(jp, ctxt); + } + + // 1.6: since we can never have type info ("natural type"; String, Boolean, Integer, Double): + // (is it an error to even call this version?) + @Override + public Integer deserializeWithType(JsonParser jp, DeserializationContext ctxt, + TypeDeserializer typeDeserializer) + throws IOException, JsonProcessingException + { + return _parseInteger(jp, ctxt); + } + } + + @JacksonStdImpl + public final static class LongDeserializer + extends PrimitiveOrWrapperDeserializer<Long> + { + public LongDeserializer(Class<Long> cls, Long nvl) + { + super(cls, nvl); + } + + @Override + public Long deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + return _parseLong(jp, ctxt); + } + } + + @JacksonStdImpl + public final static class FloatDeserializer + extends PrimitiveOrWrapperDeserializer<Float> + { + public FloatDeserializer(Class<Float> cls, Float nvl) + { + super(cls, nvl); + } + + @Override + public Float deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + /* 22-Jan-2009, tatu: Bounds/range checks would be tricky + * here, so let's not bother even trying... + */ + return _parseFloat(jp, ctxt); + } + } + + @JacksonStdImpl + public final static class DoubleDeserializer + extends PrimitiveOrWrapperDeserializer<Double> + { + public DoubleDeserializer(Class<Double> cls, Double nvl) + { + super(cls, nvl); + } + + @Override + public Double deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + return _parseDouble(jp, ctxt); + } + + // 1.6: since we can never have type info ("natural type"; String, Boolean, Integer, Double): + // (is it an error to even call this version?) + @Override + public Double deserializeWithType(JsonParser jp, DeserializationContext ctxt, + TypeDeserializer typeDeserializer) + throws IOException, JsonProcessingException + { + return _parseDouble(jp, ctxt); + } + } + + /** + * For type <code>Number.class</code>, we can just rely on type + * mappings that plain {@link JsonParser#getNumberValue} returns. + *<p> + * Since 1.5, there is one additional complication: some numeric + * types (specifically, int/Integer and double/Double) are "non-typed"; + * meaning that they will NEVER be output with type information. + * But other numeric types may need such type information. + * This is why {@link #deserializeWithType} must be overridden. + */ + @JacksonStdImpl + public final static class NumberDeserializer + extends StdScalarDeserializer<Number> + { + public NumberDeserializer() { super(Number.class); } + + @Override + public Number deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + JsonToken t = jp.getCurrentToken(); + if (t == JsonToken.VALUE_NUMBER_INT) { + if (ctxt.isEnabled(DeserializationConfig.Feature.USE_BIG_INTEGER_FOR_INTS)) { + return jp.getBigIntegerValue(); + } + return jp.getNumberValue(); + } else if (t == JsonToken.VALUE_NUMBER_FLOAT) { + /* [JACKSON-72]: need to allow overriding the behavior + * regarding which type to use + */ + if (ctxt.isEnabled(DeserializationConfig.Feature.USE_BIG_DECIMAL_FOR_FLOATS)) { + return jp.getDecimalValue(); + } + return Double.valueOf(jp.getDoubleValue()); + } + + /* Textual values are more difficult... not parsing itself, but figuring + * out 'minimal' type to use + */ + if (t == JsonToken.VALUE_STRING) { // let's do implicit re-parse + String text = jp.getText().trim(); + try { + if (text.indexOf('.') >= 0) { // floating point + // as per [JACKSON-72]: + if (ctxt.isEnabled(DeserializationConfig.Feature.USE_BIG_DECIMAL_FOR_FLOATS)) { + return new BigDecimal(text); + } + return new Double(text); + } + // as per [JACKSON-100]: + if (ctxt.isEnabled(DeserializationConfig.Feature.USE_BIG_INTEGER_FOR_INTS)) { + return new BigInteger(text); + } + long value = Long.parseLong(text); + if (value <= Integer.MAX_VALUE && value >= Integer.MIN_VALUE) { + return Integer.valueOf((int) value); + } + return Long.valueOf(value); + } catch (IllegalArgumentException iae) { + throw ctxt.weirdStringException(_valueClass, "not a valid number"); + } + } + // Otherwise, no can do: + throw ctxt.mappingException(_valueClass, t); + } + + /** + * As mentioned in class Javadoc, there is additional complexity in + * handling potentially mixed type information here. Because of this, + * we must actually check for "raw" integers and doubles first, before + * calling type deserializer. + */ + @Override + public Object deserializeWithType(JsonParser jp, DeserializationContext ctxt, + TypeDeserializer typeDeserializer) + throws IOException, JsonProcessingException + { + switch (jp.getCurrentToken()) { + case VALUE_NUMBER_INT: + case VALUE_NUMBER_FLOAT: + case VALUE_STRING: + // can not point to type information: hence must be non-typed (int/double) + return deserialize(jp, ctxt); + } + return typeDeserializer.deserializeTypedFromScalar(jp, ctxt); + } + } + + /* + /********************************************************** + /* And then bit more complicated (but non-structured) number + /* types + /********************************************************** + */ + + @JacksonStdImpl + public static class BigDecimalDeserializer + extends StdScalarDeserializer<BigDecimal> + { + public BigDecimalDeserializer() { super(BigDecimal.class); } + + @Override + public BigDecimal deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + JsonToken t = jp.getCurrentToken(); + if (t == JsonToken.VALUE_NUMBER_INT || t == JsonToken.VALUE_NUMBER_FLOAT) { + return jp.getDecimalValue(); + } + // String is ok too, can easily convert + if (t == JsonToken.VALUE_STRING) { // let's do implicit re-parse + String text = jp.getText().trim(); + if (text.length() == 0) { + return null; + } + try { + return new BigDecimal(text); + } catch (IllegalArgumentException iae) { + throw ctxt.weirdStringException(_valueClass, "not a valid representation"); + } + } + // Otherwise, no can do: + throw ctxt.mappingException(_valueClass, t); + } + } + + /** + * This is bit trickier to implement efficiently, while avoiding + * overflow problems. + */ + @JacksonStdImpl + public static class BigIntegerDeserializer + extends StdScalarDeserializer<BigInteger> + { + public BigIntegerDeserializer() { super(BigInteger.class); } + + @Override + public BigInteger deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + JsonToken t = jp.getCurrentToken(); + String text; + + if (t == JsonToken.VALUE_NUMBER_INT) { + switch (jp.getNumberType()) { + case INT: + case LONG: + return BigInteger.valueOf(jp.getLongValue()); + } + } else if (t == JsonToken.VALUE_NUMBER_FLOAT) { + /* Whether to fail if there's non-integer part? + * Could do by calling BigDecimal.toBigIntegerExact() + */ + return jp.getDecimalValue().toBigInteger(); + } else if (t != JsonToken.VALUE_STRING) { // let's do implicit re-parse + // String is ok too, can easily convert; otherwise, no can do: + throw ctxt.mappingException(_valueClass, t); + } + text = jp.getText().trim(); + if (text.length() == 0) { + return null; + } + try { + return new BigInteger(text); + } catch (IllegalArgumentException iae) { + throw ctxt.weirdStringException(_valueClass, "not a valid representation"); + } + } + } + + /* + /**************************************************** + /* Then trickier things: Date/Calendar types + /**************************************************** + */ + + /** + * Compared to plain old {@link java.util.Date}, SQL version is easier + * to deal with: mostly because it is more limited. + */ + public static class SqlDateDeserializer + extends StdScalarDeserializer<java.sql.Date> + { + public SqlDateDeserializer() { super(java.sql.Date.class); } + + @Override + public java.sql.Date deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + Date d = _parseDate(jp, ctxt); + return (d == null) ? null : new java.sql.Date(d.getTime()); + } + } + + /* + /**************************************************** + /* And other oddities + /**************************************************** + */ + + public static class StackTraceElementDeserializer + extends StdScalarDeserializer<StackTraceElement> + { + public StackTraceElementDeserializer() { super(StackTraceElement.class); } + + @Override + public StackTraceElement deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + JsonToken t = jp.getCurrentToken(); + // Must get an Object + if (t == JsonToken.START_OBJECT) { + String className = "", methodName = "", fileName = ""; + int lineNumber = -1; + + while ((t = jp.nextValue()) != JsonToken.END_OBJECT) { + String propName = jp.getCurrentName(); + if ("className".equals(propName)) { + className = jp.getText(); + } else if ("fileName".equals(propName)) { + fileName = jp.getText(); + } else if ("lineNumber".equals(propName)) { + if (t.isNumeric()) { + lineNumber = jp.getIntValue(); + } else { + throw JsonMappingException.from(jp, "Non-numeric token ("+t+") for property 'lineNumber'"); + } + } else if ("methodName".equals(propName)) { + methodName = jp.getText(); + } else if ("nativeMethod".equals(propName)) { + // no setter, not passed via constructor: ignore + } else { + handleUnknownProperty(jp, ctxt, _valueClass, propName); + } + } + return new StackTraceElement(className, methodName, fileName, lineNumber); + } + throw ctxt.mappingException(_valueClass, t); + } + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/StdKeyDeserializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/StdKeyDeserializer.java new file mode 100644 index 0000000..7639b7c --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/StdKeyDeserializer.java
@@ -0,0 +1,341 @@ +package org.codehaus.jackson.map.deser.std; + +import java.io.IOException; +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.util.UUID; + +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.io.NumberInput; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.introspect.AnnotatedMethod; +import org.codehaus.jackson.map.util.ClassUtil; +import org.codehaus.jackson.map.util.EnumResolver; + +/** + * Base class for simple key deserializers. + * + * @since 1.9 (moved from 'org.codehaus.jackson.map.deser.StdKeyDeserializer') + */ +public abstract class StdKeyDeserializer + extends KeyDeserializer +{ + final protected Class<?> _keyClass; + + protected StdKeyDeserializer(Class<?> cls) { _keyClass = cls; } + + @Override + public final Object deserializeKey(String key, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + if (key == null) { // is this even legal call? + return null; + } + try { + Object result = _parse(key, ctxt); + if (result != null) { + return result; + } + } catch (Exception re) { + throw ctxt.weirdKeyException(_keyClass, key, "not a valid representation: "+re.getMessage()); + } + throw ctxt.weirdKeyException(_keyClass, key, "not a valid representation"); + } + + public Class<?> getKeyClass() { return _keyClass; } + + protected abstract Object _parse(String key, DeserializationContext ctxt) throws Exception; + + /* + /********************************************************** + /* Helper methods for sub-classes + /********************************************************** + */ + + protected int _parseInt(String key) throws IllegalArgumentException + { + return Integer.parseInt(key); + } + + protected long _parseLong(String key) throws IllegalArgumentException + { + return Long.parseLong(key); + } + + protected double _parseDouble(String key) throws IllegalArgumentException + { + return NumberInput.parseDouble(key); + } + + /* + /********************************************************** + /* First: the standard "String as String" deserializer + /********************************************************** + */ + + final static class StringKD extends StdKeyDeserializer + { + private final static StringKD sString = new StringKD(String.class); + private final static StringKD sObject = new StringKD(Object.class); + + private StringKD(Class<?> nominalType) { super(nominalType); } + + public static StringKD forType(Class<?> nominalType) + { + if (nominalType == String.class) { + return sString; + } + if (nominalType == Object.class) { + return sObject; + } + return new StringKD(nominalType); + } + + @Override + public String _parse(String key, DeserializationContext ctxt) throws JsonMappingException { + return key; + } + } + + /* + /********************************************************** + /* Key deserializer implementations; wrappers + /********************************************************** + */ + + final static class BoolKD extends StdKeyDeserializer + { + BoolKD() { super(Boolean.class); } + + @Override + public Boolean _parse(String key, DeserializationContext ctxt) throws JsonMappingException + { + if ("true".equals(key)) { + return Boolean.TRUE; + } + if ("false".equals(key)) { + return Boolean.FALSE; + } + throw ctxt.weirdKeyException(_keyClass, key, "value not 'true' or 'false'"); + } + } + + final static class ByteKD extends StdKeyDeserializer + { + ByteKD() { super(Byte.class); } + + @Override + public Byte _parse(String key, DeserializationContext ctxt) throws JsonMappingException + { + int value = _parseInt(key); + // as per [JACKSON-804], allow range up to 255, inclusive + if (value < Byte.MIN_VALUE || value > 255) { + throw ctxt.weirdKeyException(_keyClass, key, "overflow, value can not be represented as 8-bit value"); + } + return Byte.valueOf((byte) value); + } + } + + final static class ShortKD extends StdKeyDeserializer + { + ShortKD() { super(Integer.class); } + + @Override + public Short _parse(String key, DeserializationContext ctxt) throws JsonMappingException + { + int value = _parseInt(key); + if (value < Short.MIN_VALUE || value > Short.MAX_VALUE) { + throw ctxt.weirdKeyException(_keyClass, key, "overflow, value can not be represented as 16-bit value"); + } + return Short.valueOf((short) value); + } + } + + /** + * Dealing with Characters is bit trickier: let's assume it must be a String, and that + * Unicode numeric value is never used. + */ + final static class CharKD extends StdKeyDeserializer + { + CharKD() { super(Character.class); } + + @Override + public Character _parse(String key, DeserializationContext ctxt) throws JsonMappingException + { + if (key.length() == 1) { + return Character.valueOf(key.charAt(0)); + } + throw ctxt.weirdKeyException(_keyClass, key, "can only convert 1-character Strings"); + } + } + + final static class IntKD extends StdKeyDeserializer + { + IntKD() { super(Integer.class); } + + @Override + public Integer _parse(String key, DeserializationContext ctxt) throws JsonMappingException + { + return _parseInt(key); + } + } + + final static class LongKD extends StdKeyDeserializer + { + LongKD() { super(Long.class); } + + @Override + public Long _parse(String key, DeserializationContext ctxt) throws JsonMappingException + { + return _parseLong(key); + } + } + + final static class DoubleKD extends StdKeyDeserializer + { + DoubleKD() { super(Double.class); } + + @Override + public Double _parse(String key, DeserializationContext ctxt) throws JsonMappingException + { + return _parseDouble(key); + } + } + + final static class FloatKD extends StdKeyDeserializer + { + FloatKD() { super(Float.class); } + + @Override + public Float _parse(String key, DeserializationContext ctxt) throws JsonMappingException + { + /* 22-Jan-2009, tatu: Bounds/range checks would be tricky + * here, so let's not bother even trying... + */ + return Float.valueOf((float) _parseDouble(key)); + } + } + + /* + /********************************************************** + /* Key deserializer implementations; other + /********************************************************** + */ + + final static class EnumKD extends StdKeyDeserializer + { + protected final EnumResolver<?> _resolver; + + protected final AnnotatedMethod _factory; + + protected EnumKD(EnumResolver<?> er, AnnotatedMethod factory) { + super(er.getEnumClass()); + _resolver = er; + _factory = factory; + } + + @Override + public Object _parse(String key, DeserializationContext ctxt) throws JsonMappingException + { + if (_factory != null) { + try { + return _factory.call1(key); + } catch (Exception e) { + ClassUtil.unwrapAndThrowAsIAE(e); + } + } + Enum<?> e = _resolver.findEnum(key); + if (e == null) { + throw ctxt.weirdKeyException(_keyClass, key, "not one of values for Enum class"); + } + return e; + } + } + + /** + * Key deserializer that calls a single-string-arg constructor + * to instantiate desired key type. + */ + final static class StringCtorKeyDeserializer extends StdKeyDeserializer + { + protected final Constructor<?> _ctor; + + public StringCtorKeyDeserializer(Constructor<?> ctor) { + super(ctor.getDeclaringClass()); + _ctor = ctor; + } + + @Override + public Object _parse(String key, DeserializationContext ctxt) throws Exception + { + return _ctor.newInstance(key); + } + } + + /** + * Key deserializer that calls a static no-args factory method + * to instantiate desired key type. + */ + final static class StringFactoryKeyDeserializer extends StdKeyDeserializer + { + final Method _factoryMethod; + + public StringFactoryKeyDeserializer(Method fm) { + super(fm.getDeclaringClass()); + _factoryMethod = fm; + } + + @Override + public Object _parse(String key, DeserializationContext ctxt) throws Exception + { + return _factoryMethod.invoke(null, key); + } + } + + // as per [JACKSON-657] + final static class DateKD extends StdKeyDeserializer + { + protected DateKD() { + super(java.util.Date.class); + } + + @Override + public java.util.Date _parse(String key, DeserializationContext ctxt) + throws IllegalArgumentException, JsonMappingException + { + return ctxt.parseDate(key); + } + } + + // as per [JACKSON-657] + final static class CalendarKD extends StdKeyDeserializer + { + protected CalendarKD() { + super(java.util.Calendar.class); + } + + @Override + public java.util.Calendar _parse(String key, DeserializationContext ctxt) + throws IllegalArgumentException, JsonMappingException + { + java.util.Date date = ctxt.parseDate(key); + return (date == null) ? null : ctxt.constructCalendar(date); + } + } + + // as per [JACKSON-726] + final static class UuidKD extends StdKeyDeserializer + { + protected UuidKD() { + super(UUID.class); + } + + @Override + public UUID _parse(String key, DeserializationContext ctxt) + throws IllegalArgumentException, JsonMappingException + { + return UUID.fromString(key); + } + } +} +
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/StdKeyDeserializers.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/StdKeyDeserializers.java new file mode 100644 index 0000000..a121925 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/StdKeyDeserializers.java
@@ -0,0 +1,108 @@ +package org.codehaus.jackson.map.deser.std; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.util.*; + +import org.codehaus.jackson.map.DeserializationConfig; +import org.codehaus.jackson.map.KeyDeserializer; +import org.codehaus.jackson.map.type.*; +import org.codehaus.jackson.map.introspect.AnnotatedMethod; +import org.codehaus.jackson.map.introspect.BasicBeanDescription; +import org.codehaus.jackson.map.util.ClassUtil; +import org.codehaus.jackson.map.util.EnumResolver; +import org.codehaus.jackson.type.JavaType; + +/** + * Helper class used to contain simple/well-known key deserializers. + * Following kinds of Objects can be handled currently: + *<ul> + * <li>Primitive wrappers</li> + * <li>Enums (usually not needed, since EnumMap doesn't call us)</li> + * <li>Anything with constructor that takes a single String arg + * (if not explicitly @JsonIgnore'd)</li> + * <li>Anything with 'static T valueOf(String)' factory method + * (if not explicitly @JsonIgnore'd)</li> + *</ul> + */ +public class StdKeyDeserializers +{ + protected final HashMap<JavaType, KeyDeserializer> _keyDeserializers = new HashMap<JavaType, KeyDeserializer>(); + + protected StdKeyDeserializers() + { + add(new StdKeyDeserializer.BoolKD()); + add(new StdKeyDeserializer.ByteKD()); + add(new StdKeyDeserializer.CharKD()); + add(new StdKeyDeserializer.ShortKD()); + add(new StdKeyDeserializer.IntKD()); + add(new StdKeyDeserializer.LongKD()); + add(new StdKeyDeserializer.FloatKD()); + add(new StdKeyDeserializer.DoubleKD()); + add(new StdKeyDeserializer.DateKD()); + add(new StdKeyDeserializer.CalendarKD()); + add(new StdKeyDeserializer.UuidKD()); + } + + private void add(StdKeyDeserializer kdeser) + { + Class<?> keyClass = kdeser.getKeyClass(); + /* As with other cases involving primitive types, we can use + * default TypeFactory ok, even if it's not our first choice: + */ + _keyDeserializers.put(TypeFactory.defaultInstance().uncheckedSimpleType(keyClass), kdeser); + } + + public static HashMap<JavaType, KeyDeserializer> constructAll() + { + return new StdKeyDeserializers()._keyDeserializers; + } + + /* + /********************************************************** + /* Factory methods + /********************************************************** + */ + + public static KeyDeserializer constructStringKeyDeserializer(DeserializationConfig config, JavaType type) + { + return StdKeyDeserializer.StringKD.forType(type.getClass()); + } + + public static KeyDeserializer constructEnumKeyDeserializer(EnumResolver<?> enumResolver) { + return new StdKeyDeserializer.EnumKD(enumResolver, null); + } + + public static KeyDeserializer constructEnumKeyDeserializer(EnumResolver<?> enumResolver, + AnnotatedMethod factory) { + return new StdKeyDeserializer.EnumKD(enumResolver, factory); + } + + public static KeyDeserializer findStringBasedKeyDeserializer(DeserializationConfig config, JavaType type) + { + /* We don't need full deserialization information, just need to + * know creators. + */ + BasicBeanDescription beanDesc = config.introspect(type); + // Ok, so: can we find T(String) constructor? + Constructor<?> ctor = beanDesc.findSingleArgConstructor(String.class); + if (ctor != null) { + if (config.isEnabled(DeserializationConfig.Feature.CAN_OVERRIDE_ACCESS_MODIFIERS)) { + ClassUtil.checkAndFixAccess(ctor); + } + return new StdKeyDeserializer.StringCtorKeyDeserializer(ctor); + } + /* or if not, "static T valueOf(String)" (or equivalent marked + * with @JsonCreator annotation?) + */ + Method m = beanDesc.findFactoryMethod(String.class); + if (m != null){ + if (config.isEnabled(DeserializationConfig.Feature.CAN_OVERRIDE_ACCESS_MODIFIERS)) { + ClassUtil.checkAndFixAccess(m); + } + return new StdKeyDeserializer.StringFactoryKeyDeserializer(m); + } + // nope, no such luck... + return null; + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/StdScalarDeserializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/StdScalarDeserializer.java new file mode 100644 index 0000000..42e013e --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/StdScalarDeserializer.java
@@ -0,0 +1,34 @@ +package org.codehaus.jackson.map.deser.std; + +import java.io.IOException; + +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.map.DeserializationContext; +import org.codehaus.jackson.map.TypeDeserializer; +import org.codehaus.jackson.type.JavaType; + +/** + * Base class for deserializers that handle types that are serialized + * as JSON scalars (non-structured, i.e. non-Object, non-Array, values). + * + * @since 1.9 (moved from higher-level package) + */ +public abstract class StdScalarDeserializer<T> extends StdDeserializer<T> +{ + protected StdScalarDeserializer(Class<?> vc) { + super(vc); + } + + protected StdScalarDeserializer(JavaType valueType) { + super(valueType); + } + + @Override + public Object deserializeWithType(JsonParser jp, DeserializationContext ctxt, + TypeDeserializer typeDeserializer) + throws IOException, JsonProcessingException + { + return typeDeserializer.deserializeTypedFromScalar(jp, ctxt); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/StdValueInstantiator.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/StdValueInstantiator.java new file mode 100644 index 0000000..f75406e --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/StdValueInstantiator.java
@@ -0,0 +1,392 @@ +package org.codehaus.jackson.map.deser.std; + +import java.io.IOException; + +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.map.DeserializationConfig; +import org.codehaus.jackson.map.JsonMappingException; +import org.codehaus.jackson.map.deser.SettableBeanProperty; +import org.codehaus.jackson.map.deser.ValueInstantiator; +import org.codehaus.jackson.map.deser.impl.CreatorProperty; +import org.codehaus.jackson.map.introspect.AnnotatedWithParams; +import org.codehaus.jackson.type.JavaType; + +/** + * Basic {@link ValueInstantiator} implementation, which only + * supports use of default constructor. Sub-types can add + * support for alternate construction methods, such as using + * argument-taking constructors or static factory methods. + * + * @since 1.9.0 + */ +public class StdValueInstantiator + extends ValueInstantiator +{ + /** + * Type of values that are instantiated; used + * for error reporting purposes. + */ + protected final String _valueTypeDesc; + + /** + * Are we allowed to convert empty Strings to null objects? + */ + protected final boolean _cfgEmptyStringsAsObjects; + + // // // Default (no-args) construction + + /** + * Default (no-argument) constructor to use for instantiation + * (with {@link #createUsingDefault}) + */ + protected AnnotatedWithParams _defaultCreator; + + // // // With-args (property-based) construction + + protected CreatorProperty[] _constructorArguments; + protected AnnotatedWithParams _withArgsCreator; + + // // // Delegate construction + + protected JavaType _delegateType; + protected AnnotatedWithParams _delegateCreator; + + // // // Scalar construction + + protected AnnotatedWithParams _fromStringCreator; + protected AnnotatedWithParams _fromIntCreator; + protected AnnotatedWithParams _fromLongCreator; + protected AnnotatedWithParams _fromDoubleCreator; + protected AnnotatedWithParams _fromBooleanCreator; + + /* + /********************************************************** + /* Life-cycle + /********************************************************** + */ + + public StdValueInstantiator(DeserializationConfig config, Class<?> valueType) + { + _cfgEmptyStringsAsObjects = (config == null) ? false + : config.isEnabled(DeserializationConfig.Feature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT); + _valueTypeDesc = (valueType == null) ? "UNKNOWN TYPE" : valueType.getName(); + } + + public StdValueInstantiator(DeserializationConfig config, JavaType valueType) + { + _cfgEmptyStringsAsObjects = (config == null) ? false + : config.isEnabled(DeserializationConfig.Feature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT); + _valueTypeDesc = (valueType == null) ? "UNKNOWN TYPE" : valueType.toString(); + } + + /** + * Copy-constructor that sub-classes can use when creating new instances + * by fluent-style construction + */ + protected StdValueInstantiator(StdValueInstantiator src) + { + _cfgEmptyStringsAsObjects = src._cfgEmptyStringsAsObjects; + _valueTypeDesc = src._valueTypeDesc; + + _defaultCreator = src._defaultCreator; + + _constructorArguments = src._constructorArguments; + _withArgsCreator = src._withArgsCreator; + + _delegateType = src._delegateType; + _delegateCreator = src._delegateCreator; + + _fromStringCreator = src._fromStringCreator; + _fromIntCreator = src._fromIntCreator; + _fromLongCreator = src._fromLongCreator; + _fromDoubleCreator = src._fromDoubleCreator; + _fromBooleanCreator = src._fromBooleanCreator; + } + + /** + * Method for setting properties related to instantiating values + * from JSON Object. We will choose basically only one approach (out of possible + * three), and clear other properties + */ + public void configureFromObjectSettings(AnnotatedWithParams defaultCreator, + AnnotatedWithParams delegateCreator, JavaType delegateType, + AnnotatedWithParams withArgsCreator, CreatorProperty[] constructorArgs) + { + _defaultCreator = defaultCreator; + _delegateCreator = delegateCreator; + _delegateType = delegateType; + _withArgsCreator = withArgsCreator; + _constructorArguments = constructorArgs; + } + + public void configureFromStringCreator(AnnotatedWithParams creator) { + _fromStringCreator = creator; + } + + public void configureFromIntCreator(AnnotatedWithParams creator) { + _fromIntCreator = creator; + } + + public void configureFromLongCreator(AnnotatedWithParams creator) { + _fromLongCreator = creator; + } + + public void configureFromDoubleCreator(AnnotatedWithParams creator) { + _fromDoubleCreator = creator; + } + + public void configureFromBooleanCreator(AnnotatedWithParams creator) { + _fromBooleanCreator = creator; + } + + /* + /********************************************************** + /* Public API implementation; metadata + /********************************************************** + */ + + @Override + public String getValueTypeDesc() { + return _valueTypeDesc; + } + + @Override + public boolean canCreateFromString() { + return (_fromStringCreator != null); + } + + @Override + public boolean canCreateFromInt() { + return (_fromIntCreator != null); + } + + @Override + public boolean canCreateFromLong() { + return (_fromLongCreator != null); + } + + @Override + public boolean canCreateFromDouble() { + return (_fromDoubleCreator != null); + } + + @Override + public boolean canCreateFromBoolean() { + return (_fromBooleanCreator != null); + } + + @Override + public boolean canCreateUsingDefault() { + return (_defaultCreator != null); + } + + @Override + public boolean canCreateFromObjectWith() { + return (_withArgsCreator != null); + } + + @Override + public JavaType getDelegateType() { + return _delegateType; + } + + @Override + public SettableBeanProperty[] getFromObjectArguments() { + return _constructorArguments; + } + + /* + /********************************************************** + /* Public API implementation; instantiation from JSON Object + /********************************************************** + */ + + @Override + public Object createUsingDefault() + throws IOException, JsonProcessingException + { + if (_defaultCreator == null) { // sanity-check; caller should check + throw new IllegalStateException("No default constructor for "+getValueTypeDesc()); + } + try { + return _defaultCreator.call(); + } catch (ExceptionInInitializerError e) { + throw wrapException(e); + } catch (Exception e) { + throw wrapException(e); + } + } + + @Override + public Object createFromObjectWith(Object[] args) + throws IOException, JsonProcessingException + { + if (_withArgsCreator == null) { // sanity-check; caller should check + throw new IllegalStateException("No with-args constructor for "+getValueTypeDesc()); + } + try { + return _withArgsCreator.call(args); + } catch (ExceptionInInitializerError e) { + throw wrapException(e); + } catch (Exception e) { + throw wrapException(e); + } + } + + @Override + public Object createUsingDelegate(Object delegate) + throws IOException, JsonProcessingException + { + if (_delegateCreator == null) { // sanity-check; caller should check + throw new IllegalStateException("No delegate constructor for "+getValueTypeDesc()); + } + try { + return _delegateCreator.call1(delegate); + } catch (ExceptionInInitializerError e) { + throw wrapException(e); + } catch (Exception e) { + throw wrapException(e); + } + } + + /* + /********************************************************** + /* Public API implementation; instantiation from JSON scalars + /********************************************************** + */ + + @Override + public Object createFromString(String value) throws IOException, JsonProcessingException + { + if (_fromStringCreator != null) { + try { + return _fromStringCreator.call1(value); + } catch (Exception e) { + throw wrapException(e); + } + } + return _createFromStringFallbacks(value); + } + + @Override + public Object createFromInt(int value) throws IOException, JsonProcessingException + { + try { + // First: "native" int methods work best: + if (_fromIntCreator != null) { + return _fromIntCreator.call1(Integer.valueOf(value)); + } + // but if not, can do widening conversion + if (_fromLongCreator != null) { + return _fromLongCreator.call1(Long.valueOf(value)); + } + } catch (Exception e) { + throw wrapException(e); + } + throw new JsonMappingException("Can not instantiate value of type "+getValueTypeDesc() + +" from JSON integral number; no single-int-arg constructor/factory method"); + } + + @Override + public Object createFromLong(long value) throws IOException, JsonProcessingException + { + try { + if (_fromLongCreator != null) { + return _fromLongCreator.call1(Long.valueOf(value)); + } + } catch (Exception e) { + throw wrapException(e); + } + throw new JsonMappingException("Can not instantiate value of type "+getValueTypeDesc() + +" from JSON long integral number; no single-long-arg constructor/factory method"); + } + + @Override + public Object createFromDouble(double value) throws IOException, JsonProcessingException + { + try { + if (_fromDoubleCreator != null) { + return _fromDoubleCreator.call1(Double.valueOf(value)); + } + } catch (Exception e) { + throw wrapException(e); + } + throw new JsonMappingException("Can not instantiate value of type "+getValueTypeDesc() + +" from JSON floating-point number; no one-double/Double-arg constructor/factory method"); + } + + @Override + public Object createFromBoolean(boolean value) throws IOException, JsonProcessingException + { + try { + if (_fromBooleanCreator != null) { + return _fromBooleanCreator.call1(Boolean.valueOf(value)); + } + } catch (Exception e) { + throw wrapException(e); + } + throw new JsonMappingException("Can not instantiate value of type "+getValueTypeDesc() + +" from JSON boolean value; no single-boolean/Boolean-arg constructor/factory method"); + } + + /* + /********************************************************** + /* Extended API: configuration mutators, accessors + /********************************************************** + */ + + @Override + public AnnotatedWithParams getDelegateCreator() { + return _delegateCreator; + } + + @Override + public AnnotatedWithParams getDefaultCreator() { + return _defaultCreator; + } + + @Override + public AnnotatedWithParams getWithArgsCreator() { + return _withArgsCreator; + } + + /* + /********************************************************** + /* Internal methods + /********************************************************** + */ + + protected Object _createFromStringFallbacks(String value) throws IOException, JsonProcessingException + { + /* 28-Sep-2011, tatu: Ok this is not clean at all; but since there are legacy + * systems that expect conversions in some cases, let's just add a minimal + * patch (note: same could conceivably be used for numbers too). + */ + if (_fromBooleanCreator != null) { + String str = value.trim(); + if ("true".equals(str)) { + return createFromBoolean(true); + } + if ("false".equals(str)) { + return createFromBoolean(false); + } + } + + // and finally, empty Strings might be accepted as null Object... + if (_cfgEmptyStringsAsObjects && value.length() == 0) { + return null; + } + throw new JsonMappingException("Can not instantiate value of type "+getValueTypeDesc() + +" from JSON String; no single-String constructor/factory method"); + } + + protected JsonMappingException wrapException(Throwable t) + { + while (t.getCause() != null) { + t = t.getCause(); + } + return new JsonMappingException("Instantiation of "+getValueTypeDesc()+" value failed: "+t.getMessage(), t); + } +} + +
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/StringCollectionDeserializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/StringCollectionDeserializer.java new file mode 100644 index 0000000..021ac96 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/StringCollectionDeserializer.java
@@ -0,0 +1,227 @@ +package org.codehaus.jackson.map.deser.std; + +import java.io.IOException; +import java.util.Collection; + +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.JsonToken; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.JacksonStdImpl; +import org.codehaus.jackson.map.deser.ValueInstantiator; +import org.codehaus.jackson.map.introspect.AnnotatedWithParams; +import org.codehaus.jackson.type.JavaType; + +/** + * @since 1.9 (moved from higher-level package) + */ +@JacksonStdImpl +public final class StringCollectionDeserializer + extends ContainerDeserializerBase<Collection<String>> + implements ResolvableDeserializer +{ + // // Configuration + + protected final JavaType _collectionType; + + /** + * Value deserializer; needed even if it is the standard String + * deserializer + */ + protected final JsonDeserializer<String> _valueDeserializer; + + /** + * Flag that indicates whether value deserializer is the standard + * Jackson-provided one; if it is, we can use more efficient + * handling. + */ + protected final boolean _isDefaultDeserializer; + + // // Instance construction settings: + + /** + * @since 1.9 + */ + protected final ValueInstantiator _valueInstantiator; + + /** + * Deserializer that is used iff delegate-based creator is + * to be used for deserializing from JSON Object. + */ + protected JsonDeserializer<Object> _delegateDeserializer; + + // NOTE: no PropertyBasedCreator, as JSON Arrays have no properties + + /* + /********************************************************** + /* Life-cycle + /********************************************************** + */ + + @SuppressWarnings("unchecked") + public StringCollectionDeserializer(JavaType collectionType, JsonDeserializer<?> valueDeser, + ValueInstantiator valueInstantiator) + { + super(collectionType.getRawClass()); + _collectionType = collectionType; + _valueDeserializer = (JsonDeserializer<String>) valueDeser; + _valueInstantiator = valueInstantiator; + _isDefaultDeserializer = isDefaultSerializer(valueDeser); + } + + /** + * Copy-constructor that can be used by sub-classes to allow + * copy-on-write styling copying of settings of an existing instance. + * + * @since 1.9 + */ + protected StringCollectionDeserializer(StringCollectionDeserializer src) + { + super(src._valueClass); + _collectionType = src._collectionType; + _valueDeserializer = src._valueDeserializer; + _valueInstantiator = src._valueInstantiator; + _isDefaultDeserializer = src._isDefaultDeserializer; + } + + /* + /********************************************************** + /* Validation, post-processing (ResolvableDeserializer) + /********************************************************** + */ + + /** + * Method called to finalize setup of this deserializer, + * after deserializer itself has been registered. This + * is needed to handle recursive and transitive dependencies. + */ + @Override + public void resolve(DeserializationConfig config, DeserializerProvider provider) + throws JsonMappingException + { + // May need to resolve types for delegate-based creators: + AnnotatedWithParams delegateCreator = _valueInstantiator.getDelegateCreator(); + if (delegateCreator != null) { + JavaType delegateType = _valueInstantiator.getDelegateType(); + // Need to create a temporary property to allow contextual deserializers: + BeanProperty.Std property = new BeanProperty.Std(null, + delegateType, null, delegateCreator); + _delegateDeserializer = findDeserializer(config, provider, delegateType, property); + } + } + + /* + /********************************************************** + /* ContainerDeserializerBase API + /********************************************************** + */ + + @Override + public JavaType getContentType() { + return _collectionType.getContentType(); + } + + @SuppressWarnings("unchecked") + @Override + public JsonDeserializer<Object> getContentDeserializer() { + JsonDeserializer<?> deser = _valueDeserializer; + return (JsonDeserializer<Object>) deser; + } + + /* + /********************************************************** + /* JsonDeserializer API + /********************************************************** + */ + + @SuppressWarnings("unchecked") + @Override + public Collection<String> deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + if (_delegateDeserializer != null) { + return (Collection<String>) _valueInstantiator.createUsingDelegate(_delegateDeserializer.deserialize(jp, ctxt)); + } + final Collection<String> result = (Collection<String>) _valueInstantiator.createUsingDefault(); + return deserialize(jp, ctxt, result); + } + + @Override + public Collection<String> deserialize(JsonParser jp, DeserializationContext ctxt, + Collection<String> result) + throws IOException, JsonProcessingException + { + // Ok: must point to START_ARRAY + if (!jp.isExpectedStartArrayToken()) { + return handleNonArray(jp, ctxt, result); + } + + if (!_isDefaultDeserializer) { + return deserializeUsingCustom(jp, ctxt, result); + } + JsonToken t; + + while ((t = jp.nextToken()) != JsonToken.END_ARRAY) { + result.add((t == JsonToken.VALUE_NULL) ? null : jp.getText()); + } + return result; + } + + private Collection<String> deserializeUsingCustom(JsonParser jp, DeserializationContext ctxt, + Collection<String> result) + throws IOException, JsonProcessingException + { + JsonToken t; + final JsonDeserializer<String> deser = _valueDeserializer; + + while ((t = jp.nextToken()) != JsonToken.END_ARRAY) { + String value; + + if (t == JsonToken.VALUE_NULL) { + value = null; + } else { + value = deser.deserialize(jp, ctxt); + } + result.add(value); + } + return result; + } + + @Override + public Object deserializeWithType(JsonParser jp, DeserializationContext ctxt, + TypeDeserializer typeDeserializer) + throws IOException, JsonProcessingException + { + // In future could check current token... for now this should be enough: + return typeDeserializer.deserializeTypedFromArray(jp, ctxt); + } + + /** + * Helper method called when current token is no START_ARRAY. Will either + * throw an exception, or try to handle value as if member of implicit + * array, depending on configuration. + */ + private final Collection<String> handleNonArray(JsonParser jp, DeserializationContext ctxt, + Collection<String> result) + throws IOException, JsonProcessingException + { + // [JACKSON-526]: implicit arrays from single values? + if (!ctxt.isEnabled(DeserializationConfig.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY)) { + throw ctxt.mappingException(_collectionType.getRawClass()); + } + // Strings are one of "native" (intrinsic) types, so there's never type deserializer involved + JsonDeserializer<String> valueDes = _valueDeserializer; + JsonToken t = jp.getCurrentToken(); + + String value; + + if (t == JsonToken.VALUE_NULL) { + value = null; + } else { + value = (valueDes == null) ? jp.getText() : valueDes.deserialize(jp, ctxt); + } + result.add(value); + return result; + } + +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/StringDeserializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/StringDeserializer.java new file mode 100644 index 0000000..46c47ed --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/StringDeserializer.java
@@ -0,0 +1,55 @@ +package org.codehaus.jackson.map.deser.std; + +import java.io.IOException; + +import org.codehaus.jackson.Base64Variants; +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.JsonToken; +import org.codehaus.jackson.map.DeserializationContext; +import org.codehaus.jackson.map.TypeDeserializer; +import org.codehaus.jackson.map.annotate.JacksonStdImpl; + +@JacksonStdImpl +public class StringDeserializer + extends StdScalarDeserializer<String> +{ + public StringDeserializer() { super(String.class); } + + @Override + public String deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + JsonToken curr = jp.getCurrentToken(); + // Usually should just get string value: + if (curr == JsonToken.VALUE_STRING) { + return jp.getText(); + } + // [JACKSON-330]: need to gracefully handle byte[] data, as base64 + if (curr == JsonToken.VALUE_EMBEDDED_OBJECT) { + Object ob = jp.getEmbeddedObject(); + if (ob == null) { + return null; + } + if (ob instanceof byte[]) { + return Base64Variants.getDefaultVariant().encode((byte[]) ob, false); + } + // otherwise, try conversion using toString()... + return ob.toString(); + } + // Can deserialize any scalar value, but not markers + if (curr.isScalarValue()) { + return jp.getText(); + } + throw ctxt.mappingException(_valueClass, curr); + } + + // 1.6: since we can never have type info ("natural type"; String, Boolean, Integer, Double): + // (is it an error to even call this version?) + @Override + public String deserializeWithType(JsonParser jp, DeserializationContext ctxt, + TypeDeserializer typeDeserializer) + throws IOException, JsonProcessingException + { + return deserialize(jp, ctxt); + }}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/ThrowableDeserializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/ThrowableDeserializer.java new file mode 100644 index 0000000..b177b2e --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/ThrowableDeserializer.java
@@ -0,0 +1,164 @@ +package org.codehaus.jackson.map.deser.std; + +import java.io.IOException; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.deser.BeanDeserializer; +import org.codehaus.jackson.map.deser.SettableBeanProperty; + +/** + * Deserializer that builds on basic {@link BeanDeserializer} but + * override some aspects like instance construction. + *<p> + * Note that this deserializer was significantly changed in Jackson 1.7 + * (due to massive changes in {@link BeanDeserializer}). + * + * @since 1.9 (renamed from 'org.codehaus.jackson.map.deser.ThrowableDeserializer') + */ +public class ThrowableDeserializer + extends BeanDeserializer +{ + protected final static String PROP_NAME_MESSAGE = "message"; + + /* + /************************************************************ + /* Construction + /************************************************************ + */ + + public ThrowableDeserializer(BeanDeserializer baseDeserializer) + { + super(baseDeserializer); + } + + /** + * Alternative constructor used when creating "unwrapping" deserializers + * + * @since 1.9 + */ + protected ThrowableDeserializer(BeanDeserializer src, boolean ignoreAllUnknown) + { + super(src, ignoreAllUnknown); + } + + @Override + public JsonDeserializer<Object> unwrappingDeserializer() + { + if (getClass() != ThrowableDeserializer.class) { + return this; + } + /* main thing really is to just enforce ignoring of unknown + * properties; since there may be multiple unwrapped values + * and properties for all may be interleaved... + */ + return new ThrowableDeserializer(this, true); + } + + + /* + /************************************************************ + /* Overridden methods + /************************************************************ + */ + + @Override + public Object deserializeFromObject(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + // 30-Sep-2010, tatu: Need to allow use of @JsonCreator, so: + if (_propertyBasedCreator != null) { // proper @JsonCreator + return _deserializeUsingPropertyBased(jp, ctxt); + } + if (_delegateDeserializer != null) { + return _valueInstantiator.createUsingDelegate(_delegateDeserializer.deserialize(jp, ctxt)); + } + if (_beanType.isAbstract()) { // for good measure, check this too + throw JsonMappingException.from(jp, "Can not instantiate abstract type "+_beanType + +" (need to add/enable type information?)"); + } + boolean hasStringCreator = _valueInstantiator.canCreateFromString(); + boolean hasDefaultCtor = _valueInstantiator.canCreateUsingDefault(); + // and finally, verify we do have single-String arg constructor (if no @JsonCreator) + if (!hasStringCreator && !hasDefaultCtor) { + throw new JsonMappingException("Can not deserialize Throwable of type "+_beanType + +" without having a default contructor, a single-String-arg constructor; or explicit @JsonCreator"); + } + + Object throwable = null; + Object[] pending = null; + int pendingIx = 0; + + for (; jp.getCurrentToken() != JsonToken.END_OBJECT; jp.nextToken()) { + String propName = jp.getCurrentName(); + SettableBeanProperty prop = _beanProperties.find(propName); + jp.nextToken(); // to point to field value + + if (prop != null) { // normal case + if (throwable != null) { + prop.deserializeAndSet(jp, ctxt, throwable); + continue; + } + // nope; need to defer + if (pending == null) { + int len = _beanProperties.size(); + pending = new Object[len + len]; + } + pending[pendingIx++] = prop; + pending[pendingIx++] = prop.deserialize(jp, ctxt); + continue; + } + + // Maybe it's "message"? + if (PROP_NAME_MESSAGE.equals(propName)) { + if (hasStringCreator) { + throwable = _valueInstantiator.createFromString(jp.getText()); + // any pending values? + if (pending != null) { + for (int i = 0, len = pendingIx; i < len; i += 2) { + prop = (SettableBeanProperty)pending[i]; + prop.set(throwable, pending[i+1]); + } + pending = null; + } + continue; + } + } + /* As per [JACKSON-313], things marked as ignorable should not be + * passed to any setter + */ + if (_ignorableProps != null && _ignorableProps.contains(propName)) { + jp.skipChildren(); + continue; + } + if (_anySetter != null) { + _anySetter.deserializeAndSet(jp, ctxt, throwable, propName); + continue; + } + // Unknown: let's call handler method + handleUnknownProperty(jp, ctxt, throwable, propName); + } + // Sanity check: did we find "message"? + if (throwable == null) { + /* 15-Oct-2010, tatu: Can't assume missing message is an error, since it may be + * suppressed during serialization, as per [JACKSON-388]. + * + * Should probably allow use of default constructor, too... + */ + //throw new JsonMappingException("No 'message' property found: could not deserialize "+_beanType); + if (hasStringCreator) { + throwable = _valueInstantiator.createFromString(null); + } else { + throwable = _valueInstantiator.createUsingDefault(); + } + // any pending values? + if (pending != null) { + for (int i = 0, len = pendingIx; i < len; i += 2) { + SettableBeanProperty prop = (SettableBeanProperty)pending[i]; + prop.set(throwable, pending[i+1]); + } + } + } + return throwable; + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/TimestampDeserializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/TimestampDeserializer.java new file mode 100644 index 0000000..26649d1 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/TimestampDeserializer.java
@@ -0,0 +1,30 @@ +package org.codehaus.jackson.map.deser.std; + +import java.io.IOException; +import java.sql.Timestamp; + +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.map.DeserializationContext; + +/** + * Simple deserializer for handling {@link java.sql.Timestamp} values. + *<p> + * One way to customize Timestamp formats accepted is to override method + * {@link DeserializationContext#parseDate} that this basic + * deserializer calls. + * + * @since 1.9 (moved from higher-level package) + */ +public class TimestampDeserializer + extends StdScalarDeserializer<Timestamp> +{ + public TimestampDeserializer() { super(Timestamp.class); } + + @Override + public java.sql.Timestamp deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + return new Timestamp(_parseDate(jp, ctxt).getTime()); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/TokenBufferDeserializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/TokenBufferDeserializer.java new file mode 100644 index 0000000..f97cc63 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/TokenBufferDeserializer.java
@@ -0,0 +1,36 @@ +package org.codehaus.jackson.map.deser.std; + +import java.io.IOException; + +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.map.DeserializationContext; +import org.codehaus.jackson.map.annotate.JacksonStdImpl; +import org.codehaus.jackson.util.TokenBuffer; + +/** + * We also want to directly support deserialization of + * {@link TokenBuffer}. + *<p> + * Note that we use scalar deserializer base just because we claim + * to be of scalar for type information inclusion purposes; actual + * underlying content can be of any (Object, Array, scalar) type. + * + * @since 1.9 (moved from higher-level package) + */ +@JacksonStdImpl +public class TokenBufferDeserializer + extends StdScalarDeserializer<TokenBuffer> +{ + public TokenBufferDeserializer() { super(TokenBuffer.class); } + + @Override + public TokenBuffer deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + TokenBuffer tb = new TokenBuffer(jp.getCodec()); + // quite simple, given that TokenBuffer is a JsonGenerator: + tb.copyCurrentStructure(jp); + return tb; + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/UntypedObjectDeserializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/UntypedObjectDeserializer.java new file mode 100644 index 0000000..c621969 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/UntypedObjectDeserializer.java
@@ -0,0 +1,248 @@ +package org.codehaus.jackson.map.deser.std; + +import java.io.IOException; +import java.util.*; + +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.JsonToken; +import org.codehaus.jackson.map.DeserializationConfig; +import org.codehaus.jackson.map.DeserializationContext; +import org.codehaus.jackson.map.TypeDeserializer; +import org.codehaus.jackson.map.annotate.JacksonStdImpl; +import org.codehaus.jackson.map.util.ObjectBuffer; + +/** + * Deserializer implementation that is used if it is necessary to bind content of + * "unknown" type; something declared as basic {@link java.lang.Object} + * (either explicitly, or due to type erasure). + * If so, "natural" mapping is used to convert JSON values to their natural + * Java object matches: JSON arrays to Java {@link java.util.List}s (or, if configured, + * Object[]), JSON objects to {@link java.util.Map}s, numbers to + * {@link java.lang.Number}s, booleans to {@link java.lang.Boolean}s and + * strings to {@link java.lang.String} (and nulls to nulls). + * + * @since 1.9 (moved from higher-level package) + */ +@JacksonStdImpl +public class UntypedObjectDeserializer + extends StdDeserializer<Object> +{ + private final static Object[] NO_OBJECTS = new Object[0]; + + public UntypedObjectDeserializer() { super(Object.class); } + + /* + /********************************************************** + /* Deserializer API + /********************************************************** + */ + + @Override + public Object deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + switch (jp.getCurrentToken()) { + case START_OBJECT: + return mapObject(jp, ctxt); + case END_OBJECT: // invalid + break; + case START_ARRAY: + return mapArray(jp, ctxt); + case END_ARRAY: // invalid + break; + case FIELD_NAME: + return mapObject(jp, ctxt); + case VALUE_EMBEDDED_OBJECT: + return jp.getEmbeddedObject(); + case VALUE_STRING: + return jp.getText(); + + case VALUE_NUMBER_INT: + /* [JACKSON-100]: caller may want to get all integral values + * returned as BigInteger, for consistency + */ + if (ctxt.isEnabled(DeserializationConfig.Feature.USE_BIG_INTEGER_FOR_INTS)) { + return jp.getBigIntegerValue(); // should be optimal, whatever it is + } + return jp.getNumberValue(); // should be optimal, whatever it is + + case VALUE_NUMBER_FLOAT: + /* [JACKSON-72]: need to allow overriding the behavior regarding + * which type to use + */ + if (ctxt.isEnabled(DeserializationConfig.Feature.USE_BIG_DECIMAL_FOR_FLOATS)) { + return jp.getDecimalValue(); + } + return Double.valueOf(jp.getDoubleValue()); + + case VALUE_TRUE: + return Boolean.TRUE; + case VALUE_FALSE: + return Boolean.FALSE; + + case VALUE_NULL: // should not get this but... + return null; + + } + + throw ctxt.mappingException(Object.class); + } + + @Override + public Object deserializeWithType(JsonParser jp, DeserializationContext ctxt, + TypeDeserializer typeDeserializer) + throws IOException, JsonProcessingException + { + JsonToken t = jp.getCurrentToken(); + switch (t) { + // First: does it look like we had type id wrapping of some kind? + case START_ARRAY: + case START_OBJECT: + case FIELD_NAME: + /* Output can be as JSON Object, Array or scalar: no way to know + * a this point: + */ + return typeDeserializer.deserializeTypedFromAny(jp, ctxt); + + /* Otherwise we probably got a "native" type (ones that map + * naturally and thus do not need or use type ids) + */ + case VALUE_STRING: + return jp.getText(); + + case VALUE_NUMBER_INT: + // For [JACKSON-100], see above: + if (ctxt.isEnabled(DeserializationConfig.Feature.USE_BIG_INTEGER_FOR_INTS)) { + return jp.getBigIntegerValue(); + } + return jp.getIntValue(); + + case VALUE_NUMBER_FLOAT: + // For [JACKSON-72], see above + if (ctxt.isEnabled(DeserializationConfig.Feature.USE_BIG_DECIMAL_FOR_FLOATS)) { + return jp.getDecimalValue(); + } + return Double.valueOf(jp.getDoubleValue()); + + case VALUE_TRUE: + return Boolean.TRUE; + case VALUE_FALSE: + return Boolean.FALSE; + case VALUE_EMBEDDED_OBJECT: + return jp.getEmbeddedObject(); + + case VALUE_NULL: // should not get this far really but... + return null; + } + throw ctxt.mappingException(Object.class); + } + + /* + /********************************************************** + /* Internal methods + /********************************************************** + */ + + /** + * Method called to map a JSON Array into a Java value. + */ + protected Object mapArray(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + if (ctxt.isEnabled(DeserializationConfig.Feature.USE_JAVA_ARRAY_FOR_JSON_ARRAY)) { + return mapArrayToArray(jp, ctxt); + } + // Minor optimization to handle small lists (default size for ArrayList is 10) + if (jp.nextToken() == JsonToken.END_ARRAY) { + return new ArrayList<Object>(4); + } + ObjectBuffer buffer = ctxt.leaseObjectBuffer(); + Object[] values = buffer.resetAndStart(); + int ptr = 0; + int totalSize = 0; + do { + Object value = deserialize(jp, ctxt); + ++totalSize; + if (ptr >= values.length) { + values = buffer.appendCompletedChunk(values); + ptr = 0; + } + values[ptr++] = value; + } while (jp.nextToken() != JsonToken.END_ARRAY); + // let's create almost full array, with 1/8 slack + ArrayList<Object> result = new ArrayList<Object>(totalSize + (totalSize >> 3) + 1); + buffer.completeAndClearBuffer(values, ptr, result); + return result; + } + + /** + * Method called to map a JSON Object into a Java value. + */ + protected Object mapObject(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + JsonToken t = jp.getCurrentToken(); + if (t == JsonToken.START_OBJECT) { + t = jp.nextToken(); + } + // 1.6: minor optimization; let's handle 1 and 2 entry cases separately + if (t != JsonToken.FIELD_NAME) { // and empty one too + // empty map might work; but caller may want to modify... so better just give small modifiable + return new LinkedHashMap<String,Object>(4); + } + String field1 = jp.getText(); + jp.nextToken(); + Object value1 = deserialize(jp, ctxt); + if (jp.nextToken() != JsonToken.FIELD_NAME) { // single entry; but we want modifiable + LinkedHashMap<String, Object> result = new LinkedHashMap<String, Object>(4); + result.put(field1, value1); + return result; + } + String field2 = jp.getText(); + jp.nextToken(); + Object value2 = deserialize(jp, ctxt); + if (jp.nextToken() != JsonToken.FIELD_NAME) { + LinkedHashMap<String, Object> result = new LinkedHashMap<String, Object>(4); + result.put(field1, value1); + result.put(field2, value2); + return result; + } + // And then the general case; default map size is 16 + LinkedHashMap<String, Object> result = new LinkedHashMap<String, Object>(); + result.put(field1, value1); + result.put(field2, value2); + do { + String fieldName = jp.getText(); + jp.nextToken(); + result.put(fieldName, deserialize(jp, ctxt)); + } while (jp.nextToken() != JsonToken.END_OBJECT); + return result; + } + + /** + * Method called to map a JSON Array into a Java Object array (Object[]). + * + * @since 1.9 + */ + protected Object[] mapArrayToArray(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + // Minor optimization to handle small lists (default size for ArrayList is 10) + if (jp.nextToken() == JsonToken.END_ARRAY) { + return NO_OBJECTS; + } + ObjectBuffer buffer = ctxt.leaseObjectBuffer(); + Object[] values = buffer.resetAndStart(); + int ptr = 0; + do { + Object value = deserialize(jp, ctxt); + if (ptr >= values.length) { + values = buffer.appendCompletedChunk(values); + ptr = 0; + } + values[ptr++] = value; + } while (jp.nextToken() != JsonToken.END_ARRAY); + return buffer.completeAndClearBuffer(values, ptr); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/package-info.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/package-info.java new file mode 100644 index 0000000..fe98b72 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/deser/std/package-info.java
@@ -0,0 +1,15 @@ +/** + * Contains public standard implementations of abstraction that + * Jackson uses. This means that they are not merely implementation + * details, but part of semi-public interface where project + * tries to maintain backwards compatibility at higher level + * than for 'impl' types (although less so than with fully + * public interfaces). + *<p> + * Note that since this package was only added relatively late + * in development cycle, not all classes that belong here are + * included. Plan is to move more classes over time. + * + * @since 1.9 + */ +package org.codehaus.jackson.map.deser.std;
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/exc/UnrecognizedPropertyException.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/exc/UnrecognizedPropertyException.java new file mode 100644 index 0000000..c907572 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/exc/UnrecognizedPropertyException.java
@@ -0,0 +1,75 @@ +package org.codehaus.jackson.map.exc; + +import org.codehaus.jackson.JsonLocation; +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.map.JsonMappingException; + +/** + * Specialized {@link JsonMappingException} sub-class specifically used + * to indicate problems due to encountering a JSON property that could + * not be mapped to an Object property (via getter, constructor argument + * or field). + * + * @since 1.6 + */ +public class UnrecognizedPropertyException + extends JsonMappingException +{ + private static final long serialVersionUID = 1L; + + /** + * Class that does not contain mapping for the unrecognized property. + */ + protected final Class<?> _referringClass; + + /** + *<p> + * Note: redundant information since it is also included in the + * reference path. + */ + protected final String _unrecognizedPropertyName; + + public UnrecognizedPropertyException(String msg, JsonLocation loc, + Class<?> referringClass, String propName) + { + + super(msg, loc); + _referringClass = referringClass; + _unrecognizedPropertyName = propName; + } + + public static UnrecognizedPropertyException from(JsonParser jp, Object fromObjectOrClass, String propertyName) + { + if (fromObjectOrClass == null) { + throw new IllegalArgumentException(); + } + Class<?> ref; + if (fromObjectOrClass instanceof Class<?>) { + ref = (Class<?>) fromObjectOrClass; + } else { + ref = fromObjectOrClass.getClass(); + } + String msg = "Unrecognized field \""+propertyName+"\" (Class "+ref.getName()+"), not marked as ignorable"; + UnrecognizedPropertyException e = new UnrecognizedPropertyException(msg, jp.getCurrentLocation(), ref, propertyName); + // but let's also ensure path includes this last (missing) segment + e.prependPath(fromObjectOrClass, propertyName); + return e; + } + + /** + * Method for accessing type (class) that is missing definition to allow + * binding of the unrecognized property. + */ + public Class<?> getReferringClass() { + return _referringClass; + } + + /** + * Convenience method for accessing logical property name that could + * not be mapped. Note that it is the last path reference in the + * underlying path. + */ + public String getUnrecognizedPropertyName() { + return _unrecognizedPropertyName; + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ext/CoreXMLDeserializers.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ext/CoreXMLDeserializers.java new file mode 100644 index 0000000..713eddb --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ext/CoreXMLDeserializers.java
@@ -0,0 +1,114 @@ +package org.codehaus.jackson.map.ext; + +import java.io.IOException; +import java.util.*; + +import javax.xml.datatype.DatatypeConfigurationException; +import javax.xml.datatype.DatatypeFactory; +import javax.xml.datatype.Duration; +import javax.xml.datatype.XMLGregorianCalendar; +import javax.xml.namespace.QName; + +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.map.DeserializationContext; +import org.codehaus.jackson.map.deser.std.StdDeserializer; +import org.codehaus.jackson.map.deser.std.FromStringDeserializer; +import org.codehaus.jackson.map.deser.std.StdScalarDeserializer; +import org.codehaus.jackson.map.util.Provider; + +/** + * Container deserializers that handle "core" XML types: ones included in standard + * JDK 1.5. Types are directly needed by JAXB, and are thus supported within core + * mapper package, not in "xc" package. + * + * @since 1.3 + */ +public class CoreXMLDeserializers + implements Provider<StdDeserializer<?>> +{ + /** + * Data type factories are thread-safe after instantiation (and + * configuration, if any); and since instantion (esp. implementation + * introspection) can be expensive we better reuse the instance. + */ + final static DatatypeFactory _dataTypeFactory; + static { + try { + _dataTypeFactory = DatatypeFactory.newInstance(); + } catch (DatatypeConfigurationException e) { + throw new RuntimeException(e); + } + } + + /* + /********************************************************** + /* Provider implementation + /********************************************************** + */ + + /** + * Method called by {@link org.codehaus.jackson.map.deser.BasicDeserializerFactory} + * to register deserializers this class provides. + */ + @Override + public Collection<StdDeserializer<?>> provide() + { + return Arrays.asList(new StdDeserializer<?>[] { + new DurationDeserializer() + ,new GregorianCalendarDeserializer() + ,new QNameDeserializer() + }); + } + + /* + /********************************************************** + /* Concrete deserializers + /********************************************************** + */ + + public static class DurationDeserializer + extends FromStringDeserializer<Duration> + { + public DurationDeserializer() { super(Duration.class); } + + @Override + protected Duration _deserialize(String value, DeserializationContext ctxt) + throws IllegalArgumentException + { + return _dataTypeFactory.newDuration(value); + } + } + + public static class GregorianCalendarDeserializer + extends StdScalarDeserializer<XMLGregorianCalendar> + { + public GregorianCalendarDeserializer() { super(XMLGregorianCalendar.class); } + + @Override + public XMLGregorianCalendar deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + Date d = _parseDate(jp, ctxt); + if (d == null) { + return null; + } + GregorianCalendar calendar = new GregorianCalendar(); + calendar.setTime(d); + return _dataTypeFactory.newXMLGregorianCalendar(calendar); + } + } + + public static class QNameDeserializer + extends FromStringDeserializer<QName> + { + public QNameDeserializer() { super(QName.class); } + + @Override + protected QName _deserialize(String value, DeserializationContext ctxt) + throws IllegalArgumentException + { + return QName.valueOf(value); + } + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ext/CoreXMLSerializers.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ext/CoreXMLSerializers.java new file mode 100644 index 0000000..b650985 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ext/CoreXMLSerializers.java
@@ -0,0 +1,72 @@ +package org.codehaus.jackson.map.ext; + +import java.io.IOException; +import java.lang.reflect.Type; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import javax.xml.datatype.Duration; +import javax.xml.datatype.XMLGregorianCalendar; +import javax.xml.namespace.QName; + +import org.codehaus.jackson.JsonGenerationException; +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.map.JsonMappingException; +import org.codehaus.jackson.map.JsonSerializer; +import org.codehaus.jackson.map.SerializerProvider; +import org.codehaus.jackson.map.ser.std.CalendarSerializer; +import org.codehaus.jackson.map.ser.std.SerializerBase; +import org.codehaus.jackson.map.ser.std.ToStringSerializer; +import org.codehaus.jackson.map.util.Provider; + +/** + * Provider for serializers of XML types that are part of full JDK 1.5, but + * that some alleged 1.5 platforms are missing (Android, GAE). + * And for this reason these are added using more dynamic mechanism. + *<p> + * Note: since many of classes defined are abstract, caller must take + * care not to just use straight equivalency check but rather consider + * subclassing as well. + * + * @since 1.4 + */ +public class CoreXMLSerializers + implements Provider<Map.Entry<Class<?>,JsonSerializer<?>>> +{ + final static HashMap<Class<?>,JsonSerializer<?>> _serializers = new HashMap<Class<?>,JsonSerializer<?>>(); + /** + * We will construct instances statically, during class loading, to try to + * make things fail-fast, i.e. to catch problems as soon as possible. + */ + static { + ToStringSerializer tss = ToStringSerializer.instance; + _serializers.put(Duration.class, tss); + _serializers.put(XMLGregorianCalendar.class, new XMLGregorianCalendarSerializer()); + _serializers.put(QName.class, tss); + } + + @Override + public Collection<Map.Entry<Class<?>,JsonSerializer<?>>> provide() { + return _serializers.entrySet(); + } + + public static class XMLGregorianCalendarSerializer extends SerializerBase<XMLGregorianCalendar> + { + public XMLGregorianCalendarSerializer() { + super(XMLGregorianCalendar.class); + } + + @Override + public void serialize(XMLGregorianCalendar value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException { + CalendarSerializer.instance.serialize(value.toGregorianCalendar(), jgen, provider); + } + + @Override + public JsonNode getSchema(SerializerProvider provider, Type typeHint) throws JsonMappingException { + return CalendarSerializer.instance.getSchema(provider, typeHint); + } + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ext/DOMDeserializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ext/DOMDeserializer.java new file mode 100644 index 0000000..50e6016 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ext/DOMDeserializer.java
@@ -0,0 +1,64 @@ +package org.codehaus.jackson.map.ext; + +import java.io.StringReader; + +import javax.xml.parsers.DocumentBuilderFactory; + +import org.codehaus.jackson.map.DeserializationContext; +import org.codehaus.jackson.map.deser.std.FromStringDeserializer; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.xml.sax.InputSource; + +/** + * Base for serializers that allows parsing DOM Documents from JSON Strings. + * Nominal type can be either {@link org.w3c.dom.Node} or + * {@link org.w3c.dom.Document}. + */ +public abstract class DOMDeserializer<T> extends FromStringDeserializer<T> +{ + final static DocumentBuilderFactory _parserFactory; + static { + _parserFactory = DocumentBuilderFactory.newInstance(); + // yup, only cave men do XML without recognizing namespaces... + _parserFactory.setNamespaceAware(true); + } + + protected DOMDeserializer(Class<T> cls) { super(cls); } + + @Override + public abstract T _deserialize(String value, DeserializationContext ctxt); + + protected final Document parse(String value) throws IllegalArgumentException + { + try { + return _parserFactory.newDocumentBuilder().parse(new InputSource(new StringReader(value))); + } catch (Exception e) { + throw new IllegalArgumentException("Failed to parse JSON String as XML: "+e.getMessage(), e); + } + } + + /* + /********************************************************** + /* Concrete deserializers + /********************************************************** + */ + + public static class NodeDeserializer extends DOMDeserializer<Node> + { + public NodeDeserializer() { super(Node.class); } + @Override + public Node _deserialize(String value, DeserializationContext ctxt) throws IllegalArgumentException { + return parse(value); + } + } + + public static class DocumentDeserializer extends DOMDeserializer<Document> + { + public DocumentDeserializer() { super(Document.class); } + @Override + public Document _deserialize(String value, DeserializationContext ctxt) throws IllegalArgumentException { + return parse(value); + } + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ext/DOMSerializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ext/DOMSerializer.java new file mode 100644 index 0000000..17b75d0 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ext/DOMSerializer.java
@@ -0,0 +1,47 @@ +package org.codehaus.jackson.map.ext; + +import java.io.IOException; +import org.w3c.dom.Node; +import org.w3c.dom.bootstrap.DOMImplementationRegistry; +import org.w3c.dom.ls.DOMImplementationLS; +import org.w3c.dom.ls.LSSerializer; + +import org.codehaus.jackson.JsonGenerationException; +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.map.SerializerProvider; +import org.codehaus.jackson.map.ser.std.SerializerBase; + +public class DOMSerializer + extends SerializerBase<Node> +{ + protected final DOMImplementationLS _domImpl; + + public DOMSerializer() + { + super(Node.class); + DOMImplementationRegistry registry; + try { + registry = DOMImplementationRegistry.newInstance(); + } catch (Exception e) { + throw new IllegalStateException("Could not instantiate DOMImplementationRegistry: "+e.getMessage(), e); + } + _domImpl = (DOMImplementationLS)registry.getDOMImplementation("LS"); + } + + @Override + public void serialize(Node value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + if (_domImpl == null) throw new IllegalStateException("Could not find DOM LS"); + LSSerializer writer = _domImpl.createLSSerializer(); + jgen.writeString(writer.writeToString(value)); + } + + @Override + public JsonNode getSchema(SerializerProvider provider, java.lang.reflect.Type typeHint) + { + // Well... it is serialized as String + return createSchemaNode("string", true); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ext/JodaDeserializers.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ext/JodaDeserializers.java new file mode 100644 index 0000000..3d7d6a6 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ext/JodaDeserializers.java
@@ -0,0 +1,253 @@ +package org.codehaus.jackson.map.ext; + +import java.io.IOException; +import java.util.*; + +import org.joda.time.*; +import org.joda.time.format.DateTimeFormatter; +import org.joda.time.format.ISODateTimeFormat; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.deser.std.StdDeserializer; +import org.codehaus.jackson.map.deser.std.StdScalarDeserializer; +import org.codehaus.jackson.map.util.Provider; + +/** + * Provider for deserializers that handle some basic data types + * for <a href="http://joda-time.sourceforge.net/">Joda</a> date/time library. + * + * @since 1.4 + */ +public class JodaDeserializers + implements Provider<StdDeserializer<?>> +{ + @Override + public Collection<StdDeserializer<?>> provide() { + return Arrays.asList(new StdDeserializer<?>[] { + new DateTimeDeserializer<DateTime>(DateTime.class) + ,new DateTimeDeserializer<ReadableDateTime>(ReadableDateTime.class) + ,new DateTimeDeserializer<ReadableInstant>(ReadableInstant.class) + ,new LocalDateDeserializer() + ,new LocalDateTimeDeserializer() + ,new DateMidnightDeserializer() + ,new PeriodDeserializer() + }); + } + + /* + /********************************************************************* + /* Intermediate base classes + /********************************************************************* + */ + + abstract static class JodaDeserializer<T> extends StdScalarDeserializer<T> + { + final static DateTimeFormatter _localDateTimeFormat = ISODateTimeFormat.localDateOptionalTimeParser(); + + protected JodaDeserializer(Class<T> cls) { super(cls); } + + protected DateTime parseLocal(JsonParser jp) + throws IOException, JsonProcessingException + { + String str = jp.getText().trim(); + if (str.length() == 0) { // [JACKSON-360] + return null; + } + return _localDateTimeFormat.parseDateTime(str); + } + } + + /* + /********************************************************************* + /* Concrete deserializers + /********************************************************************* + */ + + /** + * Basic deserializer for {@link DateTime}. Accepts JSON String and Number + * values and passes those to single-argument constructor. + * Does not (yet?) support JSON object; support can be added if desired. + *<p> + * Since 1.6 this has been generic, to handle multiple related types, + * including super types of {@link DateTime} + */ + public static class DateTimeDeserializer<T extends ReadableInstant> + extends JodaDeserializer<T> + { + public DateTimeDeserializer(Class<T> cls) { super(cls); } + + @SuppressWarnings("unchecked") + @Override + public T deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + JsonToken t = jp.getCurrentToken(); + if (t == JsonToken.VALUE_NUMBER_INT) { + return (T) new DateTime(jp.getLongValue(), DateTimeZone.UTC); + } + if (t == JsonToken.VALUE_STRING) { + String str = jp.getText().trim(); + if (str.length() == 0) { // [JACKSON-360] + return null; + } + return (T) new DateTime(str, DateTimeZone.UTC); + } + throw ctxt.mappingException(getValueClass()); + } + } + + /** + * @since 1.5 + */ + public static class LocalDateDeserializer + extends JodaDeserializer<LocalDate> + { + public LocalDateDeserializer() { super(LocalDate.class); } + + @Override + public LocalDate deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + // We'll accept either long (timestamp) or array: + if (jp.isExpectedStartArrayToken()) { + jp.nextToken(); // VALUE_NUMBER_INT + int year = jp.getIntValue(); + jp.nextToken(); // VALUE_NUMBER_INT + int month = jp.getIntValue(); + jp.nextToken(); // VALUE_NUMBER_INT + int day = jp.getIntValue(); + if (jp.nextToken() != JsonToken.END_ARRAY) { + throw ctxt.wrongTokenException(jp, JsonToken.END_ARRAY, "after LocalDate ints"); + } + return new LocalDate(year, month, day); + } + switch (jp.getCurrentToken()) { + case VALUE_NUMBER_INT: + return new LocalDate(jp.getLongValue()); + case VALUE_STRING: + DateTime local = parseLocal(jp); + if (local == null) { + return null; + } + return local.toLocalDate(); + } + throw ctxt.wrongTokenException(jp, JsonToken.START_ARRAY, "expected JSON Array, String or Number"); + } + } + + /** + * @since 1.5 + */ + public static class LocalDateTimeDeserializer + extends JodaDeserializer<LocalDateTime> + { + public LocalDateTimeDeserializer() { super(LocalDateTime.class); } + + @Override + public LocalDateTime deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + // We'll accept either long (timestamp) or array: + if (jp.isExpectedStartArrayToken()) { + jp.nextToken(); // VALUE_NUMBER_INT + int year = jp.getIntValue(); + jp.nextToken(); // VALUE_NUMBER_INT + int month = jp.getIntValue(); + jp.nextToken(); // VALUE_NUMBER_INT + int day = jp.getIntValue(); + jp.nextToken(); // VALUE_NUMBER_INT + int hour = jp.getIntValue(); + jp.nextToken(); // VALUE_NUMBER_INT + int minute = jp.getIntValue(); + jp.nextToken(); // VALUE_NUMBER_INT + int second = jp.getIntValue(); + // let's leave milliseconds optional? + int millisecond = 0; + if (jp.nextToken() != JsonToken.END_ARRAY) { // VALUE_NUMBER_INT + millisecond = jp.getIntValue(); + jp.nextToken(); // END_ARRAY? + } + if (jp.getCurrentToken() != JsonToken.END_ARRAY) { + throw ctxt.wrongTokenException(jp, JsonToken.END_ARRAY, "after LocalDateTime ints"); + } + return new LocalDateTime(year, month, day, hour, minute, second, millisecond); + } + + switch (jp.getCurrentToken()) { + case VALUE_NUMBER_INT: + return new LocalDateTime(jp.getLongValue()); + case VALUE_STRING: + DateTime local = parseLocal(jp); + if (local == null) { + return null; + } + return local.toLocalDateTime(); + } + throw ctxt.wrongTokenException(jp, JsonToken.START_ARRAY, "expected JSON Array or Number"); + } + } + + /** + * @since 1.5 + */ + public static class DateMidnightDeserializer + extends JodaDeserializer<DateMidnight> + { + public DateMidnightDeserializer() { super(DateMidnight.class); } + + @Override + public DateMidnight deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + // We'll accept either long (timestamp) or array: + if (jp.isExpectedStartArrayToken()) { + jp.nextToken(); // VALUE_NUMBER_INT + int year = jp.getIntValue(); + jp.nextToken(); // VALUE_NUMBER_INT + int month = jp.getIntValue(); + jp.nextToken(); // VALUE_NUMBER_INT + int day = jp.getIntValue(); + if (jp.nextToken() != JsonToken.END_ARRAY) { + throw ctxt.wrongTokenException(jp, JsonToken.END_ARRAY, "after DateMidnight ints"); + } + return new DateMidnight(year, month, day); + } + switch (jp.getCurrentToken()) { + case VALUE_NUMBER_INT: + return new DateMidnight(jp.getLongValue()); + case VALUE_STRING: + DateTime local = parseLocal(jp); + if (local == null) { + return null; + } + return local.toDateMidnight(); + } + throw ctxt.wrongTokenException(jp, JsonToken.START_ARRAY, "expected JSON Array, Number or String"); + } + } + + /** + * @since 1.9.2 + */ + public static class PeriodDeserializer + extends JodaDeserializer<ReadablePeriod> + { + public PeriodDeserializer() { super(ReadablePeriod.class); } + + @Override + public ReadablePeriod deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + // TODO: perhaps support array of numbers... + //if (jp.isExpectedStartArrayToken()) { ] + switch (jp.getCurrentToken()) { + case VALUE_NUMBER_INT: // assume it's millisecond count + return new Period(jp.getLongValue()); + case VALUE_STRING: + return new Period(jp.getText()); + } + throw ctxt.wrongTokenException(jp, JsonToken.START_ARRAY, "expected JSON Number or String"); + } + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ext/JodaSerializers.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ext/JodaSerializers.java new file mode 100644 index 0000000..9b5a5ab --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ext/JodaSerializers.java
@@ -0,0 +1,203 @@ +package org.codehaus.jackson.map.ext; + +import java.io.IOException; +import java.util.*; + +import org.joda.time.*; +import org.joda.time.format.DateTimeFormatter; +import org.joda.time.format.ISODateTimeFormat; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.ser.std.SerializerBase; +import org.codehaus.jackson.map.ser.std.ToStringSerializer; +import org.codehaus.jackson.map.util.Provider; + +/** + * Provider for serializers that handle some basic data types + * for <a href="http://joda-time.sourceforge.net/">Joda</a> date/time library. + *<p> + * Since version 1.5, more types are supported. These types use slightly + * different approach to serialization than core date types: "timestamp" + * notation is implemented using JSON arrays, for improved readability. + * + * @since 1.4 + */ +public class JodaSerializers + implements Provider<Map.Entry<Class<?>,JsonSerializer<?>>> +{ + final static HashMap<Class<?>,JsonSerializer<?>> _serializers = new HashMap<Class<?>,JsonSerializer<?>>(); + static { + _serializers.put(DateTime.class, new DateTimeSerializer()); + _serializers.put(LocalDateTime.class, new LocalDateTimeSerializer()); + _serializers.put(LocalDate.class, new LocalDateSerializer()); + _serializers.put(DateMidnight.class, new DateMidnightSerializer()); + // [JACKSON-706]: + _serializers.put(Period.class, ToStringSerializer.instance); + } + + public JodaSerializers() { } + + @Override + public Collection<Map.Entry<Class<?>,JsonSerializer<?>>> provide() { + return _serializers.entrySet(); + } + + /* + /********************************************************** + /* Intermediate base classes + /********************************************************** + */ + + protected abstract static class JodaSerializer<T> extends SerializerBase<T> + { + final static DateTimeFormatter _localDateTimeFormat = ISODateTimeFormat.dateTime(); + final static DateTimeFormatter _localDateFormat = ISODateTimeFormat.date(); + + protected JodaSerializer(Class<T> cls) { super(cls); } + + protected String printLocalDateTime(ReadablePartial dateValue) + throws IOException, JsonProcessingException + { + return _localDateTimeFormat.print(dateValue); + } + + protected String printLocalDate(ReadablePartial dateValue) + throws IOException, JsonProcessingException + { + return _localDateFormat.print(dateValue); + } + + protected String printLocalDate(ReadableInstant dateValue) + throws IOException, JsonProcessingException + { + return _localDateFormat.print(dateValue); + } + } + + /* + /********************************************************** + /* Concrete serializers + /********************************************************** + */ + + public final static class DateTimeSerializer + extends JodaSerializer<DateTime> + { + public DateTimeSerializer() { super(DateTime.class); } + + @Override + public void serialize(DateTime value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + if (provider.isEnabled(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS)) { + jgen.writeNumber(value.getMillis()); + } else { + jgen.writeString(value.toString()); + } + } + + @Override + public JsonNode getSchema(SerializerProvider provider, java.lang.reflect.Type typeHint) + { + return createSchemaNode(provider.isEnabled(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS) + ? "number" : "string", true); + } + } + + /** + * + * @since 1.5 + */ + public final static class LocalDateTimeSerializer + extends JodaSerializer<LocalDateTime> + { + public LocalDateTimeSerializer() { super(LocalDateTime.class); } + + @Override + public void serialize(LocalDateTime dt, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + if (provider.isEnabled(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS)) { + // Timestamp here actually means an array of values + jgen.writeStartArray(); + jgen.writeNumber(dt.year().get()); + jgen.writeNumber(dt.monthOfYear().get()); + jgen.writeNumber(dt.dayOfMonth().get()); + jgen.writeNumber(dt.hourOfDay().get()); + jgen.writeNumber(dt.minuteOfHour().get()); + jgen.writeNumber(dt.secondOfMinute().get()); + jgen.writeNumber(dt.millisOfSecond().get()); + jgen.writeEndArray(); + } else { + jgen.writeString(printLocalDateTime(dt)); + } + } + + @Override + public JsonNode getSchema(SerializerProvider provider, java.lang.reflect.Type typeHint) + { + return createSchemaNode(provider.isEnabled(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS) + ? "array" : "string", true); + } + } + + public final static class LocalDateSerializer + extends JodaSerializer<LocalDate> + { + public LocalDateSerializer() { super(LocalDate.class); } + + @Override + public void serialize(LocalDate dt, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + if (provider.isEnabled(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS)) { + // Timestamp here actually means an array of values + jgen.writeStartArray(); + jgen.writeNumber(dt.year().get()); + jgen.writeNumber(dt.monthOfYear().get()); + jgen.writeNumber(dt.dayOfMonth().get()); + jgen.writeEndArray(); + } else { + jgen.writeString(printLocalDate(dt)); + } + } + + @Override + public JsonNode getSchema(SerializerProvider provider, java.lang.reflect.Type typeHint) + { + return createSchemaNode(provider.isEnabled(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS) + ? "array" : "string", true); + } + } + + public final static class DateMidnightSerializer + extends JodaSerializer<DateMidnight> + { + public DateMidnightSerializer() { super(DateMidnight.class); } + + @Override + public void serialize(DateMidnight dt, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + if (provider.isEnabled(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS)) { + // same as with other date-only values + jgen.writeStartArray(); + jgen.writeNumber(dt.year().get()); + jgen.writeNumber(dt.monthOfYear().get()); + jgen.writeNumber(dt.dayOfMonth().get()); + jgen.writeEndArray(); + } else { + jgen.writeString(printLocalDate(dt)); + } + } + + @Override + public JsonNode getSchema(SerializerProvider provider, java.lang.reflect.Type typeHint) + { + return createSchemaNode(provider.isEnabled(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS) + ? "array" : "string", true); + } + } + +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ext/OptionalHandlerFactory.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ext/OptionalHandlerFactory.java new file mode 100644 index 0000000..c7cf04d --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ext/OptionalHandlerFactory.java
@@ -0,0 +1,217 @@ +package org.codehaus.jackson.map.ext; + +import java.util.Collection; +import java.util.Map; + +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.deser.std.StdDeserializer; +import org.codehaus.jackson.map.util.Provider; +import org.codehaus.jackson.type.JavaType; + +/** + * Helper class used for isolating details of handling optional+external types (Joda datetime, + * javax.xml classes) from standard factories that offer them. + * + * @author tatu + * + * @since 1.6.1 + */ +public class OptionalHandlerFactory +{ + /* 1.6.1+ To make 2 main "optional" handler groups (javax.xml.stream, Joda date/time) + * more dynamic, we better only figure out handlers completely dynamically, if and + * when they are needed. To do this we need to assume package prefixes. + */ + + private final static String PACKAGE_PREFIX_JODA_DATETIME = "org.joda.time."; + private final static String PACKAGE_PREFIX_JAVAX_XML = "javax.xml."; + + private final static String SERIALIZERS_FOR_JODA_DATETIME = "org.codehaus.jackson.map.ext.JodaSerializers"; + private final static String SERIALIZERS_FOR_JAVAX_XML = "org.codehaus.jackson.map.ext.CoreXMLSerializers"; + private final static String DESERIALIZERS_FOR_JODA_DATETIME = "org.codehaus.jackson.map.ext.JodaDeserializers"; + private final static String DESERIALIZERS_FOR_JAVAX_XML = "org.codehaus.jackson.map.ext.CoreXMLDeserializers"; + + // Plus we also have a single serializer for DOM Node: + private final static String CLASS_NAME_DOM_NODE = "org.w3c.dom.Node"; + private final static String CLASS_NAME_DOM_DOCUMENT = "org.w3c.dom.Node"; + private final static String SERIALIZER_FOR_DOM_NODE = "org.codehaus.jackson.map.ext.DOMSerializer"; + private final static String DESERIALIZER_FOR_DOM_DOCUMENT = "org.codehaus.jackson.map.ext.DOMDeserializer$DocumentDeserializer"; + private final static String DESERIALIZER_FOR_DOM_NODE = "org.codehaus.jackson.map.ext.DOMDeserializer$NodeDeserializer"; + + public final static OptionalHandlerFactory instance = new OptionalHandlerFactory(); + + protected OptionalHandlerFactory() { } + + /* + /********************************************************** + /* Public API + /********************************************************** + */ + + public JsonSerializer<?> findSerializer(SerializationConfig config, JavaType type) +// BasicBeanDescription beanInfo, BeanProperty property) + { + Class<?> rawType = type.getRawClass(); + String className = rawType.getName(); + String factoryName; + + if (className.startsWith(PACKAGE_PREFIX_JODA_DATETIME)) { + factoryName = SERIALIZERS_FOR_JODA_DATETIME; + } else if (className.startsWith(PACKAGE_PREFIX_JAVAX_XML) + || hasSupertypeStartingWith(rawType, PACKAGE_PREFIX_JAVAX_XML)) { + factoryName = SERIALIZERS_FOR_JAVAX_XML; + } else if (doesImplement(rawType, CLASS_NAME_DOM_NODE)) { + return (JsonSerializer<?>) instantiate(SERIALIZER_FOR_DOM_NODE); + } else { + return null; + } + + Object ob = instantiate(factoryName); + if (ob == null) { // could warn, if we had logging system (j.u.l?) + return null; + } + @SuppressWarnings("unchecked") + Provider<Map.Entry<Class<?>,JsonSerializer<?>>> prov = (Provider<Map.Entry<Class<?>,JsonSerializer<?>>>) ob; + Collection<Map.Entry<Class<?>,JsonSerializer<?>>> entries = prov.provide(); + + // first, check for exact match (concrete) + for (Map.Entry<Class<?>,JsonSerializer<?>> entry : entries) { + if (rawType == entry.getKey()) { + return entry.getValue(); + } + } + // if no match, check super-type match + for (Map.Entry<Class<?>,JsonSerializer<?>> entry : entries) { + if (entry.getKey().isAssignableFrom(rawType)) { + return entry.getValue(); + } + } + // but maybe there's just no match to be found? + return null; + } + + public JsonDeserializer<?> findDeserializer(JavaType type, DeserializationConfig config, DeserializerProvider p) + { + Class<?> rawType = type.getRawClass(); + String className = rawType.getName(); + String factoryName; + + if (className.startsWith(PACKAGE_PREFIX_JODA_DATETIME)) { + factoryName = DESERIALIZERS_FOR_JODA_DATETIME; + } else if (className.startsWith(PACKAGE_PREFIX_JAVAX_XML) + || hasSupertypeStartingWith(rawType, PACKAGE_PREFIX_JAVAX_XML)) { + factoryName = DESERIALIZERS_FOR_JAVAX_XML; + } else if (doesImplement(rawType, CLASS_NAME_DOM_DOCUMENT)) { + return (JsonDeserializer<?>) instantiate(DESERIALIZER_FOR_DOM_DOCUMENT); + } else if (doesImplement(rawType, CLASS_NAME_DOM_NODE)) { + return (JsonDeserializer<?>) instantiate(DESERIALIZER_FOR_DOM_NODE); + } else { + return null; + } + Object ob = instantiate(factoryName); + if (ob == null) { // could warn, if we had logging system (j.u.l?) + return null; + } + @SuppressWarnings("unchecked") + Provider<StdDeserializer<?>> prov = (Provider<StdDeserializer<?>>) ob; + Collection<StdDeserializer<?>> entries = prov.provide(); + + // first, check for exact match (concrete) + for (StdDeserializer<?> deser : entries) { + if (rawType == deser.getValueClass()) { + return deser; + } + } + // if no match, check super-type match + for (StdDeserializer<?> deser : entries) { + if (deser.getValueClass().isAssignableFrom(rawType)) { + return deser; + } + } + // but maybe there's just no match to be found? + return null; + } + + /* + /********************************************************** + /* Internal helper methods + /********************************************************** + */ + + private Object instantiate(String className) + { + try { + return Class.forName(className).newInstance(); + } + catch (LinkageError e) { } + // too many different kinds to enumerate here: + catch (Exception e) { } + return null; + } + + private boolean doesImplement(Class<?> actualType, String classNameToImplement) + { + for (Class<?> type = actualType; type != null; type = type.getSuperclass()) { + if (type.getName().equals(classNameToImplement)) { + return true; + } + // or maybe one of super-interfaces + if (hasInterface(type, classNameToImplement)) { + return true; + } + } + return false; + } + + private boolean hasInterface(Class<?> type, String interfaceToImplement) + { + Class<?>[] interfaces = type.getInterfaces(); + for (Class<?> iface : interfaces) { + if (iface.getName().equals(interfaceToImplement)) { + return true; + } + } + // maybe super-interface? + for (Class<?> iface : interfaces) { + if (hasInterface(iface, interfaceToImplement)) { + return true; + } + } + return false; + } + + private boolean hasSupertypeStartingWith(Class<?> rawType, String prefix) + { + // first, superclasses + for (Class<?> supertype = rawType.getSuperclass(); supertype != null; supertype = supertype.getSuperclass()) { + if (supertype.getName().startsWith(prefix)) { + return true; + } + } + // then interfaces + for (Class<?> cls = rawType; cls != null; cls = cls.getSuperclass()) { + if (hasInterfaceStartingWith(cls, prefix)) { + return true; + } + } + return false; + } + + private boolean hasInterfaceStartingWith(Class<?> type, String prefix) + { + Class<?>[] interfaces = type.getInterfaces(); + for (Class<?> iface : interfaces) { + if (iface.getName().startsWith(prefix)) { + return true; + } + } + // maybe super-interface? + for (Class<?> iface : interfaces) { + if (hasInterfaceStartingWith(iface, prefix)) { + return true; + } + } + return false; + } + +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ext/package-info.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ext/package-info.java new file mode 100644 index 0000000..77ebb0c --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ext/package-info.java
@@ -0,0 +1,23 @@ +/** +Contains extended support for "external" packages: things that +may or may not be present in runtime environment, but that are +commonly enough used so that explicit support can be added. +<p> +Currently supported extensions include: +<ul> + <li>Support for Java 1.5 core XML datatypes: the reason these are +considered "external" is that some platforms that claim to be 1.5 conformant +are only partially so (Google Android, GAE) and do not included these + types. + </li> + <li>Joda time. This package has superior date/time handling functionality, +and is thus supported. However, to minimize forced dependencies this +support is added as extension so that Joda is not needed by Jackson +itself: but if it is present, its core types are supported to some +degree + </li> +</ul> + +*/ + +package org.codehaus.jackson.map.ext;
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/introspect/Annotated.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/introspect/Annotated.java new file mode 100644 index 0000000..130cc85 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/introspect/Annotated.java
@@ -0,0 +1,85 @@ +package org.codehaus.jackson.map.introspect; + +import java.lang.annotation.Annotation; +import java.lang.reflect.AnnotatedElement; +import java.lang.reflect.Modifier; +import java.lang.reflect.Type; + +import org.codehaus.jackson.type.JavaType; +import org.codehaus.jackson.map.type.TypeBindings; + +/** + * Shared base class used for anything on which annotations (included + * within a {@link AnnotationMap}). + */ +public abstract class Annotated +{ + protected Annotated() { } + + public abstract <A extends Annotation> A getAnnotation(Class<A> acls); + + public final <A extends Annotation> boolean hasAnnotation(Class<A> acls) + { + return getAnnotation(acls) != null; + } + + /** + * Fluent factory method that will construct a new instance that uses specified + * instance annotations instead of currently configured ones. + * + * @since 1.9 + */ + public abstract Annotated withAnnotations(AnnotationMap fallback); + + /** + * Fluent factory method that will construct a new instance that uses + * annotations from specified {@link Annotated} as fallback annotations + * + * @since 1.9 + */ + public final Annotated withFallBackAnnotationsFrom(Annotated annotated) { + return withAnnotations(AnnotationMap.merge(getAllAnnotations(), annotated.getAllAnnotations())); + } + + /** + * Method that can be used to find actual JDK element that this instance + * represents. It is non-null, except for method/constructor parameters + * which do not have a JDK counterpart. + */ + public abstract AnnotatedElement getAnnotated(); + + protected abstract int getModifiers(); + + public final boolean isPublic() { + return Modifier.isPublic(getModifiers()); + } + + public abstract String getName(); + + /** + * Full generic type of the annotated element; definition + * of what exactly this means depends on sub-class. + */ + public JavaType getType(TypeBindings context) { + return context.resolveType(getGenericType()); + } + + /** + * Full generic type of the annotated element; definition + * of what exactly this means depends on sub-class. + * + * @since 1.5 + */ + public abstract Type getGenericType(); + + /** + * "Raw" type (type-erased class) of the annotated element; definition + * of what exactly this means depends on sub-class. + * + * @since 1.5 + */ + public abstract Class<?> getRawType(); + + protected abstract AnnotationMap getAllAnnotations(); +} +
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/introspect/AnnotatedClass.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/introspect/AnnotatedClass.java new file mode 100644 index 0000000..3e36020 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/introspect/AnnotatedClass.java
@@ -0,0 +1,992 @@ +package org.codehaus.jackson.map.introspect; + +import java.lang.annotation.Annotation; +import java.lang.reflect.*; +import java.util.*; + +import org.codehaus.jackson.map.AnnotationIntrospector; +import org.codehaus.jackson.map.ClassIntrospector.MixInResolver; +import org.codehaus.jackson.map.util.Annotations; +import org.codehaus.jackson.map.util.ClassUtil; + +public final class AnnotatedClass + extends Annotated +{ + private final static AnnotationMap[] NO_ANNOTATION_MAPS = new AnnotationMap[0]; + + /* + /********************************************************** + /* Configuration + /********************************************************** + */ + + /** + * Class for which annotations apply, and that owns other + * components (constructors, methods) + */ + final protected Class<?> _class; + + /** + * Ordered set of super classes and interfaces of the + * class itself: included in order of precedence + */ + final protected List<Class<?>> _superTypes; + + /** + * Filter used to determine which annotations to gather; used + * to optimize things so that unnecessary annotations are + * ignored. + */ + final protected AnnotationIntrospector _annotationIntrospector; + + /** + * Object that knows mapping of mix-in classes (ones that contain + * annotations to add) with their target classes (ones that + * get these additional annotations "mixed in"). + */ + final protected MixInResolver _mixInResolver; + + /** + * Primary mix-in class; one to use for the annotated class + * itself. Can be null. + */ + final protected Class<?> _primaryMixIn; + + /* + /********************************************************** + /* Gathered information + /********************************************************** + */ + + /** + * Combined list of Jackson annotations that the class has, + * including inheritable ones from super classes and interfaces + */ + protected AnnotationMap _classAnnotations; + + /** + * Default constructor of the annotated class, if it has one. + */ + protected AnnotatedConstructor _defaultConstructor; + + /** + * Single argument constructors the class has, if any. + */ + protected List<AnnotatedConstructor> _constructors; + + /** + * Single argument static methods that might be usable + * as factory methods + */ + protected List<AnnotatedMethod> _creatorMethods; + + /** + * Member methods of interest; for now ones with 0 or 1 arguments + * (just optimization, since others won't be used now) + */ + protected AnnotatedMethodMap _memberMethods; + + /** + * Member fields of interest: ones that are either public, + * or have at least one annotation. + */ + protected List<AnnotatedField> _fields; + + /* + /********************************************************** + /* Life-cycle + /********************************************************** + */ + + /** + * Constructor will not do any initializations, to allow for + * configuring instances differently depending on use cases + */ + private AnnotatedClass(Class<?> cls, List<Class<?>> superTypes, + AnnotationIntrospector aintr, MixInResolver mir, + AnnotationMap classAnnotations) + { + _class = cls; + _superTypes = superTypes; + _annotationIntrospector = aintr; + _mixInResolver = mir; + _primaryMixIn = (_mixInResolver == null) ? null + : _mixInResolver.findMixInClassFor(_class); + _classAnnotations = classAnnotations; + } + + @Override + public AnnotatedClass withAnnotations(AnnotationMap ann) { + return new AnnotatedClass(_class, _superTypes, + _annotationIntrospector, _mixInResolver, ann); + } + + /** + * Factory method that instantiates an instance. Returned instance + * will only be initialized with class annotations, but not with + * any method information. + */ + public static AnnotatedClass construct(Class<?> cls, + AnnotationIntrospector aintr, MixInResolver mir) + { + List<Class<?>> st = ClassUtil.findSuperTypes(cls, null); + AnnotatedClass ac = new AnnotatedClass(cls, st, aintr, mir, null); + ac.resolveClassAnnotations(); + return ac; + } + + /** + * Method similar to {@link #construct}, but that will NOT include + * information from supertypes; only class itself and any direct + * mix-ins it may have. + */ + public static AnnotatedClass constructWithoutSuperTypes(Class<?> cls, + AnnotationIntrospector aintr, MixInResolver mir) + { + List<Class<?>> empty = Collections.emptyList(); + AnnotatedClass ac = new AnnotatedClass(cls, empty, aintr, mir, null); + ac.resolveClassAnnotations(); + return ac; + } + + /* + /********************************************************** + /* Annotated impl + /********************************************************** + */ + + @Override + public Class<?> getAnnotated() { return _class; } + + @Override + public int getModifiers() { return _class.getModifiers(); } + + @Override + public String getName() { return _class.getName(); } + + @Override + public <A extends Annotation> A getAnnotation(Class<A> acls) + { + if (_classAnnotations == null) { + return null; + } + return _classAnnotations.get(acls); + } + + @Override + public Type getGenericType() { + return _class; + } + + @Override + public Class<?> getRawType() { + return _class; + } + + @Override + protected AnnotationMap getAllAnnotations() { + return _classAnnotations; + } + + /* + /********************************************************** + /* Public API, generic accessors + /********************************************************** + */ + + /** + * @return 1.7 + */ + public Annotations getAnnotations() { return _classAnnotations; } + + public boolean hasAnnotations() { return _classAnnotations.size() > 0; } + + public AnnotatedConstructor getDefaultConstructor() { return _defaultConstructor; } + + public List<AnnotatedConstructor> getConstructors() + { + if (_constructors == null) { + return Collections.emptyList(); + } + return _constructors; + } + + public List<AnnotatedMethod> getStaticMethods() + { + if (_creatorMethods == null) { + return Collections.emptyList(); + } + return _creatorMethods; + } + + public Iterable<AnnotatedMethod> memberMethods() + { + return _memberMethods; + } + + public int getMemberMethodCount() + { + return _memberMethods.size(); + } + + public AnnotatedMethod findMethod(String name, Class<?>[] paramTypes) + { + return _memberMethods.find(name, paramTypes); + } + + public int getFieldCount() { + return (_fields == null) ? 0 : _fields.size(); + } + + public Iterable<AnnotatedField> fields() + { + if (_fields == null) { + return Collections.emptyList(); + } + return _fields; + } + + /* + /********************************************************** + /* Public API, main-level resolution methods + /********************************************************** + */ + + /** + * Initialization method that will recursively collect Jackson + * annotations for this class and all super classes and + * interfaces. + *<p> + * Starting with 1.2, it will also apply mix-in annotations, + * as per [JACKSON-76] + */ + public void resolveClassAnnotations() + { + _classAnnotations = new AnnotationMap(); + // [JACKSON-659] Should skip processing if annotation processing disabled + if (_annotationIntrospector == null) { + return; + } + + // add mix-in annotations first (overrides) + if (_primaryMixIn != null) { + _addClassMixIns(_classAnnotations, _class, _primaryMixIn); + } + // first, annotations from the class itself: + for (Annotation a : _class.getDeclaredAnnotations()) { + if (_annotationIntrospector.isHandled(a)) { + _classAnnotations.addIfNotPresent(a); + } + } + + // and then from super types + for (Class<?> cls : _superTypes) { + // and mix mix-in annotations in-between + _addClassMixIns(_classAnnotations, cls); + for (Annotation a : cls.getDeclaredAnnotations()) { + if (_annotationIntrospector.isHandled(a)) { + _classAnnotations.addIfNotPresent(a); + } + } + } + + /* and finally... any annotations there might be for plain + * old Object.class: separate because for all other purposes + * it is just ignored (not included in super types) + */ + /* 12-Jul-2009, tatu: Should this be done for interfaces too? + * For now, yes, seems useful for some cases, and not harmful + * for any? + */ + _addClassMixIns(_classAnnotations, Object.class); + } + + /** + * Initialization method that will find out all constructors + * and potential static factory methods the class has. + *<p> + * Starting with 1.2, it will also apply mix-in annotations, + * as per [JACKSON-76] + * + * @param includeAll If true, includes all creator methods; if false, + * will only include the no-arguments "default" constructor + */ + public void resolveCreators(boolean includeAll) + { + // Then see which constructors we have + _constructors = null; + Constructor<?>[] declaredCtors = _class.getDeclaredConstructors(); + for (Constructor<?> ctor : declaredCtors) { + if (ctor.getParameterTypes().length == 0) { + _defaultConstructor = _constructConstructor(ctor, true); + } else { + if (includeAll) { + if (_constructors == null) { + _constructors = new ArrayList<AnnotatedConstructor>(Math.max(10, declaredCtors.length)); + } + _constructors.add(_constructConstructor(ctor, false)); + } + } + } + // and if need be, augment with mix-ins + if (_primaryMixIn != null) { + if (_defaultConstructor != null || _constructors != null) { + _addConstructorMixIns(_primaryMixIn); + } + } + + + /* And then... let's remove all constructors that are deemed + * ignorable after all annotations have been properly collapsed. + */ + // 14-Feb-2011, tatu: AnnotationIntrospector is null if annotations not enabled; if so, can skip: + if (_annotationIntrospector != null) { + if (_defaultConstructor != null) { + if (_annotationIntrospector.isIgnorableConstructor(_defaultConstructor)) { + _defaultConstructor = null; + } + } + if (_constructors != null) { + // count down to allow safe removal + for (int i = _constructors.size(); --i >= 0; ) { + if (_annotationIntrospector.isIgnorableConstructor(_constructors.get(i))) { + _constructors.remove(i); + } + } + } + } + + _creatorMethods = null; + + if (includeAll) { + // Then static methods which are potential factory methods + for (Method m : _class.getDeclaredMethods()) { + if (!Modifier.isStatic(m.getModifiers())) { + continue; + } + int argCount = m.getParameterTypes().length; + // factory methods take at least one arg: + if (argCount < 1) { + continue; + } + if (_creatorMethods == null) { + _creatorMethods = new ArrayList<AnnotatedMethod>(8); + } + _creatorMethods.add(_constructCreatorMethod(m)); + } + // mix-ins to mix in? + if (_primaryMixIn != null && _creatorMethods != null) { + _addFactoryMixIns(_primaryMixIn); + } + // anything to ignore at this point? + if (_annotationIntrospector != null) { + if (_creatorMethods != null) { + // count down to allow safe removal + for (int i = _creatorMethods.size(); --i >= 0; ) { + if (_annotationIntrospector.isIgnorableMethod(_creatorMethods.get(i))) { + _creatorMethods.remove(i); + } + } + } + } + } + } + + /** + * Method for resolving member method information: aggregating all non-static methods + * and combining annotations (to implement method-annotation inheritance) + * + * @param methodFilter Filter used to determine which methods to include + * + * @since 1.9 + */ + public void resolveMemberMethods(MethodFilter methodFilter) + { + _memberMethods = new AnnotatedMethodMap(); + AnnotatedMethodMap mixins = new AnnotatedMethodMap(); + // first: methods from the class itself + _addMemberMethods(_class, methodFilter, _memberMethods, _primaryMixIn, mixins); + + // and then augment these with annotations from super-types: + for (Class<?> cls : _superTypes) { + Class<?> mixin = (_mixInResolver == null) ? null : _mixInResolver.findMixInClassFor(cls); + _addMemberMethods(cls, methodFilter, _memberMethods, mixin, mixins); + } + // Special case: mix-ins for Object.class? (to apply to ALL classes) + if (_mixInResolver != null) { + Class<?> mixin = _mixInResolver.findMixInClassFor(Object.class); + if (mixin != null) { + _addMethodMixIns(_class, methodFilter, _memberMethods, mixin, mixins); + } + } + + /* Any unmatched mix-ins? Most likely error cases (not matching + * any method); but there is one possible real use case: + * exposing Object#hashCode (alas, Object#getClass can NOT be + * exposed, see [JACKSON-140]) + */ + // 14-Feb-2011, tatu: AnnotationIntrospector is null if annotations not enabled; if so, can skip: + if (_annotationIntrospector != null) { + if (!mixins.isEmpty()) { + Iterator<AnnotatedMethod> it = mixins.iterator(); + while (it.hasNext()) { + AnnotatedMethod mixIn = it.next(); + try { + Method m = Object.class.getDeclaredMethod(mixIn.getName(), mixIn.getParameterClasses()); + if (m != null) { + AnnotatedMethod am = _constructMethod(m); + _addMixOvers(mixIn.getAnnotated(), am, false); + _memberMethods.add(am); + } + } catch (Exception e) { } + } + } + } + } + + /** + * Method that will collect all member (non-static) fields + * that are either public, or have at least a single annotation + * associated with them. + * + * @since 1.9 + */ + public void resolveFields() + { + LinkedHashMap<String,AnnotatedField> foundFields = new LinkedHashMap<String,AnnotatedField>(); + _addFields(foundFields, _class); + if (foundFields.isEmpty()) { + _fields = Collections.emptyList(); + } else { + _fields = new ArrayList<AnnotatedField>(foundFields.size()); + _fields.addAll(foundFields.values()); + } + } + + /* + /********************************************************** + /* Deprecated methods + /********************************************************** + */ + + /** + * @since 1.9 Use version without arguments + */ + @Deprecated + public void resolveMemberMethods(MethodFilter methodFilter, boolean collectIgnored) + { + resolveMemberMethods(methodFilter); + } + + /** + * @since 1.9 Use version without arguments + */ + @Deprecated + public void resolveFields(boolean collectIgnored) + { + resolveFields(); + } + + /* + /********************************************************** + /* Helper methods for resolving class annotations + /* (resolution consisting of inheritance, overrides, + /* and injection of mix-ins as necessary) + /********************************************************** + */ + + /** + * Helper method for adding any mix-in annotations specified + * class might have. + */ + protected void _addClassMixIns(AnnotationMap annotations, Class<?> toMask) + { + if (_mixInResolver != null) { + _addClassMixIns(annotations, toMask, _mixInResolver.findMixInClassFor(toMask)); + } + } + + protected void _addClassMixIns(AnnotationMap annotations, Class<?> toMask, + Class<?> mixin) + { + if (mixin == null) { + return; + } + // Ok, first: annotations from mix-in class itself: + for (Annotation a : mixin.getDeclaredAnnotations()) { + if (_annotationIntrospector.isHandled(a)) { + annotations.addIfNotPresent(a); + } + } + /* And then from its supertypes, if any. But note that we will + * only consider super-types up until reaching the masked + * class (if found); this because often mix-in class + * is a sub-class (for convenience reasons). And if so, we + * absolutely must NOT include super types of masked class, + * as that would inverse precedence of annotations. + */ + for (Class<?> parent : ClassUtil.findSuperTypes(mixin, toMask)) { + for (Annotation a : parent.getDeclaredAnnotations()) { + if (_annotationIntrospector.isHandled(a)) { + annotations.addIfNotPresent(a); + } + } + } + } + + /* + /********************************************************** + /* Helper methods for populating creator (ctor, factory) information + /********************************************************** + */ + + protected void _addConstructorMixIns(Class<?> mixin) + { + MemberKey[] ctorKeys = null; + int ctorCount = (_constructors == null) ? 0 : _constructors.size(); + for (Constructor<?> ctor : mixin.getDeclaredConstructors()) { + if (ctor.getParameterTypes().length == 0) { + if (_defaultConstructor != null) { + _addMixOvers(ctor, _defaultConstructor, false); + } + } else { + if (ctorKeys == null) { + ctorKeys = new MemberKey[ctorCount]; + for (int i = 0; i < ctorCount; ++i) { + ctorKeys[i] = new MemberKey(_constructors.get(i).getAnnotated()); + } + } + MemberKey key = new MemberKey(ctor); + + for (int i = 0; i < ctorCount; ++i) { + if (!key.equals(ctorKeys[i])) { + continue; + } + _addMixOvers(ctor, _constructors.get(i), true); + break; + } + } + } + } + + protected void _addFactoryMixIns(Class<?> mixin) + { + MemberKey[] methodKeys = null; + int methodCount = _creatorMethods.size(); + + for (Method m : mixin.getDeclaredMethods()) { + if (!Modifier.isStatic(m.getModifiers())) { + continue; + } + if (m.getParameterTypes().length == 0) { + continue; + } + if (methodKeys == null) { + methodKeys = new MemberKey[methodCount]; + for (int i = 0; i < methodCount; ++i) { + methodKeys[i] = new MemberKey(_creatorMethods.get(i).getAnnotated()); + } + } + MemberKey key = new MemberKey(m); + for (int i = 0; i < methodCount; ++i) { + if (!key.equals(methodKeys[i])) { + continue; + } + _addMixOvers(m, _creatorMethods.get(i), true); + break; + } + } + } + + /* + /********************************************************** + /* Helper methods for populating method information + /********************************************************** + */ + + protected void _addMemberMethods(Class<?> cls, + MethodFilter methodFilter, AnnotatedMethodMap methods, + Class<?> mixInCls, AnnotatedMethodMap mixIns) + { + // first, mixIns, since they have higher priority then class methods + if (mixInCls != null) { + _addMethodMixIns(cls, methodFilter, methods, mixInCls, mixIns); + } + + if (cls == null) { // just so caller need not check when passing super-class + return; + } + // then methods from the class itself + for (Method m : cls.getDeclaredMethods()) { + if (!_isIncludableMethod(m, methodFilter)) { + continue; + } + AnnotatedMethod old = methods.find(m); + if (old == null) { + AnnotatedMethod newM = _constructMethod(m); + methods.add(newM); + // Ok, but is there a mix-in to connect now? + old = mixIns.remove(m); + if (old != null) { + _addMixOvers(old.getAnnotated(), newM, false); + } + } else { + /* If sub-class already has the method, we only want to augment + * annotations with entries that are not masked by sub-class. + */ + _addMixUnders(m, old); + + /* 06-Jan-2010, tatu: [JACKSON-450] Except that if method we saw first is + * from an interface, and we now find a non-interface definition, we should + * use this method, but with combination of annotations. + * This helps (or rather, is essential) with JAXB annotations and + * may also result in faster method calls (interface calls are slightly + * costlier than regular method calls) + */ + if (old.getDeclaringClass().isInterface() && !m.getDeclaringClass().isInterface()) { + methods.add(old.withMethod(m)); + } + } + } + } + + protected void _addMethodMixIns(Class<?> targetClass, + MethodFilter methodFilter, AnnotatedMethodMap methods, + Class<?> mixInCls, AnnotatedMethodMap mixIns) + { + List<Class<?>> parents = new ArrayList<Class<?>>(); + parents.add(mixInCls); + ClassUtil.findSuperTypes(mixInCls, targetClass, parents); + for (Class<?> mixin : parents) { + for (Method m : mixin.getDeclaredMethods()) { + if (!_isIncludableMethod(m, methodFilter)) { + continue; + } + AnnotatedMethod am = methods.find(m); + /* Do we already have a method to augment (from sub-class + * that will mask this mixIn)? If so, add if visible + * without masking (no such annotation) + */ + if (am != null) { + _addMixUnders(m, am); + /* Otherwise will have precedence, but must wait + * until we find the real method (mixIn methods are + * just placeholder, can't be called) + */ + } else { + mixIns.add(_constructMethod(m)); + } + } + } + } + + /* + /********************************************************** + /* Helper methods for populating field information + /********************************************************** + */ + + protected void _addFields(Map<String,AnnotatedField> fields, Class<?> c) + { + /* First, a quick test: we only care for regular classes (not + * interfaces, primitive types etc), except for Object.class. + * A simple check to rule out other cases is to see if there + * is a super class or not. + */ + Class<?> parent = c.getSuperclass(); + if (parent != null) { + // Let's add super-class' fields first, then ours. + /* 21-Feb-2010, tatu: Need to handle masking: as per [JACKSON-226] + * we otherwise get into trouble... + */ + _addFields(fields, parent); + for (Field f : c.getDeclaredFields()) { + // static fields not included, nor transient + if (!_isIncludableField(f)) { + continue; + } + /* Ok now: we can (and need) not filter out ignorable fields + * at this point; partly because mix-ins haven't been + * added, and partly because logic can be done when + * determining get/settability of the field. + */ + fields.put(f.getName(), _constructField(f)); + } + // And then... any mix-in overrides? + if (_mixInResolver != null) { + Class<?> mixin = _mixInResolver.findMixInClassFor(c); + if (mixin != null) { + _addFieldMixIns(parent, mixin, fields); + } + } + } + } + + /** + * Method called to add field mix-ins from given mix-in class (and its fields) + * into already collected actual fields (from introspected classes and their + * super-classes) + */ + protected void _addFieldMixIns(Class<?> targetClass, Class<?> mixInCls, + Map<String,AnnotatedField> fields) + { + List<Class<?>> parents = new ArrayList<Class<?>>(); + parents.add(mixInCls); + ClassUtil.findSuperTypes(mixInCls, targetClass, parents); + for (Class<?> mixin : parents) { + for (Field mixinField : mixin.getDeclaredFields()) { + /* there are some dummy things (static, synthetic); better + * ignore + */ + if (!_isIncludableField(mixinField)) { + continue; + } + String name = mixinField.getName(); + // anything to mask? (if not, quietly ignore) + AnnotatedField maskedField = fields.get(name); + if (maskedField != null) { + for (Annotation a : mixinField.getDeclaredAnnotations()) { + if (_annotationIntrospector.isHandled(a)) { + maskedField.addOrOverride(a); + } + } + } + } + } + } + + /* + /********************************************************** + /* Helper methods, constructing value types + /********************************************************** + */ + + protected AnnotatedMethod _constructMethod(Method m) + { + /* note: parameter annotations not used for regular (getter, setter) + * methods; only for creator methods (static factory methods) + * -- at least not yet! + */ + if (_annotationIntrospector == null) { // when annotation processing is disabled + return new AnnotatedMethod(m, _emptyAnnotationMap(), null); + } + return new AnnotatedMethod(m, _collectRelevantAnnotations(m.getDeclaredAnnotations()), null); + } + + protected AnnotatedConstructor _constructConstructor(Constructor<?> ctor, boolean defaultCtor) + { + if (_annotationIntrospector == null) { // when annotation processing is disabled + return new AnnotatedConstructor(ctor, _emptyAnnotationMap(), _emptyAnnotationMaps(ctor.getParameterTypes().length)); + } + if (defaultCtor) { + return new AnnotatedConstructor(ctor, _collectRelevantAnnotations(ctor.getDeclaredAnnotations()), null); + } + Annotation[][] paramAnns = ctor.getParameterAnnotations(); + int paramCount = ctor.getParameterTypes().length; + /* [JACKSON-701]: Looks like JDK has discrepancy, whereas annotations for implicit 'this' + * (for non-static inner classes) are NOT included, but type is? Strange, sounds like + * a bug. Alas, we can't really fix that... + */ + /* Also: [JACKSON-767] (enum value constructors) + */ + AnnotationMap[] resolvedAnnotations = null; + if (paramCount != paramAnns.length) { + // Limits of the work-around (to avoid hiding real errors): + // first, only applicable for member classes and then either: + + Class<?> dc = ctor.getDeclaringClass(); + // (a) is enum, which have two extra hidden params (name, index) + if (dc.isEnum() && (paramCount == paramAnns.length + 2)) { + Annotation[][] old = paramAnns; + paramAnns = new Annotation[old.length+2][]; + System.arraycopy(old, 0, paramAnns, 2, old.length); + resolvedAnnotations = _collectRelevantAnnotations(paramAnns); + } else if (dc.isMemberClass()) { + // (b) non-static inner classes, get implicit 'this' for parameter, not annotation + if (paramCount == (paramAnns.length + 1)) { + // hack attack: prepend a null entry to make things match + Annotation[][] old = paramAnns; + paramAnns = new Annotation[old.length+1][]; + System.arraycopy(old, 0, paramAnns, 1, old.length); + resolvedAnnotations = _collectRelevantAnnotations(paramAnns); + } + } + if (resolvedAnnotations == null) { + throw new IllegalStateException("Internal error: constructor for "+ctor.getDeclaringClass().getName() + +" has mismatch: "+paramCount+" parameters; "+paramAnns.length+" sets of annotations"); + } + } else { + resolvedAnnotations = _collectRelevantAnnotations(paramAnns); + } + return new AnnotatedConstructor(ctor, _collectRelevantAnnotations(ctor.getDeclaredAnnotations()), + resolvedAnnotations); + } + + protected AnnotatedMethod _constructCreatorMethod(Method m) + { + if (_annotationIntrospector == null) { // when annotation processing is disabled + return new AnnotatedMethod(m, _emptyAnnotationMap(), _emptyAnnotationMaps(m.getParameterTypes().length)); + } + return new AnnotatedMethod(m, _collectRelevantAnnotations(m.getDeclaredAnnotations()), + _collectRelevantAnnotations(m.getParameterAnnotations())); + } + + protected AnnotatedField _constructField(Field f) + { + if (_annotationIntrospector == null) { // when annotation processing is disabled + return new AnnotatedField(f, _emptyAnnotationMap()); + } + return new AnnotatedField(f, _collectRelevantAnnotations(f.getDeclaredAnnotations())); + } + + protected AnnotationMap[] _collectRelevantAnnotations(Annotation[][] anns) + { + int len = anns.length; + AnnotationMap[] result = new AnnotationMap[len]; + for (int i = 0; i < len; ++i) { + result[i] = _collectRelevantAnnotations(anns[i]); + } + return result; + } + + protected AnnotationMap _collectRelevantAnnotations(Annotation[] anns) + { + AnnotationMap annMap = new AnnotationMap(); + if (anns != null) { + for (Annotation a : anns) { + if (_annotationIntrospector.isHandled(a)) { + annMap.add(a); + } + } + } + return annMap; + } + + private AnnotationMap _emptyAnnotationMap() { + return new AnnotationMap(); + } + + private AnnotationMap[] _emptyAnnotationMaps(int count) { + if (count == 0) { + return NO_ANNOTATION_MAPS; + } + AnnotationMap[] maps = new AnnotationMap[count]; + for (int i = 0; i < count; ++i) { + maps[i] = _emptyAnnotationMap(); + } + return maps; + } + + /* + /********************************************************** + /* Helper methods, inclusion filtering + /********************************************************** + */ + + protected boolean _isIncludableMethod(Method m, MethodFilter filter) + { + if (filter != null && !filter.includeMethod(m)) { + return false; + } + /* 07-Apr-2009, tatu: Looks like generics can introduce hidden + * bridge and/or synthetic methods. I don't think we want to + * consider those... + */ + if (m.isSynthetic() || m.isBridge()) { + return false; + } + return true; + } + + private boolean _isIncludableField(Field f) + { + /* I'm pretty sure synthetic fields are to be skipped... + * (methods definitely are) + */ + if (f.isSynthetic()) { + return false; + } + // Static fields are never included, nor transient + int mods = f.getModifiers(); + if (Modifier.isStatic(mods) || Modifier.isTransient(mods)) { + return false; + } + return true; + } + + /* + /********************************************************** + /* Helper methods, attaching annotations + /********************************************************** + */ + + /** + * @param addParamAnnotations Whether parameter annotations are to be + * added as well + */ + protected void _addMixOvers(Constructor<?> mixin, AnnotatedConstructor target, + boolean addParamAnnotations) + { + for (Annotation a : mixin.getDeclaredAnnotations()) { + if (_annotationIntrospector.isHandled(a)) { + target.addOrOverride(a); + } + } + if (addParamAnnotations) { + Annotation[][] pa = mixin.getParameterAnnotations(); + for (int i = 0, len = pa.length; i < len; ++i) { + for (Annotation a : pa[i]) { + target.addOrOverrideParam(i, a); + } + } + } + } + + /** + * @param addParamAnnotations Whether parameter annotations are to be + * added as well + */ + protected void _addMixOvers(Method mixin, AnnotatedMethod target, + boolean addParamAnnotations) + { + for (Annotation a : mixin.getDeclaredAnnotations()) { + if (_annotationIntrospector.isHandled(a)) { + target.addOrOverride(a); + } + } + if (addParamAnnotations) { + Annotation[][] pa = mixin.getParameterAnnotations(); + for (int i = 0, len = pa.length; i < len; ++i) { + for (Annotation a : pa[i]) { + target.addOrOverrideParam(i, a); + } + } + } + } + + /** + * Method that will add annotations from specified source method to target method, + * but only if target does not yet have them. + */ + protected void _addMixUnders(Method src, AnnotatedMethod target) + { + for (Annotation a : src.getDeclaredAnnotations()) { + if (_annotationIntrospector.isHandled(a)) { + target.addIfNotPresent(a); + } + } + } + + /* + /********************************************************** + /* Other methods + /********************************************************** + */ + + @Override + public String toString() + { + return "[AnnotedClass "+_class.getName()+"]"; + } +} +
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/introspect/AnnotatedConstructor.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/introspect/AnnotatedConstructor.java new file mode 100644 index 0000000..dd59d71 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/introspect/AnnotatedConstructor.java
@@ -0,0 +1,143 @@ +package org.codehaus.jackson.map.introspect; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Member; +import java.lang.reflect.Type; + +import org.codehaus.jackson.map.type.TypeBindings; +import org.codehaus.jackson.type.JavaType; + +public final class AnnotatedConstructor + extends AnnotatedWithParams +{ + protected final Constructor<?> _constructor; + + /* + /********************************************************** + /* Life-cycle + /********************************************************** + */ + + public AnnotatedConstructor(Constructor<?> constructor, + AnnotationMap classAnn, AnnotationMap[] paramAnn) + { + super(classAnn, paramAnn); + if (constructor == null) { + throw new IllegalArgumentException("Null constructor not allowed"); + } + _constructor = constructor; + } + + @Override + public AnnotatedConstructor withAnnotations(AnnotationMap ann) { + return new AnnotatedConstructor(_constructor, ann, _paramAnnotations); + } + + /* + /********************************************************** + /* Annotated impl + /********************************************************** + */ + + @Override + public Constructor<?> getAnnotated() { return _constructor; } + + @Override + public int getModifiers() { return _constructor.getModifiers(); } + + @Override + public String getName() { return _constructor.getName(); } + + @Override + public Type getGenericType() { + return getRawType(); + } + + @Override + public Class<?> getRawType() { + return _constructor.getDeclaringClass(); + } + + // note: copied verbatim from AnnotatedMethod; hard to generalize + /** + * As per [JACKSON-468], we need to also allow declaration of local + * type bindings; mostly it will allow defining bounds. + */ + @Override + public JavaType getType(TypeBindings bindings) + { + return getType(bindings, _constructor.getTypeParameters()); + } + + /* + /********************************************************** + /* Extended API + /********************************************************** + */ + + @Override + public int getParameterCount() { + return _constructor.getParameterTypes().length; + } + + @Override + public Class<?> getParameterClass(int index) + { + Class<?>[] types = _constructor.getParameterTypes(); + return (index >= types.length) ? null : types[index]; + } + + @Override + public Type getParameterType(int index) + { + Type[] types = _constructor.getGenericParameterTypes(); + return (index >= types.length) ? null : types[index]; + } + + @Override + public final Object call() throws Exception { + return _constructor.newInstance(); + } + + @Override + public final Object call(Object[] args) throws Exception { + return _constructor.newInstance(args); + } + + @Override + public final Object call1(Object arg) throws Exception { + return _constructor.newInstance(arg); + } + + /* + /********************************************************** + /* AnnotatedMember impl + /********************************************************** + */ + + @Override + public Class<?> getDeclaringClass() { return _constructor.getDeclaringClass(); } + + @Override + public Member getMember() { return _constructor; } + + @Override + public void setValue(Object pojo, Object value) + throws UnsupportedOperationException + { + throw new UnsupportedOperationException("Cannot call setValue() on constructor of " + +getDeclaringClass().getName()); + } + + /* + /********************************************************** + /* Extended API, specific annotations + /********************************************************** + */ + + @Override + public String toString() { + return "[constructor for "+getName()+", annotations: "+_annotations+"]"; + } +} +
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/introspect/AnnotatedField.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/introspect/AnnotatedField.java new file mode 100644 index 0000000..dd5e76a --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/introspect/AnnotatedField.java
@@ -0,0 +1,119 @@ +package org.codehaus.jackson.map.introspect; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; +import java.lang.reflect.Member; +import java.lang.reflect.Type; + +/** + * Object that represents non-static (and usually non-transient/volatile) + * fields of a class. + * + * @author tatu + */ +public final class AnnotatedField + extends AnnotatedMember +{ + protected final Field _field; + + /* + /********************************************************** + /* Life-cycle + /********************************************************** + */ + + public AnnotatedField(Field field, AnnotationMap annMap) + { + super(annMap); + _field = field; + } + + @Override + public AnnotatedField withAnnotations(AnnotationMap ann) { + return new AnnotatedField(_field, ann); + } + + /** + * Method called to override an annotation, usually due to a mix-in + * annotation masking or overriding an annotation 'real' constructor + * has. + */ + public void addOrOverride(Annotation a) + { + _annotations.add(a); + } + + /* + /********************************************************** + /* Annotated impl + /********************************************************** + */ + + @Override + public Field getAnnotated() { return _field; } + + @Override + public int getModifiers() { return _field.getModifiers(); } + + @Override + public String getName() { return _field.getName(); } + + @Override + public <A extends Annotation> A getAnnotation(Class<A> acls) + { + return _annotations.get(acls); + } + + @Override + public Type getGenericType() { + return _field.getGenericType(); + } + + @Override + public Class<?> getRawType() { + return _field.getType(); + } + + /* + /********************************************************** + /* AnnotatedMember impl + /********************************************************** + */ + + @Override + public Class<?> getDeclaringClass() { return _field.getDeclaringClass(); } + + @Override + public Member getMember() { return _field; } + + @Override + public void setValue(Object pojo, Object value) + throws IllegalArgumentException + { + try { + _field.set(pojo, value); + } catch (IllegalAccessException e) { + throw new IllegalArgumentException("Failed to setValue() for field " + +getFullName()+": "+e.getMessage(), e); + } + } + + /* + /********************************************************** + /* Extended API, generic + /********************************************************** + */ + + public String getFullName() { + return getDeclaringClass().getName() + "#" + getName(); + } + + public int getAnnotationCount() { return _annotations.size(); } + + @Override + public String toString() + { + return "[field "+getName()+", annotations: "+_annotations+"]"; + } +} +
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/introspect/AnnotatedMember.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/introspect/AnnotatedMember.java new file mode 100644 index 0000000..e89db56 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/introspect/AnnotatedMember.java
@@ -0,0 +1,56 @@ +package org.codehaus.jackson.map.introspect; + +import java.lang.reflect.Member; + +import org.codehaus.jackson.map.util.ClassUtil; + +/** + * Intermediate base class for annotated entities that are members of + * a class; fields, methods and constructors. This is a superset + * of things that can represent logical properties as it contains + * constructors in addition to fields and methods. + * + * @author tatu + * @since 1.5 + */ +public abstract class AnnotatedMember extends Annotated +{ + protected final AnnotationMap _annotations; + + protected AnnotatedMember(AnnotationMap annotations) { + super(); + _annotations = annotations; + } + + public abstract Class<?> getDeclaringClass(); + + public abstract Member getMember(); + + @Override + protected AnnotationMap getAllAnnotations() { + return _annotations; + } + + /** + * Method that can be called to modify access rights, by calling + * {@link java.lang.reflect.AccessibleObject#setAccessible} on + * the underlying annotated element. + */ + public final void fixAccess() { + ClassUtil.checkAndFixAccess(getMember()); + } + + /** + * Optional method that can be used to assign value of + * this member on given object, if this is a supported + * operation for member type. + *<p> + * This is implemented for fiedlds and single-argument + * methods; but not for constructor parameters or + * other types of methods. + * + * @since 1.9 + */ + public abstract void setValue(Object pojo, Object value) + throws UnsupportedOperationException, IllegalArgumentException; +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/introspect/AnnotatedMethod.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/introspect/AnnotatedMethod.java new file mode 100644 index 0000000..824d408 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/introspect/AnnotatedMethod.java
@@ -0,0 +1,188 @@ +package org.codehaus.jackson.map.introspect; + +import java.lang.reflect.*; + +import org.codehaus.jackson.map.type.TypeBindings; +import org.codehaus.jackson.type.JavaType; + +public final class AnnotatedMethod + extends AnnotatedWithParams +{ + final protected Method _method; + + // // Simple lazy-caching: + + protected Class<?>[] _paramTypes; + + /* + /***************************************************** + /* Life-cycle + /***************************************************** + */ + + public AnnotatedMethod(Method method, AnnotationMap classAnn, AnnotationMap[] paramAnnotations) + { + super(classAnn, paramAnnotations); + _method = method; + } + + /** + * Method that constructs a new instance with settings (annotations, parameter annotations) + * of this instance, but with different physical {@link Method}. + * + * @since 1.7 + */ + public AnnotatedMethod withMethod(Method m) + { + return new AnnotatedMethod(m, _annotations, _paramAnnotations); + } + + @Override + public AnnotatedMethod withAnnotations(AnnotationMap ann) { + return new AnnotatedMethod(_method, ann, _paramAnnotations); + } + + /* + /***************************************************** + /* Annotated impl + /***************************************************** + */ + + @Override + public Method getAnnotated() { return _method; } + + @Override + public int getModifiers() { return _method.getModifiers(); } + + @Override + public String getName() { return _method.getName(); } + + /** + * For methods, this returns declared return type, which is only + * useful with getters (setters do not return anything; hence "void" + * type is returned here) + */ + @Override + public Type getGenericType() { + return _method.getGenericReturnType(); + } + + /** + * For methods, this returns declared return type, which is only + * useful with getters (setters do not return anything; hence "void" + * type is returned here) + */ + @Override + public Class<?> getRawType() { + return _method.getReturnType(); + } + + /** + * As per [JACKSON-468], we need to also allow declaration of local + * type bindings; mostly it will allow defining bounds. + */ + @Override + public JavaType getType(TypeBindings bindings) { + return getType(bindings, _method.getTypeParameters()); + } + + @Override + public final Object call() throws Exception { + return _method.invoke(null); + } + + @Override + public final Object call(Object[] args) throws Exception { + return _method.invoke(null, args); + } + + @Override + public final Object call1(Object arg) throws Exception { + return _method.invoke(null, arg); + } + + /* + /******************************************************** + /* AnnotatedMember impl + /******************************************************** + */ + + @Override + public Class<?> getDeclaringClass() { return _method.getDeclaringClass(); } + + @Override + public Member getMember() { return _method; } + + @Override + public void setValue(Object pojo, Object value) + throws IllegalArgumentException + { + try { + _method.invoke(pojo, value); + } catch (IllegalAccessException e) { + throw new IllegalArgumentException("Failed to setValue() with method " + +getFullName()+": "+e.getMessage(), e); + } catch (InvocationTargetException e) { + throw new IllegalArgumentException("Failed to setValue() with method " + +getFullName()+": "+e.getMessage(), e); + } + } + + /* + /***************************************************** + /* Extended API, generic + /***************************************************** + */ + + @Override + public int getParameterCount() { + return getParameterTypes().length; + } + + public Type[] getParameterTypes() { + return _method.getGenericParameterTypes(); + } + + @Override + public Class<?> getParameterClass(int index) + { + Class<?>[] types = _method.getParameterTypes(); + return (index >= types.length) ? null : types[index]; + } + + @Override + public Type getParameterType(int index) + { + Type[] types = _method.getGenericParameterTypes(); + return (index >= types.length) ? null : types[index]; + } + + public Class<?>[] getParameterClasses() + { + if (_paramTypes == null) { + _paramTypes = _method.getParameterTypes(); + } + return _paramTypes; + } + + //public Type getGenericReturnType() { return _method.getGenericReturnType(); } + + //public Class<?> getReturnType() { return _method.getReturnType(); } + + public String getFullName() { + return getDeclaringClass().getName() + "#" + getName() + "(" + +getParameterCount()+" params)"; + } + + /* + /******************************************************** + /* Other + /******************************************************** + */ + + @Override + public String toString() + { + return "[method "+getName()+", annotations: "+_annotations+"]"; + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/introspect/AnnotatedMethodMap.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/introspect/AnnotatedMethodMap.java new file mode 100644 index 0000000..23b2b71 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/introspect/AnnotatedMethodMap.java
@@ -0,0 +1,85 @@ +package org.codehaus.jackson.map.introspect; + +import java.lang.reflect.Method; +import java.util.*; + +/** + * Simple helper class used to keep track of collection of + * {@link AnnotatedMethod}s, accessible by lookup. Lookup + * is usually needed for augmenting and overriding annotations. + */ +public final class AnnotatedMethodMap + implements Iterable<AnnotatedMethod> +{ + protected LinkedHashMap<MemberKey,AnnotatedMethod> _methods; + + public AnnotatedMethodMap() { } + + /** + * Method called to add specified annotated method in the Map. + */ + public void add(AnnotatedMethod am) + { + if (_methods == null) { + _methods = new LinkedHashMap<MemberKey,AnnotatedMethod>(); + } + _methods.put(new MemberKey(am.getAnnotated()), am); + } + + /** + * Method called to remove specified method, assuming + * it exists in the Map + */ + public AnnotatedMethod remove(AnnotatedMethod am) + { + return remove(am.getAnnotated()); + } + + public AnnotatedMethod remove(Method m) + { + if (_methods != null) { + return _methods.remove(new MemberKey(m)); + } + return null; + } + + public boolean isEmpty() { + return (_methods == null || _methods.size() == 0); + } + + public int size() { + return (_methods == null) ? 0 : _methods.size(); + } + + public AnnotatedMethod find(String name, Class<?>[] paramTypes) + { + if (_methods == null) { + return null; + } + return _methods.get(new MemberKey(name, paramTypes)); + } + + public AnnotatedMethod find(Method m) + { + if (_methods == null) { + return null; + } + return _methods.get(new MemberKey(m)); + } + + /* + /********************************************************** + /* Iterable implementation (for iterating over values) + /********************************************************** + */ + + @Override + public Iterator<AnnotatedMethod> iterator() + { + if (_methods != null) { + return _methods.values().iterator(); + } + List<AnnotatedMethod> empty = Collections.emptyList(); + return empty.iterator(); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/introspect/AnnotatedParameter.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/introspect/AnnotatedParameter.java new file mode 100644 index 0000000..d2d550e --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/introspect/AnnotatedParameter.java
@@ -0,0 +1,191 @@ +package org.codehaus.jackson.map.introspect; + +import java.lang.annotation.Annotation; +import java.lang.reflect.AnnotatedElement; +import java.lang.reflect.Member; +import java.lang.reflect.Type; + +import org.codehaus.jackson.map.type.TypeFactory; +import org.codehaus.jackson.type.JavaType; + +/** + * Object that represents method parameters, mostly so that associated + * annotations can be processed conveniently. Note that many of accessors + * can not return meaningful values since parameters do not have stand-alone + * JDK objects associated; so access should mostly be limited to checking + * annotation values which are properly aggregated and included. + *<p> + * Note: as of version 1.7, this type extends {@link AnnotatedMember}, since + * it behaves like a member for the most part, but earlier it just extended + * {@link Annotated} + */ +public final class AnnotatedParameter + extends AnnotatedMember +{ + /** + * Member (method, constructor) that this parameter belongs to + * + * @since 1.7 + */ + protected final AnnotatedWithParams _owner; + + /** + * JDK type of the parameter, possibly contains generic type information + */ + protected final Type _type; + + /** + * Index of the parameter within argument list + * + * @since 1.9 + */ + protected final int _index; + + /* + /********************************************************** + /* Life-cycle + /********************************************************** + */ + + public AnnotatedParameter(AnnotatedWithParams owner, Type type, AnnotationMap annotations, + int index) + { + super(annotations); + _owner = owner; + _type = type; + _index = index; + } + + @Override + public AnnotatedParameter withAnnotations(AnnotationMap ann) { + if (ann == _annotations) { + return this; + } + return _owner.replaceParameterAnnotations(_index, ann); + } + + public void addOrOverride(Annotation a) + { + _annotations.add(a); + } + + /* + /********************************************************** + /* Annotated impl + /********************************************************** + */ + + /** + * Since there is no matching JDK element, this method will + * always return null + */ + @Override + public AnnotatedElement getAnnotated() { return null; } + + /** + * Returns modifiers of the constructor, as parameters do not + * have independent modifiers. + */ + @Override + public int getModifiers() { return _owner.getModifiers(); } + + /** + * Parameters have no names in bytecode (unlike in source code), + * will always return empty String (""). + */ + @Override + public String getName() { return ""; } + + /** + * Accessor for annotations; all annotations associated with parameters + * are properly passed and accessible. + */ + @Override + public <A extends Annotation> A getAnnotation(Class<A> acls) + { + return _annotations.get(acls); + } + + @Override + public Type getGenericType() { + return _type; + } + + @Override + public Class<?> getRawType() + { + if (_type instanceof Class<?>) { + return (Class<?>) _type; + } + // 14-Mar-2011, tatu: Not optimal, but has to do for now... + JavaType t = TypeFactory.defaultInstance().constructType(_type); + return t.getRawClass(); + } + + /* + /********************************************************** + /* AnnotatedMember extras + /********************************************************** + */ + + @Override + public Class<?> getDeclaringClass() { + return _owner.getDeclaringClass(); + } + + @Override + public Member getMember() { + /* This is bit tricky: since there is no JDK equivalent; can either + * return null or owner... let's do latter, for now. + */ + return _owner.getMember(); + } + + @Override + public void setValue(Object pojo, Object value) + throws UnsupportedOperationException + { + throw new UnsupportedOperationException("Cannot call setValue() on constructor parameter of " + +getDeclaringClass().getName()); + } + + /* + /********************************************************** + /* Extended API + /********************************************************** + */ + + public Type getParameterType() { return _type; } + + /** + * Accessor for 'owner' of this parameter; method or constructor that + * has this parameter as member of its argument list. + * + * @return Owner (member or creator) object of this parameter + * + * @since 1.9 + */ + public AnnotatedWithParams getOwner() { return _owner; } + + /** + * Accessor for index of this parameter within argument list + * + * @return Index of this parameter within argument list + * + * @since 1.9 + */ + public int getIndex() { return _index; } + + /* + /******************************************************** + /* Other + /******************************************************** + */ + + @Override + public String toString() + { + return "[parameter #"+getIndex()+", annotations: "+_annotations+"]"; + } +} +
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/introspect/AnnotatedWithParams.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/introspect/AnnotatedWithParams.java new file mode 100644 index 0000000..75d831d --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/introspect/AnnotatedWithParams.java
@@ -0,0 +1,195 @@ +package org.codehaus.jackson.map.introspect; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; + +import org.codehaus.jackson.map.type.TypeBindings; +import org.codehaus.jackson.map.type.TypeFactory; +import org.codehaus.jackson.type.JavaType; + +/** + * Intermediate base class that encapsulates features that + * constructors and methods share. + */ +public abstract class AnnotatedWithParams + extends AnnotatedMember +{ + /** + * Annotations associated with parameters of the annotated + * entity (method or constructor parameters) + */ + protected final AnnotationMap[] _paramAnnotations; + + /* + /********************************************************** + /* Life-cycle + /********************************************************** + */ + + protected AnnotatedWithParams(AnnotationMap annotations, AnnotationMap[] paramAnnotations) + { + super(annotations); + _paramAnnotations = paramAnnotations; + } + + /** + * Method called to override a class annotation, usually due to a mix-in + * annotation masking or overriding an annotation 'real' class + */ + public final void addOrOverride(Annotation a) + { + _annotations.add(a); + } + + /** + * Method called to override a method parameter annotation, + * usually due to a mix-in + * annotation masking or overriding an annotation 'real' method + * has. + */ + public final void addOrOverrideParam(int paramIndex, Annotation a) + { + AnnotationMap old = _paramAnnotations[paramIndex]; + if (old == null) { + old = new AnnotationMap(); + _paramAnnotations[paramIndex] = old; + } + old.add(a); + } + + /** + * Method called to augment annotations, by adding specified + * annotation if and only if it is not yet present in the + * annotation map we have. + */ + public final void addIfNotPresent(Annotation a) + { + _annotations.addIfNotPresent(a); + } + + + /** + * Method called by parameter object when an augmented instance is created; + * needs to replace parameter with new instance + * + * @since 1.9 + */ + protected AnnotatedParameter replaceParameterAnnotations(int index, AnnotationMap ann) + { + _paramAnnotations[index] = ann; + return getParameter(index); + } + + /* + /********************************************************** + /* Helper methods for subclasses + /********************************************************** + */ + + protected JavaType getType(TypeBindings bindings, TypeVariable<?>[] typeParams) + { + // [JACKSON-468] Need to consider local type binding declarations too... + if (typeParams != null && typeParams.length > 0) { + bindings = bindings.childInstance(); + for (TypeVariable<?> var : typeParams) { + String name = var.getName(); + // to prevent infinite loops, need to first add placeholder ("<T extends Enum<T>>" etc) + bindings._addPlaceholder(name); + // About only useful piece of information is the lower bound (which is at least Object.class) + Type lowerBound = var.getBounds()[0]; + JavaType type = (lowerBound == null) ? TypeFactory.unknownType() + : bindings.resolveType(lowerBound); + bindings.addBinding(var.getName(), type); + } + } + return bindings.resolveType(getGenericType()); + } + + /* + /********************************************************** + /* Partial Annotated impl + /********************************************************** + */ + + @Override + public final <A extends Annotation> A getAnnotation(Class<A> acls) + { + return _annotations.get(acls); + } + + /* + /********************************************************** + /* Extended API + /********************************************************** + */ + + public final AnnotationMap getParameterAnnotations(int index) + { + if (_paramAnnotations != null) { + if (index >= 0 && index <= _paramAnnotations.length) { + return _paramAnnotations[index]; + } + } + return null; + } + + public final AnnotatedParameter getParameter(int index) { + return new AnnotatedParameter(this, getParameterType(index), + _paramAnnotations[index], index); + } + + public abstract int getParameterCount(); + + public abstract Class<?> getParameterClass(int index); + + public abstract Type getParameterType(int index); + + /** + * Method called to fully resolve type of one of parameters, given + * specified type variable bindings. + * + * @since 1.8 + */ + public final JavaType resolveParameterType(int index, TypeBindings bindings) { + return bindings.resolveType(getParameterType(index)); + } + + public final int getAnnotationCount() { return _annotations.size(); } + + /** + * Method that can be used to (try to) call this object without arguments. + * This may succeed or fail, depending on expected number + * of arguments: caller needs to take care to pass correct number. + * Exceptions are thrown directly from actual low-level call. + *<p> + * Note: only works for constructors and static methods. + * + * @since 1.9 + */ + public abstract Object call() throws Exception; + + /** + * Method that can be used to (try to) call this object with specified arguments. + * This may succeed or fail, depending on expected number + * of arguments: caller needs to take care to pass correct number. + * Exceptions are thrown directly from actual low-level call. + *<p> + * Note: only works for constructors and static methods. + * + * @since 1.9 + */ + public abstract Object call(Object[] args) throws Exception; + + /** + * Method that can be used to (try to) call this object with single arguments. + * This may succeed or fail, depending on expected number + * of arguments: caller needs to take care to pass correct number. + * Exceptions are thrown directly from actual low-level call. + *<p> + * Note: only works for constructors and static methods. + * + * @since 1.9 + */ + public abstract Object call1(Object arg) throws Exception; +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/introspect/AnnotationMap.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/introspect/AnnotationMap.java new file mode 100644 index 0000000..8689d43 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/introspect/AnnotationMap.java
@@ -0,0 +1,101 @@ +package org.codehaus.jackson.map.introspect; + +import java.lang.annotation.Annotation; +import java.util.*; + +import org.codehaus.jackson.map.util.Annotations; + +/** + * Simple helper class used to keep track of collection of + * Jackson Annotations associated with annotatable things + * (methods, constructors, classes). + * Note that only Jackson-owned annotations are tracked (for now?). + */ +public final class AnnotationMap implements Annotations +{ + protected HashMap<Class<? extends Annotation>,Annotation> _annotations; + + public AnnotationMap() { } + private AnnotationMap(HashMap<Class<? extends Annotation>,Annotation> a) { + _annotations = a; + } + + @SuppressWarnings("unchecked") + @Override + public <A extends Annotation> A get(Class<A> cls) + { + if (_annotations == null) { + return null; + } + return (A) _annotations.get(cls); + } + + public static AnnotationMap merge(AnnotationMap primary, AnnotationMap secondary) + { + if (primary == null || primary._annotations == null || primary._annotations.isEmpty()) { + return secondary; + } + if (secondary == null || secondary._annotations == null || secondary._annotations.isEmpty()) { + return primary; + } + HashMap<Class<? extends Annotation>,Annotation> annotations + = new HashMap<Class<? extends Annotation>,Annotation>(); + // add secondary ones first + for (Annotation ann : secondary._annotations.values()) { + annotations.put(ann.annotationType(), ann); + } + // to be overridden by primary ones + for (Annotation ann : primary._annotations.values()) { + annotations.put(ann.annotationType(), ann); + } + return new AnnotationMap(annotations); + } + + @Override + public int size() { + return (_annotations == null) ? 0 : _annotations.size(); + } + + /** + * Method called to add specified annotation in the Map, but + * only if it didn't yet exist. + */ + public void addIfNotPresent(Annotation ann) + { + if (_annotations == null || !_annotations.containsKey(ann.annotationType())) { + _add(ann); + } + } + + /** + * Method called to add specified annotation in the Map. + */ + public void add(Annotation ann) { + _add(ann); + } + + @Override + public String toString() + { + if (_annotations == null) { + return "[null]"; + } + return _annotations.toString(); + } + + /* + /********************************************************** + /* Helper methods + /********************************************************** + */ + + protected final void _add(Annotation ann) + { + if (_annotations == null) { + _annotations = new HashMap<Class<? extends Annotation>,Annotation>(); + } + _annotations.put(ann.annotationType(), ann); + } +} + +
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/introspect/BasicBeanDescription.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/introspect/BasicBeanDescription.java new file mode 100644 index 0000000..6655e89 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/introspect/BasicBeanDescription.java
@@ -0,0 +1,615 @@ +package org.codehaus.jackson.map.introspect; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.util.*; + +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.JsonSerialize; +import org.codehaus.jackson.map.type.TypeBindings; +import org.codehaus.jackson.map.util.Annotations; +import org.codehaus.jackson.type.JavaType; + +/** + * Default {@link BeanDescription} implementation. + * Can theoretically be subclassed to customize + * some aspects of property introspection. + */ +public class BasicBeanDescription extends BeanDescription +{ + /* + /********************************************************** + /* General configuration + /********************************************************** + */ + + final protected MapperConfig<?> _config; + + final protected AnnotationIntrospector _annotationIntrospector; + + /** + * Information collected about the class introspected. + */ + final protected AnnotatedClass _classInfo; + + /** + * We may need type bindings for the bean type. If so, we'll + * construct it lazily + */ + protected TypeBindings _bindings; + + /* + /********************************************************** + /* Member information + /********************************************************** + */ + + /** + * Properties collected for the POJO. + */ + protected final List<BeanPropertyDefinition> _properties; + + // // for deserialization + + protected AnnotatedMethod _anySetterMethod; + + protected Map<Object, AnnotatedMember> _injectables; + + /** + * Set of properties that can be ignored during deserialization, due + * to being marked as ignored. + */ + protected Set<String> _ignoredPropertyNames; + + /** + * @since 1.9.4 + */ + protected Set<String> _ignoredPropertyNamesForDeser; + + // // for serialization + + protected AnnotatedMethod _jsonValueMethod; + + protected AnnotatedMethod _anyGetterMethod; + + /* + /********************************************************** + /* Life-cycle + /********************************************************** + */ + + /** + * @deprecated Since 1.9, should use factory methods instead + */ + @Deprecated + public BasicBeanDescription(MapperConfig<?> config, JavaType type, + AnnotatedClass ac) + { + this(config, type, ac, Collections.<BeanPropertyDefinition>emptyList()); + } + + /** + * @since 1.9 + */ + protected BasicBeanDescription(MapperConfig<?> config, JavaType type, + AnnotatedClass ac, List<BeanPropertyDefinition> properties) + { + super(type); + _config = config; + _annotationIntrospector = (config == null) ? null : config.getAnnotationIntrospector(); + _classInfo = ac; + _properties = properties; + } + + /** + * Factory method to use for constructing an instance to use for building + * deserializers. + * + * @since 1.9 + */ + public static BasicBeanDescription forDeserialization(POJOPropertiesCollector coll) + { + BasicBeanDescription desc = new BasicBeanDescription(coll.getConfig(), + coll.getType(), coll.getClassDef(), coll.getProperties()); + desc._anySetterMethod = coll.getAnySetterMethod(); + desc._ignoredPropertyNames = coll.getIgnoredPropertyNames(); + desc._ignoredPropertyNamesForDeser = coll.getIgnoredPropertyNamesForDeser(); + desc._injectables = coll.getInjectables(); + return desc; + } + + /** + * Factory method to use for constructing an instance to use for building + * serializers. + * + * @since 1.9 + */ + public static BasicBeanDescription forSerialization(POJOPropertiesCollector coll) + { + BasicBeanDescription desc = new BasicBeanDescription(coll.getConfig(), + coll.getType(), coll.getClassDef(), coll.getProperties()); + desc._jsonValueMethod = coll.getJsonValueMethod(); + desc._anyGetterMethod = coll.getAnyGetterMethod(); + return desc; + } + + /** + * Factory method to use for constructing an instance to use for purposes + * other than building serializers or deserializers; will only have information + * on class, not on properties. + * + * @since 1.9 + */ + public static BasicBeanDescription forOtherUse(MapperConfig<?> config, + JavaType type, AnnotatedClass ac) + { + return new BasicBeanDescription(config, type, + ac, Collections.<BeanPropertyDefinition>emptyList()); + } + + /* + /********************************************************** + /* Simple accessors from BeanDescription + /********************************************************** + */ + + /** + * @since 1.9 + */ + @Override + public AnnotatedClass getClassInfo() { return _classInfo; } + + @Override + public List<BeanPropertyDefinition> findProperties() { + return _properties; + } + + /** + * Method for locating the getter method that is annotated with + * {@link org.codehaus.jackson.annotate.JsonValue} annotation, + * if any. If multiple ones are found, + * an error is reported by throwing {@link IllegalArgumentException} + */ + @Override + public AnnotatedMethod findJsonValueMethod() + { + return _jsonValueMethod; + } + + @Override + public Set<String> getIgnoredPropertyNames() { + if (_ignoredPropertyNames == null) { + return Collections.emptySet(); + } + return _ignoredPropertyNames; + } + + public Set<String> getIgnoredPropertyNamesForDeser() { + return _ignoredPropertyNamesForDeser; + } + + /** + * Method for checking whether class being described has any + * annotations recognized by registered annotation introspector. + */ + @Override + public boolean hasKnownClassAnnotations() { + return _classInfo.hasAnnotations(); + } + + @Override + public Annotations getClassAnnotations() { + return _classInfo.getAnnotations(); + } + + @Override + public TypeBindings bindingsForBeanType() + { + if (_bindings == null) { + _bindings = new TypeBindings(_config.getTypeFactory(), _type); + } + return _bindings; + } + + @Override + public JavaType resolveType(java.lang.reflect.Type jdkType) { + if (jdkType == null) { + return null; + } + return bindingsForBeanType().resolveType(jdkType); + } + + /** + * Method that will locate the no-arg constructor for this class, + * if it has one, and that constructor has not been marked as + * ignorable. + * + * @since 1.9 + */ + @Override + public AnnotatedConstructor findDefaultConstructor() + { + return _classInfo.getDefaultConstructor(); + } + + /** + * Method used to locate the method of introspected class that + * implements {@link org.codehaus.jackson.annotate.JsonAnySetter}. If no such method exists + * null is returned. If more than one are found, an exception + * is thrown. + * Additional checks are also made to see that method signature + * is acceptable: needs to take 2 arguments, first one String or + * Object; second any can be any type. + */ + @Override + public AnnotatedMethod findAnySetter() throws IllegalArgumentException + { + if (_anySetterMethod != null) { + /* Also, let's be somewhat strict on how field name is to be + * passed; String, Object make sense, others not + * so much. + */ + /* !!! 18-May-2009, tatu: how about enums? Can add support if + * requested; easy enough for devs to add support within + * method. + */ + Class<?> type = _anySetterMethod.getParameterClass(0); + if (type != String.class && type != Object.class) { + throw new IllegalArgumentException("Invalid 'any-setter' annotation on method "+_anySetterMethod.getName()+"(): first argument not of type String or Object, but "+type.getName()); + } + } + return _anySetterMethod; + } + + @Override + public Map<Object, AnnotatedMember> findInjectables() + { + return _injectables; + } + + public List<AnnotatedConstructor> getConstructors() + { + return _classInfo.getConstructors(); + } + + /* + /********************************************************** + /* Simple accessors, extended + /********************************************************** + */ + + public AnnotatedMethod findMethod(String name, Class<?>[] paramTypes) + { + return _classInfo.findMethod(name, paramTypes); + } + + /** + * Method called to create a "default instance" of the bean, currently + * only needed for obtaining default field values which may be used for + * suppressing serialization of fields that have "not changed". + * + * @param fixAccess If true, method is allowed to fix access to the + * default constructor (to be able to call non-public constructor); + * if false, has to use constructor as is. + * + * @return Instance of class represented by this descriptor, if + * suitable default constructor was found; null otherwise. + */ + public Object instantiateBean(boolean fixAccess) + { + AnnotatedConstructor ac = _classInfo.getDefaultConstructor(); + if (ac == null) { + return null; + } + if (fixAccess) { + ac.fixAccess(); + } + try { + return ac.getAnnotated().newInstance(); + } catch (Exception e) { + Throwable t = e; + while (t.getCause() != null) { + t = t.getCause(); + } + if (t instanceof Error) throw (Error) t; + if (t instanceof RuntimeException) throw (RuntimeException) t; + throw new IllegalArgumentException("Failed to instantiate bean of type "+_classInfo.getAnnotated().getName()+": ("+t.getClass().getName()+") "+t.getMessage(), t); + } + } + + /* + /********************************************************** + /* Introspection for serialization, factories + /********************************************************** + */ + + public List<AnnotatedMethod> getFactoryMethods() + { + // must filter out anything that clearly is not a factory method + List<AnnotatedMethod> candidates = _classInfo.getStaticMethods(); + if (candidates.isEmpty()) { + return candidates; + } + ArrayList<AnnotatedMethod> result = new ArrayList<AnnotatedMethod>(); + for (AnnotatedMethod am : candidates) { + if (isFactoryMethod(am)) { + result.add(am); + } + } + return result; + } + + /** + * Method that can be called to locate a single-arg constructor that + * takes specified exact type (will not accept supertype constructors) + * + * @param argTypes Type(s) of the argument that we are looking for + */ + public Constructor<?> findSingleArgConstructor(Class<?>... argTypes) + { + for (AnnotatedConstructor ac : _classInfo.getConstructors()) { + // This list is already filtered to only include accessible + /* (note: for now this is a redundant check; but in future + * that may change; thus leaving here for now) + */ + if (ac.getParameterCount() == 1) { + Class<?> actArg = ac.getParameterClass(0); + for (Class<?> expArg : argTypes) { + if (expArg == actArg) { + return ac.getAnnotated(); + } + } + } + } + return null; + } + + /** + * Method that can be called to find if introspected class declares + * a static "valueOf" factory method that returns an instance of + * introspected type, given one of acceptable types. + * + * @param expArgTypes Types that the matching single argument factory + * method can take: will also accept super types of these types + * (ie. arg just has to be assignable from expArgType) + */ + public Method findFactoryMethod(Class<?>... expArgTypes) + { + // So, of all single-arg static methods: + for (AnnotatedMethod am : _classInfo.getStaticMethods()) { + if (isFactoryMethod(am)) { + // And must take one of expected arg types (or supertype) + Class<?> actualArgType = am.getParameterClass(0); + for (Class<?> expArgType : expArgTypes) { + // And one that matches what we would pass in + if (actualArgType.isAssignableFrom(expArgType)) { + return am.getAnnotated(); + } + } + } + } + return null; + } + + protected boolean isFactoryMethod(AnnotatedMethod am) + { + /* First: return type must be compatible with the introspected class + * (i.e. allowed to be sub-class, although usually is the same + * class) + */ + Class<?> rt = am.getRawType(); + if (!getBeanClass().isAssignableFrom(rt)) { + return false; + } + + /* Also: must be a recognized factory method, meaning: + * (a) marked with @JsonCreator annotation, or + * (a) "valueOf" (at this point, need not be public) + */ + if (_annotationIntrospector.hasCreatorAnnotation(am)) { + return true; + } + if ("valueOf".equals(am.getName())) { + return true; + } + return false; + } + + /** + * Method for getting ordered list of named Creator properties. + * Returns an empty list is none found. If multiple Creator + * methods are defined, order between properties from different + * methods is undefined; however, properties for each such + * Creator are ordered properly relative to each other. For the + * usual case of just a single Creator, named properties are + * thus properly ordered. + */ + public List<String> findCreatorPropertyNames() + { + List<String> names = null; + + for (int i = 0; i < 2; ++i) { + List<? extends AnnotatedWithParams> l = (i == 0) + ? getConstructors() : getFactoryMethods(); + for (AnnotatedWithParams creator : l) { + int argCount = creator.getParameterCount(); + if (argCount < 1) continue; + String name = _annotationIntrospector.findPropertyNameForParam(creator.getParameter(0)); + if (name == null) continue; + if (names == null) { + names = new ArrayList<String>(); + } + names.add(name); + for (int p = 1; p < argCount; ++p) { + names.add(_annotationIntrospector.findPropertyNameForParam(creator.getParameter(p))); + } + } + } + if (names == null) { + return Collections.emptyList(); + } + return names; + } + + /* + /********************************************************** + /* Introspection for serialization, other + /********************************************************** + */ + + /** + * Method for determining whether null properties should be written + * out for a Bean of introspected type. This is based on global + * feature (lowest priority, passed as argument) + * and per-class annotation (highest priority). + */ + public JsonSerialize.Inclusion findSerializationInclusion(JsonSerialize.Inclusion defValue) + { + if (_annotationIntrospector == null) { + return defValue; + } + return _annotationIntrospector.findSerializationInclusion(_classInfo, defValue); + } + + /** + * Method used to locate the method of introspected class that + * implements {@link org.codehaus.jackson.annotate.JsonAnyGetter}. + * If no such method exists null is returned. + * If more than one are found, an exception is thrown. + * + * @since 1.6 + */ + @Override + public AnnotatedMethod findAnyGetter() throws IllegalArgumentException + { + if (_anyGetterMethod != null) { + /* For now let's require a Map; in future can add support for other + * types like perhaps Iterable<Map.Entry>? + */ + Class<?> type = _anyGetterMethod.getRawType(); + if (!Map.class.isAssignableFrom(type)) { + throw new IllegalArgumentException("Invalid 'any-getter' annotation on method "+_anyGetterMethod.getName()+"(): return type is not instance of java.util.Map"); + } + } + return _anyGetterMethod; + } + + /** + * Method for locating all back-reference properties (setters, fields) bean has + * + * @since 1.6 + */ + public Map<String,AnnotatedMember> findBackReferenceProperties() + { + HashMap<String,AnnotatedMember> result = null; + for (BeanPropertyDefinition property : _properties) { + AnnotatedMember am = property.getMutator(); + if (am == null) { + continue; + } + AnnotationIntrospector.ReferenceProperty refDef = _annotationIntrospector.findReferenceType(am); + if (refDef != null && refDef.isBackReference()) { + if (result == null) { + result = new HashMap<String,AnnotatedMember>(); + } + String refName = refDef.getName(); + if (result.put(refName, am) != null) { + throw new IllegalArgumentException("Multiple back-reference properties with name '"+refName+"'"); + } + } + } + return result; + } + + /* + /********************************************************** + /* Helper methods for field introspection + /********************************************************** + */ + + /** + * @param ignoredProperties (optional) names of properties to ignore; + * any fields that would be recognized as one of these properties + * is ignored. + * @param forSerialization If true, will collect serializable property + * fields; if false, deserializable + * + * @return Ordered Map with logical property name as key, and + * matching field as value. + */ + public LinkedHashMap<String,AnnotatedField> _findPropertyFields( + Collection<String> ignoredProperties, boolean forSerialization) + { + LinkedHashMap<String,AnnotatedField> results = new LinkedHashMap<String,AnnotatedField>(); + for (BeanPropertyDefinition property : _properties) { + AnnotatedField f = property.getField(); + if (f != null) { + String name = property.getName(); + if (ignoredProperties != null) { + if (ignoredProperties.contains(name)) { + continue; + } + } + results.put(name, f); + } + } + return results; + } + + /* + /********************************************************** + /* Deprecated methods from BeanDescription + /********************************************************** + */ + + @SuppressWarnings("deprecation") + @Override + public LinkedHashMap<String,AnnotatedMethod> findGetters(VisibilityChecker<?> visibilityChecker, + Collection<String> ignoredProperties) + { + LinkedHashMap<String,AnnotatedMethod> results = new LinkedHashMap<String,AnnotatedMethod>(); + for (BeanPropertyDefinition property : _properties) { + AnnotatedMethod m = property.getGetter(); + if (m != null) { + String name = property.getName(); + if (ignoredProperties != null) { + if (ignoredProperties.contains(name)) { + continue; + } + } + results.put(name, m); + } + } + return results; + } + + @SuppressWarnings("deprecation") + @Override + public LinkedHashMap<String,AnnotatedMethod> findSetters(VisibilityChecker<?> visibilityChecker) + { + LinkedHashMap<String,AnnotatedMethod> results = new LinkedHashMap<String,AnnotatedMethod>(); + for (BeanPropertyDefinition property : _properties) { + AnnotatedMethod m = property.getSetter(); + if (m != null) { + results.put(property.getName(), m); + } + } + return results; + } + + @SuppressWarnings("deprecation") + @Override + public LinkedHashMap<String,AnnotatedField> findSerializableFields(VisibilityChecker<?> visibilityChecker, + Collection<String> ignoredProperties) + { + return _findPropertyFields(ignoredProperties, true); + } + + @SuppressWarnings("deprecation") + @Override + public LinkedHashMap<String,AnnotatedField> findDeserializableFields(VisibilityChecker<?> visibilityChecker, + Collection<String> ignoredProperties) + { + return _findPropertyFields(ignoredProperties, false); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/introspect/BasicClassIntrospector.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/introspect/BasicClassIntrospector.java new file mode 100644 index 0000000..e8b0d0b --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/introspect/BasicClassIntrospector.java
@@ -0,0 +1,364 @@ +package org.codehaus.jackson.map.introspect; + +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.*; + +import org.codehaus.jackson.map.AnnotationIntrospector; +import org.codehaus.jackson.map.ClassIntrospector; +import org.codehaus.jackson.map.DeserializationConfig; +import org.codehaus.jackson.map.MapperConfig; +import org.codehaus.jackson.map.SerializationConfig; +import org.codehaus.jackson.map.type.SimpleType; +import org.codehaus.jackson.map.util.ClassUtil; +import org.codehaus.jackson.type.JavaType; + +public class BasicClassIntrospector + extends ClassIntrospector<BasicBeanDescription> +{ + /* We keep a small set of pre-constructed descriptions to use for + * common non-structured values, such as Numbers and Strings. + * This is strictly performance optimization to reduce what is + * usually one-time cost, but seems useful for some cases considering + * simplicity. + */ + + protected final static BasicBeanDescription STRING_DESC; + static { + AnnotatedClass ac = AnnotatedClass.constructWithoutSuperTypes(String.class, null, null); + STRING_DESC = BasicBeanDescription.forOtherUse(null, SimpleType.constructUnsafe(String.class), ac); + } + protected final static BasicBeanDescription BOOLEAN_DESC; + static { + AnnotatedClass ac = AnnotatedClass.constructWithoutSuperTypes(Boolean.TYPE, null, null); + BOOLEAN_DESC = BasicBeanDescription.forOtherUse(null, SimpleType.constructUnsafe(Boolean.TYPE), ac); + } + protected final static BasicBeanDescription INT_DESC; + static { + AnnotatedClass ac = AnnotatedClass.constructWithoutSuperTypes(Integer.TYPE, null, null); + INT_DESC = BasicBeanDescription.forOtherUse(null, SimpleType.constructUnsafe(Integer.TYPE), ac); + } + protected final static BasicBeanDescription LONG_DESC; + static { + AnnotatedClass ac = AnnotatedClass.constructWithoutSuperTypes(Long.TYPE, null, null); + LONG_DESC = BasicBeanDescription.forOtherUse(null, SimpleType.constructUnsafe(Long.TYPE), ac); + } + + + // // // Then static filter singletons + + /** + * @since 1.8 + * @deprecated Since 1.9 just don't use + */ + @Deprecated + public final static GetterMethodFilter DEFAULT_GETTER_FILTER = new GetterMethodFilter(); + + /** + * @since 1.8 + * @deprecated Since 1.9 just don't use + */ + @Deprecated + public final static SetterMethodFilter DEFAULT_SETTER_FILTER = new SetterMethodFilter(); + + /** + * @since 1.8 + * @deprecated Since 1.9 just don't use + */ + @Deprecated + public final static SetterAndGetterMethodFilter DEFAULT_SETTER_AND_GETTER_FILTER = new SetterAndGetterMethodFilter(); + + protected final static MethodFilter MINIMAL_FILTER = new MinimalMethodFilter(); + + /* + /********************************************************** + /* Life cycle + /********************************************************** + */ + + public final static BasicClassIntrospector instance = new BasicClassIntrospector(); + + public BasicClassIntrospector() { } + + /* + /********************************************************** + /* Factory method impls + /********************************************************** + */ + + @Override + public BasicBeanDescription forSerialization(SerializationConfig cfg, + JavaType type, MixInResolver r) + { + // minor optimization: for JDK types do minimal introspection + BasicBeanDescription desc = _findCachedDesc(type); + if (desc == null) { + desc = BasicBeanDescription.forSerialization(collectProperties(cfg, type, r, true)); + } + return desc; + } + + @Override + public BasicBeanDescription forDeserialization(DeserializationConfig cfg, + JavaType type, MixInResolver r) + { + // minor optimization: for JDK types do minimal introspection + BasicBeanDescription desc = _findCachedDesc(type); + if (desc == null) { + desc = BasicBeanDescription.forDeserialization(collectProperties(cfg, type, r, false)); + } + return desc; + } + + @Override + public BasicBeanDescription forCreation(DeserializationConfig cfg, + JavaType type, MixInResolver r) + { + BasicBeanDescription desc = _findCachedDesc(type); + if (desc == null) { + desc = BasicBeanDescription.forDeserialization(collectProperties(cfg, type, r, false)); + } + return desc; + } + + @Override + public BasicBeanDescription forClassAnnotations(MapperConfig<?> cfg, + JavaType type, MixInResolver r) + { + boolean useAnnotations = cfg.isAnnotationProcessingEnabled(); + AnnotationIntrospector ai = cfg.getAnnotationIntrospector(); + AnnotatedClass ac = AnnotatedClass.construct(type.getRawClass(), (useAnnotations ? ai : null), r); + return BasicBeanDescription.forOtherUse(cfg, type, ac); + } + + @Override + public BasicBeanDescription forDirectClassAnnotations(MapperConfig<?> cfg, + JavaType type, MixInResolver r) + { + boolean useAnnotations = cfg.isAnnotationProcessingEnabled(); + AnnotationIntrospector ai = cfg.getAnnotationIntrospector(); + AnnotatedClass ac = AnnotatedClass.constructWithoutSuperTypes(type.getRawClass(), + (useAnnotations ? ai : null), r); + return BasicBeanDescription.forOtherUse(cfg, type, ac); + } + + /* + /********************************************************** + /* Overridable helper methods + /********************************************************** + */ + + /** + * @since 1.9 + */ + public POJOPropertiesCollector collectProperties(MapperConfig<?> config, + JavaType type, MixInResolver r, boolean forSerialization) + { + AnnotatedClass ac = classWithCreators(config, type, r); + ac.resolveMemberMethods(MINIMAL_FILTER); + ac.resolveFields(); + return constructPropertyCollector(config, ac, type, forSerialization).collect(); + } + + /** + * Overridable method called for creating {@link POJOPropertiesCollector} instance + * to use; override is needed if a custom sub-class is to be used. + * + * @since 1.9 + */ + protected POJOPropertiesCollector constructPropertyCollector(MapperConfig<?> config, + AnnotatedClass ac, JavaType type, + boolean forSerialization) + { + return new POJOPropertiesCollector(config, forSerialization, type, ac); + } + + /** + * @since 1.9 + */ + public AnnotatedClass classWithCreators(MapperConfig<?> config, + JavaType type, MixInResolver r) + { + boolean useAnnotations = config.isAnnotationProcessingEnabled(); + AnnotationIntrospector ai = config.getAnnotationIntrospector(); + AnnotatedClass ac = AnnotatedClass.construct(type.getRawClass(), (useAnnotations ? ai : null), r); + ac.resolveMemberMethods(MINIMAL_FILTER); + // true -> include all creators, not just default constructor + ac.resolveCreators(true); + return ac; + } + + /** + * Method called to see if type is one of core JDK types + * that we have cached for efficiency. + * + * @since 1.9 + */ + protected BasicBeanDescription _findCachedDesc(JavaType type) + { + Class<?> cls = type.getRawClass(); + if (cls == String.class) { + return STRING_DESC; + } + if (cls == Boolean.TYPE) { + return BOOLEAN_DESC; + } + if (cls == Integer.TYPE) { + return INT_DESC; + } + if (cls == Long.TYPE) { + return LONG_DESC; + } + return null; + } + + /** + * Helper method for getting access to filter that only guarantees + * that methods used for serialization are to be included. + * + * @deprecated Since 1.9 just don't use + */ + @Deprecated + protected MethodFilter getSerializationMethodFilter(SerializationConfig cfg) + { + return DEFAULT_GETTER_FILTER; + } + + /** + * Helper method for getting access to filter that only guarantees + * that methods used for deserialization are to be included. + * + * @deprecated Since 1.9 just don't use + */ + @Deprecated + protected MethodFilter getDeserializationMethodFilter(DeserializationConfig cfg) + { + /* [JACKSON-88]: may also need to include getters (at least for + * Collection and Map types) + */ + if (cfg.isEnabled(DeserializationConfig.Feature.USE_GETTERS_AS_SETTERS)) { + return DEFAULT_SETTER_AND_GETTER_FILTER; + + } + return DEFAULT_SETTER_FILTER; + } + + /* + /********************************************************** + /* Helper classes + /********************************************************** + */ + + /** + * Going forward, we will only do very minimal filtering; + * mostly just gets rid of static methods really. + * + * @since 1.9 + */ + private static class MinimalMethodFilter + implements MethodFilter + { + @Override + public boolean includeMethod(Method m) + { + if (Modifier.isStatic(m.getModifiers())) { + return false; + } + int pcount = m.getParameterTypes().length; + return (pcount <= 2); + } + } + + /** + * Filter used to only include methods that have signature that is + * compatible with "getters": take no arguments, are non-static, + * and return something. + * + * @deprecated Since 1.9 just don't use + */ + @Deprecated + public static class GetterMethodFilter + implements MethodFilter + { + private GetterMethodFilter() { } + + @Override + public boolean includeMethod(Method m) + { + return ClassUtil.hasGetterSignature(m); + } + } + + /** + * Filter used to only include methods that have signature that is + * compatible with "setters": take one and only argument and + * are non-static. + *<p> + * Actually, also need to include 2-arg methods to support + * "any setters"; as well as 0-arg getters as long as they + * return Collection or Map type. + * + * @deprecated Since 1.9 just don't use + */ + @Deprecated + public static class SetterMethodFilter + implements MethodFilter + { + @Override + public boolean includeMethod(Method m) + { + // First: we can't use static methods + if (Modifier.isStatic(m.getModifiers())) { + return false; + } + int pcount = m.getParameterTypes().length; + // Ok; multiple acceptable parameter counts: + switch (pcount) { + case 1: + // Regular setters take just one param, so include: + return true; + case 2: + /* 2-arg version only for "AnySetters"; they are not + * auto-detected, and need to have an annotation. + * However, due to annotation inheritance we do, we + * don't yet know if sub-classes might have annotations... + * so shouldn't leave out any methods quite yet. + */ + //if (m.getAnnotation(JsonAnySetter.class) != null) { ... } + + return true; + } + return false; + } + } + + /** + * Filter used if some getters (namely, once needed for "setterless + * collection injection") are also needed, not just setters. + * + * @deprecated Since 1.9 just don't use + */ + @Deprecated + public final static class SetterAndGetterMethodFilter + extends SetterMethodFilter + { + @SuppressWarnings("deprecation") + @Override + public boolean includeMethod(Method m) + { + if (super.includeMethod(m)) { + return true; + } + if (!ClassUtil.hasGetterSignature(m)) { + return false; + } + // but furthermore, only accept Collections & Maps, for now + Class<?> rt = m.getReturnType(); + if (Collection.class.isAssignableFrom(rt) + || Map.class.isAssignableFrom(rt)) { + return true; + } + return false; + } + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/introspect/JacksonAnnotationIntrospector.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/introspect/JacksonAnnotationIntrospector.java new file mode 100644 index 0000000..d828087 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/introspect/JacksonAnnotationIntrospector.java
@@ -0,0 +1,813 @@ +package org.codehaus.jackson.map.introspect; + +import java.lang.annotation.Annotation; +import java.util.ArrayList; +import java.util.List; + +import org.codehaus.jackson.annotate.*; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.*; +import org.codehaus.jackson.map.jsontype.NamedType; +import org.codehaus.jackson.map.jsontype.TypeIdResolver; +import org.codehaus.jackson.map.jsontype.TypeResolverBuilder; +import org.codehaus.jackson.map.jsontype.impl.StdTypeResolverBuilder; +import org.codehaus.jackson.map.ser.std.RawSerializer; +import org.codehaus.jackson.type.JavaType; + +/** + * {@link AnnotationIntrospector} implementation that handles standard + * Jackson annotations. + */ +public class JacksonAnnotationIntrospector + extends AnnotationIntrospector +{ + public JacksonAnnotationIntrospector() { } + + /* + /********************************************************** + /* General annotation properties + /********************************************************** + */ + + @Override + public boolean isHandled(Annotation ann) + { + Class<? extends Annotation> acls = ann.annotationType(); + + /* 16-May-2009, tatu: used to check this like so... + final String JACKSON_PKG_PREFIX = "org.codehaus.jackson"; + + Package pkg = acls.getPackage(); + return (pkg != null) && (pkg.getName().startsWith(JACKSON_PKG_PREFIX)); + */ + + // but this is more reliable, now that we have tag annotation: + return acls.getAnnotation(JacksonAnnotation.class) != null; + } + + /* + /********************************************************** + /* General annotations + /********************************************************** + */ + + @Override + public String findEnumValue(Enum<?> value) + { + return value.name(); + } + + /* + /********************************************************** + /* General class annotations + /********************************************************** + */ + + @Override + public Boolean findCachability(AnnotatedClass ac) + { + JsonCachable ann = ac.getAnnotation(JsonCachable.class); + if (ann == null) { + return null; + } + return ann.value() ? Boolean.TRUE : Boolean.FALSE; + } + + @Override + public String findRootName(AnnotatedClass ac) + { + JsonRootName ann = ac.getAnnotation(JsonRootName.class); + return (ann == null) ? null : ann.value(); + } + + @Override + public String[] findPropertiesToIgnore(AnnotatedClass ac) { + JsonIgnoreProperties ignore = ac.getAnnotation(JsonIgnoreProperties.class); + return (ignore == null) ? null : ignore.value(); + } + + @Override + public Boolean findIgnoreUnknownProperties(AnnotatedClass ac) { + JsonIgnoreProperties ignore = ac.getAnnotation(JsonIgnoreProperties.class); + return (ignore == null) ? null : ignore.ignoreUnknown(); + } + + @Override + public Boolean isIgnorableType(AnnotatedClass ac) { + JsonIgnoreType ignore = ac.getAnnotation(JsonIgnoreType.class); + return (ignore == null) ? null : ignore.value(); + } + + @Override + public Object findFilterId(AnnotatedClass ac) + { + JsonFilter ann = ac.getAnnotation(JsonFilter.class); + if (ann != null) { + String id = ann.value(); + // Empty String is same as not having annotation, to allow overrides + if (id.length() > 0) { + return id; + } + } + return null; + } + + /* + /********************************************************** + /* Property auto-detection + /********************************************************** + */ + + @Override + public VisibilityChecker<?> findAutoDetectVisibility(AnnotatedClass ac, + VisibilityChecker<?> checker) + { + JsonAutoDetect ann = ac.getAnnotation(JsonAutoDetect.class); + return (ann == null) ? checker : checker.with(ann); + } + + /* + /********************************************************** + /* General member (field, method/constructor) annotations + /********************************************************** + */ + + // @since 1.6 + @Override + public ReferenceProperty findReferenceType(AnnotatedMember member) + { + JsonManagedReference ref1 = member.getAnnotation(JsonManagedReference.class); + if (ref1 != null) { + return AnnotationIntrospector.ReferenceProperty.managed(ref1.value()); + } + JsonBackReference ref2 = member.getAnnotation(JsonBackReference.class); + if (ref2 != null) { + return AnnotationIntrospector.ReferenceProperty.back(ref2.value()); + } + return null; + } + + @Override + public Boolean shouldUnwrapProperty(AnnotatedMember member) + { + JsonUnwrapped ann = member.getAnnotation(JsonUnwrapped.class); + // if not enabled, just means annotation is not enabled; not necessarily + // that unwrapping should not be done (relevant when using chained introspectors) + return (ann != null && ann.enabled()) ? Boolean.TRUE : null; + } + + @Override + public boolean hasIgnoreMarker(AnnotatedMember m) { + return _isIgnorable(m); + } + + @Override + public Object findInjectableValueId(AnnotatedMember m) + { + JacksonInject ann = m.getAnnotation(JacksonInject.class); + if (ann == null) { + return null; + } + /* Empty String means that we should use name of declared + * value class. + */ + String id = ann.value(); + if (id.length() == 0) { + // slight complication; for setters, type + if (!(m instanceof AnnotatedMethod)) { + return m.getRawType().getName(); + } + AnnotatedMethod am = (AnnotatedMethod) m; + if (am.getParameterCount() == 0) { + return m.getRawType().getName(); + } + return am.getParameterClass(0).getName(); + } + return id; + } + + /* + /********************************************************** + /* Class annotations for PM type handling (1.5+) + /********************************************************** + */ + + @Override + public TypeResolverBuilder<?> findTypeResolver(MapperConfig<?> config, + AnnotatedClass ac, JavaType baseType) + { + return _findTypeResolver(config, ac, baseType); + } + + /** + * Since 1.7, it is possible to use {@link JsonTypeInfo} from a property too. + */ + @Override + public TypeResolverBuilder<?> findPropertyTypeResolver(MapperConfig<?> config, + AnnotatedMember am, JavaType baseType) + { + /* As per definition of @JsonTypeInfo, should only apply to contents of container + * (collection, map) types, not container types themselves: + */ + if (baseType.isContainerType()) return null; + // No per-member type overrides (yet) + return _findTypeResolver(config, am, baseType); + } + + /** + * Since 1.7, it is possible to use {@link JsonTypeInfo} from a property too. + */ + @Override + public TypeResolverBuilder<?> findPropertyContentTypeResolver(MapperConfig<?> config, + AnnotatedMember am, JavaType containerType) + { + /* First: let's ensure property is a container type: caller should have + * verified but just to be sure + */ + if (!containerType.isContainerType()) { + throw new IllegalArgumentException("Must call method with a container type (got "+containerType+")"); + } + return _findTypeResolver(config, am, containerType); + } + + @Override + public List<NamedType> findSubtypes(Annotated a) + { + JsonSubTypes t = a.getAnnotation(JsonSubTypes.class); + if (t == null) return null; + JsonSubTypes.Type[] types = t.value(); + ArrayList<NamedType> result = new ArrayList<NamedType>(types.length); + for (JsonSubTypes.Type type : types) { + result.add(new NamedType(type.value(), type.name())); + } + return result; + } + + @Override + public String findTypeName(AnnotatedClass ac) + { + JsonTypeName tn = ac.getAnnotation(JsonTypeName.class); + return (tn == null) ? null : tn.value(); + } + + /* + /********************************************************** + /* General method annotations + /********************************************************** + */ + + @Override + public boolean isIgnorableMethod(AnnotatedMethod m) { + return _isIgnorable(m); + } + + @Override + public boolean isIgnorableConstructor(AnnotatedConstructor c) { + return _isIgnorable(c); + } + + /* + /********************************************************** + /* General field annotations + /********************************************************** + */ + + @Override + public boolean isIgnorableField(AnnotatedField f) { + return _isIgnorable(f); + } + + /* + /********************************************************** + /* Serialization: general annotations + /********************************************************** + */ + + @Override + public Object findSerializer(Annotated a) + { + /* 21-May-2009, tatu: Slight change; primary annotation is now + * @JsonSerialize; @JsonUseSerializer is deprecated + */ + JsonSerialize ann = a.getAnnotation(JsonSerialize.class); + if (ann != null) { + Class<? extends JsonSerializer<?>> serClass = ann.using(); + if (serClass != JsonSerializer.None.class) { + return serClass; + } + } + + /* 18-Oct-2010, tatu: [JACKSON-351] @JsonRawValue handled just here, for now; + * if we need to get raw indicator from other sources need to add + * separate accessor within {@link AnnotationIntrospector} interface. + */ + JsonRawValue annRaw = a.getAnnotation(JsonRawValue.class); + if ((annRaw != null) && annRaw.value()) { + // let's construct instance with nominal type: + Class<?> cls = a.getRawType(); + return new RawSerializer<Object>(cls); + } + return null; + } + + @Override + public Class<? extends JsonSerializer<?>> findKeySerializer(Annotated a) + { + JsonSerialize ann = a.getAnnotation(JsonSerialize.class); + if (ann != null) { + Class<? extends JsonSerializer<?>> serClass = ann.keyUsing(); + if (serClass != JsonSerializer.None.class) { + return serClass; + } + } + return null; + } + + @Override + public Class<? extends JsonSerializer<?>> findContentSerializer(Annotated a) + { + JsonSerialize ann = a.getAnnotation(JsonSerialize.class); + if (ann != null) { + Class<? extends JsonSerializer<?>> serClass = ann.contentUsing(); + if (serClass != JsonSerializer.None.class) { + return serClass; + } + } + return null; + } + + @SuppressWarnings("deprecation") + @Override + public JsonSerialize.Inclusion findSerializationInclusion(Annotated a, JsonSerialize.Inclusion defValue) + { + JsonSerialize ann = a.getAnnotation(JsonSerialize.class); + if (ann != null) { + return ann.include(); + } + /* 23-May-2009, tatu: Will still support now-deprecated (as of 1.1) + * legacy annotation too: + */ + JsonWriteNullProperties oldAnn = a.getAnnotation(JsonWriteNullProperties.class); + if (oldAnn != null) { + boolean writeNulls = oldAnn.value(); + return writeNulls ? JsonSerialize.Inclusion.ALWAYS : JsonSerialize.Inclusion.NON_NULL; + } + return defValue; + } + + @Override + public Class<?> findSerializationType(Annotated am) + { + JsonSerialize ann = am.getAnnotation(JsonSerialize.class); + if (ann != null) { + Class<?> cls = ann.as(); + if (cls != NoClass.class) { + return cls; + } + } + return null; + } + + @Override + public Class<?> findSerializationKeyType(Annotated am, JavaType baseType) + { + JsonSerialize ann = am.getAnnotation(JsonSerialize.class); + if (ann != null) { + Class<?> cls = ann.keyAs(); + if (cls != NoClass.class) { + return cls; + } + } + return null; + } + + @Override + public Class<?> findSerializationContentType(Annotated am, JavaType baseType) + { + JsonSerialize ann = am.getAnnotation(JsonSerialize.class); + if (ann != null) { + Class<?> cls = ann.contentAs(); + if (cls != NoClass.class) { + return cls; + } + } + return null; + } + + @Override + public JsonSerialize.Typing findSerializationTyping(Annotated a) + { + JsonSerialize ann = a.getAnnotation(JsonSerialize.class); + return (ann == null) ? null : ann.typing(); + } + + @Override + public Class<?>[] findSerializationViews(Annotated a) + { + JsonView ann = a.getAnnotation(JsonView.class); + return (ann == null) ? null : ann.value(); + } + + /* + /********************************************************** + /* Serialization: class annotations + /********************************************************** + */ + + @Override + public String[] findSerializationPropertyOrder(AnnotatedClass ac) { + JsonPropertyOrder order = ac.getAnnotation(JsonPropertyOrder.class); + return (order == null) ? null : order.value(); + } + + @Override + public Boolean findSerializationSortAlphabetically(AnnotatedClass ac) { + JsonPropertyOrder order = ac.getAnnotation(JsonPropertyOrder.class); + return (order == null) ? null : order.alphabetic(); + } + + /* + /********************************************************** + /* Serialization: method annotations + /********************************************************** + */ + + @SuppressWarnings("deprecation") + @Override + public String findGettablePropertyName(AnnotatedMethod am) + { + /* 22-May-2009, tatu: JsonProperty is the primary annotation + * to check for + */ + JsonProperty pann = am.getAnnotation(JsonProperty.class); + if (pann != null) { + return pann.value(); + } + /* 22-May-2009, tatu: JsonGetter is deprecated as of 1.1 + * but still supported + */ + JsonGetter ann = am.getAnnotation(JsonGetter.class); + if (ann != null) { + return ann.value(); + } + /* 22-May-2009, tatu: And finally, JsonSerialize implies + * that there is a property, although doesn't define name + */ + // 09-Apr-2010, tatu: Ditto for JsonView + if (am.hasAnnotation(JsonSerialize.class) || am.hasAnnotation(JsonView.class)) { + return ""; + } + return null; + } + + @Override + public boolean hasAsValueAnnotation(AnnotatedMethod am) + { + JsonValue ann = am.getAnnotation(JsonValue.class); + // value of 'false' means disabled... + return (ann != null && ann.value()); + } + + /* + /********************************************************** + /* Serialization: field annotations + /********************************************************** + */ + + @Override + public String findSerializablePropertyName(AnnotatedField af) + { + JsonProperty pann = af.getAnnotation(JsonProperty.class); + if (pann != null) { + return pann.value(); + } + // Also: having JsonSerialize implies it is such a property + // 09-Apr-2010, tatu: Ditto for JsonView + if (af.hasAnnotation(JsonSerialize.class) || af.hasAnnotation(JsonView.class)) { + return ""; + } + return null; + } + + /* + /********************************************************** + /* Deserialization: general annotations + /********************************************************** + */ + + @Override + public Class<? extends JsonDeserializer<?>> findDeserializer(Annotated a) + { + /* 21-May-2009, tatu: Slight change; primary annotation is now + * @JsonDeserialize; @JsonUseDeserializer is deprecated + */ + JsonDeserialize ann = a.getAnnotation(JsonDeserialize.class); + if (ann != null) { + Class<? extends JsonDeserializer<?>> deserClass = ann.using(); + if (deserClass != JsonDeserializer.None.class) { + return deserClass; + } + } + // 31-Jan-2010, tatus: @JsonUseDeserializer removed as of 1.5 + return null; + } + + @Override + public Class<? extends KeyDeserializer> findKeyDeserializer(Annotated a) + { + JsonDeserialize ann = a.getAnnotation(JsonDeserialize.class); + if (ann != null) { + Class<? extends KeyDeserializer> deserClass = ann.keyUsing(); + if (deserClass != KeyDeserializer.None.class) { + return deserClass; + } + } + return null; + } + + @Override + public Class<? extends JsonDeserializer<?>> findContentDeserializer(Annotated a) + { + JsonDeserialize ann = a.getAnnotation(JsonDeserialize.class); + if (ann != null) { + Class<? extends JsonDeserializer<?>> deserClass = ann.contentUsing(); + if (deserClass != JsonDeserializer.None.class) { + return deserClass; + } + } + return null; + } + + @Override + public Class<?> findDeserializationType(Annotated am, JavaType baseType, + String propName) + { + // Primary annotation, JsonDeserialize + JsonDeserialize ann = am.getAnnotation(JsonDeserialize.class); + if (ann != null) { + Class<?> cls = ann.as(); + if (cls != NoClass.class) { + return cls; + } + } + /* 30-Jun-2011, tatu: Here we used to have support for @JsonClass; + * removed in 1.9 + */ + return null; + } + + @Override + public Class<?> findDeserializationKeyType(Annotated am, JavaType baseKeyType, + String propName) + { + // Primary annotation, JsonDeserialize + JsonDeserialize ann = am.getAnnotation(JsonDeserialize.class); + if (ann != null) { + Class<?> cls = ann.keyAs(); + if (cls != NoClass.class) { + return cls; + } + } + /* 30-Jun-2011, tatu: Here we used to have support for @JsonKeyClass; + * removed in 1.9 + */ + return null; + } + + @Override + public Class<?> findDeserializationContentType(Annotated am, JavaType baseContentType, + String propName) + { + // Primary annotation, JsonDeserialize + JsonDeserialize ann = am.getAnnotation(JsonDeserialize.class); + if (ann != null) { + Class<?> cls = ann.contentAs(); + if (cls != NoClass.class) { + return cls; + } + } + /* 30-Jun-2011, tatu: Here we used to have support for @JsonContentClass; + * removed in 1.9 + */ + return null; + } + + /* + /********************************************************** + /* Deserialization: Class annotations + /********************************************************** + */ + + @Override + public Object findValueInstantiator(AnnotatedClass ac) + { + JsonValueInstantiator ann = ac.getAnnotation(JsonValueInstantiator.class); + // no 'null' marker yet, so: + return (ann == null) ? null : ann.value(); + } + + /* + /********************************************************** + /* Deserialization: Method annotations + /********************************************************** + */ + + @Override + public String findSettablePropertyName(AnnotatedMethod am) + { + /* 16-Apr-2010, tatu: Existing priority (since 1.1) is that + * @JsonProperty is checked first; and @JsonSetter next. + * This is not quite optimal now that @JsonSetter is un-deprecated. + * However, it is better to have stable behavior rather than + * cause compatibility problems by fine-tuning. + */ + JsonProperty pann = am.getAnnotation(JsonProperty.class); + if (pann != null) { + return pann.value(); + } + JsonSetter ann = am.getAnnotation(JsonSetter.class); + if (ann != null) { + return ann.value(); + } + /* 22-May-2009, tatu: And finally, JsonSerialize implies + * that there is a property, although doesn't define name + */ + // 09-Apr-2010, tatu: Ditto for JsonView + // 19-Oct-2011, tatu: And JsonBackReference/JsonManagedReference + if (am.hasAnnotation(JsonDeserialize.class) + || am.hasAnnotation(JsonView.class) + || am.hasAnnotation(JsonBackReference.class) + || am.hasAnnotation(JsonManagedReference.class) + ) { + return ""; + } + return null; + } + + @Override + public boolean hasAnySetterAnnotation(AnnotatedMethod am) + { + /* No dedicated disabling; regular @JsonIgnore used + * if needs to be ignored (and if so, is handled prior + * to this method getting called) + */ + return am.hasAnnotation(JsonAnySetter.class); + } + + @Override + public boolean hasAnyGetterAnnotation(AnnotatedMethod am) + { + /* No dedicated disabling; regular @JsonIgnore used + * if needs to be ignored (handled separately + */ + return am.hasAnnotation(JsonAnyGetter.class); + } + + @Override + public boolean hasCreatorAnnotation(Annotated a) + { + /* No dedicated disabling; regular @JsonIgnore used + * if needs to be ignored (and if so, is handled prior + * to this method getting called) + */ + return a.hasAnnotation(JsonCreator.class); + } + + /* + /********************************************************** + /* Deserialization: field annotations + /********************************************************** + */ + + @Override + public String findDeserializablePropertyName(AnnotatedField af) + { + JsonProperty pann = af.getAnnotation(JsonProperty.class); + if (pann != null) { + return pann.value(); + } + // Also: having JsonDeserialize implies it is such a property + // 09-Apr-2010, tatu: Ditto for JsonView + if (af.hasAnnotation(JsonDeserialize.class) + || af.hasAnnotation(JsonView.class) + || af.hasAnnotation(JsonBackReference.class) + || af.hasAnnotation(JsonManagedReference.class) + ) { + return ""; + } + return null; + } + + /* + /********************************************************** + /* Deserialization: parameters annotations + /********************************************************** + */ + + @Override + public String findPropertyNameForParam(AnnotatedParameter param) + { + if (param != null) { + JsonProperty pann = param.getAnnotation(JsonProperty.class); + if (pann != null) { + return pann.value(); + } + /* And can not use JsonDeserialize as we can not use + * name auto-detection (names of local variables including + * parameters are not necessarily preserved in bytecode) + */ + } + return null; + } + + /* + /********************************************************** + /* Helper methods + /********************************************************** + */ + + protected boolean _isIgnorable(Annotated a) + { + JsonIgnore ann = a.getAnnotation(JsonIgnore.class); + return (ann != null && ann.value()); + } + + /** + * Helper method called to construct and initialize instance of {@link TypeResolverBuilder} + * if given annotated element indicates one is needed. + */ + protected TypeResolverBuilder<?> _findTypeResolver(MapperConfig<?> config, + Annotated ann, JavaType baseType) + { + // First: maybe we have explicit type resolver? + TypeResolverBuilder<?> b; + JsonTypeInfo info = ann.getAnnotation(JsonTypeInfo.class); + JsonTypeResolver resAnn = ann.getAnnotation(JsonTypeResolver.class); + if (resAnn != null) { + /* 14-Aug-2010, tatu: not sure if this can ever happen normally, but unit + * tests were able to trigger this... so let's check: + */ + if (info == null) { + return null; + } + /* let's not try to force access override (would need to pass + * settings through if we did, since that's not doable on some + * platforms) + */ + b = config.typeResolverBuilderInstance(ann, resAnn.value()); + } else { // if not, use standard one, if indicated by annotations + if (info == null) { + return null; + } + // bit special; must return 'marker' to block use of default typing: + if (info.use() == JsonTypeInfo.Id.NONE) { + return _constructNoTypeResolverBuilder(); + } + b = _constructStdTypeResolverBuilder(); + } + // Does it define a custom type id resolver? + JsonTypeIdResolver idResInfo = ann.getAnnotation(JsonTypeIdResolver.class); + TypeIdResolver idRes = (idResInfo == null) ? null + : config.typeIdResolverInstance(ann, idResInfo.value()); + if (idRes != null) { // [JACKSON-359] + idRes.init(baseType); + } + b = b.init(info.use(), idRes); + /* 13-Aug-2011, tatu: One complication wrt [JACKSON-453]; external id + * only works for properties; so if declared for a Class, we will need + * to map it to "PROPERTY" instead of "EXTERNAL_PROPERTY" + */ + JsonTypeInfo.As inclusion = info.include(); + if (inclusion == JsonTypeInfo.As.EXTERNAL_PROPERTY && (ann instanceof AnnotatedClass)) { + inclusion = JsonTypeInfo.As.PROPERTY; + } + b = b.inclusion(inclusion); + b = b.typeProperty(info.property()); + Class<?> defaultImpl = info.defaultImpl(); + if (defaultImpl != JsonTypeInfo.None.class) { + b = b.defaultImpl(defaultImpl); + } + return b; + } + + /** + * Helper method for constructing standard {@link TypeResolverBuilder} + * implementation. + * + * @since 1.7 + */ + protected StdTypeResolverBuilder _constructStdTypeResolverBuilder() + { + return new StdTypeResolverBuilder(); + } + + /** + * Helper method for dealing with "no type info" marker; can't be null + * (as it'd be replaced by default typing) + * + * @since 1.9.4 + */ + protected StdTypeResolverBuilder _constructNoTypeResolverBuilder() { + return StdTypeResolverBuilder.noTypeInfoBuilder(); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/introspect/MemberKey.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/introspect/MemberKey.java new file mode 100644 index 0000000..e602892 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/introspect/MemberKey.java
@@ -0,0 +1,83 @@ +package org.codehaus.jackson.map.introspect; + +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; + +/** + * Helper class needed to be able to efficiently access class + * member functions ({@link Method}s and {@link Constructor}s) + * in {@link java.util.Map}s. + */ +public final class MemberKey +{ + final static Class<?>[] NO_CLASSES = new Class<?>[0]; + + final String _name; + final Class<?>[] _argTypes; + + public MemberKey(Method m) + { + this(m.getName(), m.getParameterTypes()); + } + + public MemberKey(Constructor<?> ctor) + { + this("", ctor.getParameterTypes()); + } + + public MemberKey(String name, Class<?>[] argTypes) + { + _name = name; + _argTypes = (argTypes == null) ? NO_CLASSES : argTypes; + } + + @Override + public String toString() { + return _name + "(" + _argTypes.length+"-args)"; + } + + @Override + public int hashCode() + { + return _name.hashCode() + _argTypes.length; + } + + @Override + public boolean equals(Object o) + { + if (o == this) return true; + if (o == null) return false; + if (o.getClass() != getClass()) { + return false; + } + MemberKey other = (MemberKey) o; + if (!_name.equals(other._name)) { + return false; + } + Class<?>[] otherArgs = other._argTypes; + int len = _argTypes.length; + if (otherArgs.length != len) { + return false; + } + for (int i = 0; i < len; ++i) { + Class<?> type1 = otherArgs[i]; + Class<?> type2 = _argTypes[i]; + if (type1 == type2) { + continue; + } + /* 23-Feb-2009, tatu: Are there any cases where we would have to + * consider some narrowing conversions or such? For now let's + * assume exact type match is enough + */ + /* 07-Apr-2009, tatu: Indeed there are (see [JACKSON-97]). + * This happens with generics when a bound is specified. + * I hope this works; check here must be transitive + */ + if (type1.isAssignableFrom(type2) || type2.isAssignableFrom(type1)) { + continue; + } + return false; + } + return true; + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/introspect/MethodFilter.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/introspect/MethodFilter.java new file mode 100644 index 0000000..fe3df1d --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/introspect/MethodFilter.java
@@ -0,0 +1,12 @@ +package org.codehaus.jackson.map.introspect; + +import java.lang.reflect.Method; + +/** + * Simple interface that defines API used to filter out irrelevant + * methods + */ +public interface MethodFilter +{ + public boolean includeMethod(Method m); +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/introspect/NopAnnotationIntrospector.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/introspect/NopAnnotationIntrospector.java new file mode 100644 index 0000000..72012c1 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/introspect/NopAnnotationIntrospector.java
@@ -0,0 +1,209 @@ +package org.codehaus.jackson.map.introspect; + +import java.lang.annotation.Annotation; + +import org.codehaus.jackson.type.JavaType; +import org.codehaus.jackson.map.JsonDeserializer; +import org.codehaus.jackson.map.KeyDeserializer; +import org.codehaus.jackson.map.AnnotationIntrospector; +import org.codehaus.jackson.map.annotate.JsonSerialize.Typing; + +/** + * Dummy, "no-operation" implementation of {@link AnnotationIntrospector}. + * Can be used as is to suppress handling of annotations; or as a basis + * for simple complementary annotators + */ +public class NopAnnotationIntrospector + extends AnnotationIntrospector +{ + /** + * Static immutable and shareable instance that can be used as + * "null" introspector: one that never finds any annotation + * information. + */ + public final static NopAnnotationIntrospector instance = new NopAnnotationIntrospector(); + + /* + /********************************************************** + /* General annotation properties + /********************************************************** + */ + + @Override + public boolean isHandled(Annotation ann) { + return false; + } + + /* + /********************************************************** + /* General annotations + /********************************************************** + */ + + @Override + public String findEnumValue(Enum<?> value) { + return null; + } + + /* + /********************************************************** + /* General Class annotations + /********************************************************** + */ + + @Override + public String findRootName(AnnotatedClass ac) { + return null; + } + + @Override + public String[] findPropertiesToIgnore(AnnotatedClass ac) { + return null; + } + + @Override + public Boolean findIgnoreUnknownProperties(AnnotatedClass ac) { + return null; + } + + /* + /********************************************************** + /* General member (field, method/constructor) annotations + /********************************************************** + */ + + @Override + public boolean hasIgnoreMarker(AnnotatedMember member) { + return false; + } + + /* + /********************************************************** + /* General Method annotations + /********************************************************** + */ + + @Override + public boolean isIgnorableConstructor(AnnotatedConstructor c) { + return false; + } + + @Override + public boolean isIgnorableMethod(AnnotatedMethod m) { + return false; + } + + /* + /********************************************************** + /* General field annotations + /********************************************************** + */ + + @Override + public boolean isIgnorableField(AnnotatedField f) { + return false; + } + + /* + /********************************************************** + /* Serialization: general annotations + /********************************************************** + */ + + @Override + public Object findSerializer(Annotated am) { + return null; + } + + @Override + public Class<?> findSerializationType(Annotated a) { + return null; + } + + @Override + public Typing findSerializationTyping(Annotated a) { + return null; + } + + @Override + public Class<?>[] findSerializationViews(Annotated a) { + return null; + } + + /* + /********************************************************** + /* Serialization: class annotations + /********************************************************** + */ + + @Override + public String[] findSerializationPropertyOrder(AnnotatedClass ac) { + return null; + } + + @Override + public Boolean findSerializationSortAlphabetically(AnnotatedClass ac) { + return null; + } + + /* + /********************************************************** + /* Serialization: method annotations + /********************************************************** + */ + + @Override + public String findGettablePropertyName(AnnotatedMethod am) { + return null; + } + + @Override + public boolean hasAsValueAnnotation(AnnotatedMethod am) { + return false; + } + + @Override + public String findDeserializablePropertyName(AnnotatedField af) { + return null; + } + + @Override + public Class<?> findDeserializationContentType(Annotated am, JavaType t, String propName) { + return null; + } + + @Override + public Class<?> findDeserializationKeyType(Annotated am, JavaType t, String propName) { + return null; + } + + @Override + public Class<?> findDeserializationType(Annotated am, JavaType t, String propName) { + return null; + } + + @Override + public Object findDeserializer(Annotated am) { return null; } + + @Override + public Class<KeyDeserializer> findKeyDeserializer(Annotated am) { return null; } + + @Override + public Class<JsonDeserializer<?>> findContentDeserializer(Annotated am) { return null; } + + + @Override + public String findPropertyNameForParam(AnnotatedParameter param) { + return null; + } + + @Override + public String findSerializablePropertyName(AnnotatedField af) { + return null; + } + + @Override + public String findSettablePropertyName(AnnotatedMethod am) { + return null; + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/introspect/POJOPropertiesCollector.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/introspect/POJOPropertiesCollector.java new file mode 100644 index 0000000..d1af9df --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/introspect/POJOPropertiesCollector.java
@@ -0,0 +1,713 @@ +package org.codehaus.jackson.map.introspect; + +import java.util.*; + +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.util.BeanUtil; +import org.codehaus.jackson.type.JavaType; + +/** + * Helper class used for aggregating information about all possible + * properties of a POJO. + * + * @since 1.9 + */ +public class POJOPropertiesCollector +{ + /* + /********************************************************** + /* Configuration + /********************************************************** + */ + + /** + * Configuration settings + */ + protected final MapperConfig<?> _config; + + /** + * True if introspection is done for serialization (giving + * precedence for serialization annotations), or not (false, deserialization) + */ + protected final boolean _forSerialization; + + /** + * Type of POJO for which properties are being collected. + */ + protected final JavaType _type; + + /** + * Low-level introspected class information (methods, fields etc) + */ + protected final AnnotatedClass _classDef; + + protected final VisibilityChecker<?> _visibilityChecker; + + protected final AnnotationIntrospector _annotationIntrospector; + + /* + /********************************************************** + /* Collected information + /********************************************************** + */ + + /** + * Set of logical property information collected so far + */ + protected final LinkedHashMap<String, POJOPropertyBuilder> _properties + = new LinkedHashMap<String, POJOPropertyBuilder>(); + + protected LinkedList<POJOPropertyBuilder> _creatorProperties = null; + + protected LinkedList<AnnotatedMethod> _anyGetters = null; + + protected LinkedList<AnnotatedMethod> _anySetters = null; + + /** + * Method(s) marked with 'JsonValue' annotation + */ + protected LinkedList<AnnotatedMethod> _jsonValueGetters = null; + + /** + * Lazily collected list of properties that can be implicitly + * ignored during serialization; only updated when collecting + * information for deserialization purposes + */ + protected Set<String> _ignoredPropertyNames; + + /** + * Alternate set of property names that have been marked for + * explicit ignoral for deserialization: needed to deal with + * 1.x definition of ignorable with respect to "any setter" + * (see [JACKSON-313], [JACKSON-383]) + * + * @since 1.9.4 + */ + protected Set<String> _ignoredPropertyNamesForDeser; + + /** + * Lazily collected list of members that were annotated to + * indicate that they represent mutators for deserializer + * value injection. + */ + protected LinkedHashMap<Object, AnnotatedMember> _injectables; + + /* + /********************************************************** + /* Life-cycle + /********************************************************** + */ + + protected POJOPropertiesCollector(MapperConfig<?> config, boolean forSerialization, + JavaType type, AnnotatedClass classDef) + { + _config = config; + _forSerialization = forSerialization; + _type = type; + _classDef = classDef; + _annotationIntrospector = config.isAnnotationProcessingEnabled() ? + _config.getAnnotationIntrospector() : null; + if (_annotationIntrospector == null) { + _visibilityChecker = _config.getDefaultVisibilityChecker(); + } else { + _visibilityChecker = _annotationIntrospector.findAutoDetectVisibility(classDef, + _config.getDefaultVisibilityChecker()); + } + } + + /* + /********************************************************** + /* Public API + /********************************************************** + */ + + public MapperConfig<?> getConfig() { + return _config; + } + + public JavaType getType() { + return _type; + } + + public AnnotatedClass getClassDef() { + return _classDef; + } + + public AnnotationIntrospector getAnnotationIntrospector() { + return _annotationIntrospector; + } + + public List<BeanPropertyDefinition> getProperties() { + // make sure we return a copy, so caller can remove entries if need be: + return new ArrayList<BeanPropertyDefinition>(_properties.values()); + } + + public Map<Object, AnnotatedMember> getInjectables() { + return _injectables; + } + + public AnnotatedMethod getJsonValueMethod() + { + // If @JsonValue defined, must have a single one + if (_jsonValueGetters != null) { + if (_jsonValueGetters.size() > 1) { + reportProblem("Multiple value properties defined ("+_jsonValueGetters.get(0)+" vs " + +_jsonValueGetters.get(1)+")"); + } + // otherwise we won't greatly care + return _jsonValueGetters.get(0); + } + return null; + } + + public AnnotatedMethod getAnyGetterMethod() + { + if (_anyGetters != null) { + if (_anyGetters.size() > 1) { + reportProblem("Multiple 'any-getters' defined ("+_anyGetters.get(0)+" vs " + +_anyGetters.get(1)+")"); + } + return _anyGetters.getFirst(); + } + return null; + } + + public AnnotatedMethod getAnySetterMethod() + { + if (_anySetters != null) { + if (_anySetters.size() > 1) { + reportProblem("Multiple 'any-setters' defined ("+_anySetters.get(0)+" vs " + +_anySetters.get(1)+")"); + } + return _anySetters.getFirst(); + } + return null; + } + + public Set<String> getIgnoredPropertyNames() { + return _ignoredPropertyNames; + } + + /** + * @since 1.9.4 + */ + public Set<String> getIgnoredPropertyNamesForDeser() { + return _ignoredPropertyNamesForDeser; + } + + // for unit tests: + protected Map<String, POJOPropertyBuilder> getPropertyMap() { + return _properties; + } + + /* + /********************************************************** + /* Public API: main-level collection + /********************************************************** + */ + + /** + * Method that orchestrates collection activities, and needs to be called + * after creating the instance. + */ + public POJOPropertiesCollector collect() + { + _properties.clear(); + + // First: gather basic data + _addFields(); + _addMethods(); + _addCreators(); + _addInjectables(); + + // Remove ignored properties, individual entries + _removeUnwantedProperties(); + + // Rename remaining properties + _renameProperties(); + // And use custom naming strategy, if applicable... + PropertyNamingStrategy naming = _config.getPropertyNamingStrategy(); + if (naming != null) { + _renameUsing(naming); + } + + /* Sort by visibility (explicit over implicit); drop all but first + * of member type (getter, setter etc) if there is visibility + * difference + */ + for (POJOPropertyBuilder property : _properties.values()) { + property.trimByVisibility(); + } + + // and then the final step, "merge" annotations + for (POJOPropertyBuilder property : _properties.values()) { + property.mergeAnnotations(_forSerialization); + } + + // well, almost last: there's still ordering... + _sortProperties(); + return this; + } + + /* + /********************************************************** + /* Overridable internal methods, sorting + /********************************************************** + */ + + /* First, order by [JACKSON-90] (explicit ordering and/or alphabetic) + * and then for [JACKSON-170] (implicitly order creator properties before others) + */ + protected void _sortProperties() + { + // Then how about explicit ordering? + AnnotationIntrospector intr = _config.getAnnotationIntrospector(); + boolean sort; + Boolean alpha = intr.findSerializationSortAlphabetically(_classDef); + + if (alpha == null) { + sort = _config.shouldSortPropertiesAlphabetically(); + } else { + sort = alpha.booleanValue(); + } + String[] propertyOrder = intr.findSerializationPropertyOrder(_classDef); + + // no sorting? no need to shuffle, then + if (!sort && (_creatorProperties == null) && (propertyOrder == null)) { + return; + } + int size = _properties.size(); + Map<String, POJOPropertyBuilder> all; + // Need to (re)sort alphabetically? + if (sort) { + all = new TreeMap<String,POJOPropertyBuilder>(); + } else { + all = new LinkedHashMap<String,POJOPropertyBuilder>(size+size); + } + + for (POJOPropertyBuilder prop : _properties.values()) { + all.put(prop.getName(), prop); + } + Map<String,POJOPropertyBuilder> ordered = new LinkedHashMap<String,POJOPropertyBuilder>(size+size); + // Ok: primarily by explicit order + if (propertyOrder != null) { + for (String name : propertyOrder) { + POJOPropertyBuilder w = all.get(name); + if (w == null) { // also, as per [JACKSON-268], we will allow use of "implicit" names + for (POJOPropertyBuilder prop : _properties.values()) { + if (name.equals(prop.getInternalName())) { + w = prop; + // plus re-map to external name, to avoid dups: + name = prop.getName(); + break; + } + } + } + if (w != null) { + ordered.put(name, w); + } + } + } + // And secondly by sorting Creator properties before other unordered properties + if (_creatorProperties != null) { + for (POJOPropertyBuilder prop : _creatorProperties) { + ordered.put(prop.getName(), prop); + } + } + // And finally whatever is left (trying to put again will not change ordering) + ordered.putAll(all); + + _properties.clear(); + _properties.putAll(ordered); + } + + /* + /********************************************************** + /* Overridable internal methods, adding members + /********************************************************** + */ + + /** + * Method for collecting basic information on all fields found + */ + protected void _addFields() + { + final AnnotationIntrospector ai = _annotationIntrospector; + + for (AnnotatedField f : _classDef.fields()) { + String implName = f.getName(); + + String explName; + if (ai == null) { + explName = null; + } else if (_forSerialization) { + /* 18-Aug-2011, tatu: As per existing unit tests, we should only + * use serialization annotation (@JsonSerializer) when serializing + * fields, and similarly for deserialize-only annotations... so + * no fallbacks in this particular case. + */ + explName = ai.findSerializablePropertyName(f); + } else { + explName = ai.findDeserializablePropertyName(f); + } + if ("".equals(explName)) { // empty String meaning "use default name", here just means "same as field name" + explName = implName; + } + // having explicit name means that field is visible; otherwise need to check the rules + boolean visible = (explName != null); + if (!visible) { + visible = _visibilityChecker.isFieldVisible(f); + } + // and finally, may also have explicit ignoral + boolean ignored = (ai != null) && ai.hasIgnoreMarker(f); + _property(implName).addField(f, explName, visible, ignored); + } + } + + /** + * Method for collecting basic information on constructor(s) found + */ + protected void _addCreators() + { + final AnnotationIntrospector ai = _annotationIntrospector; + // can be null if annotation processing is disabled... + if (ai == null) { + return; + } + for (AnnotatedConstructor ctor : _classDef.getConstructors()) { + if (_creatorProperties == null) { + _creatorProperties = new LinkedList<POJOPropertyBuilder>(); + } + for (int i = 0, len = ctor.getParameterCount(); i < len; ++i) { + AnnotatedParameter param = ctor.getParameter(i); + String name = ai.findPropertyNameForParam(param); + // is it legal not to have name? + if (name != null) { + // shouldn't need to worry about @JsonIgnore (no real point, so) + POJOPropertyBuilder prop = _property(name); + prop.addCtor(param, name, true, false); + _creatorProperties.add(prop); + } + } + } + for (AnnotatedMethod factory : _classDef.getStaticMethods()) { + if (_creatorProperties == null) { + _creatorProperties = new LinkedList<POJOPropertyBuilder>(); + } + for (int i = 0, len = factory.getParameterCount(); i < len; ++i) { + AnnotatedParameter param = factory.getParameter(i); + String name = ai.findPropertyNameForParam(param); + // is it legal not to have name? + if (name != null) { + // shouldn't need to worry about @JsonIgnore (no real point, so) + POJOPropertyBuilder prop = _property(name); + prop.addCtor(param, name, true, false); + _creatorProperties.add(prop); + } + } + } + } + + /** + * Method for collecting basic information on all fields found + */ + protected void _addMethods() + { + final AnnotationIntrospector ai = _annotationIntrospector; + + for (AnnotatedMethod m : _classDef.memberMethods()) { + String explName; // from annotation(s) + String implName; // from naming convention + + /* For methods, handling differs between getters and setters; and + * we will also only consider entries that either follow the bean + * naming convention or are explicitly marked: just being visible + * is not enough (unlike with fields) + */ + int argCount = m.getParameterCount(); + boolean visible; + + if (argCount == 0) { // getters (including 'any getter') + // any getter? + if (ai != null) { + if (ai.hasAnyGetterAnnotation(m)) { + if (_anyGetters == null) { + _anyGetters = new LinkedList<AnnotatedMethod>(); + } + _anyGetters.add(m); + continue; + } + // @JsonValue? + if (ai.hasAsValueAnnotation(m)) { + if (_jsonValueGetters == null) { + _jsonValueGetters = new LinkedList<AnnotatedMethod>(); + } + _jsonValueGetters.add(m); + continue; + } + } + + explName = (ai == null) ? null : ai.findGettablePropertyName(m); + if (explName == null) { // no explicit name; must follow naming convention + implName = BeanUtil.okNameForRegularGetter(m, m.getName()); + if (implName == null) { // if not, must skip + implName = BeanUtil.okNameForIsGetter(m, m.getName()); + if (implName == null) { + continue; + } + visible = _visibilityChecker.isIsGetterVisible(m); + } else { + visible = _visibilityChecker.isGetterVisible(m); + } + } else { // explicit indication of inclusion, but may be empty + // we still need implicit name to link with other pieces + implName = BeanUtil.okNameForGetter(m); + // if not regular getter name, use method name as is + if (implName == null) { + implName = m.getName(); + } + if (explName.length() == 0) { + explName = implName; + } + visible = true; + } + boolean ignore = (ai == null) ? false : ai.hasIgnoreMarker(m); + _property(implName).addGetter(m, explName, visible, ignore); + } else if (argCount == 1) { // setters + explName = (ai == null) ? null : ai.findSettablePropertyName(m); + if (explName == null) { // no explicit name; must follow naming convention + implName = BeanUtil.okNameForSetter(m); + if (implName == null) { // if not, must skip + continue; + } + visible = _visibilityChecker.isSetterVisible(m); + } else { // explicit indication of inclusion, but may be empty + // we still need implicit name to link with other pieces + implName = BeanUtil.okNameForSetter(m); + // if not regular getter name, use method name as is + if (implName == null) { + implName = m.getName(); + } + if (explName.length() == 0) { + explName = implName; + } + visible = true; + } + boolean ignore = (ai == null) ? false : ai.hasIgnoreMarker(m); + _property(implName).addSetter(m, explName, visible, ignore); + + } else if (argCount == 2) { // any getter? + if (ai != null && ai.hasAnySetterAnnotation(m)) { + if (_anySetters == null) { + _anySetters = new LinkedList<AnnotatedMethod>(); + } + _anySetters.add(m); + } + } + } + } + + protected void _addInjectables() + { + final AnnotationIntrospector ai = _annotationIntrospector; + if (ai == null) { + return; + } + + // first fields, then methods + for (AnnotatedField f : _classDef.fields()) { + _doAddInjectable(ai.findInjectableValueId(f), f); + } + + for (AnnotatedMethod m : _classDef.memberMethods()) { + /* for now, only allow injection of a single arg + * (to be changed in future) + */ + if (m.getParameterCount() != 1) { + continue; + } + _doAddInjectable(ai.findInjectableValueId(m), m); + } + } + + protected void _doAddInjectable(Object id, AnnotatedMember m) + { + if (id == null) { + return; + } + if (_injectables == null) { + _injectables = new LinkedHashMap<Object, AnnotatedMember>(); + } + AnnotatedMember prev = _injectables.put(id, m); + if (prev != null) { + String type = (id == null) ? "[null]" : id.getClass().getName(); + throw new IllegalArgumentException("Duplicate injectable value with id '" + +String.valueOf(id)+"' (of type "+type+")"); + } + } + + /* + /********************************************************** + /* Internal methods; removing ignored properties + /********************************************************** + */ + + /** + * Method called to get rid of candidate properties that are marked + * as ignored, or that are not visible. + */ + protected void _removeUnwantedProperties() + { + Iterator<Map.Entry<String,POJOPropertyBuilder>> it = _properties.entrySet().iterator(); + while (it.hasNext()) { + Map.Entry<String, POJOPropertyBuilder> entry = it.next(); + POJOPropertyBuilder prop = entry.getValue(); + + // First: if nothing visible, just remove altogether + if (!prop.anyVisible()) { + it.remove(); + continue; + } + // Otherwise, check ignorals + if (prop.anyIgnorals()) { + _addIgnored(prop); + // first: if one or more ignorals, and no explicit markers, remove the whole thing + if (!prop.anyExplicitNames()) { + it.remove(); + continue; + } + // otherwise just remove explicitly ignored (and retain others) + prop.removeIgnored(); + } + // and finally, handle removal of individual non-visible elements + prop.removeNonVisible(); + } + } + + private void _addIgnored(POJOPropertyBuilder prop) + { + // not used in any way for serialization side: + if (_forSerialization) { + return; + } + /* and with deserialization, two aspects: whether it's ok to see + * property ('ignore for failure reporting') and whether we forcifully + * ignore it even if there was "any setter" available. + */ + // but do not add unless ignoral was for field, setter or ctor param + String name = prop.getName(); + _ignoredPropertyNames = addToSet(_ignoredPropertyNames, name); + if (prop.anyDeserializeIgnorals()) { + _ignoredPropertyNamesForDeser = addToSet(_ignoredPropertyNamesForDeser, name); + } + } + + /* + /********************************************************** + /* Internal methods; renaming properties + /********************************************************** + */ + + protected void _renameProperties() + { + // With renaming need to do in phases: first, find properties to rename + Iterator<Map.Entry<String,POJOPropertyBuilder>> it = _properties.entrySet().iterator(); + LinkedList<POJOPropertyBuilder> renamed = null; + while (it.hasNext()) { + Map.Entry<String, POJOPropertyBuilder> entry = it.next(); + POJOPropertyBuilder prop = entry.getValue(); + String newName = prop.findNewName(); + if (newName != null) { + if (renamed == null) { + renamed = new LinkedList<POJOPropertyBuilder>(); + } + prop = prop.withName(newName); + renamed.add(prop); + it.remove(); + } + } + + // and if any were renamed, merge back in... + if (renamed != null) { + for (POJOPropertyBuilder prop : renamed) { + String name = prop.getName(); + POJOPropertyBuilder old = _properties.get(name); + if (old == null) { + _properties.put(name, prop); + } else { + old.addAll(prop); + } + } + } + } + + protected void _renameUsing(PropertyNamingStrategy naming) + { + POJOPropertyBuilder[] props = _properties.values().toArray(new POJOPropertyBuilder[_properties.size()]); + _properties.clear(); + for (POJOPropertyBuilder prop : props) { + String name = prop.getName(); + if (_forSerialization) { + if (prop.hasGetter()) { + name = naming.nameForGetterMethod(_config, prop.getGetter(), name); + } else if (prop.hasField()) { + name = naming.nameForField(_config, prop.getField(), name); + } + } else { + if (prop.hasSetter()) { + name = naming.nameForSetterMethod(_config, prop.getSetter(), name); + } else if (prop.hasConstructorParameter()) { + name = naming.nameForConstructorParameter(_config, prop.getConstructorParameter(), name); + } else if (prop.hasField()) { + name = naming.nameForField(_config, prop.getField(), name); + } else if (prop.hasGetter()) { + /* Plus, when getter-as-setter is used, need to convert that too.. + * (should we verify that's enabled? For now, assume it's ok always) + */ + name = naming.nameForGetterMethod(_config, prop.getGetter(), name); + } + } + if (!name.equals(prop.getName())) { + prop = prop.withName(name); + } + /* As per [JACKSON-687], need to consider case where there may already be + * something in there... + */ + POJOPropertyBuilder old = _properties.get(name); + if (old == null) { + _properties.put(name, prop); + } else { + old.addAll(prop); + } + } + } + + /* + /********************************************************** + /* Internal methods; helpers + /********************************************************** + */ + + protected void reportProblem(String msg) { + throw new IllegalArgumentException("Problem with definition of "+_classDef+": "+msg); + } + + protected POJOPropertyBuilder _property(String implName) + { + POJOPropertyBuilder prop = _properties.get(implName); + if (prop == null) { + prop = new POJOPropertyBuilder(implName); + _properties.put(implName, prop); + } + return prop; + } + + private Set<String> addToSet(Set<String> set, String str) + { + if (set == null) { + set = new HashSet<String>(); + } + set.add(str); + return set; + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/introspect/POJOPropertyBuilder.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/introspect/POJOPropertyBuilder.java new file mode 100644 index 0000000..8aad5c8 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/introspect/POJOPropertyBuilder.java
@@ -0,0 +1,653 @@ +package org.codehaus.jackson.map.introspect; + +import org.codehaus.jackson.map.BeanPropertyDefinition; + +/** + * Helper class used for aggregating information about a single + * potential POJO property. + * + * @since 1.9 + */ +public class POJOPropertyBuilder + extends BeanPropertyDefinition + implements Comparable<POJOPropertyBuilder> +{ + /** + * External name of logical property; may change with + * renaming (by new instance being constructed using + * a new name) + */ + protected final String _name; + + /** + * Original internal name, derived from accessor, of this + * property. Will not be changed by renaming. + */ + protected final String _internalName; + + protected Node<AnnotatedField> _fields; + + protected Node<AnnotatedParameter> _ctorParameters; + + protected Node<AnnotatedMethod> _getters; + + protected Node<AnnotatedMethod> _setters; + + public POJOPropertyBuilder(String internalName) + { + _internalName = internalName; + _name = internalName; + } + + public POJOPropertyBuilder(POJOPropertyBuilder src, String newName) + { + _internalName = src._internalName; + _name = newName; + _fields = src._fields; + _ctorParameters = src._ctorParameters; + _getters = src._getters; + _setters = src._setters; + } + + /** + * Method for constructing a renamed instance + */ + public POJOPropertyBuilder withName(String newName) { + return new POJOPropertyBuilder(this, newName); + } + + /* + /********************************************************** + /* Comparable implementation: sort alphabetically, except + /* that properties with constructor parameters sorted + /* before other properties + /********************************************************** + */ + + @Override + public int compareTo(POJOPropertyBuilder other) + { + // first, if one has ctor params, that should come first: + if (_ctorParameters != null) { + if (other._ctorParameters == null) { + return -1; + } + } else if (other._ctorParameters != null) { + return 1; + } + /* otherwise sort by external name (including sorting of + * ctor parameters) + */ + return getName().compareTo(other.getName()); + } + + /* + /********************************************************** + /* BeanPropertyDefinition implementation + /********************************************************** + */ + + @Override + public String getName() { return _name; } + + @Override + public String getInternalName() { return _internalName; } + + @Override + public boolean isExplicitlyIncluded() { + return anyExplicitNames(); + } + + @Override + public boolean hasGetter() { return _getters != null; } + + @Override + public boolean hasSetter() { return _setters != null; } + + @Override + public boolean hasField() { return _fields != null; } + + @Override + public boolean hasConstructorParameter() { return _ctorParameters != null; } + + @Override + public AnnotatedMember getAccessor() + { + AnnotatedMember m = getGetter(); + if (m == null) { + m = getField(); + } + return m; + } + + @Override + public AnnotatedMember getMutator() + { + AnnotatedMember m = getConstructorParameter(); + if (m == null) { + m = getSetter(); + if (m == null) { + m = getField(); + } + } + return m; + } + + @Override + public boolean couldSerialize() { + return (_getters != null) || (_fields != null); + } + + @Override + public AnnotatedMethod getGetter() + { + if (_getters == null) { + return null; + } + // If multiple, verify that they do not conflict... + AnnotatedMethod getter = _getters.value; + Node<AnnotatedMethod> next = _getters.next; + for (; next != null; next = next.next) { + /* [JACKSON-255] Allow masking, i.e. report exception only if + * declarations in same class, or there's no inheritance relationship + * (sibling interfaces etc) + */ + AnnotatedMethod nextGetter = next.value; + Class<?> getterClass = getter.getDeclaringClass(); + Class<?> nextClass = nextGetter.getDeclaringClass(); + if (getterClass != nextClass) { + if (getterClass.isAssignableFrom(nextClass)) { // next is more specific + getter = nextGetter; + continue; + } + if (nextClass.isAssignableFrom(getterClass)) { // getter more specific + continue; + } + } + throw new IllegalArgumentException("Conflicting getter definitions for property \""+getName()+"\": " + +getter.getFullName()+" vs "+nextGetter.getFullName()); + } + return getter; + } + + @Override + public AnnotatedMethod getSetter() + { + if (_setters == null) { + return null; + } + // If multiple, verify that they do not conflict... + AnnotatedMethod setter = _setters.value; + Node<AnnotatedMethod> next = _setters.next; + for (; next != null; next = next.next) { + /* [JACKSON-255] Allow masking, i.e. report exception only if + * declarations in same class, or there's no inheritance relationship + * (sibling interfaces etc) + */ + AnnotatedMethod nextSetter = next.value; + Class<?> setterClass = setter.getDeclaringClass(); + Class<?> nextClass = nextSetter.getDeclaringClass(); + if (setterClass != nextClass) { + if (setterClass.isAssignableFrom(nextClass)) { // next is more specific + setter = nextSetter; + continue; + } + if (nextClass.isAssignableFrom(setterClass)) { // getter more specific + continue; + } + } + throw new IllegalArgumentException("Conflicting setter definitions for property \""+getName()+"\": " + +setter.getFullName()+" vs "+nextSetter.getFullName()); + } + return setter; + } + + @Override + public AnnotatedField getField() + { + if (_fields == null) { + return null; + } + // If multiple, verify that they do not conflict... + AnnotatedField field = _fields.value; + Node<AnnotatedField> next = _fields.next; + for (; next != null; next = next.next) { + AnnotatedField nextField = next.value; + Class<?> fieldClass = field.getDeclaringClass(); + Class<?> nextClass = nextField.getDeclaringClass(); + if (fieldClass != nextClass) { + if (fieldClass.isAssignableFrom(nextClass)) { // next is more specific + field = nextField; + continue; + } + if (nextClass.isAssignableFrom(fieldClass)) { // getter more specific + continue; + } + } + throw new IllegalArgumentException("Multiple fields representing property \""+getName()+"\": " + +field.getFullName()+" vs "+nextField.getFullName()); + } + return field; + } + + @Override + public AnnotatedParameter getConstructorParameter() + { + if (_ctorParameters == null) { + return null; + } + /* Hmmh. Checking for constructor parameters is trickier; for one, + * we must allow creator and factory method annotations. + * If this is the case, constructor parameter has the precedence. + * + * So, for now, just try finding the first constructor parameter; + * if none, first factory method. And don't check for dups, if we must, + * can start checking for them later on. + */ + Node<AnnotatedParameter> curr = _ctorParameters; + do { + if (curr.value.getOwner() instanceof AnnotatedConstructor) { + return curr.value; + } + curr = curr.next; + } while (curr != null); + return _ctorParameters.value; + } + + /* + /********************************************************** + /* Data aggregation + /********************************************************** + */ + + public void addField(AnnotatedField a, String ename, boolean visible, boolean ignored) { + _fields = new Node<AnnotatedField>(a, _fields, ename, visible, ignored); + } + + public void addCtor(AnnotatedParameter a, String ename, boolean visible, boolean ignored) { + _ctorParameters = new Node<AnnotatedParameter>(a, _ctorParameters, ename, visible, ignored); + } + + public void addGetter(AnnotatedMethod a, String ename, boolean visible, boolean ignored) { + _getters = new Node<AnnotatedMethod>(a, _getters, ename, visible, ignored); + } + + public void addSetter(AnnotatedMethod a, String ename, boolean visible, boolean ignored) { + _setters = new Node<AnnotatedMethod>(a, _setters, ename, visible, ignored); + } + + /** + * Method for adding all property members from specified collector into + * this collector. + */ + public void addAll(POJOPropertyBuilder src) + { + _fields = merge(_fields, src._fields); + _ctorParameters = merge(_ctorParameters, src._ctorParameters); + _getters= merge(_getters, src._getters); + _setters = merge(_setters, src._setters); + } + + private static <T> Node<T> merge(Node<T> chain1, Node<T> chain2) + { + if (chain1 == null) { + return chain2; + } + if (chain2 == null) { + return chain1; + } + return chain1.append(chain2); + } + + /* + /********************************************************** + /* Modifications + /********************************************************** + */ + + /** + * Method called to remove all entries that are marked as + * ignored. + */ + public void removeIgnored() + { + _fields = _removeIgnored(_fields); + _getters = _removeIgnored(_getters); + _setters = _removeIgnored(_setters); + _ctorParameters = _removeIgnored(_ctorParameters); + } + + public void removeNonVisible() + { + /* 21-Aug-2011, tatu: This is tricky part -- if and when allow + * non-visible property elements to be "pulled in" by visible + * counterparts? + * For now, we will only do this to pull in setter or field used + * as setter, if an explicit getter is found. + */ + _getters = _removeNonVisible(_getters); + _ctorParameters = _removeNonVisible(_ctorParameters); + + if (_getters == null) { + _fields = _removeNonVisible(_fields); + _setters = _removeNonVisible(_setters); + } + } + + /** + * Method called to trim unnecessary entries, such as implicit + * getter if there is an explict one available. This is important + * for later stages, to avoid unnecessary conflicts. + */ + public void trimByVisibility() + { + _fields = _trimByVisibility(_fields); + _getters = _trimByVisibility(_getters); + _setters = _trimByVisibility(_setters); + _ctorParameters = _trimByVisibility(_ctorParameters); + } + + @SuppressWarnings("unchecked") + public void mergeAnnotations(boolean forSerialization) + { + if (forSerialization) { + if (_getters != null) { + AnnotationMap ann = _mergeAnnotations(0, _getters, _fields, _ctorParameters, _setters); + _getters = _getters.withValue(_getters.value.withAnnotations(ann)); + } else if (_fields != null) { + AnnotationMap ann = _mergeAnnotations(0, _fields, _ctorParameters, _setters); + _fields = _fields.withValue(_fields.value.withAnnotations(ann)); + } + } else { + if (_ctorParameters != null) { + AnnotationMap ann = _mergeAnnotations(0, _ctorParameters, _setters, _fields, _getters); + _ctorParameters = _ctorParameters.withValue(_ctorParameters.value.withAnnotations(ann)); + } else if (_setters != null) { + AnnotationMap ann = _mergeAnnotations(0, _setters, _fields, _getters); + _setters = _setters.withValue(_setters.value.withAnnotations(ann)); + } else if (_fields != null) { + AnnotationMap ann = _mergeAnnotations(0, _fields, _getters); + _fields = _fields.withValue(_fields.value.withAnnotations(ann)); + } + } + } + + private AnnotationMap _mergeAnnotations(int index, Node<? extends AnnotatedMember>... nodes) + { + AnnotationMap ann = nodes[index].value.getAllAnnotations(); + ++index; + for (; index < nodes.length; ++index) { + if (nodes[index] != null) { + return AnnotationMap.merge(ann, _mergeAnnotations(index, nodes)); + } + } + return ann; + } + + private <T> Node<T> _removeIgnored(Node<T> node) + { + if (node == null) { + return node; + } + return node.withoutIgnored(); + } + + private <T> Node<T> _removeNonVisible(Node<T> node) + { + if (node == null) { + return node; + } + return node.withoutNonVisible(); + } + + private <T> Node<T> _trimByVisibility(Node<T> node) + { + if (node == null) { + return node; + } + return node.trimByVisibility(); + } + + /* + /********************************************************** + /* Accessors for aggregate information + /********************************************************** + */ + + public boolean anyExplicitNames() { + return _anyExplicitNames(_fields) + || _anyExplicitNames(_getters) + || _anyExplicitNames(_setters) + || _anyExplicitNames(_ctorParameters) + ; + } + + private <T> boolean _anyExplicitNames(Node<T> n) + { + for (; n != null; n = n.next) { + if (n.explicitName != null && n.explicitName.length() > 0) { + return true; + } + } + return false; + } + + public boolean anyVisible() { + return _anyVisible(_fields) + || _anyVisible(_getters) + || _anyVisible(_setters) + || _anyVisible(_ctorParameters) + ; + } + + private <T> boolean _anyVisible(Node<T> n) + { + for (; n != null; n = n.next) { + if (n.isVisible) { + return true; + } + } + return false; + } + + public boolean anyIgnorals() { + return _anyIgnorals(_fields) + || _anyIgnorals(_getters) + || _anyIgnorals(_setters) + || _anyIgnorals(_ctorParameters) + ; + } + + public boolean anyDeserializeIgnorals() { + return _anyIgnorals(_fields) + || _anyIgnorals(_setters) + || _anyIgnorals(_ctorParameters) + ; + } + + public boolean anySerializeIgnorals() { + return _anyIgnorals(_fields) + || _anyIgnorals(_getters) + ; + } + + private <T> boolean _anyIgnorals(Node<T> n) + { + for (; n != null; n = n.next) { + if (n.isMarkedIgnored) { + return true; + } + } + return false; + } + + /** + * Method called to check whether property represented by this collector + * should be renamed from the implicit name; and also verify that there + * are no conflicting rename definitions. + */ + public String findNewName() + { + Node<? extends AnnotatedMember> renamed = null; + renamed = findRenamed(_fields, renamed); + renamed = findRenamed(_getters, renamed); + renamed = findRenamed(_setters, renamed); + renamed = findRenamed(_ctorParameters, renamed); + return (renamed == null) ? null : renamed.explicitName; + } + + private Node<? extends AnnotatedMember> findRenamed(Node<? extends AnnotatedMember> node, + Node<? extends AnnotatedMember> renamed) + { + for (; node != null; node = node.next) { + String explName = node.explicitName; + if (explName == null) { + continue; + } + // different from default name? + if (explName.equals(_name)) { // nope, skip + continue; + } + if (renamed == null) { + renamed = node; + } else { + // different from an earlier renaming? problem + if (!explName.equals(renamed.explicitName)) { + throw new IllegalStateException("Conflicting property name definitions: '" + +renamed.explicitName+"' (for "+renamed.value+") vs '" + +node.explicitName+"' (for "+node.value+")"); + } + } + } + return renamed; + } + + // For trouble-shooting + @Override + public String toString() + { + StringBuilder sb = new StringBuilder(); + sb.append("[Property '").append(_name) + .append("'; ctors: ").append(_ctorParameters) + .append(", field(s): ").append(_fields) + .append(", getter(s): ").append(_getters) + .append(", setter(s): ").append(_setters) + ; + sb.append("]"); + return sb.toString(); + } + + /* + /********************************************************** + /* Helper classes + /********************************************************** + */ + + /** + * Node used for creating simple linked lists to efficiently store small sets + * of things. + */ + private final static class Node<T> + { + public final T value; + public final Node<T> next; + + public final String explicitName; + public final boolean isVisible; + public final boolean isMarkedIgnored; + + public Node(T v, Node<T> n, + String explName, boolean visible, boolean ignored) + { + value = v; + next = n; + // ensure that we'll never have missing names + if (explName == null) { + explicitName = null; + } else { + explicitName = (explName.length() == 0) ? null : explName; + } + isVisible = visible; + isMarkedIgnored = ignored; + } + + public Node<T> withValue(T newValue) + { + if (newValue == value) { + return this; + } + return new Node<T>(newValue, next, explicitName, isVisible, isMarkedIgnored); + } + + public Node<T> withNext(Node<T> newNext) { + if (newNext == next) { + return this; + } + return new Node<T>(value, newNext, explicitName, isVisible, isMarkedIgnored); + } + + public Node<T> withoutIgnored() + { + if (isMarkedIgnored) { + return (next == null) ? null : next.withoutIgnored(); + } + if (next != null) { + Node<T> newNext = next.withoutIgnored(); + if (newNext != next) { + return withNext(newNext); + } + } + return this; + } + + public Node<T> withoutNonVisible() + { + Node<T> newNext = (next == null) ? null : next.withoutNonVisible(); + return isVisible ? withNext(newNext) : newNext; + } + + /** + * Method called to append given node(s) at the end of this + * node chain. + */ + private Node<T> append(Node<T> appendable) + { + if (next == null) { + return withNext(appendable); + } + return withNext(next.append(appendable)); + } + + public Node<T> trimByVisibility() + { + if (next == null) { + return this; + } + Node<T> newNext = next.trimByVisibility(); + if (explicitName != null) { // this already has highest; how about next one? + if (newNext.explicitName == null) { // next one not, drop it + return withNext(null); + } + // both have it, keep + return withNext(newNext); + } + if (newNext.explicitName != null) { // next one has higher, return it... + return newNext; + } + // neither has explicit name; how about visibility? + if (isVisible == newNext.isVisible) { // same; keep both in current order + return withNext(newNext); + } + return isVisible ? withNext(null) : newNext; + } + + @Override + public String toString() { + String msg = value.toString()+"[visible="+isVisible+"]"; + if (next != null) { + msg = msg + ", "+next.toString(); + } + return msg; + } + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/introspect/VisibilityChecker.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/introspect/VisibilityChecker.java new file mode 100644 index 0000000..8f5ac67 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/introspect/VisibilityChecker.java
@@ -0,0 +1,424 @@ +package org.codehaus.jackson.map.introspect; + +import org.codehaus.jackson.annotate.JsonAutoDetect; +import org.codehaus.jackson.annotate.JsonAutoDetect.Visibility; +import org.codehaus.jackson.annotate.JsonMethod; + +import java.lang.reflect.Field; +import java.lang.reflect.Member; +import java.lang.reflect.Method; + +/** + * Interface for object used for determine which property elements + * (methods, fields, constructors) can be auto-detected, with respect + * to their visibility modifiers. + *<p> + * Note on type declaration: funky recursive type is necessary to + * support builder/fluent pattern. + *<p> + * Note on compatibility: 1.9 introduced overloaded "with" method + * (which takes {@link Visibility} as value to assign); which could + * be potential issue, but assumption here is that all custom implementations + * are based on "Std" base class + * + * @author tatu + * @since 1.5 + */ +public interface VisibilityChecker<T extends VisibilityChecker<T>> +{ + // // Builder methods + + /** + * Builder method that will return an instance that has same + * settings as this instance has, except for values that + * given annotation overrides. + */ + public T with(JsonAutoDetect ann); + + /** + * Builder method that will create and return an instance that has specified + * {@link Visibility} value to use for all property elements. + * Typical usage would be something like: + *<pre> + * mapper.setVisibilityChecker( + * mapper.getVisibilityChecker().with(Visibility.NONE)); + *</pre> + * (which would basically disable all auto-detection) + * + * @since 1.9 + */ + public T with(Visibility v); + + /** + * Builder method that will create and return an instance that has specified + * {@link Visibility} value to use for specified property. + * Typical usage would be: + *<pre> + * mapper.setVisibilityChecker( + * mapper.getVisibilityChecker().withVisibility(JsonMethod.FIELD, Visibility.ANY)); + *</pre> + * (which would basically enable auto-detection for all member fields) + * + * @since 1.9 + */ + public T withVisibility(JsonMethod method, Visibility v); + + /** + * Builder method that will return a checker instance that has + * specified minimum visibility level for regular ("getXxx") getters. + */ + public T withGetterVisibility(Visibility v); + + /** + * Builder method that will return a checker instance that has + * specified minimum visibility level for "is-getters" ("isXxx"). + */ + public T withIsGetterVisibility(Visibility v); + + /** + * Builder method that will return a checker instance that has + * specified minimum visibility level for setters. + */ + public T withSetterVisibility(Visibility v); + + /** + * Builder method that will return a checker instance that has + * specified minimum visibility level for creator methods + * (constructors, factory methods) + */ + public T withCreatorVisibility(Visibility v); + + /** + * Builder method that will return a checker instance that has + * specified minimum visibility level for fields. + */ + public T withFieldVisibility(Visibility v); + + // // Accessors + + /** + * Method for checking whether given method is auto-detectable + * as regular getter, with respect to its visibility (not considering + * method signature or name, just visibility) + */ + public boolean isGetterVisible(Method m); + public boolean isGetterVisible(AnnotatedMethod m); + + /** + * Method for checking whether given method is auto-detectable + * as is-getter, with respect to its visibility (not considering + * method signature or name, just visibility) + */ + public boolean isIsGetterVisible(Method m); + public boolean isIsGetterVisible(AnnotatedMethod m); + + /** + * Method for checking whether given method is auto-detectable + * as setter, with respect to its visibility (not considering + * method signature or name, just visibility) + */ + public boolean isSetterVisible(Method m); + public boolean isSetterVisible(AnnotatedMethod m); + + /** + * Method for checking whether given method is auto-detectable + * as Creator, with respect to its visibility (not considering + * method signature or name, just visibility) + */ + public boolean isCreatorVisible(Member m); + public boolean isCreatorVisible(AnnotatedMember m); + + /** + * Method for checking whether given field is auto-detectable + * as property, with respect to its visibility (not considering + * method signature or name, just visibility) + */ + public boolean isFieldVisible(Field f); + public boolean isFieldVisible(AnnotatedField f); + + /* + /******************************************************** + /* Standard implementation suitable for basic use + /******************************************************** + */ + + /** + * Default standard implementation is purely based on visibility + * modifier of given class members, and its configured minimum + * levels. + * Implemented using "builder" (aka "Fluid") pattern, whereas instances + * are immutable, and configuration is achieved by chainable factory + * methods. As a result, type is declared is funky recursive generic + * type, to allow for sub-classing of build methods with property type + * co-variance. + *<p> + * Note on <code>JsonAutoDetect</code> annotation: it is used to + * access default minimum visibility access definitions. + */ + @JsonAutoDetect( + getterVisibility = Visibility.PUBLIC_ONLY, + isGetterVisibility = Visibility.PUBLIC_ONLY, + setterVisibility = Visibility.ANY, + /** + * By default, all matching single-arg constructed are found, + * regardless of visibility. Does not apply to factory methods, + * they can not be auto-detected; ditto for multiple-argument + * constructors. + */ + creatorVisibility = Visibility.ANY, + fieldVisibility = Visibility.PUBLIC_ONLY + ) + public static class Std + implements VisibilityChecker<Std> + { + /** + * This is the canonical base instance, configured with default + * visibility values + */ + protected final static Std DEFAULT = new Std(Std.class.getAnnotation(JsonAutoDetect.class)); + + protected final Visibility _getterMinLevel; + protected final Visibility _isGetterMinLevel; + protected final Visibility _setterMinLevel; + protected final Visibility _creatorMinLevel; + protected final Visibility _fieldMinLevel; + + public static Std defaultInstance() { return DEFAULT; } + + /** + * Constructor used for building instance that has minumum visibility + * levels as indicated by given annotation instance + * + * @param ann Annotations to use for determining minimum visibility levels + */ + public Std(JsonAutoDetect ann) + { + JsonMethod[] incl = ann.value(); + // let's combine checks for enabled/disabled, with minimimum level checks: + _getterMinLevel = hasMethod(incl, JsonMethod.GETTER) ? ann.getterVisibility() : Visibility.NONE; + _isGetterMinLevel = hasMethod(incl, JsonMethod.IS_GETTER) ? ann.isGetterVisibility() : Visibility.NONE; + _setterMinLevel = hasMethod(incl, JsonMethod.SETTER) ? ann.setterVisibility() : Visibility.NONE; + _creatorMinLevel = hasMethod(incl, JsonMethod.CREATOR) ? ann.creatorVisibility() : Visibility.NONE; + _fieldMinLevel = hasMethod(incl, JsonMethod.FIELD) ? ann.fieldVisibility() : Visibility.NONE; + } + + /** + * Constructor that allows directly specifying minimum visibility levels to use + */ + public Std(Visibility getter, Visibility isGetter, Visibility setter, Visibility creator, Visibility field) + { + _getterMinLevel = getter; + _isGetterMinLevel = isGetter; + _setterMinLevel = setter; + _creatorMinLevel = creator; + _fieldMinLevel = field; + } + + /** + * Costructor that will assign given visibility value for all + * properties. + * + * @param v level to use for all property types + * + * @since 1.9 + */ + public Std(Visibility v) + { + // typically we shouldn't get this value; but let's handle it if we do: + if (v == Visibility.DEFAULT) { + _getterMinLevel = DEFAULT._getterMinLevel; + _isGetterMinLevel = DEFAULT._isGetterMinLevel; + _setterMinLevel = DEFAULT._setterMinLevel; + _creatorMinLevel = DEFAULT._creatorMinLevel; + _fieldMinLevel = DEFAULT._fieldMinLevel; + } else { + _getterMinLevel = v; + _isGetterMinLevel = v; + _setterMinLevel = v; + _creatorMinLevel = v; + _fieldMinLevel = v; + } + } + + /* + /******************************************************** + /* Builder/fluent methods for instantiating configured + /* instances + /******************************************************** + */ + + @Override + public Std with(JsonAutoDetect ann) + { + if (ann == null) return this; + Std curr = this; + + JsonMethod[] incl = ann.value(); + Visibility v; + + v = hasMethod(incl, JsonMethod.GETTER) ? ann.getterVisibility() : Visibility.NONE; + curr = curr.withGetterVisibility(v); + v = hasMethod(incl, JsonMethod.IS_GETTER) ? ann.isGetterVisibility() : Visibility.NONE; + curr = curr.withIsGetterVisibility(v); + v = hasMethod(incl, JsonMethod.SETTER) ? ann.setterVisibility() : Visibility.NONE; + curr = curr.withSetterVisibility(v); + v = hasMethod(incl, JsonMethod.CREATOR) ? ann.creatorVisibility() : Visibility.NONE; + curr = curr.withCreatorVisibility(v); + v = hasMethod(incl, JsonMethod.FIELD) ? ann.fieldVisibility() : Visibility.NONE; + curr = curr.withFieldVisibility(v); + return curr; + } + + @Override + public Std with(Visibility v) + { + if (v == Visibility.DEFAULT) { + return DEFAULT; + } + return new Std(v); + } + + @Override + public Std withVisibility(JsonMethod method, Visibility v) + { + switch (method) { + case GETTER: + return withGetterVisibility(v); + case SETTER: + return withSetterVisibility(v); + case CREATOR: + return withCreatorVisibility(v); + case FIELD: + return withFieldVisibility(v); + case IS_GETTER: + return withIsGetterVisibility(v); + case ALL: + return with(v); + //case NONE: + // break; + } + return this; + } + + @Override + public Std withGetterVisibility(Visibility v) { + if (v == Visibility.DEFAULT) v = DEFAULT._getterMinLevel; + if (_getterMinLevel == v) return this; + return new Std(v, _isGetterMinLevel, _setterMinLevel, _creatorMinLevel, _fieldMinLevel); + } + + @Override + public Std withIsGetterVisibility(Visibility v) { + if (v == Visibility.DEFAULT) v = DEFAULT._isGetterMinLevel; + if (_isGetterMinLevel == v) return this; + return new Std(_getterMinLevel, v, _setterMinLevel, _creatorMinLevel, _fieldMinLevel); + } + + @Override + public Std withSetterVisibility(Visibility v) { + if (v == Visibility.DEFAULT) v = DEFAULT._setterMinLevel; + if (_setterMinLevel == v) return this; + return new Std(_getterMinLevel, _isGetterMinLevel, v, _creatorMinLevel, _fieldMinLevel); + } + + @Override + public Std withCreatorVisibility(Visibility v) { + if (v == Visibility.DEFAULT) v = DEFAULT._creatorMinLevel; + if (_creatorMinLevel == v) return this; + return new Std(_getterMinLevel, _isGetterMinLevel, _setterMinLevel, v, _fieldMinLevel); + } + + @Override + public Std withFieldVisibility(Visibility v) { + if (v == Visibility.DEFAULT) v = DEFAULT._fieldMinLevel; + if (_fieldMinLevel == v) return this; + return new Std(_getterMinLevel, _isGetterMinLevel, _setterMinLevel, _creatorMinLevel, v); + } + + /* + /******************************************************** + /* Public API impl + /******************************************************** + */ + + @Override + public boolean isCreatorVisible(Member m) { + return _creatorMinLevel.isVisible(m); + } + + @Override + public boolean isCreatorVisible(AnnotatedMember m) { + return isCreatorVisible(m.getMember()); + } + + @Override + public boolean isFieldVisible(Field f) { + return _fieldMinLevel.isVisible(f); + } + + @Override + public boolean isFieldVisible(AnnotatedField f) { + return isFieldVisible(f.getAnnotated()); + } + + @Override + public boolean isGetterVisible(Method m) { + return _getterMinLevel.isVisible(m); + } + + @Override + public boolean isGetterVisible(AnnotatedMethod m) { + return isGetterVisible(m.getAnnotated()); + } + + @Override + public boolean isIsGetterVisible(Method m) { + return _isGetterMinLevel.isVisible(m); + } + + @Override + public boolean isIsGetterVisible(AnnotatedMethod m) { + return isIsGetterVisible(m.getAnnotated()); + } + + @Override + public boolean isSetterVisible(Method m) { + return _setterMinLevel.isVisible(m); + } + + @Override + public boolean isSetterVisible(AnnotatedMethod m) { + return isSetterVisible(m.getAnnotated()); + } + + /* + /******************************************************** + /* Helper methods + /******************************************************** + */ + + private static boolean hasMethod(JsonMethod[] methods, JsonMethod method) + { + for (JsonMethod curr : methods) { + if (curr == method || curr == JsonMethod.ALL) return true; + } + return false; + } + + /* + /******************************************************** + /* Standard methods + /******************************************************** + */ + @Override + public String toString() { + return new StringBuilder("[Visibility:") + .append(" getter: ").append(_getterMinLevel) + .append(", isGetter: ").append(_isGetterMinLevel) + .append(", setter: ").append(_setterMinLevel) + .append(", creator: ").append(_creatorMinLevel) + .append(", field: ").append(_fieldMinLevel) + .append("]").toString(); + } + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/introspect/package-info.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/introspect/package-info.java new file mode 100644 index 0000000..bd65ad9 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/introspect/package-info.java
@@ -0,0 +1,12 @@ +/** + * Functionality needed for Bean introspection, required for detecting + * accessors and mutators for Beans, as well as locating and handling + * method annotations. + *<p> + * Beyond collecting annotations, additional "method annotation inheritance" + * is also supported: whereas regular JDK classes do not add annotations + * from overridden methods in any situation. But code in this package does. + * Similarly class-annotations are inherited properly from interfaces, in + * addition to abstract and concrete classes. + */ +package org.codehaus.jackson.map.introspect;
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/NamedType.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/NamedType.java new file mode 100644 index 0000000..c48bac8 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/NamedType.java
@@ -0,0 +1,53 @@ +package org.codehaus.jackson.map.jsontype; + +/** + * Simple container class for types with optional logical name, used + * as external identifier + * + * @author tatu + * @since 1.5 + */ +public final class NamedType +{ + protected final Class<?> _class; + protected final int _hashCode; + + protected String _name; + + public NamedType(Class<?> c) { this(c, null); } + + public NamedType(Class<?> c, String name) + { + _class = c; + _hashCode = c.getName().hashCode(); + setName(name); + } + + public Class<?> getType() { return _class; } + public String getName() { return _name; } + public void setName(String name) { + _name = (name == null || name.length() == 0) ? null : name; + } + + public boolean hasName() { return _name != null; } + + /** + * Equality is defined based on class only, not on name + */ + @Override + public boolean equals(Object o) + { + if (o == this) return true; + if (o == null) return false; + if (o.getClass() != getClass()) return false; + return _class == ((NamedType) o)._class; + } + + @Override + public int hashCode() { return _hashCode; } + + @Override + public String toString() { + return "[NamedType, class "+_class.getName()+", name: "+(_name == null ? "null" :("'"+_name+"'"))+"]"; + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/SubtypeResolver.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/SubtypeResolver.java new file mode 100644 index 0000000..57b794a --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/SubtypeResolver.java
@@ -0,0 +1,39 @@ +package org.codehaus.jackson.map.jsontype; + +import java.util.Collection; + +import org.codehaus.jackson.map.AnnotationIntrospector; +import org.codehaus.jackson.map.MapperConfig; +import org.codehaus.jackson.map.introspect.AnnotatedClass; +import org.codehaus.jackson.map.introspect.AnnotatedMember; + +/** + * Helper object used for handling registration on resolving of supertypes + * to subtypes. + * + * @since 1.5 + */ +public abstract class SubtypeResolver +{ + /** + * Method for registering specified subtypes (possibly including type + * names); for type entries without name, non-qualified class name + * as used as name (unless overridden by annotation). + */ + public abstract void registerSubtypes(NamedType... types); + + public abstract void registerSubtypes(Class<?>... classes); + + /** + * Method for finding out all reachable subtypes for a property specified + * by given element (method or field) + */ + public abstract Collection<NamedType> collectAndResolveSubtypes(AnnotatedMember property, + MapperConfig<?> config, AnnotationIntrospector ai); + + /** + * Method for finding out all reachable subtypes for given type. + */ + public abstract Collection<NamedType> collectAndResolveSubtypes(AnnotatedClass basetype, + MapperConfig<?> config, AnnotationIntrospector ai); +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/TypeIdResolver.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/TypeIdResolver.java new file mode 100644 index 0000000..1ac222e --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/TypeIdResolver.java
@@ -0,0 +1,74 @@ +package org.codehaus.jackson.map.jsontype; + +import org.codehaus.jackson.annotate.JsonTypeInfo; +import org.codehaus.jackson.type.JavaType; + +/** + * Interface that defines standard API for converting types + * to type identifiers and vice versa. Used by type resolvers + * ({@link org.codehaus.jackson.map.TypeSerializer}, + * {@link org.codehaus.jackson.map.TypeDeserializer}) for converting + * between type and matching id; id is stored in JSON and needed for + * creating instances of proper subtypes when deserializing values. + * + * @since 1.5 + */ +public interface TypeIdResolver +{ + /* + /********************************************************** + /* Initialization/configuration methods + /********************************************************** + */ + + /** + * Method that will be called once before any type resolution calls; + * used to initialize instance with configuration. This is necessary + * since instances may be created via reflection, without ability to + * call specific constructor to pass in configuration settings. + * + * @param baseType Base type for which this id resolver instance is + * used + */ + public void init(JavaType baseType); + + /* + /********************************************************** + /* Conversions between types and type ids + /********************************************************** + */ + + /** + * Method called to serialize type of the type of given value + * as a String to include in serialized JSON content. + */ + public String idFromValue(Object value); + + /** + * Alternative method used for determining type from combination of + * value and type, using suggested type (that serializer provides) + * and possibly value of that type. Most common implementation will + * use suggested type as is. + * + * @since 1.8 + */ + public String idFromValueAndType(Object value, Class<?> suggestedType); + + /** + * Method called to resolve type from given type identifier. + */ + public JavaType typeFromId(String id); + + /* + /********************************************************** + /* Accessors for metadata + /********************************************************** + */ + + /** + * Accessor for mechanism that this resolver uses for determining + * type id from type. Mostly informational; not required to be called + * or used. + */ + public JsonTypeInfo.Id getMechanism(); +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/TypeResolverBuilder.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/TypeResolverBuilder.java new file mode 100644 index 0000000..7da6274 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/TypeResolverBuilder.java
@@ -0,0 +1,151 @@ +package org.codehaus.jackson.map.jsontype; + +import java.util.Collection; + +import org.codehaus.jackson.annotate.JsonTypeInfo; +import org.codehaus.jackson.annotate.JsonTypeInfo.As; +import org.codehaus.jackson.map.BeanProperty; +import org.codehaus.jackson.map.DeserializationConfig; +import org.codehaus.jackson.map.SerializationConfig; +import org.codehaus.jackson.map.TypeDeserializer; +import org.codehaus.jackson.map.TypeSerializer; +import org.codehaus.jackson.type.JavaType; + +/** + * Interface that defines builders that are configured based on + * annotations (like {@link JsonTypeInfo} or JAXB annotations), + * and produce type serializers and deserializers used for + * handling type information embedded in JSON to allow for safe + * polymorphic type handling. + *<p> + * Builder is first initialized by calling {@link #init} method, and then + * configured using <code>setXxx</code> (and <code>registerXxx</code>) + * methods. Finally, after calling all configuration methods, + * {@link #buildTypeSerializer} or {@link #buildTypeDeserializer} + * will be called to get actual type resolver constructed + * and used for resolving types for configured base type and its + * subtypes. + *<p> + * Note that instances are used for two related but distinct use cases: + *<ul> + * <li>To create builders to use with explicit type information + * inclusion (usually via <code>@JsonTypeInfo</code> annotation) + * </li> + * <li>To create builders when "default typing" is used; if so, type information + * is automatically included for certain kind of types, regardless of annotations + * </li> + *</ul> + * Important distinction between the cases is that in first case, calls to + * create builders are only made when builders are certainly needed; whereas + * in second case builder has to first verify whether type information is + * applicable for given type, and if not, just return null to indicate this. + * + * @since 1.5 + * @author tatu + */ +public interface TypeResolverBuilder<T extends TypeResolverBuilder<T>> +{ + /* + /********************************************************** + /* Accessors + /********************************************************** + */ + + /** + * Accessor for currently configured default type; implementation + * class that may be used in case no valid type information is + * available during type resolution + * + * @since 1.9 + */ + public Class<?> getDefaultImpl(); + + /* + /********************************************************** + /* Actual builder methods + /********************************************************** + */ + + /** + * Method for building type serializer based on current configuration + * of this builder. + * + * @param baseType Base type that constructed resolver will + * handle; super type of all types it will be used for. + */ + public TypeSerializer buildTypeSerializer(SerializationConfig config, + JavaType baseType, Collection<NamedType> subtypes, BeanProperty property); + + /** + * Method for building type deserializer based on current configuration + * of this builder. + * + * @param baseType Base type that constructed resolver will + * handle; super type of all types it will be used for. + * @param subtypes Known subtypes of the base type. + */ + public TypeDeserializer buildTypeDeserializer( DeserializationConfig config, + JavaType baseType, Collection<NamedType> subtypes, BeanProperty property); + + /* + /********************************************************** + /* Initialization method(s) that must be called before other + /* configuration + /********************************************************** + */ + + /** + * Initialization method that is called right after constructing + * the builder instance. + * + * @param idType Which type metadata is used + * @param res (optional) Custom type id resolver used, if any + * + * @return Resulting builder instance (usually this builder, + * but not necessarily) + */ + public T init(JsonTypeInfo.Id idType, TypeIdResolver res); + + /* + /********************************************************** + /* Methods for configuring resolver to build + /********************************************************** + */ + + /** + * Method for specifying mechanism to use for including type metadata + * in JSON. + * If not explicitly called, setting defaults to + * {@link As#PROPERTY}. + * + * @param includeAs Mechanism used for including type metadata in JSON + * + * @return Resulting builder instance (usually this builder, + * but not necessarily) + */ + public T inclusion(As includeAs); + + /** + * Method for specifying name of property used for including type + * information. Not used for all inclusion mechanisms; + * usually only used with {@link As#PROPERTY}. + *<p> + * If not explicitly called, name of property to use is based on + * defaults for {@link org.codehaus.jackson.annotate.JsonTypeInfo.Id} configured. + * + * @param propName Name of JSON property to use for including + * type information + * + * @return Resulting builder instance (usually this builder, + * but not necessarily) + */ + public T typeProperty(String propName); + + /** + * Method for specifying default implementation to use if type id + * is either not available, or can not be resolved. + * + * @since 1.9 + */ + public T defaultImpl(Class<?> defaultImpl); +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/impl/AsArrayTypeDeserializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/impl/AsArrayTypeDeserializer.java new file mode 100644 index 0000000..0eb7e3c --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/impl/AsArrayTypeDeserializer.java
@@ -0,0 +1,126 @@ +package org.codehaus.jackson.map.jsontype.impl; + +import java.io.IOException; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.annotate.JsonTypeInfo.As; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.jsontype.TypeIdResolver; +import org.codehaus.jackson.type.JavaType; + +/** + * Type deserializer used with {@link As#WRAPPER_ARRAY} + * inclusion mechanism. Simple since JSON structure used is always + * the same, regardless of structure used for actual value: wrapping + * is done using a 2-element JSON Array where type id is the first + * element, and actual object data as second element. + * + * @author tatus + */ +public class AsArrayTypeDeserializer extends TypeDeserializerBase +{ + @Deprecated // since 1.9 + public AsArrayTypeDeserializer(JavaType bt, TypeIdResolver idRes, BeanProperty property) { + this(bt, idRes, property, null); + } + + public AsArrayTypeDeserializer(JavaType bt, TypeIdResolver idRes, BeanProperty property, + Class<?> defaultImpl) + { + super(bt, idRes, property, defaultImpl); + } + + @Override + public As getTypeInclusion() { + return As.WRAPPER_ARRAY; + } + + /** + * Method called when actual object is serialized as JSON Array. + */ + @Override + public Object deserializeTypedFromArray(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + return _deserialize(jp, ctxt); + } + + /** + * Method called when actual object is serialized as JSON Object + */ + @Override + public Object deserializeTypedFromObject(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + return _deserialize(jp, ctxt); + } + + @Override + public Object deserializeTypedFromScalar(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + return _deserialize(jp, ctxt); + } + + @Override + public Object deserializeTypedFromAny(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + return _deserialize(jp, ctxt); + } + + /* + /*************************************************************** + /* Internal methods + /*************************************************************** + */ + + /** + * Method that handles type information wrapper, locates actual + * subtype deserializer to use, and calls it to do actual + * deserialization. + */ + private final Object _deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + boolean hadStartArray = jp.isExpectedStartArrayToken(); + JsonDeserializer<Object> deser = _findDeserializer(ctxt, _locateTypeId(jp, ctxt)); + Object value = deser.deserialize(jp, ctxt); + // And then need the closing END_ARRAY + if (hadStartArray && jp.nextToken() != JsonToken.END_ARRAY) { + throw ctxt.wrongTokenException(jp, JsonToken.END_ARRAY, + "expected closing END_ARRAY after type information and deserialized value"); + } + return value; + } + + protected final String _locateTypeId(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + if (!jp.isExpectedStartArrayToken()) { + // Add instanceof check because we cannot add method to TypeIdResolver interface due to backwards + // compatibility issues. We can however add it to the base method, which gets at least some of + // the functionality we want. Falls back to old exception for other types of TypeIdResolvers + if (_idResolver instanceof TypeIdResolverBase) { + if (_defaultImpl != null) { // but let's require existence of default impl, as a safeguard + return ((TypeIdResolverBase) _idResolver).idFromBaseType(); + } + } + throw ctxt.wrongTokenException(jp, JsonToken.START_ARRAY, + "need JSON Array to contain As.WRAPPER_ARRAY type information for class "+baseTypeName()); + } + // And then type id as a String + if (jp.nextToken() != JsonToken.VALUE_STRING) { + if (_idResolver instanceof TypeIdResolverBase) { + if (_defaultImpl != null) { // but let's require existence of default impl, as a safeguard + return ((TypeIdResolverBase) _idResolver).idFromBaseType(); + } + } + throw ctxt.wrongTokenException(jp, JsonToken.VALUE_STRING, + "need JSON String that contains type id (for subtype of "+baseTypeName()+")"); + } + String result = jp.getText(); + jp.nextToken(); + return result; + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/impl/AsArrayTypeSerializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/impl/AsArrayTypeSerializer.java new file mode 100644 index 0000000..4082964 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/impl/AsArrayTypeSerializer.java
@@ -0,0 +1,110 @@ +package org.codehaus.jackson.map.jsontype.impl; + +import java.io.IOException; + +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.annotate.JsonTypeInfo.As; +import org.codehaus.jackson.map.BeanProperty; +import org.codehaus.jackson.map.jsontype.TypeIdResolver; + +/** + * Type serializer that will embed type information in an array, + * as the first element, and actual value as the second element. + * + * @since 1.5 + * @author tatu + */ +public class AsArrayTypeSerializer + extends TypeSerializerBase +{ + public AsArrayTypeSerializer(TypeIdResolver idRes, BeanProperty property) + { + super(idRes, property); + } + + @Override + public As getTypeInclusion() { return As.WRAPPER_ARRAY; } + + @Override + public void writeTypePrefixForObject(Object value, JsonGenerator jgen) + throws IOException, JsonProcessingException + { + jgen.writeStartArray(); + jgen.writeString(_idResolver.idFromValue(value)); + jgen.writeStartObject(); + } + + @Override + public void writeTypePrefixForObject(Object value, JsonGenerator jgen, + Class<?> type) + throws IOException, JsonProcessingException + { + jgen.writeStartArray(); + jgen.writeString(_idResolver.idFromValueAndType(value, type)); + jgen.writeStartObject(); + } + + @Override + public void writeTypePrefixForArray(Object value, JsonGenerator jgen) + throws IOException, JsonProcessingException + { + jgen.writeStartArray(); + jgen.writeString(_idResolver.idFromValue(value)); + jgen.writeStartArray(); + } + + @Override + public void writeTypePrefixForArray(Object value, JsonGenerator jgen, + Class<?> type) + throws IOException, JsonProcessingException + { + jgen.writeStartArray(); + jgen.writeString(_idResolver.idFromValueAndType(value, type)); + jgen.writeStartArray(); + } + + @Override + public void writeTypePrefixForScalar(Object value, JsonGenerator jgen) + throws IOException, JsonProcessingException + { + // only need the wrapper array + jgen.writeStartArray(); + jgen.writeString(_idResolver.idFromValue(value)); + } + + @Override + public void writeTypePrefixForScalar(Object value, JsonGenerator jgen, + Class<?> type) + throws IOException, JsonProcessingException + { + // only need the wrapper array + jgen.writeStartArray(); + jgen.writeString(_idResolver.idFromValueAndType(value, type)); + } + + @Override + public void writeTypeSuffixForObject(Object value, JsonGenerator jgen) + throws IOException, JsonProcessingException + { + jgen.writeEndObject(); + jgen.writeEndArray(); + } + + @Override + public void writeTypeSuffixForArray(Object value, JsonGenerator jgen) + throws IOException, JsonProcessingException + { + // wrapper array first, and then array caller needs to close + jgen.writeEndArray(); + jgen.writeEndArray(); + } + + @Override + public void writeTypeSuffixForScalar(Object value, JsonGenerator jgen) + throws IOException, JsonProcessingException + { + // just the wrapper array to close + jgen.writeEndArray(); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/impl/AsExternalTypeDeserializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/impl/AsExternalTypeDeserializer.java new file mode 100644 index 0000000..b4748a0 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/impl/AsExternalTypeDeserializer.java
@@ -0,0 +1,37 @@ +package org.codehaus.jackson.map.jsontype.impl; + +import org.codehaus.jackson.annotate.JsonTypeInfo.As; +import org.codehaus.jackson.map.BeanProperty; +import org.codehaus.jackson.map.jsontype.TypeIdResolver; +import org.codehaus.jackson.type.JavaType; + +/** + * Type deserializer used with {@link As#EXTERNAL_PROPERTY} inclusion mechanism. + * Actual implementation may look bit strange since it depends on comprehensive + * pre-processing done by {@link org.codehaus.jackson.map.deser.BeanDeserializer} + * to basically transform external type id into structure that looks more like + * "wrapper-array" style inclusion. This intermediate form is chosen to allow + * supporting all possible JSON structures. + * + * @since 1.9 + */ +public class AsExternalTypeDeserializer extends AsArrayTypeDeserializer +{ + protected final String _typePropertyName; + + public AsExternalTypeDeserializer(JavaType bt, TypeIdResolver idRes, BeanProperty property, + Class<?> defaultImpl, + String typePropName) + { + super(bt, idRes, property, defaultImpl); + _typePropertyName = typePropName; + } + + @Override + public As getTypeInclusion() { + return As.EXTERNAL_PROPERTY; + } + + @Override + public String getPropertyName() { return _typePropertyName; } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/impl/AsExternalTypeSerializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/impl/AsExternalTypeSerializer.java new file mode 100644 index 0000000..ae6786a --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/impl/AsExternalTypeSerializer.java
@@ -0,0 +1,129 @@ +package org.codehaus.jackson.map.jsontype.impl; + +import java.io.IOException; + +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.annotate.JsonTypeInfo.As; +import org.codehaus.jackson.map.BeanProperty; +import org.codehaus.jackson.map.jsontype.TypeIdResolver; + +/** + * Type serializer that preferably embeds type information as an "external" + * type property; embedded in enclosing JSON object. + * Note that this serializer should only be used when value is being output + * at JSON Object context; otherwise it can not work reliably, and will have + * to revert operation similar to {@link AsPropertyTypeSerializer}. + *<p> + * Note that implementation of serialization is bit cumbersome as we must + * serialized external type id AFTER object; this because callback only + * occurs after field name has been written. + * + * @since 1.9 + */ +public class AsExternalTypeSerializer + extends TypeSerializerBase +{ + protected final String _typePropertyName; + + public AsExternalTypeSerializer(TypeIdResolver idRes, BeanProperty property, + String propName) + { + super(idRes, property); + _typePropertyName = propName; + } + + @Override + public String getPropertyName() { return _typePropertyName; } + + @Override + public As getTypeInclusion() { return As.EXTERNAL_PROPERTY; } + + @Override + public void writeTypePrefixForObject(Object value, JsonGenerator jgen) + throws IOException, JsonProcessingException + { + _writePrefix(value, jgen); + } + + @Override + public void writeTypePrefixForObject(Object value, JsonGenerator jgen, Class<?> type) + throws IOException, JsonProcessingException + { + _writePrefix(value, jgen, type); + } + + @Override + public void writeTypePrefixForArray(Object value, JsonGenerator jgen) + throws IOException, JsonProcessingException + { + _writePrefix(value, jgen); + } + + @Override + public void writeTypePrefixForArray(Object value, JsonGenerator jgen, Class<?> type) + throws IOException, JsonProcessingException + { + _writePrefix(value, jgen, type); + } + + @Override + public void writeTypePrefixForScalar(Object value, JsonGenerator jgen) + throws IOException, JsonProcessingException + { + _writePrefix(value, jgen); + } + + @Override + public void writeTypePrefixForScalar(Object value, JsonGenerator jgen, Class<?> type) + throws IOException, JsonProcessingException + { + _writePrefix(value, jgen, type); + } + + @Override + public void writeTypeSuffixForObject(Object value, JsonGenerator jgen) + throws IOException, JsonProcessingException + { + _writeSuffix(value, jgen); + } + + @Override + public void writeTypeSuffixForArray(Object value, JsonGenerator jgen) + throws IOException, JsonProcessingException + { + _writeSuffix(value, jgen); + } + + @Override + public void writeTypeSuffixForScalar(Object value, JsonGenerator jgen) + throws IOException, JsonProcessingException + { + _writeSuffix(value, jgen); + } + + /* + /********************************************************** + /* Helper methods + /********************************************************** + */ + + protected final void _writePrefix(Object value, JsonGenerator jgen) + throws IOException, JsonProcessingException + { + jgen.writeStartObject(); + } + + protected final void _writePrefix(Object value, JsonGenerator jgen, Class<?> type) + throws IOException, JsonProcessingException + { + jgen.writeStartObject(); + } + + protected final void _writeSuffix(Object value, JsonGenerator jgen) + throws IOException, JsonProcessingException + { + jgen.writeEndObject(); + jgen.writeStringField(_typePropertyName, _idResolver.idFromValue(value)); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/impl/AsPropertyTypeDeserializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/impl/AsPropertyTypeDeserializer.java new file mode 100644 index 0000000..6062879 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/impl/AsPropertyTypeDeserializer.java
@@ -0,0 +1,191 @@ +package org.codehaus.jackson.map.jsontype.impl; + +import java.io.IOException; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.annotate.JsonTypeInfo.As; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.jsontype.TypeIdResolver; +import org.codehaus.jackson.type.JavaType; +import org.codehaus.jackson.util.JsonParserSequence; +import org.codehaus.jackson.util.TokenBuffer; + +/** + * Type deserializer used with {@link As#PROPERTY} + * inclusion mechanism. + * Uses regular form (additional key/value entry before actual data) + * when typed object is expressed as JSON Object; otherwise behaves similar to how + * {@link As#WRAPPER_ARRAY} works. + * Latter is used if JSON representation is polymorphic + * + * @since 1.5 + * @author tatu + */ +public class AsPropertyTypeDeserializer extends AsArrayTypeDeserializer +{ + protected final String _typePropertyName; + + @Deprecated // since 1.9 + public AsPropertyTypeDeserializer(JavaType bt, TypeIdResolver idRes, BeanProperty property, + String typePropName) { + this(bt, idRes, property, null, typePropName); + } + + public AsPropertyTypeDeserializer(JavaType bt, TypeIdResolver idRes, BeanProperty property, + Class<?> defaultImpl, + String typePropName) + { + super(bt, idRes, property, defaultImpl); + _typePropertyName = typePropName; + } + + @Override + public As getTypeInclusion() { + return As.PROPERTY; + } + + @Override + public String getPropertyName() { return _typePropertyName; } + + /** + * This is the trickiest thing to handle, since property we are looking + * for may be anywhere... + */ + @Override + public Object deserializeTypedFromObject(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + // but first, sanity check to ensure we have START_OBJECT or FIELD_NAME + JsonToken t = jp.getCurrentToken(); + if (t == JsonToken.START_OBJECT) { + t = jp.nextToken(); + } else if (t == JsonToken.START_ARRAY) { + /* This is most likely due to the fact that not all Java types are + * serialized as JSON Objects; so if "as-property" inclusion is requested, + * serialization of things like Lists must be instead handled as if + * "as-wrapper-array" was requested. + * But this can also be due to some custom handling: so, if "defaultImpl" + * is defined, it will be asked to handle this case. + */ + return _deserializeTypedUsingDefaultImpl(jp, ctxt, null); + } else if (t != JsonToken.FIELD_NAME) { + return _deserializeTypedUsingDefaultImpl(jp, ctxt, null); + } + // Ok, let's try to find the property. But first, need token buffer... + TokenBuffer tb = null; + + for (; t == JsonToken.FIELD_NAME; t = jp.nextToken()) { + String name = jp.getCurrentName(); + jp.nextToken(); // to point to the value + if (_typePropertyName.equals(name)) { // gotcha! + String typeId = jp.getText(); + JsonDeserializer<Object> deser = _findDeserializer(ctxt, typeId); + // deserializer should take care of closing END_OBJECT as well + if (tb != null) { + jp = JsonParserSequence.createFlattened(tb.asParser(jp), jp); + } + /* Must point to the next value; tb had no current, jp + * pointed to VALUE_STRING: + */ + jp.nextToken(); // to skip past String value + // deserializer should take care of closing END_OBJECT as well + return deser.deserialize(jp, ctxt); + } + if (tb == null) { + tb = new TokenBuffer(null); + } + tb.writeFieldName(name); + tb.copyCurrentStructure(jp); + } + return _deserializeTypedUsingDefaultImpl(jp, ctxt, tb); + } + + // off-lined to keep main method lean and mean... + protected Object _deserializeTypedUsingDefaultImpl(JsonParser jp, + DeserializationContext ctxt, TokenBuffer tb) + throws IOException, JsonProcessingException + { + // As per [JACKSON-614], may have default implementation to use + if (_defaultImpl != null) { + JsonDeserializer<Object> deser = _findDefaultImplDeserializer(ctxt); + if (tb != null) { + tb.writeEndObject(); + jp = tb.asParser(jp); + // must move to point to the first token: + jp.nextToken(); + } + return deser.deserialize(jp, ctxt); + } + // or, perhaps we just bumped into a "natural" value (boolean/int/double/String)? + Object result = _deserializeIfNatural(jp, ctxt); + if (result != null) { + return result; + } + // or, something for which "as-property" won't work, changed into "wrapper-array" type: + if (jp.getCurrentToken() == JsonToken.START_ARRAY) { + return super.deserializeTypedFromAny(jp, ctxt); + } + throw ctxt.wrongTokenException(jp, JsonToken.FIELD_NAME, + "missing property '"+_typePropertyName+"' that is to contain type id (for class "+baseTypeName()+")"); + } + + /* As per [JACKSON-352], also need to re-route "unknown" version. Need to think + * this through bit more in future, but for now this does address issue and has + * no negative side effects (at least within existing unit test suite). + */ + @Override + public Object deserializeTypedFromAny(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + /* [JACKSON-387]: Sometimes, however, we get an array wrapper; specifically + * when an array or list has been serialized with type information. + */ + if (jp.getCurrentToken() == JsonToken.START_ARRAY) { + return super.deserializeTypedFromArray(jp, ctxt); + } + return deserializeTypedFromObject(jp, ctxt); + } + + // These are fine from base class: + //public Object deserializeTypedFromArray(JsonParser jp, DeserializationContext ctxt) + //public Object deserializeTypedFromScalar(JsonParser jp, DeserializationContext ctxt) + + /** + * Helper method used to check if given parser might be pointing to + * a "natural" value, and one that would be acceptable as the + * result value (compatible with declared base type) + */ + protected Object _deserializeIfNatural(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + switch (jp.getCurrentToken()) { + case VALUE_STRING: + if (_baseType.getRawClass().isAssignableFrom(String.class)) { + return jp.getText(); + } + break; + case VALUE_NUMBER_INT: + if (_baseType.getRawClass().isAssignableFrom(Integer.class)) { + return jp.getIntValue(); + } + break; + + case VALUE_NUMBER_FLOAT: + if (_baseType.getRawClass().isAssignableFrom(Double.class)) { + return Double.valueOf(jp.getDoubleValue()); + } + break; + case VALUE_TRUE: + if (_baseType.getRawClass().isAssignableFrom(Boolean.class)) { + return Boolean.TRUE; + } + break; + case VALUE_FALSE: + if (_baseType.getRawClass().isAssignableFrom(Boolean.class)) { + return Boolean.FALSE; + } + break; + } + return null; + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/impl/AsPropertyTypeSerializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/impl/AsPropertyTypeSerializer.java new file mode 100644 index 0000000..53f1052 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/impl/AsPropertyTypeSerializer.java
@@ -0,0 +1,69 @@ +package org.codehaus.jackson.map.jsontype.impl; + +import java.io.IOException; + +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.annotate.JsonTypeInfo.As; +import org.codehaus.jackson.map.BeanProperty; +import org.codehaus.jackson.map.jsontype.TypeIdResolver; + +/** + * Type serializer that preferably embeds type information as an additional + * JSON Object property, if possible (when resulting serialization would + * use JSON Object). If this is not possible (for JSON Arrays, scalars), + * uses a JSON Array wrapper (similar to how + * {@link As#WRAPPER_ARRAY} always works) as a fallback. + * + * @since 1.5 + * @author tatus + */ +public class AsPropertyTypeSerializer + extends AsArrayTypeSerializer +{ + protected final String _typePropertyName; + + public AsPropertyTypeSerializer(TypeIdResolver idRes, BeanProperty property, + String propName) + { + super(idRes, property); + _typePropertyName = propName; + } + + @Override + public String getPropertyName() { return _typePropertyName; } + + @Override + public As getTypeInclusion() { return As.PROPERTY; } + + @Override + public void writeTypePrefixForObject(Object value, JsonGenerator jgen) + throws IOException, JsonProcessingException + { + jgen.writeStartObject(); + jgen.writeStringField(_typePropertyName, _idResolver.idFromValue(value)); + } + + @Override + public void writeTypePrefixForObject(Object value, JsonGenerator jgen, Class<?> type) + throws IOException, JsonProcessingException + { + jgen.writeStartObject(); + jgen.writeStringField(_typePropertyName, _idResolver.idFromValueAndType(value, type)); + } + + //public void writeTypePrefixForArray(Object value, JsonGenerator jgen) + //public void writeTypePrefixForArray(Object value, JsonGenerator jgen, Class<?> type) + //public void writeTypePrefixForScalar(Object value, JsonGenerator jgen) + //public void writeTypePrefixForScalar(Object value, JsonGenerator jgen, Class<?> type) + + @Override + public void writeTypeSuffixForObject(Object value, JsonGenerator jgen) + throws IOException, JsonProcessingException + { + jgen.writeEndObject(); + } + + //public void writeTypeSuffixForArray(Object value, JsonGenerator jgen) + //public void writeTypeSuffixForScalar(Object value, JsonGenerator jgen) +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/impl/AsWrapperTypeDeserializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/impl/AsWrapperTypeDeserializer.java new file mode 100644 index 0000000..dd9dab5 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/impl/AsWrapperTypeDeserializer.java
@@ -0,0 +1,103 @@ +package org.codehaus.jackson.map.jsontype.impl; + +import java.io.IOException; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.annotate.JsonTypeInfo.As; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.jsontype.TypeIdResolver; +import org.codehaus.jackson.type.JavaType; + +/** + * Type deserializer used with {@link As#WRAPPER_OBJECT} + * inclusion mechanism. Simple since JSON structure used is always + * the same, regardless of structure used for actual value: wrapping + * is done using a single-element JSON Object where type id is the key, + * and actual object data as the value. + * + * @author tatus + */ +public class AsWrapperTypeDeserializer extends TypeDeserializerBase +{ + @Deprecated // since 1.9 + public AsWrapperTypeDeserializer(JavaType bt, TypeIdResolver idRes, BeanProperty property) { + this(bt, idRes, property, null); + } + + public AsWrapperTypeDeserializer(JavaType bt, TypeIdResolver idRes, BeanProperty property, + Class<?> defaultImpl) + { + super(bt, idRes, property, null); + } + + @Override + public As getTypeInclusion() { + return As.WRAPPER_OBJECT; + } + + /** + * Deserializing type id enclosed using WRAPPER_OBJECT style is straightforward + */ + @Override + public Object deserializeTypedFromObject(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + return _deserialize(jp, ctxt); + } + + @Override + public Object deserializeTypedFromArray(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + return _deserialize(jp, ctxt); + } + + @Override + public Object deserializeTypedFromScalar(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + return _deserialize(jp, ctxt); + } + + @Override + public Object deserializeTypedFromAny(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + return _deserialize(jp, ctxt); + } + + /* + /*************************************************************** + /* Internal methods + /*************************************************************** + */ + + /** + * Method that handles type information wrapper, locates actual + * subtype deserializer to use, and calls it to do actual + * deserialization. + */ + private final Object _deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + // first, sanity checks + if (jp.getCurrentToken() != JsonToken.START_OBJECT) { + throw ctxt.wrongTokenException(jp, JsonToken.START_OBJECT, + "need JSON Object to contain As.WRAPPER_OBJECT type information for class "+baseTypeName()); + } + // should always get field name, but just in case... + if (jp.nextToken() != JsonToken.FIELD_NAME) { + throw ctxt.wrongTokenException(jp, JsonToken.FIELD_NAME, + "need JSON String that contains type id (for subtype of "+baseTypeName()+")"); + } + JsonDeserializer<Object> deser = _findDeserializer(ctxt, jp.getText()); + jp.nextToken(); + Object value = deser.deserialize(jp, ctxt); + // And then need the closing END_OBJECT + if (jp.nextToken() != JsonToken.END_OBJECT) { + throw ctxt.wrongTokenException(jp, JsonToken.END_OBJECT, + "expected closing END_OBJECT after type information and deserialized value"); + } + return value; + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/impl/AsWrapperTypeSerializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/impl/AsWrapperTypeSerializer.java new file mode 100644 index 0000000..80ee1f9 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/impl/AsWrapperTypeSerializer.java
@@ -0,0 +1,121 @@ +package org.codehaus.jackson.map.jsontype.impl; + +import java.io.IOException; + +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.annotate.JsonTypeInfo.As; +import org.codehaus.jackson.map.BeanProperty; +import org.codehaus.jackson.map.jsontype.TypeIdResolver; + +/** + * Type wrapper that tries to use an extra JSON Object, with a single + * entry that has type name as key, to serialize type information. + * If this is not possible (value is serialize as array or primitive), + * will use {@link As#WRAPPER_ARRAY} mechanism as fallback: that is, + * just use a wrapping array with type information as the first element + * and value as second. + * + * @since 1.5 + * @author tatus + */ +public class AsWrapperTypeSerializer + extends TypeSerializerBase +{ + public AsWrapperTypeSerializer(TypeIdResolver idRes, BeanProperty property) + { + super(idRes, property); + } + + @Override + public As getTypeInclusion() { return As.WRAPPER_OBJECT; } + + @Override + public void writeTypePrefixForObject(Object value, JsonGenerator jgen) + throws IOException, JsonProcessingException + { + // wrapper + jgen.writeStartObject(); + // and then JSON Object start caller wants + jgen.writeObjectFieldStart(_idResolver.idFromValue(value)); + } + + @Override + public void writeTypePrefixForObject(Object value, JsonGenerator jgen, + Class<?> type) + throws IOException, JsonProcessingException + { + // wrapper + jgen.writeStartObject(); + // and then JSON Object start caller wants + jgen.writeObjectFieldStart(_idResolver.idFromValueAndType(value, type)); + } + + @Override + public void writeTypePrefixForArray(Object value, JsonGenerator jgen) + throws IOException, JsonProcessingException + { + // can still wrap ok + jgen.writeStartObject(); + // and then JSON Array start caller wants + jgen.writeArrayFieldStart(_idResolver.idFromValue(value)); + } + + @Override + public void writeTypePrefixForArray(Object value, JsonGenerator jgen, + Class<?> type) + throws IOException, JsonProcessingException + { + // can still wrap ok + jgen.writeStartObject(); + // and then JSON Array start caller wants + jgen.writeArrayFieldStart(_idResolver.idFromValueAndType(value, type)); + } + + @Override + public void writeTypePrefixForScalar(Object value, JsonGenerator jgen) + throws IOException, JsonProcessingException + { + // can still wrap ok + jgen.writeStartObject(); + jgen.writeFieldName(_idResolver.idFromValue(value)); + } + + @Override + public void writeTypePrefixForScalar(Object value, JsonGenerator jgen, + Class<?> type) + throws IOException, JsonProcessingException + { + // can still wrap ok + jgen.writeStartObject(); + jgen.writeFieldName(_idResolver.idFromValueAndType(value, type)); + } + + @Override + public void writeTypeSuffixForObject(Object value, JsonGenerator jgen) + throws IOException, JsonProcessingException + { + // first close JSON Object caller used + jgen.writeEndObject(); + // and then wrapper + jgen.writeEndObject(); + } + + @Override + public void writeTypeSuffixForArray(Object value, JsonGenerator jgen) + throws IOException, JsonProcessingException + { + // first close array caller needed + jgen.writeEndArray(); + // then wrapper object + jgen.writeEndObject(); + } + + @Override + public void writeTypeSuffixForScalar(Object value, JsonGenerator jgen) + throws IOException, JsonProcessingException + { + // just need to close the wrapper object + jgen.writeEndObject(); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/impl/ClassNameIdResolver.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/impl/ClassNameIdResolver.java new file mode 100644 index 0000000..c9fd65e --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/impl/ClassNameIdResolver.java
@@ -0,0 +1,133 @@ +package org.codehaus.jackson.map.jsontype.impl; + +import java.util.*; + +import org.codehaus.jackson.type.JavaType; +import org.codehaus.jackson.annotate.JsonTypeInfo; +import org.codehaus.jackson.map.type.TypeFactory; +import org.codehaus.jackson.map.util.ClassUtil; + +/** + * {@link org.codehaus.jackson.map.jsontype.TypeIdResolver} implementation + * that converts between fully-qualified + * Java class names and (JSON) Strings. + */ +public class ClassNameIdResolver + extends TypeIdResolverBase +{ + public ClassNameIdResolver(JavaType baseType, TypeFactory typeFactory) { + super(baseType, typeFactory); + } + + @Override + public JsonTypeInfo.Id getMechanism() { return JsonTypeInfo.Id.CLASS; } + + public void registerSubtype(Class<?> type, String name) { + // not used with class name - based resolvers + } + + @Override + public String idFromValue(Object value) + { + return _idFrom(value, value.getClass()); + } + + @Override + public String idFromValueAndType(Object value, Class<?> type) + { + return _idFrom(value, type); + } + + @Override + public JavaType typeFromId(String id) + { + /* 30-Jan-2010, tatu: Most ids are basic class names; so let's first + * check if any generics info is added; and only then ask factory + * to do translation when necessary + */ + if (id.indexOf('<') > 0) { + JavaType t = TypeFactory.fromCanonical(id); + // note: may want to try combining with specialization (esp for EnumMap) + return t; + } + try { + Class<?> cls = ClassUtil.findClass(id); + return _typeFactory.constructSpecializedType(_baseType, cls); + } catch (ClassNotFoundException e) { + throw new IllegalArgumentException("Invalid type id '"+id+"' (for id type 'Id.class'): no such class found"); + } catch (Exception e) { + throw new IllegalArgumentException("Invalid type id '"+id+"' (for id type 'Id.class'): "+e.getMessage(), e); + } + } + + /* + /********************************************************** + /* Internal methods + /********************************************************** + */ + + protected final String _idFrom(Object value, Class<?> cls) + { + // [JACKSON-380] Need to ensure that "enum subtypes" work too + if (Enum.class.isAssignableFrom(cls)) { + if (!cls.isEnum()) { // means that it's sub-class of base enum, so: + cls = cls.getSuperclass(); + } + } + String str = cls.getName(); + if (str.startsWith("java.util")) { + /* 25-Jan-2009, tatu: There are some internal classes that + * we can not access as is. We need better mechanism; for + * now this has to do... + */ + /* Enum sets and maps are problematic since we MUST know + * type of contained enums, to be able to deserialize. + * In addition, EnumSet is not a concrete type either + */ + if (value instanceof EnumSet<?>) { // Regular- and JumboEnumSet... + Class<?> enumClass = ClassUtil.findEnumType((EnumSet<?>) value); + // not optimal: but EnumSet is not a customizable type so this is sort of ok + str = TypeFactory.defaultInstance().constructCollectionType(EnumSet.class, enumClass).toCanonical(); + } else if (value instanceof EnumMap<?,?>) { + Class<?> enumClass = ClassUtil.findEnumType((EnumMap<?,?>) value); + Class<?> valueClass = Object.class; + // not optimal: but EnumMap is not a customizable type so this is sort of ok + str = TypeFactory.defaultInstance().constructMapType(EnumMap.class, enumClass, valueClass).toCanonical(); + } else { + String end = str.substring(9); + if ((end.startsWith(".Arrays$") || end.startsWith(".Collections$")) + && str.indexOf("List") >= 0) { + /* 17-Feb-2010, tatus: Another such case: result of + * Arrays.asList() is named like so in Sun JDK... + * Let's just plain old ArrayList in its place + * NOTE: chances are there are plenty of similar cases + * for other wrappers... (immutable, singleton, synced etc) + */ + str = "java.util.ArrayList"; + } + } + } else if (str.indexOf('$') >= 0) { + /* Other special handling may be needed for inner classes, [JACKSON-584]. + * The best way to handle would be to find 'hidden' constructor; pass parent + * value etc (which is actually done for non-anonymous static classes!), + * but that is just not possible due to various things. So, we will instead + * try to generalize type into something we will be more likely to be able + * construct. + */ + Class<?> outer = ClassUtil.getOuterClass(cls); + if (outer != null) { + /* one more check: let's actually not worry if the declared + * static type is non-static as well; if so, deserializer does + * have a chance at figuring it all out. + */ + Class<?> staticType = _baseType.getRawClass(); + if (ClassUtil.getOuterClass(staticType) == null) { + // Is this always correct? Seems like it should be... + cls = _baseType.getRawClass(); + str = cls.getName(); + } + } + } + return str; + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/impl/MinimalClassNameIdResolver.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/impl/MinimalClassNameIdResolver.java new file mode 100644 index 0000000..1972cff --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/impl/MinimalClassNameIdResolver.java
@@ -0,0 +1,66 @@ +package org.codehaus.jackson.map.jsontype.impl; + +import org.codehaus.jackson.map.type.TypeFactory; +import org.codehaus.jackson.type.JavaType; +import org.codehaus.jackson.annotate.JsonTypeInfo; + +public class MinimalClassNameIdResolver + extends ClassNameIdResolver +{ + /** + * Package name of the base class, to be used for determining common + * prefix that can be omitted from included type id. + * Does not include the trailing dot. + */ + protected final String _basePackageName; + + /** + * Same as {@link #_basePackageName}, but includes trailing dot. + */ + protected final String _basePackagePrefix; + + protected MinimalClassNameIdResolver(JavaType baseType, TypeFactory typeFactory) + { + super(baseType, typeFactory); + String base = baseType.getRawClass().getName(); + int ix = base.lastIndexOf('.'); + if (ix < 0) { // can this ever occur? + _basePackageName = ""; + _basePackagePrefix = "."; + } else { + _basePackagePrefix = base.substring(0, ix+1); + _basePackageName = base.substring(0, ix); + } + } + + @Override + public JsonTypeInfo.Id getMechanism() { return JsonTypeInfo.Id.MINIMAL_CLASS; } + + @Override + public String idFromValue(Object value) + { + String n = value.getClass().getName(); + if (n.startsWith(_basePackagePrefix)) { + // note: we will leave the leading dot in there + return n.substring(_basePackagePrefix.length()-1); + } + return n; + } + + @Override + public JavaType typeFromId(String id) + { + if (id.startsWith(".")) { + StringBuilder sb = new StringBuilder(id.length() + _basePackageName.length()); + if (_basePackageName.length() == 0) { + // no package; must remove leading '.' from id + sb.append(id.substring(1)); + } else { + // otherwise just concatenate package, with leading-dot-partial name + sb.append(_basePackageName).append(id); + } + id = sb.toString(); + } + return super.typeFromId(id); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/impl/StdSubtypeResolver.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/impl/StdSubtypeResolver.java new file mode 100644 index 0000000..cebc848 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/impl/StdSubtypeResolver.java
@@ -0,0 +1,151 @@ +package org.codehaus.jackson.map.jsontype.impl; + +import java.util.*; + +import org.codehaus.jackson.map.AnnotationIntrospector; +import org.codehaus.jackson.map.MapperConfig; +import org.codehaus.jackson.map.introspect.*; +import org.codehaus.jackson.map.jsontype.NamedType; +import org.codehaus.jackson.map.jsontype.SubtypeResolver; + +/** + * @since 1.5 + */ +public class StdSubtypeResolver extends SubtypeResolver +{ + protected LinkedHashSet<NamedType> _registeredSubtypes; + + public StdSubtypeResolver() { } + + /* + /********************************************************** + /* Public API + /********************************************************** + */ + + @Override + public void registerSubtypes(NamedType... types) + { + if (_registeredSubtypes == null) { + _registeredSubtypes = new LinkedHashSet<NamedType>(); + } + for (NamedType type : types) { + _registeredSubtypes.add(type); + } + } + + @Override + public void registerSubtypes(Class<?>... classes) + { + NamedType[] types = new NamedType[classes.length]; + for (int i = 0, len = classes.length; i < len; ++i) { + types[i] = new NamedType(classes[i]); + } + registerSubtypes(types); + } + + /** + * + * @param property Base member to use for type resolution: either annotated type (class), + * or property (field, getter/setter) + */ + @Override + public Collection<NamedType> collectAndResolveSubtypes(AnnotatedMember property, + MapperConfig<?> config, AnnotationIntrospector ai) + { + HashMap<NamedType, NamedType> collected = new HashMap<NamedType, NamedType>(); + // start with registered subtypes (which have precedence) + if (_registeredSubtypes != null) { + Class<?> rawBase = property.getRawType(); + for (NamedType subtype : _registeredSubtypes) { + // is it a subtype of root type? + if (rawBase.isAssignableFrom(subtype.getType())) { // yes + AnnotatedClass curr = AnnotatedClass.constructWithoutSuperTypes(subtype.getType(), ai, config); + _collectAndResolve(curr, subtype, config, ai, collected); + } + } + } + + // then annotated types for property itself + Collection<NamedType> st = ai.findSubtypes(property); + if (st != null) { + for (NamedType nt : st) { + AnnotatedClass ac = AnnotatedClass.constructWithoutSuperTypes(nt.getType(), ai, config); + _collectAndResolve(ac, nt, config, ai, collected); + } + } + NamedType rootType = new NamedType(property.getRawType(), null); + AnnotatedClass ac = AnnotatedClass.constructWithoutSuperTypes(property.getRawType(), ai, config); + + // and finally subtypes via annotations from base type (recursively) + _collectAndResolve(ac, rootType, config, ai, collected); + return new ArrayList<NamedType>(collected.values()); + } + + @Override + public Collection<NamedType> collectAndResolveSubtypes(AnnotatedClass type, + MapperConfig<?> config, AnnotationIntrospector ai) + { + HashMap<NamedType, NamedType> subtypes = new HashMap<NamedType, NamedType>(); + // [JACKSON-257] then consider registered subtypes (which have precedence over annotations) + if (_registeredSubtypes != null) { + Class<?> rawBase = type.getRawType(); + for (NamedType subtype : _registeredSubtypes) { + // is it a subtype of root type? + if (rawBase.isAssignableFrom(subtype.getType())) { // yes + AnnotatedClass curr = AnnotatedClass.constructWithoutSuperTypes(subtype.getType(), ai, config); + _collectAndResolve(curr, subtype, config, ai, subtypes); + } + } + } + // and then check subtypes via annotations from base type (recursively) + NamedType rootType = new NamedType(type.getRawType(), null); + _collectAndResolve(type, rootType, config, ai, subtypes); + return new ArrayList<NamedType>(subtypes.values()); + } + + /* + /********************************************************** + /* Internal methods + /********************************************************** + */ + + /** + * Method called to find subtypes for a specific type (class) + */ + protected void _collectAndResolve(AnnotatedClass annotatedType, NamedType namedType, + MapperConfig<?> config, AnnotationIntrospector ai, HashMap<NamedType, NamedType> collectedSubtypes) + { + if (!namedType.hasName()) { + String name = ai.findTypeName(annotatedType); + if (name != null) { + namedType = new NamedType(namedType.getType(), name); + } + } + + // First things first: is base type itself included? + if (collectedSubtypes.containsKey(namedType)) { + // if so, no recursion; however, may need to update name? + if (namedType.hasName()) { + NamedType prev = collectedSubtypes.get(namedType); + if (!prev.hasName()) { + collectedSubtypes.put(namedType, namedType); + } + } + return; + } + // if it wasn't, add and check subtypes recursively + collectedSubtypes.put(namedType, namedType); + Collection<NamedType> st = ai.findSubtypes(annotatedType); + if (st != null && !st.isEmpty()) { + for (NamedType subtype : st) { + AnnotatedClass subtypeClass = AnnotatedClass.constructWithoutSuperTypes(subtype.getType(), ai, config); + // One more thing: name may be either in reference, or in subtype: + if (!subtype.hasName()) { + subtype = new NamedType(subtype.getType(), ai.findTypeName(subtypeClass)); + } + _collectAndResolve(subtypeClass, subtype, config, ai, collectedSubtypes); + } + } + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/impl/StdTypeResolverBuilder.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/impl/StdTypeResolverBuilder.java new file mode 100644 index 0000000..5bb481c --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/impl/StdTypeResolverBuilder.java
@@ -0,0 +1,202 @@ +package org.codehaus.jackson.map.jsontype.impl; + +import java.util.Collection; + +import org.codehaus.jackson.annotate.JsonTypeInfo; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.jsontype.NamedType; +import org.codehaus.jackson.map.jsontype.TypeIdResolver; +import org.codehaus.jackson.map.jsontype.TypeResolverBuilder; +import org.codehaus.jackson.type.JavaType; + +/** + * Default {@link TypeResolverBuilder} implementation. + * + * @author tatu + * @since 1.5 + */ +public class StdTypeResolverBuilder + implements TypeResolverBuilder<StdTypeResolverBuilder> +{ + // Configuration settings: + + protected JsonTypeInfo.Id _idType; + + protected JsonTypeInfo.As _includeAs; + + protected String _typeProperty; + + /** + * @since 1.9 + */ + protected Class<?> _defaultImpl; + + // Objects + + protected TypeIdResolver _customIdResolver; + + /* + /********************************************************** + /* Accessors + /********************************************************** + */ + + @Override + public Class<?> getDefaultImpl() { + return _defaultImpl; + } + + /* + /********************************************************** + /* Construction, initialization, actual building + /********************************************************** + */ + + public StdTypeResolverBuilder() { } + + public static StdTypeResolverBuilder noTypeInfoBuilder() { + return new StdTypeResolverBuilder().init(JsonTypeInfo.Id.NONE, null); + } + + @Override + public StdTypeResolverBuilder init(JsonTypeInfo.Id idType, TypeIdResolver idRes) + { + // sanity checks + if (idType == null) { + throw new IllegalArgumentException("idType can not be null"); + } + _idType = idType; + _customIdResolver = idRes; + // Let's also initialize property name as per idType default + _typeProperty = idType.getDefaultPropertyName(); + return this; + } + + @Override + public TypeSerializer buildTypeSerializer(SerializationConfig config, + JavaType baseType, Collection<NamedType> subtypes, BeanProperty property) + { + if (_idType == JsonTypeInfo.Id.NONE) { + return null; + } + TypeIdResolver idRes = idResolver(config, baseType, subtypes, true, false); + switch (_includeAs) { + case WRAPPER_ARRAY: + return new AsArrayTypeSerializer(idRes, property); + case PROPERTY: + return new AsPropertyTypeSerializer(idRes, property, _typeProperty); + case WRAPPER_OBJECT: + return new AsWrapperTypeSerializer(idRes, property); + case EXTERNAL_PROPERTY: + return new AsExternalTypeSerializer(idRes, property, _typeProperty); + } + throw new IllegalStateException("Do not know how to construct standard type serializer for inclusion type: "+_includeAs); + } + + @Override + public TypeDeserializer buildTypeDeserializer(DeserializationConfig config, + JavaType baseType, Collection<NamedType> subtypes, BeanProperty property) + { + if (_idType == JsonTypeInfo.Id.NONE) { + return null; + } + + TypeIdResolver idRes = idResolver(config, baseType, subtypes, false, true); + + // First, method for converting type info to type id: + switch (_includeAs) { + case WRAPPER_ARRAY: + return new AsArrayTypeDeserializer(baseType, idRes, property, _defaultImpl); + case PROPERTY: + return new AsPropertyTypeDeserializer(baseType, idRes, property, + _defaultImpl, _typeProperty); + case WRAPPER_OBJECT: + return new AsWrapperTypeDeserializer(baseType, idRes, property, _defaultImpl); + case EXTERNAL_PROPERTY: + return new AsExternalTypeDeserializer(baseType, idRes, property, + _defaultImpl, _typeProperty); + } + throw new IllegalStateException("Do not know how to construct standard type serializer for inclusion type: "+_includeAs); + } + + /* + /********************************************************** + /* Construction, configuration + /********************************************************** + */ + + @Override + public StdTypeResolverBuilder inclusion(JsonTypeInfo.As includeAs) { + if (includeAs == null) { + throw new IllegalArgumentException("includeAs can not be null"); + } + _includeAs = includeAs; + return this; + } + + /** + * Method for constructing an instance with specified type property name + * (property name to use for type id when using "as-property" inclusion). + */ + @Override + public StdTypeResolverBuilder typeProperty(String typeIdPropName) + { + // ok to have null/empty; will restore to use defaults + if (typeIdPropName == null || typeIdPropName.length() == 0) { + typeIdPropName = _idType.getDefaultPropertyName(); + } + _typeProperty = typeIdPropName; + return this; + } + + @Override + public StdTypeResolverBuilder defaultImpl(Class<?> defaultImpl) + { + _defaultImpl = defaultImpl; + return this; + } + + /* + /********************************************************** + /* Accessors + /********************************************************** + */ + + public String getTypeProperty() { return _typeProperty; } + + /* + /********************************************************** + /* Internal methods + /********************************************************** + */ + + /** + * Helper method that will either return configured custom + * type id resolver, or construct a standard resolver + * given configuration. + */ + protected TypeIdResolver idResolver(MapperConfig<?> config, + JavaType baseType, Collection<NamedType> subtypes, + boolean forSer, boolean forDeser) + { + // Custom id resolver? + if (_customIdResolver != null) { + return _customIdResolver; + } + if (_idType == null) { + throw new IllegalStateException("Can not build, 'init()' not yet called"); + } + switch (_idType) { + case CLASS: + return new ClassNameIdResolver(baseType, config.getTypeFactory()); + case MINIMAL_CLASS: + return new MinimalClassNameIdResolver(baseType, config.getTypeFactory()); + case NAME: + return TypeNameIdResolver.construct(config, baseType, subtypes, forSer, forDeser); + case NONE: // hmmh. should never get this far with 'none' + return null; + case CUSTOM: // need custom resolver... + } + throw new IllegalStateException("Do not know how to construct standard type id resolver for idType: "+_idType); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/impl/TypeDeserializerBase.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/impl/TypeDeserializerBase.java new file mode 100644 index 0000000..3d6aa5c --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/impl/TypeDeserializerBase.java
@@ -0,0 +1,154 @@ +package org.codehaus.jackson.map.jsontype.impl; + +import java.io.IOException; +import java.util.HashMap; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.annotate.JsonTypeInfo; +import org.codehaus.jackson.map.BeanProperty; +import org.codehaus.jackson.map.DeserializationContext; +import org.codehaus.jackson.map.JsonDeserializer; +import org.codehaus.jackson.map.TypeDeserializer; +import org.codehaus.jackson.map.jsontype.TypeIdResolver; +import org.codehaus.jackson.type.JavaType; + +/** + * @since 1.5 + * @author tatus + */ +public abstract class TypeDeserializerBase extends TypeDeserializer +{ + protected final TypeIdResolver _idResolver; + + protected final JavaType _baseType; + + protected final BeanProperty _property; + + /** + * Type to use as the default implementation, if type id is + * missing or can not be resolved. + * + * @since 1.9 + */ + protected final JavaType _defaultImpl; + + /** + * For efficient operation we will lazily build mappings from type ids + * to actual deserializers, once needed. + */ + protected final HashMap<String,JsonDeserializer<Object>> _deserializers; + + /** + * @since 1.9 + */ + protected JsonDeserializer<Object> _defaultImplDeserializer; + + /** + * @deprecated Since 1.9, use the constructor that takes 'defaultImpl' + */ + @Deprecated + protected TypeDeserializerBase(JavaType baseType, TypeIdResolver idRes, BeanProperty property) { + this(baseType, idRes, property, null); + } + + protected TypeDeserializerBase(JavaType baseType, TypeIdResolver idRes, BeanProperty property, + Class<?> defaultImpl) + { + _baseType = baseType; + _idResolver = idRes; + _property = property; + _deserializers = new HashMap<String,JsonDeserializer<Object>>(); + if (defaultImpl == null) { + _defaultImpl = null; + } else { + /* 16-Oct-2011, tatu: should call this via TypeFactory; this is + * not entirely safe... however, since Collections/Maps are + * seldom (if ever) base types, may be ok. + */ + _defaultImpl = baseType.forcedNarrowBy(defaultImpl); + } + } + + @Override + public abstract JsonTypeInfo.As getTypeInclusion(); + + public String baseTypeName() { return _baseType.getRawClass().getName(); } + + @Override + public String getPropertyName() { return null; } + + @Override + public TypeIdResolver getTypeIdResolver() { return _idResolver; } + + @Override + public Class<?> getDefaultImpl() { + return (_defaultImpl == null) ? null : _defaultImpl.getRawClass(); + } + + @Override + public String toString() + { + StringBuilder sb = new StringBuilder(); + sb.append('[').append(getClass().getName()); + sb.append("; base-type:").append(_baseType); + sb.append("; id-resolver: ").append(_idResolver); + sb.append(']'); + return sb.toString(); + } + + /* + /********************************************************** + /* Helper methods for sub-classes + /********************************************************** + */ + + protected final JsonDeserializer<Object> _findDeserializer(DeserializationContext ctxt, String typeId) + throws IOException, JsonProcessingException + { + JsonDeserializer<Object> deser; + + synchronized (_deserializers) { + deser = _deserializers.get(typeId); + if (deser == null) { + JavaType type = _idResolver.typeFromId(typeId); + if (type == null) { + // As per [JACKSON-614], use the default impl if no type id available: + if (_defaultImpl == null) { + throw ctxt.unknownTypeException(_baseType, typeId); + } + deser = _findDefaultImplDeserializer(ctxt); + } else { + /* 16-Dec-2010, tatu: Since nominal type we get here has no (generic) type parameters, + * we actually now need to explicitly narrow from base type (which may have parameterization) + * using raw type. + * + * One complication, though; can not change 'type class' (simple type to container); otherwise + * we may try to narrow a SimpleType (Object.class) into MapType (Map.class), losing actual + * type in process (getting SimpleType of Map.class which will not work as expected) + */ + if (_baseType != null && _baseType.getClass() == type.getClass()) { + type = _baseType.narrowBy(type.getRawClass()); + } + deser = ctxt.getDeserializerProvider().findValueDeserializer(ctxt.getConfig(), type, _property); + } + _deserializers.put(typeId, deser); + } + } + return deser; + } + + protected final JsonDeserializer<Object> _findDefaultImplDeserializer(DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + if (_defaultImpl == null) { + return null; + } + synchronized (_defaultImpl) { + if (_defaultImplDeserializer == null) { + _defaultImplDeserializer = ctxt.getDeserializerProvider().findValueDeserializer(ctxt.getConfig(), + _defaultImpl, _property); + } + return _defaultImplDeserializer; + } + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/impl/TypeIdResolverBase.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/impl/TypeIdResolverBase.java new file mode 100644 index 0000000..a0db873 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/impl/TypeIdResolverBase.java
@@ -0,0 +1,37 @@ +package org.codehaus.jackson.map.jsontype.impl; + +import org.codehaus.jackson.map.jsontype.TypeIdResolver; +import org.codehaus.jackson.map.type.TypeFactory; +import org.codehaus.jackson.type.JavaType; + +public abstract class TypeIdResolverBase + implements TypeIdResolver +{ + protected final TypeFactory _typeFactory; + + /** + * Common base type for all polymorphic instances handled. + */ + protected final JavaType _baseType; + + protected TypeIdResolverBase(JavaType baseType, TypeFactory typeFactory) + { + _baseType = baseType; + _typeFactory = typeFactory; + } + + @Override + public void init(JavaType bt) { + /* Standard type id resolvers do not need this; + * only useful for custom ones. + */ + } + + /** + * @since 1.9.4 + */ + public String idFromBaseType() + { + return idFromValueAndType(null, _baseType.getRawClass()); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/impl/TypeNameIdResolver.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/impl/TypeNameIdResolver.java new file mode 100644 index 0000000..7cd473e --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/impl/TypeNameIdResolver.java
@@ -0,0 +1,154 @@ +package org.codehaus.jackson.map.jsontype.impl; + +import java.util.*; + +import org.codehaus.jackson.annotate.JsonTypeInfo; +import org.codehaus.jackson.map.MapperConfig; +import org.codehaus.jackson.map.introspect.BasicBeanDescription; +import org.codehaus.jackson.map.jsontype.NamedType; +import org.codehaus.jackson.type.JavaType; + +public class TypeNameIdResolver + extends TypeIdResolverBase +{ + /** + * @since 1.8 + */ + protected final MapperConfig<?> _config; + + /** + * Mappings from class name to type id, used for serialization + */ + protected final HashMap<String, String> _typeToId; + + /** + * Mappings from type id to JavaType, used for deserialization + */ + protected final HashMap<String, JavaType> _idToType; + + protected TypeNameIdResolver(MapperConfig<?> config, JavaType baseType, + HashMap<String, String> typeToId, HashMap<String, JavaType> idToType) + { + super(baseType, config.getTypeFactory()); + _config = config; + _typeToId = typeToId; + _idToType = idToType; + } + + public static TypeNameIdResolver construct(MapperConfig<?> config, + JavaType baseType, + Collection<NamedType> subtypes, boolean forSer, boolean forDeser) + { + // sanity check + if (forSer == forDeser) throw new IllegalArgumentException(); + HashMap<String, String> typeToId = null; + HashMap<String, JavaType> idToType = null; + + if (forSer) { + typeToId = new HashMap<String, String>(); + } + if (forDeser) { + idToType = new HashMap<String, JavaType>(); + } + if (subtypes != null) { + for (NamedType t : subtypes) { + /* no name? Need to figure out default; for now, let's just + * use non-qualified class name + */ + Class<?> cls = t.getType(); + String id = t.hasName() ? t.getName() : _defaultTypeId(cls); + if (forSer) { + typeToId.put(cls.getName(), id); + } + if (forDeser) { + /* 24-Feb-2011, tatu: [JACKSON-498] One more problem; sometimes + * we have same name for multiple types; if so, use most specific + * one. + */ + JavaType prev = idToType.get(id); + if (prev != null) { // Can only override if more specific + if (cls.isAssignableFrom(prev.getRawClass())) { // nope, more generic (or same) + continue; + } + } + idToType.put(id, config.constructType(cls)); + } + } + } + return new TypeNameIdResolver(config, baseType, typeToId, idToType); + } + + @Override + public JsonTypeInfo.Id getMechanism() { return JsonTypeInfo.Id.NAME; } + + @Override + public String idFromValue(Object value) + { + Class<?> cls = value.getClass(); + final String key = cls.getName(); + String name; + synchronized (_typeToId) { + name = _typeToId.get(key); + if (name == null) { + // 24-Feb-2011, tatu: As per [JACKSON-498], may need to dynamically look up name + // can either throw an exception, or use default name... + if (_config.isAnnotationProcessingEnabled()) { + BasicBeanDescription beanDesc = _config.introspectClassAnnotations(cls); + name = _config.getAnnotationIntrospector().findTypeName(beanDesc.getClassInfo()); + } + if (name == null) { + // And if still not found, let's choose default? + name = _defaultTypeId(cls); + } + _typeToId.put(key, name); + } + } + return name; + } + + @Override + public String idFromValueAndType(Object value, Class<?> type) + { + return idFromValue(value); + } + + @Override + public JavaType typeFromId(String id) + throws IllegalArgumentException + { + JavaType t = _idToType.get(id); + /* Now: if no type is found, should we try to locate it by + * some other means? (specifically, if in same package as base type, + * could just try Class.forName) + * For now let's not add any such workarounds; can add if need be + */ + return t; + } + + @Override + public String toString() + { + StringBuilder sb = new StringBuilder(); + sb.append('[').append(getClass().getName()); + sb.append("; id-to-type=").append(_idToType); + sb.append(']'); + return sb.toString(); + } + + /* + /********************************************************* + /* Helper methods + /********************************************************* + */ + + /** + * If no name was explicitly given for a class, we will just + * use non-qualified class name + */ + protected static String _defaultTypeId(Class<?> cls) + { + String n = cls.getName(); + int ix = n.lastIndexOf('.'); + return (ix < 0) ? n : n.substring(ix+1); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/impl/TypeSerializerBase.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/impl/TypeSerializerBase.java new file mode 100644 index 0000000..df2e6e0 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/impl/TypeSerializerBase.java
@@ -0,0 +1,31 @@ +package org.codehaus.jackson.map.jsontype.impl; + +import org.codehaus.jackson.annotate.JsonTypeInfo; +import org.codehaus.jackson.map.BeanProperty; +import org.codehaus.jackson.map.TypeSerializer; +import org.codehaus.jackson.map.jsontype.TypeIdResolver; + +/** + * @since 1.5 + */ +public abstract class TypeSerializerBase extends TypeSerializer +{ + protected final TypeIdResolver _idResolver; + + protected final BeanProperty _property; + + protected TypeSerializerBase(TypeIdResolver idRes, BeanProperty property) + { + _idResolver = idRes; + _property = property; + } + + @Override + public abstract JsonTypeInfo.As getTypeInclusion(); + + @Override + public String getPropertyName() { return null; } + + @Override + public TypeIdResolver getTypeIdResolver() { return _idResolver; } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/impl/package-info.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/impl/package-info.java new file mode 100644 index 0000000..03d3ec2 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/impl/package-info.java
@@ -0,0 +1,9 @@ +/** + * Package that contains standard implementations for + * {@link org.codehaus.jackson.map.jsontype.TypeResolverBuilder} + * and + * {@link org.codehaus.jackson.map.jsontype.TypeIdResolver}. + * + * @since 1.5 + */ +package org.codehaus.jackson.map.jsontype.impl;
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/package-info.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/package-info.java new file mode 100644 index 0000000..c9de959 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/jsontype/package-info.java
@@ -0,0 +1,10 @@ +/** + * Package that contains interfaces that define how to implement + * functionality for dynamically resolving type during deserialization. + * This is needed for complete handling of polymorphic types, where + * actual type can not be determined statically (declared type is + * a supertype of actual polymorphic serialized types). + * + * @since 1.5 + */ +package org.codehaus.jackson.map.jsontype;
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/module/SimpleAbstractTypeResolver.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/module/SimpleAbstractTypeResolver.java new file mode 100644 index 0000000..e5aa521 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/module/SimpleAbstractTypeResolver.java
@@ -0,0 +1,86 @@ +package org.codehaus.jackson.map.module; + +import java.lang.reflect.Modifier; +import java.util.*; + +import org.codehaus.jackson.map.AbstractTypeResolver; +import org.codehaus.jackson.map.DeserializationConfig; +import org.codehaus.jackson.map.type.ClassKey; +import org.codehaus.jackson.type.JavaType; + +/** + * Simple {@link AbstractTypeResolver} implementation, which is + * based on static mapping from abstract super types into + * sub types (concrete or abstract), but retaining generic + * parameterization. + * Can be used for things like specifying which implementation of + * {@link java.util.Collection} to use: + *<pre> + * SimpleAbstractTypeResolver resolver = new SimpleAbstractTypeResolver(); + * // To make all properties declared as Collection, List, to LinkedList + * resolver.addMapping(Collection.class, LinkedList.class); + * resolver.addMapping(List.class, LinkedList.class); + *</pre> + * Can also be used as an alternative to per-class annotations when defining + * concrete implementations; however, only works with abstract types (since + * this is only called for abstract types) + * + * @since 1.8 + */ +public class SimpleAbstractTypeResolver extends AbstractTypeResolver +{ + /** + * Mappings from super types to subtypes + */ + protected final HashMap<ClassKey,Class<?>> _mappings = new HashMap<ClassKey,Class<?>>(); + + /** + * Method for adding a mapping from super type to specific subtype. + * Arguments will be checked by method, to ensure that <code>superType</code> + * is abstract (since resolver is never called for concrete classes); + * as well as to ensure that there is supertype/subtype relationship + * (to ensure there won't be cycles during resolution). + * + * @param superType Abstract type to resolve + * @param subType Sub-class of superType, to map superTo to + * + * @return This resolver, to allow chaining of initializations + */ + public <T> SimpleAbstractTypeResolver addMapping(Class<T> superType, Class<? extends T> subType) + { + // Sanity checks, just in case someone tries to force typing... + if (superType == subType) { + throw new IllegalArgumentException("Can not add mapping from class to itself"); + } + if (!superType.isAssignableFrom(subType)) { + throw new IllegalArgumentException("Can not add mapping from class "+superType.getName() + +" to "+subType.getName()+", as latter is not a subtype of former"); + } + if (!Modifier.isAbstract(superType.getModifiers())) { + throw new IllegalArgumentException("Can not add mapping from class "+superType.getName() + +" since it is not abstract"); + } + _mappings.put(new ClassKey(superType), subType); + return this; + } + + @Override + public JavaType findTypeMapping(DeserializationConfig config, JavaType type) + { + // this is the main mapping base, so let's + Class<?> src = type.getRawClass(); + Class<?> dst = _mappings.get(new ClassKey(src)); + if (dst == null) { + return null; + } + return type.narrowBy(dst); + } + + + @Override + public JavaType resolveAbstractType(DeserializationConfig config, JavaType type) + { + // never materialize anything, so: + return null; + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/module/SimpleDeserializers.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/module/SimpleDeserializers.java new file mode 100644 index 0000000..d90666a --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/module/SimpleDeserializers.java
@@ -0,0 +1,130 @@ +package org.codehaus.jackson.map.module; + +import java.util.*; + +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.type.*; +import org.codehaus.jackson.type.JavaType; + +/** + * Simple implementation {@link Deserializers} which allows registration of + * deserializers based on raw (type erased class). + * It can work well for basic bean and scalar type deserializers, but is not + * a good fit for handling generic types (like {@link Map}s and {@link Collection}s + * or array types). + *<p> + * Unlike {@link SimpleSerializers}, this class does not currently support generic mappings; + * all mappings must be to exact declared deserialization type. + * + * @since 1.7 + */ +public class SimpleDeserializers implements Deserializers +{ + protected HashMap<ClassKey,JsonDeserializer<?>> _classMappings = null; + + /* + /********************************************************** + /* Life-cycle, construction and configuring + /********************************************************** + */ + + public SimpleDeserializers() { } + + public <T> void addDeserializer(Class<T> forClass, JsonDeserializer<? extends T> deser) + { + ClassKey key = new ClassKey(forClass); + if (_classMappings == null) { + _classMappings = new HashMap<ClassKey,JsonDeserializer<?>>(); + } + _classMappings.put(key, deser); + } + + /* + /********************************************************** + /* Serializers implementation + /********************************************************** + */ + + @Override + public JsonDeserializer<?> findArrayDeserializer(ArrayType type, + DeserializationConfig config, DeserializerProvider provider, + BeanProperty property, + TypeDeserializer elementTypeDeserializer, + JsonDeserializer<?> elementDeserializer) + throws JsonMappingException + { + return (_classMappings == null) ? null : _classMappings.get(new ClassKey(type.getRawClass())); + } + + @Override + public JsonDeserializer<?> findBeanDeserializer(JavaType type, + DeserializationConfig config, DeserializerProvider provider, + BeanDescription beanDesc, BeanProperty property) + throws JsonMappingException + { + return (_classMappings == null) ? null : _classMappings.get(new ClassKey(type.getRawClass())); + } + + @Override + public JsonDeserializer<?> findCollectionDeserializer(CollectionType type, + DeserializationConfig config, DeserializerProvider provider, + BeanDescription beanDesc, BeanProperty property, + TypeDeserializer elementTypeDeserializer, + JsonDeserializer<?> elementDeserializer) + throws JsonMappingException + { + return (_classMappings == null) ? null : _classMappings.get(new ClassKey(type.getRawClass())); + } + + @Override + public JsonDeserializer<?> findCollectionLikeDeserializer(CollectionLikeType type, + DeserializationConfig config, DeserializerProvider provider, + BeanDescription beanDesc, BeanProperty property, + TypeDeserializer elementTypeDeserializer, + JsonDeserializer<?> elementDeserializer) + throws JsonMappingException + { + return (_classMappings == null) ? null : _classMappings.get(new ClassKey(type.getRawClass())); + } + + @Override + public JsonDeserializer<?> findEnumDeserializer(Class<?> type, + DeserializationConfig config, BeanDescription beanDesc, BeanProperty property) + throws JsonMappingException + { + return (_classMappings == null) ? null : _classMappings.get(new ClassKey(type)); + } + + @Override + public JsonDeserializer<?> findMapDeserializer(MapType type, + DeserializationConfig config, DeserializerProvider provider, + BeanDescription beanDesc, BeanProperty property, + KeyDeserializer keyDeserializer, + TypeDeserializer elementTypeDeserializer, + JsonDeserializer<?> elementDeserializer) + throws JsonMappingException + { + return (_classMappings == null) ? null : _classMappings.get(new ClassKey(type.getRawClass())); + } + + @Override + public JsonDeserializer<?> findMapLikeDeserializer(MapLikeType type, + DeserializationConfig config, DeserializerProvider provider, + BeanDescription beanDesc, BeanProperty property, + KeyDeserializer keyDeserializer, + TypeDeserializer elementTypeDeserializer, + JsonDeserializer<?> elementDeserializer) + throws JsonMappingException + { + return (_classMappings == null) ? null : _classMappings.get(new ClassKey(type.getRawClass())); + } + + @Override + public JsonDeserializer<?> findTreeNodeDeserializer(Class<? extends JsonNode> nodeType, + DeserializationConfig config, BeanProperty property) + throws JsonMappingException + { + return (_classMappings == null) ? null : _classMappings.get(new ClassKey(nodeType)); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/module/SimpleKeyDeserializers.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/module/SimpleKeyDeserializers.java new file mode 100644 index 0000000..23feeff --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/module/SimpleKeyDeserializers.java
@@ -0,0 +1,59 @@ +package org.codehaus.jackson.map.module; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.type.ClassKey; +import org.codehaus.jackson.type.JavaType; + +/** + * Simple implementation {@link KeyDeserializers} which allows registration of + * deserializers based on raw (type erased class). + * It can work well for basic bean and scalar type deserializers, but is not + * a good fit for handling generic types (like {@link Map}s and {@link Collection}s + * or array types). + *<p> + * Unlike {@link SimpleSerializers}, this class does not currently support generic mappings; + * all mappings must be to exact declared deserialization type. + * + * @since 1.7 + */ +public class SimpleKeyDeserializers implements KeyDeserializers +{ + protected HashMap<ClassKey,KeyDeserializer> _classMappings = null; + + /* + /********************************************************** + /* Life-cycle, construction and configuring + /********************************************************** + */ + + public SimpleKeyDeserializers() { } + + public SimpleKeyDeserializers addDeserializer(Class<?> forClass, KeyDeserializer deser) + { + if (_classMappings == null) { + _classMappings = new HashMap<ClassKey,KeyDeserializer>(); + } + _classMappings.put(new ClassKey(forClass), deser); + return this; + } + + /* + /********************************************************** + /* Serializers implementation + /********************************************************** + */ + + @Override + public KeyDeserializer findKeyDeserializer(JavaType type, DeserializationConfig config, + BeanDescription beanDesc, BeanProperty property) + { + if (_classMappings == null) { + return null; + } + return _classMappings.get(new ClassKey(type.getRawClass())); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/module/SimpleModule.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/module/SimpleModule.java new file mode 100644 index 0000000..c36d0a8 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/module/SimpleModule.java
@@ -0,0 +1,265 @@ +package org.codehaus.jackson.map.module; + +import java.util.HashMap; +import java.util.Map; + +import org.codehaus.jackson.Version; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.deser.ValueInstantiator; + +/** + * Simple {@link Module} implementation that allows registration + * of serializers and deserializers, and bean serializer + * and deserializer modifiers. + * + * @since 1.7 + */ +public class SimpleModule extends Module +{ + protected final String _name; + protected final Version _version; + + protected SimpleSerializers _serializers = null; + protected SimpleDeserializers _deserializers = null; + + protected SimpleSerializers _keySerializers = null; + protected SimpleKeyDeserializers _keyDeserializers = null; + + /** + * Lazily-constructed resolver used for storing mappings from + * abstract classes to more specific implementing classes + * (which may be abstract or concrete) + */ + protected SimpleAbstractTypeResolver _abstractTypes = null; + + /** + * Lazily-constructed resolver used for storing mappings from + * abstract classes to more specific implementing classes + * (which may be abstract or concrete) + */ + protected SimpleValueInstantiators _valueInstantiators = null; + + /** + * Lazily-constructed map that contains mix-in definitions, indexed + * by target class, value being mix-in to apply. + * + * @since 1.9 + */ + protected HashMap<Class<?>, Class<?>> _mixins = null; + + /* + /********************************************************** + /* Life-cycle: creation + /********************************************************** + */ + + public SimpleModule(String name, Version version) + { + _name = name; + _version = version; + } + + /* + /********************************************************** + /* Simple setters to allow overriding + /********************************************************** + */ + + /** + * Resets all currently configured serializers. + * + * @since 1.9 + */ + public void setSerializers(SimpleSerializers s) { + _serializers = s; + } + + /** + * Resets all currently configured deserializers. + * + * @since 1.9 + */ + public void setDeserializers(SimpleDeserializers d) { + _deserializers = d; + } + + /** + * Resets all currently configured key serializers. + * + * @since 1.9 + */ + public void setKeySerializers(SimpleSerializers ks) { + _keySerializers = ks; + } + + /** + * Resets all currently configured key deserializers. + * + * @since 1.9 + */ + public void setKeyDeserializers(SimpleKeyDeserializers kd) { + _keyDeserializers = kd; + } + + /** + * Resets currently configured abstract type mappings + * + * @since 1.9 + */ + public void setAbstractTypes(SimpleAbstractTypeResolver atr) { + _abstractTypes = atr; + } + + /** + * Resets all currently configured value instantiators + * + * @since 1.9 + */ + public void setValueInstantiators(SimpleValueInstantiators svi) { + _valueInstantiators = svi; + } + + /* + /********************************************************** + /* Configuration methods + /********************************************************** + */ + + public SimpleModule addSerializer(JsonSerializer<?> ser) + { + if (_serializers == null) { + _serializers = new SimpleSerializers(); + } + _serializers.addSerializer(ser); + return this; + } + + public <T> SimpleModule addSerializer(Class<? extends T> type, JsonSerializer<T> ser) + { + if (_serializers == null) { + _serializers = new SimpleSerializers(); + } + _serializers.addSerializer(type, ser); + return this; + } + + public <T> SimpleModule addKeySerializer(Class<? extends T> type, JsonSerializer<T> ser) + { + if (_keySerializers == null) { + _keySerializers = new SimpleSerializers(); + } + _keySerializers.addSerializer(type, ser); + return this; + } + + public <T> SimpleModule addDeserializer(Class<T> type, JsonDeserializer<? extends T> deser) + { + if (_deserializers == null) { + _deserializers = new SimpleDeserializers(); + } + _deserializers.addDeserializer(type, deser); + return this; + } + + public SimpleModule addKeyDeserializer(Class<?> type, KeyDeserializer deser) + { + if (_keyDeserializers == null) { + _keyDeserializers = new SimpleKeyDeserializers(); + } + _keyDeserializers.addDeserializer(type, deser); + return this; + } + + /** + * Lazily-constructed resolver used for storing mappings from + * abstract classes to more specific implementing classes + * (which may be abstract or concrete) + */ + public <T> SimpleModule addAbstractTypeMapping(Class<T> superType, + Class<? extends T> subType) + { + if (_abstractTypes == null) { + _abstractTypes = new SimpleAbstractTypeResolver(); + } + // note: addMapping() will verify arguments + _abstractTypes = _abstractTypes.addMapping(superType, subType); + return this; + } + + /** + * Method for registering {@link ValueInstantiator} to use when deserializing + * instances of type <code>beanType</code>. + *<p> + * Instantiator is + * registered when module is registered for <code>ObjectMapper</code>. + */ + public SimpleModule addValueInstantiator(Class<?> beanType, ValueInstantiator inst) + { + if (_valueInstantiators == null) { + _valueInstantiators = new SimpleValueInstantiators(); + } + _valueInstantiators = _valueInstantiators.addValueInstantiator(beanType, inst); + return this; + } + + /** + * Method for specifying that annotations define by <code>mixinClass</code> + * should be "mixed in" with annotations that <code>targetType</code> + * has (as if they were directly included on it!). + *<p> + * Mix-in annotations are + * registered when module is registered for <code>ObjectMapper</code>. + */ + public SimpleModule setMixInAnnotation(Class<?> targetType, Class<?> mixinClass) + { + if (_mixins == null) { + _mixins = new HashMap<Class<?>, Class<?>>(); + } + _mixins.put(targetType, mixinClass); + return this; + } + + /* + /********************************************************** + /* Module impl + /********************************************************** + */ + + @Override + public String getModuleName() { + return _name; + } + + @Override + public void setupModule(SetupContext context) + { + if (_serializers != null) { + context.addSerializers(_serializers); + } + if (_deserializers != null) { + context.addDeserializers(_deserializers); + } + if (_keySerializers != null) { + context.addKeySerializers(_keySerializers); + } + if (_keyDeserializers != null) { + context.addKeyDeserializers(_keyDeserializers); + } + if (_abstractTypes != null) { + context.addAbstractTypeResolver(_abstractTypes); + } + if (_valueInstantiators != null) { + context.addValueInstantiators(_valueInstantiators); + } + if (_mixins != null) { + for (Map.Entry<Class<?>,Class<?>> entry : _mixins.entrySet()) { + context.setMixInAnnotations(entry.getKey(), entry.getValue()); + } + } + } + + @Override + public Version version() { + return _version; + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/module/SimpleSerializers.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/module/SimpleSerializers.java new file mode 100644 index 0000000..42e4471 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/module/SimpleSerializers.java
@@ -0,0 +1,206 @@ +package org.codehaus.jackson.map.module; + +import java.util.*; + +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.type.ArrayType; +import org.codehaus.jackson.map.type.ClassKey; +import org.codehaus.jackson.map.type.CollectionLikeType; +import org.codehaus.jackson.map.type.CollectionType; +import org.codehaus.jackson.map.type.MapLikeType; +import org.codehaus.jackson.map.type.MapType; +import org.codehaus.jackson.type.JavaType; + +/** + * Simple implementation {@link Serializers} which allows registration of + * serializers based on raw (type erased class). + * It can work well for basic bean and scalar type serializers, but is not + * a good fit for handling generic types (like {@link Map}s and {@link Collection}s). + *<p> + * Type registrations are assumed to be general; meaning that registration of serializer + * for a super type will also be used for handling subtypes, unless an exact match + * is found first. As an example, handler for {@link CharSequence} would also be used + * serializing {@link StringBuilder} instances, unless a direct mapping was found. + * + * @since 1.7 + */ +public class SimpleSerializers extends Serializers.Base +{ + /** + * Class-based mappings that are used both for exact and + * sub-class matches. + */ + protected HashMap<ClassKey,JsonSerializer<?>> _classMappings = null; + + /** + * Interface-based matches. + */ + protected HashMap<ClassKey,JsonSerializer<?>> _interfaceMappings = null; + + /* + /********************************************************** + /* Life-cycle, construction and configuring + /********************************************************** + */ + + public SimpleSerializers() { } + + /** + * Method for adding given serializer for type that {@link JsonSerializer#handledType} + * specifies (which MUST return a non-null class; and can NOT be {@link Object}, as a + * sanity check). + * For serializers that do not declare handled type, use the variant that takes + * two arguments. + * + * @param ser + */ + public void addSerializer(JsonSerializer<?> ser) + { + // Interface to match? + Class<?> cls = ser.handledType(); + if (cls == null || cls == Object.class) { + throw new IllegalArgumentException("JsonSerializer of type "+ser.getClass().getName() + +" does not define valid handledType() -- must either register with method that takes type argument " + +" or make serializer extend 'org.codehaus.jackson.map.ser.std.SerializerBase'"); + } + _addSerializer(cls, ser); + } + + public <T> void addSerializer(Class<? extends T> type, JsonSerializer<T> ser) + { + _addSerializer(type, ser); + } + + private void _addSerializer(Class<?> cls, JsonSerializer<?> ser) + { + ClassKey key = new ClassKey(cls); + // Interface or class type? + if (cls.isInterface()) { + if (_interfaceMappings == null) { + _interfaceMappings = new HashMap<ClassKey,JsonSerializer<?>>(); + } + _interfaceMappings.put(key, ser); + } else { // nope, class: + if (_classMappings == null) { + _classMappings = new HashMap<ClassKey,JsonSerializer<?>>(); + } + _classMappings.put(key, ser); + } + } + + /* + /********************************************************** + /* Serializers implementation + /********************************************************** + */ + + @Override + public JsonSerializer<?> findSerializer(SerializationConfig config, JavaType type, + BeanDescription beanDesc, BeanProperty property) + { + Class<?> cls = type.getRawClass(); + ClassKey key = new ClassKey(cls); + JsonSerializer<?> ser = null; + + // First: direct match? + if (cls.isInterface()) { + if (_interfaceMappings != null) { + ser = _interfaceMappings.get(key); + if (ser != null) { + return ser; + } + } + } else { + if (_classMappings != null) { + ser = _classMappings.get(key); + if (ser != null) { + return ser; + } + // If not direct match, maybe super-class match? + for (Class<?> curr = cls; (curr != null); curr = curr.getSuperclass()) { + key.reset(curr); + ser = _classMappings.get(key); + if (ser != null) { + return ser; + } + } + } + } + // No direct match? How about super-interfaces? + if (_interfaceMappings != null) { + ser = _findInterfaceMapping(cls, key); + if (ser != null) { + return ser; + } + // still no matches? Maybe interfaces of super classes + if (!cls.isInterface()) { + while ((cls = cls.getSuperclass()) != null) { + ser = _findInterfaceMapping(cls, key); + if (ser != null) { + return ser; + } + } + } + } + return null; + } + + @Override + public JsonSerializer<?> findArraySerializer(SerializationConfig config, + ArrayType type, BeanDescription beanDesc, BeanProperty property, + TypeSerializer elementTypeSerializer, JsonSerializer<Object> elementValueSerializer) { + return findSerializer(config, type, beanDesc, property); + } + + @Override + public JsonSerializer<?> findCollectionSerializer(SerializationConfig config, + CollectionType type, BeanDescription beanDesc, BeanProperty property, + TypeSerializer elementTypeSerializer, JsonSerializer<Object> elementValueSerializer) { + return findSerializer(config, type, beanDesc, property); + } + + @Override + public JsonSerializer<?> findCollectionLikeSerializer(SerializationConfig config, + CollectionLikeType type, BeanDescription beanDesc, BeanProperty property, + TypeSerializer elementTypeSerializer, JsonSerializer<Object> elementValueSerializer) { + return findSerializer(config, type, beanDesc, property); + } + + @Override + public JsonSerializer<?> findMapSerializer(SerializationConfig config, + MapType type, BeanDescription beanDesc, BeanProperty property, + JsonSerializer<Object> keySerializer, + TypeSerializer elementTypeSerializer, JsonSerializer<Object> elementValueSerializer) { + return findSerializer(config, type, beanDesc, property); + } + + @Override + public JsonSerializer<?> findMapLikeSerializer(SerializationConfig config, + MapLikeType type, BeanDescription beanDesc, BeanProperty property, + JsonSerializer<Object> keySerializer, + TypeSerializer elementTypeSerializer, JsonSerializer<Object> elementValueSerializer) { + return findSerializer(config, type, beanDesc, property); + } + + /* + /********************************************************** + /* Internal methods + /********************************************************** + */ + + protected JsonSerializer<?> _findInterfaceMapping(Class<?> cls, ClassKey key) + { + for (Class<?> iface : cls.getInterfaces()) { + key.reset(iface); + JsonSerializer<?> ser = _interfaceMappings.get(key); + if (ser != null) { + return ser; + } + ser = _findInterfaceMapping(iface, key); + if (ser != null) { + return ser; + } + } + return null; + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/module/SimpleValueInstantiators.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/module/SimpleValueInstantiators.java new file mode 100644 index 0000000..85c8c03 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/module/SimpleValueInstantiators.java
@@ -0,0 +1,45 @@ +package org.codehaus.jackson.map.module; + +import java.util.HashMap; + +import org.codehaus.jackson.map.BeanDescription; +import org.codehaus.jackson.map.DeserializationConfig; +import org.codehaus.jackson.map.deser.ValueInstantiator; +import org.codehaus.jackson.map.deser.ValueInstantiators; +import org.codehaus.jackson.map.type.ClassKey; + +public class SimpleValueInstantiators + extends ValueInstantiators.Base +{ + /** + * Mappings from raw (type-erased, i.e. non-generic) types + * to matching {@link ValueInstantiator} instances. + */ + protected HashMap<ClassKey,ValueInstantiator> _classMappings; + + /* + /********************************************************** + /* Life-cycle, construction and configuring + /********************************************************** + */ + + public SimpleValueInstantiators() + { + _classMappings = new HashMap<ClassKey,ValueInstantiator>(); + } + + public SimpleValueInstantiators addValueInstantiator(Class<?> forType, + ValueInstantiator inst) + { + _classMappings.put(new ClassKey(forType), inst); + return this; + } + + @Override + public ValueInstantiator findValueInstantiator(DeserializationConfig config, + BeanDescription beanDesc, ValueInstantiator defaultInstantiator) + { + ValueInstantiator inst = _classMappings.get(new ClassKey(beanDesc.getBeanClass())); + return (inst == null) ? defaultInstantiator : inst; + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/module/package-info.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/module/package-info.java new file mode 100644 index 0000000..7347186 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/module/package-info.java
@@ -0,0 +1,16 @@ +/** + * Package that contains classes and interfaces to help implement + * custom extension {@link org.codehaus.jackson.map.Module}s + * (which are registered using + * {@link org.codehaus.jackson.map.ObjectMapper#registerModule}. + *<p> + * Note that classes in the package only support registering + * handlers for non-generic types (types without type + * parameterization) -- hence "simple" -- which works for + * many cases, but not all. So if you will need to register + * handlers for generic types, you will usually need to either + * sub-class handlers, or implement/extend base types directly. + * + * @since 1.7 + */ +package org.codehaus.jackson.map.module;
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/package-info.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/package-info.java new file mode 100644 index 0000000..b8ed530 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/package-info.java
@@ -0,0 +1,34 @@ +/** +Contains basic mapper (conversion) functionality that +allows for converting between regular streaming json content and +Java objects (beans or Tree Model: support for both is via +{@link org.codehaus.jackson.map.ObjectMapper} class, as well +as convenience methods included in +{@link org.codehaus.jackson.JsonParser} +<p> +Object mapper will convert Json content to ant from +basic Java wrapper types (Integer, Boolean, Double), +Collection types (List, Map), Java Beans, +Strings and nulls. +<p> +Tree mapper builds dynamically typed tree of <code>JsonNode</code>s +from Json content (and writes such trees as Json), +similar to how DOM model works with xml. +Main benefits over Object mapping are: +<ul> + <li>No null checks are needed (dummy +nodes are created as necessary to represent "missing" Object fields +and Array elements) + </li> + <li>No type casts are usually needed: all public access methods are defined +in basic JsonNode class, and when "incompatible" method (such as Array +element access on, say, Boolean node) is used, returned node is +virtual "missing" node. + </li> +</ul> +Because of its dynamic nature, Tree mapping is often convenient +for basic path access and tree navigation, where structure of +the resulting tree is known in advance. +*/ + +package org.codehaus.jackson.map;
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/AnyGetterWriter.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/AnyGetterWriter.java new file mode 100644 index 0000000..ee831fd --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/AnyGetterWriter.java
@@ -0,0 +1,48 @@ +package org.codehaus.jackson.map.ser; + +import java.lang.reflect.Method; +import java.util.Map; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.introspect.AnnotatedMethod; +import org.codehaus.jackson.map.ser.std.MapSerializer; +import org.codehaus.jackson.map.*; + +/** + * Class similar to {@link BeanPropertyWriter}, but that will be used + * for serializing {@link org.codehaus.jackson.annotate.JsonAnyGetter} annotated + * (Map) properties + * + * @since 1.6 + */ +public class AnyGetterWriter +{ + protected final Method _anyGetter; + + protected final MapSerializer _serializer; + + public AnyGetterWriter(AnnotatedMethod anyGetter, MapSerializer serializer) + { + _anyGetter = anyGetter.getAnnotated(); + _serializer = serializer; + } + + public void getAndSerialize(Object bean, JsonGenerator jgen, SerializerProvider provider) + throws Exception + { + Object value = _anyGetter.invoke(bean); + if (value == null) { + return; + } + if (!(value instanceof Map<?,?>)) { + throw new JsonMappingException("Value returned by 'any-getter' ("+_anyGetter.getName()+"()) not java.util.Map but " + +value.getClass().getName()); + } + _serializer.serializeFields((Map<?,?>) value, jgen, provider); + } + + public void resolve(SerializerProvider provider) throws JsonMappingException + { + _serializer.resolve(provider); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/ArraySerializers.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/ArraySerializers.java new file mode 100644 index 0000000..26addc3 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/ArraySerializers.java
@@ -0,0 +1,7 @@ +package org.codehaus.jackson.map.ser; + +/** + * @deprecated Since 1.9 use {@link org.codehaus.jackson.map.ser.std.StdArraySerializers} + */ +@Deprecated +public class ArraySerializers extends org.codehaus.jackson.map.ser.std.StdArraySerializers { }
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/BasicSerializerFactory.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/BasicSerializerFactory.java new file mode 100644 index 0000000..76de697 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/BasicSerializerFactory.java
@@ -0,0 +1,806 @@ +package org.codehaus.jackson.map.ser; + +import java.lang.reflect.Method; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.net.InetAddress; +import java.util.*; + +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.JsonSerialize; +import org.codehaus.jackson.map.ext.OptionalHandlerFactory; +import org.codehaus.jackson.map.introspect.*; +import org.codehaus.jackson.map.jsontype.NamedType; +import org.codehaus.jackson.map.jsontype.TypeResolverBuilder; +import org.codehaus.jackson.map.ser.std.StdArraySerializers; +import org.codehaus.jackson.map.ser.std.CalendarSerializer; +import org.codehaus.jackson.map.ser.std.StdJdkSerializers; +import org.codehaus.jackson.map.ser.std.StdContainerSerializers; +import org.codehaus.jackson.map.ser.std.DateSerializer; +import org.codehaus.jackson.map.ser.std.EnumMapSerializer; +import org.codehaus.jackson.map.ser.std.EnumSerializer; +import org.codehaus.jackson.map.ser.std.IndexedStringListSerializer; +import org.codehaus.jackson.map.ser.std.InetAddressSerializer; +import org.codehaus.jackson.map.ser.std.JsonValueSerializer; +import org.codehaus.jackson.map.ser.std.MapSerializer; +import org.codehaus.jackson.map.ser.std.NullSerializer; +import org.codehaus.jackson.map.ser.std.ObjectArraySerializer; +import org.codehaus.jackson.map.ser.std.SerializableSerializer; +import org.codehaus.jackson.map.ser.std.SerializableWithTypeSerializer; +import org.codehaus.jackson.map.ser.std.StringCollectionSerializer; +import org.codehaus.jackson.map.ser.std.StringSerializer; +import org.codehaus.jackson.map.ser.std.TimeZoneSerializer; +import org.codehaus.jackson.map.ser.std.ToStringSerializer; +import org.codehaus.jackson.map.ser.std.TokenBufferSerializer; +import org.codehaus.jackson.map.type.*; +import org.codehaus.jackson.map.util.ClassUtil; +import org.codehaus.jackson.map.util.EnumValues; +import org.codehaus.jackson.type.JavaType; +import org.codehaus.jackson.util.TokenBuffer; + +/** + * Factory class that can provide serializers for standard JDK classes, + * as well as custom classes that extend standard classes or implement + * one of "well-known" interfaces (such as {@link java.util.Collection}). + *<p> + * Since all the serializers are eagerly instantiated, and there is + * no additional introspection or customizability of these types, + * this factory is essentially stateless. + */ +public abstract class BasicSerializerFactory + extends SerializerFactory +{ + + /* + /********************************************************** + /* Configuration, lookup tables/maps + /********************************************************** + */ + + /** + * Since these are all JDK classes, we shouldn't have to worry + * about ClassLoader used to load them. Rather, we can just + * use the class name, and keep things simple and efficient. + */ + protected final static HashMap<String, JsonSerializer<?>> _concrete = + new HashMap<String, JsonSerializer<?>>(); + + /** + * Actually it may not make much sense to eagerly instantiate all + * kinds of serializers: so this Map actually contains class references, + * not instances + * + * @since 1.6 + */ + protected final static HashMap<String, Class<? extends JsonSerializer<?>>> _concreteLazy = + new HashMap<String, Class<? extends JsonSerializer<?>>>(); + + static { + /* String and string-like types (note: date types explicitly + * not included -- can use either textual or numeric serialization) + */ + _concrete.put(String.class.getName(), new StringSerializer()); + final ToStringSerializer sls = ToStringSerializer.instance; + _concrete.put(StringBuffer.class.getName(), sls); + _concrete.put(StringBuilder.class.getName(), sls); + _concrete.put(Character.class.getName(), sls); + _concrete.put(Character.TYPE.getName(), sls); + + // Primitives/wrappers for primitives (primitives needed for Beans) + _concrete.put(Boolean.TYPE.getName(), new StdSerializers.BooleanSerializer(true)); + _concrete.put(Boolean.class.getName(), new StdSerializers.BooleanSerializer(false)); + final JsonSerializer<?> intS = new StdSerializers.IntegerSerializer(); + _concrete.put(Integer.class.getName(), intS); + _concrete.put(Integer.TYPE.getName(), intS); + _concrete.put(Long.class.getName(), StdSerializers.LongSerializer.instance); + _concrete.put(Long.TYPE.getName(), StdSerializers.LongSerializer.instance); + _concrete.put(Byte.class.getName(), StdSerializers.IntLikeSerializer.instance); + _concrete.put(Byte.TYPE.getName(), StdSerializers.IntLikeSerializer.instance); + _concrete.put(Short.class.getName(), StdSerializers.IntLikeSerializer.instance); + _concrete.put(Short.TYPE.getName(), StdSerializers.IntLikeSerializer.instance); + + // Numbers, limited length floating point + _concrete.put(Float.class.getName(), StdSerializers.FloatSerializer.instance); + _concrete.put(Float.TYPE.getName(), StdSerializers.FloatSerializer.instance); + _concrete.put(Double.class.getName(), StdSerializers.DoubleSerializer.instance); + _concrete.put(Double.TYPE.getName(), StdSerializers.DoubleSerializer.instance); + + // Other numbers, more complicated + final JsonSerializer<?> ns = new StdSerializers.NumberSerializer(); + _concrete.put(BigInteger.class.getName(), ns); + _concrete.put(BigDecimal.class.getName(), ns); + + // Other discrete non-container types: + // First, Date/Time zoo: + _concrete.put(Calendar.class.getName(), CalendarSerializer.instance); + DateSerializer dateSer = DateSerializer.instance; + _concrete.put(java.util.Date.class.getName(), dateSer); + // note: timestamps are very similar to java.util.Date, thus serialized as such + _concrete.put(java.sql.Timestamp.class.getName(), dateSer); + _concrete.put(java.sql.Date.class.getName(), new StdSerializers.SqlDateSerializer()); + _concrete.put(java.sql.Time.class.getName(), new StdSerializers.SqlTimeSerializer()); + + // And then other standard non-structured JDK types + for (Map.Entry<Class<?>,Object> en : new StdJdkSerializers().provide()) { + Object value = en.getValue(); + if (value instanceof JsonSerializer<?>) { + _concrete.put(en.getKey().getName(), (JsonSerializer<?>) value); + } else if (value instanceof Class<?>) { + @SuppressWarnings("unchecked") + Class<? extends JsonSerializer<?>> cls = (Class<? extends JsonSerializer<?>>) value; + _concreteLazy.put(en.getKey().getName(), cls); + } else { // should never happen, but: + throw new IllegalStateException("Internal error: unrecognized value of type "+en.getClass().getName()); + } + } + + // Jackson-specific type(s) + // (Q: can this ever be sub-classed?) + _concreteLazy.put(TokenBuffer.class.getName(), TokenBufferSerializer.class); + } + + protected final static HashMap<String, JsonSerializer<?>> _arraySerializers = + new HashMap<String, JsonSerializer<?>>(); + static { + // Arrays of various types (including common object types) + _arraySerializers.put(boolean[].class.getName(), new StdArraySerializers.BooleanArraySerializer()); + _arraySerializers.put(byte[].class.getName(), new StdArraySerializers.ByteArraySerializer()); + _arraySerializers.put(char[].class.getName(), new StdArraySerializers.CharArraySerializer()); + _arraySerializers.put(short[].class.getName(), new StdArraySerializers.ShortArraySerializer()); + _arraySerializers.put(int[].class.getName(), new StdArraySerializers.IntArraySerializer()); + _arraySerializers.put(long[].class.getName(), new StdArraySerializers.LongArraySerializer()); + _arraySerializers.put(float[].class.getName(), new StdArraySerializers.FloatArraySerializer()); + _arraySerializers.put(double[].class.getName(), new StdArraySerializers.DoubleArraySerializer()); + } + + /** + * Helper object used to deal with serializers for optional JDK types (like ones + * omitted from GAE, Android) + */ + protected OptionalHandlerFactory optionalHandlers = OptionalHandlerFactory.instance; + + /* + /********************************************************** + /* Life cycle + /********************************************************** + */ + + /** + * We will provide default constructor to allow sub-classing, + * but make it protected so that no non-singleton instances of + * the class will be instantiated. + */ + protected BasicSerializerFactory() { } + + /* + /********************************************************** + /* SerializerFactory impl + /********************************************************** + */ + + // Implemented by sub-classes + @Override + public abstract JsonSerializer<Object> createSerializer(SerializationConfig config, JavaType type, + BeanProperty property) + throws JsonMappingException; + + /** + * Method called to construct a type serializer for values with given declared + * base type. This is called for values other than those of bean property + * types. + */ + @Override + public TypeSerializer createTypeSerializer(SerializationConfig config, JavaType baseType, + BeanProperty property) + { + BasicBeanDescription bean = config.introspectClassAnnotations(baseType.getRawClass()); + AnnotatedClass ac = bean.getClassInfo(); + AnnotationIntrospector ai = config.getAnnotationIntrospector(); + TypeResolverBuilder<?> b = ai.findTypeResolver(config, ac, baseType); + /* Ok: if there is no explicit type info handler, we may want to + * use a default. If so, config object knows what to use. + */ + Collection<NamedType> subtypes = null; + if (b == null) { + b = config.getDefaultTyper(baseType); + } else { + subtypes = config.getSubtypeResolver().collectAndResolveSubtypes(ac, config, ai); + } + return (b == null) ? null : b.buildTypeSerializer(config, baseType, subtypes, property); + } + + + /* + /********************************************************** + /* Additional API for other core classes + /********************************************************** + */ + + public final JsonSerializer<?> getNullSerializer() { + return NullSerializer.instance; + } + + protected abstract Iterable<Serializers> customSerializers(); + + /* + /********************************************************** + /* Overridable secondary serializer accessor methods + /********************************************************** + */ + + /** + * Method that will use fast lookup (and identity comparison) methods to + * see if we know serializer to use for given type. + */ + public final JsonSerializer<?> findSerializerByLookup(JavaType type, SerializationConfig config, + BasicBeanDescription beanDesc, BeanProperty property, + boolean staticTyping) + { + Class<?> raw = type.getRawClass(); + String clsName = raw.getName(); + JsonSerializer<?> ser = _concrete.get(clsName); + if (ser != null) { + return ser; + } + Class<? extends JsonSerializer<?>> serClass = _concreteLazy.get(clsName); + if (serClass != null) { + try { + return serClass.newInstance(); + } catch (Exception e) { + throw new IllegalStateException("Failed to instantiate standard serializer (of type "+serClass.getName()+"): " + +e.getMessage(), e); + } + } + return null; + } + + /** + * Method for checking if we can determine serializer to use based on set of + * known primary types, checking for set of known base types (exact matches + * having been compared against with <code>findSerializerByLookup</code>). + * This does not include "secondary" interfaces, but + * mostly concrete or abstract base classes. + */ + @SuppressWarnings("deprecation") + public final JsonSerializer<?> findSerializerByPrimaryType(JavaType type, SerializationConfig config, + BasicBeanDescription beanDesc, BeanProperty property, + boolean staticTyping) + throws JsonMappingException + { + Class<?> raw = type.getRawClass(); + // First: JsonSerializable and related + if (JsonSerializable.class.isAssignableFrom(raw)) { + if (JsonSerializableWithType.class.isAssignableFrom(raw)) { + return SerializableWithTypeSerializer.instance; + } + return SerializableSerializer.instance; + } + // Second: as per [JACKSON-193] consider @JsonValue for any types: + AnnotatedMethod valueMethod = beanDesc.findJsonValueMethod(); + if (valueMethod != null) { + // [JACKSON-586]: need to ensure accessibility of method + Method m = valueMethod.getAnnotated(); + if (config.isEnabled(SerializationConfig.Feature.CAN_OVERRIDE_ACCESS_MODIFIERS)) { + ClassUtil.checkAndFixAccess(m); + } + JsonSerializer<Object> ser = findSerializerFromAnnotation(config, valueMethod, property); + return new JsonValueSerializer(m, ser, property); + } + + // One unfortunate special case, as per [JACKSON-484] + if (InetAddress.class.isAssignableFrom(raw)) { + return InetAddressSerializer.instance; + } + // ... and another one, [JACKSON-522], for TimeZone + if (TimeZone.class.isAssignableFrom(raw)) { + return TimeZoneSerializer.instance; + } + // and yet one more [JACKSON-789] + if (java.nio.charset.Charset.class.isAssignableFrom(raw)) { + return ToStringSerializer.instance; + } + + // Then check for optional/external serializers [JACKSON-386] + JsonSerializer<?> ser = optionalHandlers.findSerializer(config, type); + if (ser != null) { + return ser; + } + + if (Number.class.isAssignableFrom(raw)) { + return StdSerializers.NumberSerializer.instance; + } + if (Enum.class.isAssignableFrom(raw)) { + @SuppressWarnings("unchecked") + Class<Enum<?>> enumClass = (Class<Enum<?>>) raw; + return EnumSerializer.construct(enumClass, config, beanDesc); + } + if (Calendar.class.isAssignableFrom(raw)) { + return CalendarSerializer.instance; + } + if (java.util.Date.class.isAssignableFrom(raw)) { + return DateSerializer.instance; + } + return null; + } + + /** + * Reflection-based serialized find method, which checks if + * given class implements one of recognized "add-on" interfaces. + * Add-on here means a role that is usually or can be a secondary + * trait: for example, + * bean classes may implement {@link Iterable}, but their main + * function is usually something else. The reason for + */ + public final JsonSerializer<?> findSerializerByAddonType(SerializationConfig config, JavaType javaType, + BasicBeanDescription beanDesc, BeanProperty property, + boolean staticTyping) + throws JsonMappingException + { + Class<?> type = javaType.getRawClass(); + + // These need to be in decreasing order of specificity... + if (Iterator.class.isAssignableFrom(type)) { + return buildIteratorSerializer(config, javaType, beanDesc, property, staticTyping); + } + if (Iterable.class.isAssignableFrom(type)) { + return buildIterableSerializer(config, javaType, beanDesc, property, staticTyping); + } + if (CharSequence.class.isAssignableFrom(type)) { + return ToStringSerializer.instance; + } + return null; + } + + /** + * Helper method called to check if a class or method + * has an annotation + * (@link org.codehaus.jackson.map.ser.JsonSerialize#using) + * that tells the class to use for serialization. + * Returns null if no such annotation found. + */ + @SuppressWarnings("unchecked") + protected JsonSerializer<Object> findSerializerFromAnnotation(SerializationConfig config, Annotated a, + BeanProperty property) + throws JsonMappingException + { + Object serDef = config.getAnnotationIntrospector().findSerializer(a); + if (serDef == null) { + return null; + } + if (serDef instanceof JsonSerializer) { + JsonSerializer<Object> ser = (JsonSerializer<Object>) serDef; + if (ser instanceof ContextualSerializer<?>) { + return ((ContextualSerializer<Object>) ser).createContextual(config, property); + } + return ser; + } + /* Alas, there's no way to force return type of "either class + * X or Y" -- need to throw an exception after the fact + */ + if (!(serDef instanceof Class)) { + throw new IllegalStateException("AnnotationIntrospector returned value of type "+serDef.getClass().getName()+"; expected type JsonSerializer or Class<JsonSerializer> instead"); + } + Class<?> cls = (Class<?>) serDef; + if (!JsonSerializer.class.isAssignableFrom(cls)) { + throw new IllegalStateException("AnnotationIntrospector returned Class "+cls.getName()+"; expected Class<JsonSerializer>"); + } + JsonSerializer<Object> ser = config.serializerInstance(a, (Class<? extends JsonSerializer<?>>) cls); + if (ser instanceof ContextualSerializer<?>) { + return ((ContextualSerializer<Object>) ser).createContextual(config, property); + } + return ser; + } + + /* + /********************************************************** + /* Factory methods, container types: + /********************************************************** + */ + + public JsonSerializer<?> buildContainerSerializer(SerializationConfig config, JavaType type, + BasicBeanDescription beanDesc, BeanProperty property, boolean staticTyping) + { + // Let's see what we can learn about element/content/value type, type serializer for it: + JavaType elementType = type.getContentType(); + TypeSerializer elementTypeSerializer = createTypeSerializer(config, elementType, property); + + // if elements have type serializer, can not force static typing: + if (elementTypeSerializer != null) { + staticTyping = false; + } else if (!staticTyping) { + staticTyping = usesStaticTyping(config, beanDesc, elementTypeSerializer, property); + } + JsonSerializer<Object> elementValueSerializer = findContentSerializer(config, + beanDesc.getClassInfo(), property); + + if (type.isMapLikeType()) { // implements java.util.Map + MapLikeType mlt = (MapLikeType) type; + JsonSerializer<Object> keySerializer = findKeySerializer(config, beanDesc.getClassInfo(), property); + if (mlt.isTrueMapType()) { + return buildMapSerializer(config, (MapType) mlt, beanDesc, property, staticTyping, + keySerializer, elementTypeSerializer, elementValueSerializer); + } + return buildMapLikeSerializer(config, mlt, beanDesc, property, staticTyping, + keySerializer, elementTypeSerializer, elementValueSerializer); + } + if (type.isCollectionLikeType()) { + CollectionLikeType clt = (CollectionLikeType) type; + if (clt.isTrueCollectionType()) { + return buildCollectionSerializer(config, (CollectionType) clt, beanDesc, property, staticTyping, + elementTypeSerializer, elementValueSerializer); + } + return buildCollectionLikeSerializer(config, clt, beanDesc, property, staticTyping, + elementTypeSerializer, elementValueSerializer); + } + if (type.isArrayType()) { + return buildArraySerializer(config, (ArrayType) type, beanDesc, property, staticTyping, + elementTypeSerializer, elementValueSerializer); + } + return null; + } + + /** + * Helper method that handles configuration details when constructing serializers for + * Collection and Collection-like types. + * + * @since 1.8 + */ + protected JsonSerializer<?> buildCollectionLikeSerializer(SerializationConfig config, + CollectionLikeType type, + BasicBeanDescription beanDesc, BeanProperty property, + boolean staticTyping, + TypeSerializer elementTypeSerializer, JsonSerializer<Object> elementValueSerializer) + { + for (Serializers serializers : customSerializers()) { + JsonSerializer<?> ser = serializers.findCollectionLikeSerializer(config, type, beanDesc, property, + elementTypeSerializer, elementValueSerializer); + if (ser != null) { + return ser; + } + } + return null; + } + + /** + * Helper method that handles configuration details when constructing serializers for + * {@link java.util.List} types that support efficient by-index access + *<p> + * Note: signature changed in 1.8, to take 'staticTyping' argument + */ + protected JsonSerializer<?> buildCollectionSerializer(SerializationConfig config, + CollectionType type, + BasicBeanDescription beanDesc, BeanProperty property, + boolean staticTyping, + TypeSerializer elementTypeSerializer, JsonSerializer<Object> elementValueSerializer) + { + // Module-provided custom collection serializers? + for (Serializers serializers : customSerializers()) { + JsonSerializer<?> ser = serializers.findCollectionSerializer(config, type, beanDesc, property, + elementTypeSerializer, elementValueSerializer); + if (ser != null) { + return ser; + } + } + Class<?> raw = type.getRawClass(); + if (EnumSet.class.isAssignableFrom(raw)) { + return buildEnumSetSerializer(config, type, beanDesc, property, staticTyping, + elementTypeSerializer, elementValueSerializer); + } + Class<?> elementRaw = type.getContentType().getRawClass(); + if (isIndexedList(raw)) { + if (elementRaw == String.class) { + return new IndexedStringListSerializer(property, elementValueSerializer); + } + return StdContainerSerializers.indexedListSerializer(type.getContentType(), staticTyping, + elementTypeSerializer, property, elementValueSerializer); + } + if (elementRaw == String.class) { + return new StringCollectionSerializer(property, elementValueSerializer); + } + return StdContainerSerializers.collectionSerializer(type.getContentType(), staticTyping, + elementTypeSerializer, property, elementValueSerializer); + } + + protected JsonSerializer<?> buildEnumSetSerializer(SerializationConfig config, JavaType type, + BasicBeanDescription beanDesc, BeanProperty property, + boolean staticTyping, + TypeSerializer elementTypeSerializer, JsonSerializer<Object> elementValueSerializer) + { + // this may or may not be available (Class doesn't; type of field/method does) + JavaType enumType = type.getContentType(); + // and even if nominally there is something, only use if it really is enum + if (!enumType.isEnumType()) { + enumType = null; + } + return StdContainerSerializers.enumSetSerializer(enumType, property); + } + + /** + * @since 1.8 + */ + protected boolean isIndexedList(Class<?> cls) + { + return RandomAccess.class.isAssignableFrom(cls); + } + + /* + /********************************************************** + /* Factory methods, for Maps + /********************************************************** + */ + + /** + * Helper method that handles configuration details when constructing serializers for + * all "Map-like" types; both ones that implement {@link java.util.Map} and + * ones that do not (but that have been indicated to behave like Maps). + * + * @since 1.8 + */ + protected JsonSerializer<?> buildMapLikeSerializer(SerializationConfig config, MapLikeType type, + BasicBeanDescription beanDesc, BeanProperty property, + boolean staticTyping, + JsonSerializer<Object> keySerializer, + TypeSerializer elementTypeSerializer, JsonSerializer<Object> elementValueSerializer) + { + for (Serializers serializers : customSerializers()) { + JsonSerializer<?> ser = serializers.findMapLikeSerializer(config, type, beanDesc, property, + keySerializer, elementTypeSerializer, elementValueSerializer); + if (ser != null) { + return ser; + } + } + return null; + } + + /** + * Helper method that handles configuration details when constructing serializers for + * {@link java.util.Map} types. + *<p> + * Note: signature changed in 1.8, to take 'staticTyping' argument + */ + protected JsonSerializer<?> buildMapSerializer(SerializationConfig config, MapType type, + BasicBeanDescription beanDesc, BeanProperty property, + boolean staticTyping, + JsonSerializer<Object> keySerializer, + TypeSerializer elementTypeSerializer, JsonSerializer<Object> elementValueSerializer) + { + for (Serializers serializers : customSerializers()) { + JsonSerializer<?> ser = serializers.findMapSerializer(config, type, beanDesc, property, + keySerializer, elementTypeSerializer, elementValueSerializer); + if (ser != null) { + return ser; + } + } + if (EnumMap.class.isAssignableFrom(type.getRawClass())) { + return buildEnumMapSerializer(config, type, beanDesc, property, staticTyping, + elementTypeSerializer, elementValueSerializer); + } + return MapSerializer.construct(config.getAnnotationIntrospector().findPropertiesToIgnore(beanDesc.getClassInfo()), + type, staticTyping, elementTypeSerializer, property, + keySerializer, elementValueSerializer); + } + + /** + * Helper method that handles configuration details when constructing serializers for + * {@link java.util.EnumMap} types. + *<p> + * Note: signature changed in 1.8, to take 'staticTyping' argument + */ + protected JsonSerializer<?> buildEnumMapSerializer(SerializationConfig config, JavaType type, + BasicBeanDescription beanDesc, BeanProperty property, + boolean staticTyping, + TypeSerializer elementTypeSerializer, JsonSerializer<Object> elementValueSerializer) + { + JavaType keyType = type.getKeyType(); + // Need to find key enum values... + EnumValues enums = null; + if (keyType.isEnumType()) { // non-enum if we got it as type erased class (from instance) + @SuppressWarnings("unchecked") + Class<Enum<?>> enumClass = (Class<Enum<?>>) keyType.getRawClass(); + enums = EnumValues.construct(enumClass, config.getAnnotationIntrospector()); + } + return new EnumMapSerializer(type.getContentType(), staticTyping, enums, + elementTypeSerializer, property, elementValueSerializer); + } + + /* + /********************************************************** + /* Factory methods, for Arrays + /********************************************************** + */ + + /** + * Helper method that handles configuration details when constructing serializers for + * <code>Object[]</code> (and subtypes, except for String). + */ + protected JsonSerializer<?> buildArraySerializer(SerializationConfig config, ArrayType type, + BasicBeanDescription beanDesc, BeanProperty property, + boolean staticTyping, + TypeSerializer elementTypeSerializer, JsonSerializer<Object> elementValueSerializer) + { + Class<?> raw = type.getRawClass(); + if (String[].class == raw) { + return new StdArraySerializers.StringArraySerializer(property); + } + // other standard types? + JsonSerializer<?> ser = _arraySerializers.get(raw.getName()); + if (ser != null) { + return ser; + } + return new ObjectArraySerializer(type.getContentType(), staticTyping, elementTypeSerializer, + property, elementValueSerializer); + } + + /* + /********************************************************** + /* Factory methods, for non-container types + /********************************************************** + */ + + protected JsonSerializer<?> buildIteratorSerializer(SerializationConfig config, JavaType type, + BasicBeanDescription beanDesc, BeanProperty property, + boolean staticTyping) + { + // if there's generic type, it'll be the first contained type + JavaType valueType = type.containedType(0); + if (valueType == null) { + valueType = TypeFactory.unknownType(); + } + TypeSerializer vts = createTypeSerializer(config, valueType, property); + return StdContainerSerializers.iteratorSerializer(valueType, + usesStaticTyping(config, beanDesc, vts, property), vts, property); + } + + protected JsonSerializer<?> buildIterableSerializer(SerializationConfig config, JavaType type, + BasicBeanDescription beanDesc, BeanProperty property, + boolean staticTyping) + { + // if there's generic type, it'll be the first contained type + JavaType valueType = type.containedType(0); + if (valueType == null) { + valueType = TypeFactory.unknownType(); + } + TypeSerializer vts = createTypeSerializer(config, valueType, property); + return StdContainerSerializers.iterableSerializer(valueType, + usesStaticTyping(config, beanDesc, vts, property), vts, property); + } + + /* + /********************************************************** + /* Other helper methods + /********************************************************** + */ + + /** + * Helper method used to encapsulate details of annotation-based type + * coercion + * + * @since 1.8 + */ + @SuppressWarnings("unchecked") + protected <T extends JavaType> T modifyTypeByAnnotation(SerializationConfig config, Annotated a, T type) + { + // first: let's check class for the instance itself: + Class<?> superclass = config.getAnnotationIntrospector().findSerializationType(a); + if (superclass != null) { + try { + type = (T) type.widenBy(superclass); + } catch (IllegalArgumentException iae) { + throw new IllegalArgumentException("Failed to widen type "+type+" with concrete-type annotation (value "+superclass.getName()+"), method '"+a.getName()+"': "+iae.getMessage()); + } + } + return modifySecondaryTypesByAnnotation(config, a, type); + } + + /** + * @since 1.8 + */ + @SuppressWarnings("unchecked") + protected static <T extends JavaType> T modifySecondaryTypesByAnnotation(SerializationConfig config, Annotated a, T type) + { + AnnotationIntrospector intr = config.getAnnotationIntrospector(); + // then key class + if (type.isContainerType()) { + Class<?> keyClass = intr.findSerializationKeyType(a, type.getKeyType()); + if (keyClass != null) { + // illegal to use on non-Maps + if (!(type instanceof MapType)) { + throw new IllegalArgumentException("Illegal key-type annotation: type "+type+" is not a Map type"); + } + try { + type = (T) ((MapType) type).widenKey(keyClass); + } catch (IllegalArgumentException iae) { + throw new IllegalArgumentException("Failed to narrow key type "+type+" with key-type annotation ("+keyClass.getName()+"): "+iae.getMessage()); + } + } + + // and finally content class; only applicable to structured types + Class<?> cc = intr.findSerializationContentType(a, type.getContentType()); + if (cc != null) { + try { + type = (T) type.widenContentsBy(cc); + } catch (IllegalArgumentException iae) { + throw new IllegalArgumentException("Failed to narrow content type "+type+" with content-type annotation ("+cc.getName()+"): "+iae.getMessage()); + } + } + } + return type; + } + + protected static JsonSerializer<Object> findKeySerializer(SerializationConfig config, + Annotated a, BeanProperty property) + { + AnnotationIntrospector intr = config.getAnnotationIntrospector(); + Class<? extends JsonSerializer<?>> serClass = intr.findKeySerializer(a); + if (serClass == null || serClass == JsonSerializer.None.class) { + if (property != null) { + serClass = intr.findKeySerializer(property.getMember()); + } + } + if (serClass != null && serClass != JsonSerializer.None.class) { + return config.serializerInstance(a, serClass); + } + return null; + } + + protected static JsonSerializer<Object> findContentSerializer(SerializationConfig config, + Annotated a, BeanProperty property) + { + AnnotationIntrospector intr = config.getAnnotationIntrospector(); + Class<? extends JsonSerializer<?>> serClass = intr.findContentSerializer(a); + if (serClass == null || serClass == JsonSerializer.None.class) { + if (property != null) { + serClass = intr.findContentSerializer(property.getMember()); + } + } + if (serClass != null && serClass != JsonSerializer.None.class) { + return config.serializerInstance(a, serClass); + } + return null; + } + + /** + * Helper method to check whether global settings and/or class + * annotations for the bean class indicate that static typing + * (declared types) should be used for properties. + * (instead of dynamic runtime types). + */ + protected boolean usesStaticTyping(SerializationConfig config, BasicBeanDescription beanDesc, + TypeSerializer typeSer, BeanProperty property) + { + /* 16-Aug-2010, tatu: If there is a (value) type serializer, we can not force + * static typing; that would make it impossible to handle expected subtypes + */ + if (typeSer != null) { + return false; + } + AnnotationIntrospector intr = config.getAnnotationIntrospector(); + JsonSerialize.Typing t = intr.findSerializationTyping(beanDesc.getClassInfo()); + if (t != null) { + if (t == JsonSerialize.Typing.STATIC) { + return true; + } + } else { + if (config.isEnabled(SerializationConfig.Feature.USE_STATIC_TYPING)) { + return true; + } + } + /* 11-Mar-2011, tatu: Ok. This is bit hacky, but we really need to be able to find cases + * where key and/or value serializers were specified, to force use of static typing + */ + if (property != null) { + JavaType type = property.getType(); + if (type.isContainerType()) { + if (intr.findSerializationContentType(property.getMember(), property.getType()) != null) { + return true; + } + if (type instanceof MapType) { + if (intr.findSerializationKeyType(property.getMember(), property.getType()) != null) { + return true; + } + } + } + } + return false; + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/BeanPropertyFilter.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/BeanPropertyFilter.java new file mode 100644 index 0000000..0d827f7 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/BeanPropertyFilter.java
@@ -0,0 +1,30 @@ +package org.codehaus.jackson.map.ser; + +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.map.SerializerProvider; + +/** + * Interface that defines API for filter objects use (as configured + * using {@link org.codehaus.jackson.map.annotate.JsonFilter}) + * for filtering bean properties to serialize. + * + * @since 1.7 + */ +public interface BeanPropertyFilter +{ + /** + * Method called by {@link BeanSerializer} to let filter decide what to do with + * given bean property value: the usual choices are to either filter out (i.e. + * do nothing) or write using given {@link BeanPropertyWriter}, although filters + * can choose other to do something different altogether. + * + * @param bean Bean of which property value to serialize + * @param jgen Generator use for serializing value + * @param prov Provider that can be used for accessing dynamic aspects of serialization + * processing + * @param writer Default bean property serializer to use + */ + public void serializeAsField(Object bean, JsonGenerator jgen, SerializerProvider prov, + BeanPropertyWriter writer) + throws Exception; +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/BeanPropertyWriter.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/BeanPropertyWriter.java new file mode 100644 index 0000000..e7e880d --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/BeanPropertyWriter.java
@@ -0,0 +1,512 @@ +package org.codehaus.jackson.map.ser; + +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.map.BeanProperty; +import org.codehaus.jackson.map.JsonMappingException; +import org.codehaus.jackson.map.JsonSerializer; +import org.codehaus.jackson.map.SerializerProvider; +import org.codehaus.jackson.map.TypeSerializer; +import org.codehaus.jackson.map.introspect.AnnotatedMember; +import org.codehaus.jackson.map.ser.impl.PropertySerializerMap; +import org.codehaus.jackson.map.ser.impl.UnwrappingBeanPropertyWriter; +import org.codehaus.jackson.map.util.Annotations; +import org.codehaus.jackson.io.SerializedString; +import org.codehaus.jackson.type.JavaType; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Type; +import java.util.HashMap; + +/** + * Base bean property handler class, which implements common parts of + * reflection-based functionality for accessing a property value + * and serializing it. + */ +public class BeanPropertyWriter + implements BeanProperty +{ + /* + /********************************************************** + /* Settings for accessing property value to serialize + /********************************************************** + */ + + /** + * Member (field, method) that represents property and allows access + * to associated annotations. + * + * @since 1.7 + */ + protected final AnnotatedMember _member; + + /** + * Annotations from context (most often, class that declares property, + * or in case of sub-class serializer, from that sub-class) + */ + protected final Annotations _contextAnnotations; + + /** + * Type property is declared to have, either in class definition + * or associated annotations. + */ + protected final JavaType _declaredType; + + /** + * Accessor method used to get property value, for + * method-accessible properties. + * Null if and only if {@link #_field} is null. + */ + protected final Method _accessorMethod; + + /** + * Field that contains the property value for field-accessible + * properties. + * Null if and only if {@link #_accessorMethod} is null. + */ + protected final Field _field; + + /* + /********************************************************** + /* Opaque internal data that bean serializer factory and + /* bean serializers can add. + /* + /* @since 1.7 + /********************************************************** + */ + + protected HashMap<Object,Object> _internalSettings; + + /* + /********************************************************** + /* Serialization settings + /********************************************************** + */ + + /** + * Logical name of the property; will be used as the field name + * under which value for the property is written. + */ + protected final SerializedString _name; + + /** + * Type to use for locating serializer; normally same as return + * type of the accessor method, but may be overridden by annotations. + */ + protected final JavaType _cfgSerializationType; + + /** + * Serializer to use for writing out the value: null if it can not + * be known statically; non-null if it can. + */ + protected final JsonSerializer<Object> _serializer; + + /** + * In case serializer is not known statically (i.e. <code>_serializer</code> + * is null), we will use a lookup structure for storing dynamically + * resolved mapping from type(s) to serializer(s). + * + * @since 1.7 + */ + protected PropertySerializerMap _dynamicSerializers; + + /** + * Flag to indicate that null values for this property are not + * to be written out. That is, if property has value null, + * no entry will be written + */ + protected final boolean _suppressNulls; + + /** + * Value that is considered default value of the property; used for + * default-value-suppression if enabled. + */ + protected final Object _suppressableValue; + + /** + * Alternate set of property writers used when view-based filtering + * is available for the Bean. + * + * @since 1.4 + */ + protected Class<?>[] _includeInViews; + + /** + * If property being serialized needs type information to be + * included this is the type serializer to use. + * Declared type (possibly augmented with annotations) of property + * is used for determining exact mechanism to use (compared to + * actual runtime type used for serializing actual state). + */ + protected TypeSerializer _typeSerializer; + + /** + * Base type of the property, if the declared type is "non-trivial"; + * meaning it is either a structured type (collection, map, array), + * or parametrized. Used to retain type information about contained + * type, which is mostly necessary if type metadata is to be + * included. + * + * @since 1.5 + */ + protected JavaType _nonTrivialBaseType; + + /* + /********************************************************** + /* Construction, configuration + /********************************************************** + */ + + public BeanPropertyWriter(AnnotatedMember member, Annotations contextAnnotations, + String name, JavaType declaredType, + JsonSerializer<Object> ser, TypeSerializer typeSer, JavaType serType, + Method m, Field f, + boolean suppressNulls, Object suppressableValue) + { + this(member, contextAnnotations, new SerializedString(name), declaredType, + ser, typeSer, serType, + m, f, suppressNulls, suppressableValue); + } + + public BeanPropertyWriter(AnnotatedMember member, Annotations contextAnnotations, + SerializedString name, JavaType declaredType, + JsonSerializer<Object> ser, TypeSerializer typeSer, JavaType serType, + Method m, Field f, boolean suppressNulls, Object suppressableValue) + { + _member = member; + _contextAnnotations = contextAnnotations; + _name = name; + _declaredType = declaredType; + _serializer = ser; + _dynamicSerializers = (ser == null) ? PropertySerializerMap.emptyMap() : null; + _typeSerializer = typeSer; + _cfgSerializationType = serType; + _accessorMethod = m; + _field = f; + _suppressNulls = suppressNulls; + _suppressableValue = suppressableValue; + } + + /** + * "Copy constructor" to be used by filtering sub-classes + */ + protected BeanPropertyWriter(BeanPropertyWriter base) + { + this(base, base._serializer); + } + + /** + * "Copy constructor" to be used by filtering sub-classes + */ + protected BeanPropertyWriter(BeanPropertyWriter base, JsonSerializer<Object> ser) + { + _serializer = ser; + + _member = base._member; + _contextAnnotations = base._contextAnnotations; + _declaredType = base._declaredType; + _accessorMethod = base._accessorMethod; + _field = base._field; + // one more thing: copy internal settings, if any (since 1.7) + if (base._internalSettings != null) { + _internalSettings = new HashMap<Object,Object>(base._internalSettings); + } + _name = base._name; + _cfgSerializationType = base._cfgSerializationType; + _dynamicSerializers = base._dynamicSerializers; + _suppressNulls = base._suppressNulls; + _suppressableValue = base._suppressableValue; + _includeInViews = base._includeInViews; + _typeSerializer = base._typeSerializer; + _nonTrivialBaseType = base._nonTrivialBaseType; + } + + /** + * Method that will construct and return a new writer that has + * same properties as this writer, but uses specified serializer + * instead of currently configured one (if any). + */ + public BeanPropertyWriter withSerializer(JsonSerializer<Object> ser) + { + // sanity check to ensure sub-classes override... + if (getClass() != BeanPropertyWriter.class) { + throw new IllegalStateException("BeanPropertyWriter sub-class does not override 'withSerializer()'; needs to!"); + } + return new BeanPropertyWriter(this, ser); + } + + /** + * Method called create an instance that handles details of unwrapping + * contained value. + * + * @since 1.9 + */ + public BeanPropertyWriter unwrappingWriter() { + return new UnwrappingBeanPropertyWriter(this); + } + + /** + * Method for defining which views to included value of this + * property in. If left undefined, will always be included; + * otherwise active view definition will be checked against + * definition list and value is only included if active + * view is one of defined views, or its sub-view (as defined + * by class/sub-class relationship). + */ + public void setViews(Class<?>[] views) { _includeInViews = views; } + + /** + * Method called to define type to consider as "non-trivial" basetype, + * needed for dynamic serialization resolution for complex (usually container) + * types + * + * @since 1.5 + */ + public void setNonTrivialBaseType(JavaType t) { + _nonTrivialBaseType = t; + } + + /* + /********************************************************** + /* BeanProperty impl + /********************************************************** + */ + + @Override + public String getName() { + return _name.getValue(); + } + + @Override + public JavaType getType() { + return _declaredType; + } + + @Override + public <A extends Annotation> A getAnnotation(Class<A> acls) { + return _member.getAnnotation(acls); + } + + @Override + public <A extends Annotation> A getContextAnnotation(Class<A> acls) { + return _contextAnnotations.get(acls); + } + + @Override + public AnnotatedMember getMember() { + return _member; + } + + /* + /********************************************************** + /* Managing and accessing of opaque internal settings + /* (used by extensions) + /********************************************************** + */ + + /** + * Method for accessing value of specified internal setting. + * + * @return Value of the setting, if any; null if none. + * + * @since 1.7 + */ + public Object getInternalSetting(Object key) + { + if (_internalSettings == null) { + return null; + } + return _internalSettings.get(key); + } + + /** + * Method for setting specific internal setting to given value + * + * @return Old value of the setting, if any (null if none) + * + * @since 1.7 + */ + public Object setInternalSetting(Object key, Object value) + { + if (_internalSettings == null) { + _internalSettings = new HashMap<Object,Object>(); + } + return _internalSettings.put(key, value); + } + + /** + * Method for removing entry for specified internal setting. + * + * @return Existing value of the setting, if any (null if none) + * + * @since 1.7 + */ + public Object removeInternalSetting(Object key) + { + Object removed = null; + if (_internalSettings != null) { + removed = _internalSettings.remove(key); + // to reduce memory usage, let's also drop the Map itself, if empty + if (_internalSettings.size() == 0) { + _internalSettings = null; + } + } + return removed; + } + + /* + /********************************************************** + /* Accessors + /********************************************************** + */ + + public SerializedString getSerializedName() { return _name; } + + public boolean hasSerializer() { return _serializer != null; } + + // Needed by BeanSerializer#getSchema + public JsonSerializer<Object> getSerializer() { + return _serializer; + } + + public JavaType getSerializationType() { + return _cfgSerializationType; + } + + public Class<?> getRawSerializationType() { + return (_cfgSerializationType == null) ? null : _cfgSerializationType.getRawClass(); + } + + public Class<?> getPropertyType() + { + if (_accessorMethod != null) { + return _accessorMethod.getReturnType(); + } + return _field.getType(); + } + + /** + * Get the generic property type of this property writer. + * + * @return The property type, or null if not found. + */ + public Type getGenericPropertyType() + { + if (_accessorMethod != null) { + return _accessorMethod.getGenericReturnType(); + } + return _field.getGenericType(); + } + + public Class<?>[] getViews() { return _includeInViews; } + + /* + /********************************************************** + /* Serialization functionality + /********************************************************** + */ + + /** + * Method called to access property that this bean stands for, from + * within given bean, and to serialize it as a JSON Object field + * using appropriate serializer. + */ + public void serializeAsField(Object bean, JsonGenerator jgen, SerializerProvider prov) + throws Exception + { + Object value = get(bean); + // Null handling is bit different, check that first + if (value == null) { + if (!_suppressNulls) { + jgen.writeFieldName(_name); + prov.defaultSerializeNull(jgen); + } + return; + } + // For non-nulls, first: simple check for direct cycles + if (value == bean) { + _reportSelfReference(bean); + } + if (_suppressableValue != null && _suppressableValue.equals(value)) { + return; + } + + JsonSerializer<Object> ser = _serializer; + if (ser == null) { + Class<?> cls = value.getClass(); + PropertySerializerMap map = _dynamicSerializers; + ser = map.serializerFor(cls); + if (ser == null) { + ser = _findAndAddDynamic(map, cls, prov); + } + } + jgen.writeFieldName(_name); + if (_typeSerializer == null) { + ser.serialize(value, jgen, prov); + } else { + ser.serializeWithType(value, jgen, prov, _typeSerializer); + } + } + + /** + * @since 1.7 + */ + protected JsonSerializer<Object> _findAndAddDynamic(PropertySerializerMap map, + Class<?> type, SerializerProvider provider) throws JsonMappingException + { + PropertySerializerMap.SerializerAndMapResult result; + if (_nonTrivialBaseType != null) { + JavaType t = provider.constructSpecializedType(_nonTrivialBaseType, type); + result = map.findAndAddSerializer(t, provider, this); + } else { + result = map.findAndAddSerializer(type, provider, this); + } + // did we get a new map of serializers? If so, start using it + if (map != result.map) { + _dynamicSerializers = result.map; + } + return result.serializer; + } + + /** + * Method that can be used to access value of the property this + * Object describes, from given bean instance. + *<p> + * Note: method is final as it should not need to be overridden -- rather, + * calling method(s) ({@link #serializeAsField}) should be overridden + * to change the behavior + */ + public final Object get(Object bean) throws Exception + { + if (_accessorMethod != null) { + return _accessorMethod.invoke(bean); + } + return _field.get(bean); + } + + protected void _reportSelfReference(Object bean) + throws JsonMappingException + { + throw new JsonMappingException("Direct self-reference leading to cycle"); + } + + @Override + public String toString() + { + StringBuilder sb = new StringBuilder(40); + sb.append("property '").append(getName()).append("' ("); + if (_accessorMethod != null) { + sb.append("via method ").append(_accessorMethod.getDeclaringClass().getName()).append("#").append(_accessorMethod.getName()); + } else { + sb.append("field \"").append(_field.getDeclaringClass().getName()).append("#").append(_field.getName()); + } + if (_serializer == null) { + sb.append(", no static serializer"); + } else { + sb.append(", static serializer of type "+_serializer.getClass().getName()); + } + sb.append(')'); + return sb.toString(); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/BeanSerializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/BeanSerializer.java new file mode 100644 index 0000000..2cdbc18 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/BeanSerializer.java
@@ -0,0 +1,126 @@ +package org.codehaus.jackson.map.ser; + +import java.io.IOException; + +import org.codehaus.jackson.JsonGenerationException; +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.ser.impl.UnwrappingBeanSerializer; +import org.codehaus.jackson.map.ser.std.BeanSerializerBase; +import org.codehaus.jackson.type.JavaType; + +/** + * Serializer class that can serialize arbitrary bean objects + *<p> + * Implementation note: we will post-process resulting serializer, + * to figure out actual serializers for final types. This must be + * done from {@link #resolve} method, and NOT from constructor; + * otherwise we could end up with an infinite loop. + *<p> + * Since 1.7 instances are immutable; this is achieved by using a + * separate builder during construction process. + */ +public class BeanSerializer + extends BeanSerializerBase +{ + /* + /********************************************************** + /* Life-cycle: constructors + /********************************************************** + */ + + /** + * @param type Nominal type of values handled by this serializer + * @param properties Property writers used for actual serialization + */ + public BeanSerializer(JavaType type, + BeanPropertyWriter[] properties, BeanPropertyWriter[] filteredProperties, + AnyGetterWriter anyGetterWriter, + Object filterId) + { + super(type, properties, filteredProperties, anyGetterWriter, filterId); + } + + public BeanSerializer(Class<?> rawType, + BeanPropertyWriter[] properties, BeanPropertyWriter[] filteredProperties, + AnyGetterWriter anyGetterWriter, + Object filterId) + { + super(rawType, properties, filteredProperties, anyGetterWriter, filterId); + } + + /** + * Copy-constructor that is useful for sub-classes that just want to + * copy all super-class properties without modifications. + * + * @since 1.7 + */ + protected BeanSerializer(BeanSerializer src) { + super(src); + } + + /** + * Alternate copy constructor that can be used to construct + * standard {@link BeanSerializer} passing an instance of + * "compatible enough" source serializer. + * + * @since 1.9 + */ + protected BeanSerializer(BeanSerializerBase src) { + super(src); + } + + /* + /********************************************************** + /* Life-cycle: factory methods, fluent factories + /********************************************************** + */ + + /** + * Method for constructing dummy bean deserializer; one that + * never outputs any properties + */ + public static BeanSerializer createDummy(Class<?> forType) + { + return new BeanSerializer(forType, NO_PROPS, null, null, null); + } + + @Override + public JsonSerializer<Object> unwrappingSerializer() { + return new UnwrappingBeanSerializer(this); + } + + /* + /********************************************************** + /* JsonSerializer implementation that differs between impls + /********************************************************** + */ + + /** + * Main serialization method that will delegate actual output to + * configured + * {@link BeanPropertyWriter} instances. + */ + @Override + public final void serialize(Object bean, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + jgen.writeStartObject(); + if (_propertyFilterId != null) { + serializeFieldsFiltered(bean, jgen, provider); + } else { + serializeFields(bean, jgen, provider); + } + jgen.writeEndObject(); + } + + /* + /********************************************************** + /* Standard methods + /********************************************************** + */ + + @Override public String toString() { + return "BeanSerializer for "+handledType().getName(); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/BeanSerializerBuilder.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/BeanSerializerBuilder.java new file mode 100644 index 0000000..83641db --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/BeanSerializerBuilder.java
@@ -0,0 +1,140 @@ +package org.codehaus.jackson.map.ser; + +import java.util.*; + +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.introspect.BasicBeanDescription; + +/** + * Builder class used for aggregating deserialization information about + * a POJO, in order to build a {@link JsonSerializer} for serializing + * intances. + * Main reason for using separate builder class is that this makes it easier + * to make actual serializer class fully immutable. + * + * @since 1.7 + */ +public class BeanSerializerBuilder +{ + private final static BeanPropertyWriter[] NO_PROPERTIES = new BeanPropertyWriter[0]; + + /* + /********************************************************** + /* General information about POJO + /********************************************************** + */ + + final protected BasicBeanDescription _beanDesc; + + /* + /********************************************************** + /* Accumulated information about properties + /********************************************************** + */ + + /** + * Bean properties, in order of serialization + */ + protected List<BeanPropertyWriter> _properties; + + /** + * Optional array of filtered property writers; if null, no + * view-based filtering is performed. + */ + protected BeanPropertyWriter[] _filteredProperties; + + /** + * Writer used for "any getter" properties, if any. + */ + protected AnyGetterWriter _anyGetter; + + /** + * Id of the property filter to use for POJO, if any. + */ + protected Object _filterId; + + /* + /********************************************************** + /* Construction and setter methods + /********************************************************** + */ + + public BeanSerializerBuilder(BasicBeanDescription beanDesc) { + _beanDesc = beanDesc; + } + + /** + * Copy-constructor that may be used for sub-classing + */ + protected BeanSerializerBuilder(BeanSerializerBuilder src) { + _beanDesc = src._beanDesc; + _properties = src._properties; + _filteredProperties = src._filteredProperties; + _anyGetter = src._anyGetter; + _filterId = src._filterId; + } + + public BasicBeanDescription getBeanDescription() { return _beanDesc; } + public List<BeanPropertyWriter> getProperties() { return _properties; } + public BeanPropertyWriter[] getFilteredProperties() { return _filteredProperties; } + + /** + * @since 1.9 + */ + public boolean hasProperties() { + return (_properties != null) && (_properties.size() > 0); + } + + public void setProperties(List<BeanPropertyWriter> properties) { + _properties = properties; + } + + public void setFilteredProperties(BeanPropertyWriter[] properties) { + _filteredProperties = properties; + } + + public void setAnyGetter(AnyGetterWriter anyGetter) { + _anyGetter = anyGetter; + } + + public void setFilterId(Object filterId) { + _filterId = filterId; + } + + /* + /********************************************************** + /* Build methods for actually creating serializer instance + /********************************************************** + */ + + /** + * Method called to create {@link BeanSerializer} instance with + * all accumulated information. Will construct a serializer if we + * have enough information, or return null if not. + */ + public JsonSerializer<?> build() + { + BeanPropertyWriter[] properties; + // No properties or any getter? No real serializer; caller gets to handle + if (_properties == null || _properties.isEmpty()) { + if (_anyGetter == null) { + return null; + } + properties = NO_PROPERTIES; + } else { + properties = _properties.toArray(new BeanPropertyWriter[_properties.size()]); + + } + return new BeanSerializer(_beanDesc.getType(), properties, _filteredProperties, _anyGetter, _filterId); + } + + /** + * Factory method for constructing an "empty" serializer; one that + * outputs no properties (but handles JSON objects properly, including + * type information) + */ + public BeanSerializer createDummy() { + return BeanSerializer.createDummy(_beanDesc.getBeanClass()); + } +} +
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/BeanSerializerFactory.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/BeanSerializerFactory.java new file mode 100644 index 0000000..124d892 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/BeanSerializerFactory.java
@@ -0,0 +1,786 @@ +package org.codehaus.jackson.map.ser; + +import java.util.*; + +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.introspect.*; +import org.codehaus.jackson.map.jsontype.NamedType; +import org.codehaus.jackson.map.jsontype.TypeResolverBuilder; +import org.codehaus.jackson.map.ser.std.MapSerializer; +import org.codehaus.jackson.map.type.*; +import org.codehaus.jackson.map.util.ArrayBuilders; +import org.codehaus.jackson.map.util.ClassUtil; +import org.codehaus.jackson.type.JavaType; + +/** + * Factory class that can provide serializers for any regular Java beans + * (as defined by "having at least one get method recognizable as bean + * accessor" -- where {@link Object#getClass} does not count); + * as well as for "standard" JDK types. Latter is achieved + * by delegating calls to {@link BasicSerializerFactory} + * to find serializers both for "standard" JDK types (and in some cases, + * sub-classes as is the case for collection classes like + * {@link java.util.List}s and {@link java.util.Map}s) and bean (value) + * classes. + *<p> + * Note about delegating calls to {@link BasicSerializerFactory}: + * although it would be nicer to use linear delegation + * for construction (to essentially dispatch all calls first to the + * underlying {@link BasicSerializerFactory}; or alternatively after + * failing to provide bean-based serializer}, there is a problem: + * priority levels for detecting standard types are mixed. That is, + * we want to check if a type is a bean after some of "standard" JDK + * types, but before the rest. + * As a result, "mixed" delegation used, and calls are NOT done using + * regular {@link SerializerFactory} interface but rather via + * direct calls to {@link BasicSerializerFactory}. + *<p> + * Finally, since all caching is handled by the serializer provider + * (not factory) and there is no configurability, this + * factory is stateless. + * This means that a global singleton instance can be used. + *<p> + * Notes for version 1.7 (and above): the new module registration system + * required addition of {@link #withConfig}, which has to + * be redefined by sub-classes so that they can work properly with + * pluggable additional serializer providing components. + */ +public class BeanSerializerFactory + extends BasicSerializerFactory +{ + /** + * Like {@link BasicSerializerFactory}, this factory is stateless, and + * thus a single shared global (== singleton) instance can be used + * without thread-safety issues. + */ + public final static BeanSerializerFactory instance = new BeanSerializerFactory(null); + + /** + * Configuration settings for this factory; immutable instance (just like this + * factory), new version created via copy-constructor (fluent-style) + * + * @since 1.7 + */ + protected final Config _factoryConfig; + + /* + /********************************************************** + /* Config class implementation + /********************************************************** + */ + + /** + * Configuration settings container class for bean serializer factory + * + * @since 1.7 + */ + public static class ConfigImpl extends Config + { + /** + * Constant for empty <code>Serializers</code> array (which by definition + * is stateless and reusable) + */ + protected final static Serializers[] NO_SERIALIZERS = new Serializers[0]; + + protected final static BeanSerializerModifier[] NO_MODIFIERS = new BeanSerializerModifier[0]; + + /** + * List of providers for additional serializers, checked before considering default + * basic or bean serialializers. + * + * @since 1.7 + */ + protected final Serializers[] _additionalSerializers; + + /** + * @since 1.8 + */ + protected final Serializers[] _additionalKeySerializers; + + /** + * List of modifiers that can change the way {@link BeanSerializer} instances + * are configured and constructed. + */ + protected final BeanSerializerModifier[] _modifiers; + + public ConfigImpl() { + this(null, null, null); + } + + protected ConfigImpl(Serializers[] allAdditionalSerializers, + Serializers[] allAdditionalKeySerializers, + BeanSerializerModifier[] modifiers) + { + _additionalSerializers = (allAdditionalSerializers == null) ? + NO_SERIALIZERS : allAdditionalSerializers; + _additionalKeySerializers = (allAdditionalKeySerializers == null) ? + NO_SERIALIZERS : allAdditionalKeySerializers; + _modifiers = (modifiers == null) ? NO_MODIFIERS : modifiers; + } + + @Override + public Config withAdditionalSerializers(Serializers additional) + { + if (additional == null) { + throw new IllegalArgumentException("Can not pass null Serializers"); + } + Serializers[] all = ArrayBuilders.insertInListNoDup(_additionalSerializers, additional); + return new ConfigImpl(all, _additionalKeySerializers, _modifiers); + } + + @Override + public Config withAdditionalKeySerializers(Serializers additional) + { + if (additional == null) { + throw new IllegalArgumentException("Can not pass null Serializers"); + } + Serializers[] all = ArrayBuilders.insertInListNoDup(_additionalKeySerializers, additional); + return new ConfigImpl(_additionalSerializers, all, _modifiers); + } + + @Override + public Config withSerializerModifier(BeanSerializerModifier modifier) + { + if (modifier == null) { + throw new IllegalArgumentException("Can not pass null modifier"); + } + BeanSerializerModifier[] modifiers = ArrayBuilders.insertInListNoDup(_modifiers, modifier); + return new ConfigImpl(_additionalSerializers, _additionalKeySerializers, modifiers); + } + + @Override + public boolean hasSerializers() { return _additionalSerializers.length > 0; } + + @Override + public boolean hasKeySerializers() { return _additionalKeySerializers.length > 0; } + + @Override + public boolean hasSerializerModifiers() { return _modifiers.length > 0; } + + @Override + public Iterable<Serializers> serializers() { + return ArrayBuilders.arrayAsIterable(_additionalSerializers); + } + + @Override + public Iterable<Serializers> keySerializers() { + return ArrayBuilders.arrayAsIterable(_additionalKeySerializers); + } + + @Override + public Iterable<BeanSerializerModifier> serializerModifiers() { + return ArrayBuilders.arrayAsIterable(_modifiers); + } + } + + /* + /********************************************************** + /* Life-cycle: creation, configuration + /********************************************************** + */ + + /** + * Constructor for creating instances with specified configuration. + */ + protected BeanSerializerFactory(Config config) + { + if (config == null) { + config = new ConfigImpl(); + } + _factoryConfig = config; + } + + @Override public Config getConfig() { return _factoryConfig; } + + /** + * Method used by module registration functionality, to attach additional + * serializer providers into this serializer factory. This is typically + * handled by constructing a new instance with additional serializers, + * to ensure thread-safe access. + * + * @since 1.7 + */ + @Override + public SerializerFactory withConfig(Config config) + { + if (_factoryConfig == config) { + return this; + } + /* 22-Nov-2010, tatu: Handling of subtypes is tricky if we do immutable-with-copy-ctor; + * and we pretty much have to here either choose between losing subtype instance + * when registering additional serializers, or losing serializers. + * Instead, let's actually just throw an error if this method is called when subtype + * has not properly overridden this method; this to indicate problem as soon as possible. + */ + if (getClass() != BeanSerializerFactory.class) { + throw new IllegalStateException("Subtype of BeanSerializerFactory ("+getClass().getName() + +") has not properly overridden method 'withAdditionalSerializers': can not instantiate subtype with " + +"additional serializer definitions"); + } + return new BeanSerializerFactory(config); + } + + @Override + protected Iterable<Serializers> customSerializers() { + return _factoryConfig.serializers(); + } + + /* + /********************************************************** + /* SerializerFactory impl + /********************************************************** + */ + + /** + * Main serializer constructor method. We will have to be careful + * with respect to ordering of various method calls: essentially + * we want to reliably figure out which classes are standard types, + * and which are beans. The problem is that some bean Classes may + * implement standard interfaces (say, {@link java.lang.Iterable}. + *<p> + * Note: sub-classes may choose to complete replace implementation, + * if they want to alter priority of serializer lookups. + */ + @Override + @SuppressWarnings("unchecked") + public JsonSerializer<Object> createSerializer(SerializationConfig config, JavaType origType, + BeanProperty property) + throws JsonMappingException + { + // Very first thing, let's check if there is explicit serializer annotation: + BasicBeanDescription beanDesc = config.introspect(origType); + JsonSerializer<?> ser = findSerializerFromAnnotation(config, beanDesc.getClassInfo(), property); + if (ser != null) { + return (JsonSerializer<Object>) ser; + } + + // Next: we may have annotations that further define types to use... + JavaType type = modifyTypeByAnnotation(config, beanDesc.getClassInfo(), origType); + // and if so, we consider it implicit "force static typing" instruction + boolean staticTyping = (type != origType); + if (type != origType && type.getRawClass() != origType.getRawClass()) { + // [JACKSON-799]: need to re-introspect + beanDesc = config.introspect(type); + } + + // Container types differ from non-container types: + if (origType.isContainerType()) { + return (JsonSerializer<Object>) buildContainerSerializer(config, type, beanDesc, property, staticTyping); + } + + // Modules may provide serializers of all types: + for (Serializers serializers : _factoryConfig.serializers()) { + ser = serializers.findSerializer(config, type, beanDesc, property); + if (ser != null) { + return (JsonSerializer<Object>) ser; + } + } + + /* Otherwise, we will check "primary types"; both marker types that + * indicate specific handling (JsonSerializable), or main types that have + * precedence over container types + */ + ser = findSerializerByLookup(type, config, beanDesc, property, staticTyping); + if (ser == null) { + ser = findSerializerByPrimaryType(type, config, beanDesc, property, staticTyping); + if (ser == null) { + /* And this is where this class comes in: if type is not a + * known "primary JDK type", perhaps it's a bean? We can still + * get a null, if we can't find a single suitable bean property. + */ + ser = findBeanSerializer(config, type, beanDesc, property); + /* Finally: maybe we can still deal with it as an + * implementation of some basic JDK interface? + */ + if (ser == null) { + ser = findSerializerByAddonType(config, type, beanDesc, property, staticTyping); + } + } + } + return (JsonSerializer<Object>) ser; + } + + @Override + @SuppressWarnings("unchecked") + public JsonSerializer<Object> createKeySerializer(SerializationConfig config, JavaType type, + BeanProperty property) + { + // Minor optimization: to avoid constructing beanDesc, bail out if none registered + if (!_factoryConfig.hasKeySerializers()) { + return null; + } + + // We should not need any member method info; at most class annotations for Map type + BasicBeanDescription beanDesc = config.introspectClassAnnotations(type.getRawClass()); + JsonSerializer<?> ser = null; + + // Only thing we have here are module-provided key serializers: + for (Serializers serializers : _factoryConfig.keySerializers()) { + ser = serializers.findSerializer(config, type, beanDesc, property); + if (ser != null) { + break; + } + } + return (JsonSerializer<Object>) ser; + } + + /* + /********************************************************** + /* Other public methods that are not part of + /* JsonSerializerFactory API + /********************************************************** + */ + + /** + * Method that will try to construct a {@link BeanSerializer} for + * given class. Returns null if no properties are found. + */ + @SuppressWarnings("unchecked") + public JsonSerializer<Object> findBeanSerializer(SerializationConfig config, JavaType type, + BasicBeanDescription beanDesc, BeanProperty property) + throws JsonMappingException + { + // First things first: we know some types are not beans... + if (!isPotentialBeanType(type.getRawClass())) { + return null; + } + JsonSerializer<Object> serializer = constructBeanSerializer(config, beanDesc, property); + // [JACKSON-440] Need to allow overriding actual serializer, as well... + if (_factoryConfig.hasSerializerModifiers()) { + for (BeanSerializerModifier mod : _factoryConfig.serializerModifiers()) { + serializer = (JsonSerializer<Object>)mod.modifySerializer(config, beanDesc, serializer); + } + } + return serializer; + } + + /** + * Method called to create a type information serializer for values of given + * non-container property + * if one is needed. If not needed (no polymorphic handling configured), should + * return null. + * + * @param baseType Declared type to use as the base type for type information serializer + * + * @return Type serializer to use for property values, if one is needed; null if not. + * + * @since 1.5 + */ + public TypeSerializer findPropertyTypeSerializer(JavaType baseType, SerializationConfig config, + AnnotatedMember accessor, BeanProperty property) + throws JsonMappingException + { + AnnotationIntrospector ai = config.getAnnotationIntrospector(); + TypeResolverBuilder<?> b = ai.findPropertyTypeResolver(config, accessor, baseType); + // Defaulting: if no annotations on member, check value class + if (b == null) { + return createTypeSerializer(config, baseType, property); + } + Collection<NamedType> subtypes = config.getSubtypeResolver().collectAndResolveSubtypes(accessor, config, ai); + return b.buildTypeSerializer(config, baseType, subtypes, property); + } + + /** + * Method called to create a type information serializer for values of given + * container property + * if one is needed. If not needed (no polymorphic handling configured), should + * return null. + * + * @param containerType Declared type of the container to use as the base type for type information serializer + * + * @return Type serializer to use for property value contents, if one is needed; null if not. + * + * @since 1.5 + */ + public TypeSerializer findPropertyContentTypeSerializer(JavaType containerType, SerializationConfig config, + AnnotatedMember accessor, BeanProperty property) + throws JsonMappingException + { + JavaType contentType = containerType.getContentType(); + AnnotationIntrospector ai = config.getAnnotationIntrospector(); + TypeResolverBuilder<?> b = ai.findPropertyContentTypeResolver(config, accessor, containerType); + // Defaulting: if no annotations on member, check value class + if (b == null) { + return createTypeSerializer(config, contentType, property); + } + Collection<NamedType> subtypes = config.getSubtypeResolver().collectAndResolveSubtypes(accessor, config, ai); + return b.buildTypeSerializer(config, contentType, subtypes, property); + } + + /* + /********************************************************** + /* Overridable non-public factory methods + /********************************************************** + */ + + /** + * Method called to construct serializer for serializing specified bean type. + * + * @since 1.6 + */ + @SuppressWarnings("unchecked") + protected JsonSerializer<Object> constructBeanSerializer(SerializationConfig config, + BasicBeanDescription beanDesc, BeanProperty property) + throws JsonMappingException + { + // 13-Oct-2010, tatu: quick sanity check: never try to create bean serializer for plain Object + if (beanDesc.getBeanClass() == Object.class) { + throw new IllegalArgumentException("Can not create bean serializer for Object.class"); + } + + BeanSerializerBuilder builder = constructBeanSerializerBuilder(beanDesc); + + // First: any detectable (auto-detect, annotations) properties to serialize? + List<BeanPropertyWriter> props = findBeanProperties(config, beanDesc); + + if (props == null) { + props = new ArrayList<BeanPropertyWriter>(); + } + // [JACKSON-440] Need to allow modification bean properties to serialize: + if (_factoryConfig.hasSerializerModifiers()) { + for (BeanSerializerModifier mod : _factoryConfig.serializerModifiers()) { + props = mod.changeProperties(config, beanDesc, props); + } + } + + // Any properties to suppress? + props = filterBeanProperties(config, beanDesc, props); + // Do they need to be sorted in some special way? + props = sortBeanProperties(config, beanDesc, props); + + // [JACKSON-440] Need to allow reordering of properties to serialize + if (_factoryConfig.hasSerializerModifiers()) { + for (BeanSerializerModifier mod : _factoryConfig.serializerModifiers()) { + props = mod.orderProperties(config, beanDesc, props); + } + } + + builder.setProperties(props); + builder.setFilterId(findFilterId(config, beanDesc)); + + AnnotatedMethod anyGetter = beanDesc.findAnyGetter(); + if (anyGetter != null) { // since 1.6 + if (config.isEnabled(SerializationConfig.Feature.CAN_OVERRIDE_ACCESS_MODIFIERS)) { + anyGetter.fixAccess(); + } + JavaType type = anyGetter.getType(beanDesc.bindingsForBeanType()); + // copied from BasicSerializerFactory.buildMapSerializer(): + boolean staticTyping = config.isEnabled(SerializationConfig.Feature.USE_STATIC_TYPING); + JavaType valueType = type.getContentType(); + TypeSerializer typeSer = createTypeSerializer(config, valueType, property); + // last 2 nulls; don't know key, value serializers (yet) + MapSerializer mapSer = MapSerializer.construct(/* ignored props*/ null, type, staticTyping, + typeSer, property, null, null); + builder.setAnyGetter(new AnyGetterWriter(anyGetter, mapSer)); + } + // One more thing: need to gather view information, if any: + processViews(config, builder); + // And maybe let interested parties mess with the result bit more... + if (_factoryConfig.hasSerializerModifiers()) { + for (BeanSerializerModifier mod : _factoryConfig.serializerModifiers()) { + builder = mod.updateBuilder(config, beanDesc, builder); + } + } + JsonSerializer<Object> ser = (JsonSerializer<Object>) builder.build(); + + /* However, after all modifications: no properties, no serializer + * (note; as per [JACKSON-670], check was moved later on from an earlier location) + */ + if (ser == null) { + /* 27-Nov-2009, tatu: Except that as per [JACKSON-201], we are + * ok with that as long as it has a recognized class annotation + * (which may come from a mix-in too) + */ + if (beanDesc.hasKnownClassAnnotations()) { + return builder.createDummy(); + } + } + return ser; + } + + /** + * Method called to construct a filtered writer, for given view + * definitions. Default implementation constructs filter that checks + * active view type to views property is to be included in. + */ + protected BeanPropertyWriter constructFilteredBeanWriter(BeanPropertyWriter writer, Class<?>[] inViews) + { + return FilteredBeanPropertyWriter.constructViewBased(writer, inViews); + } + + protected PropertyBuilder constructPropertyBuilder(SerializationConfig config, + BasicBeanDescription beanDesc) + { + return new PropertyBuilder(config, beanDesc); + } + + protected BeanSerializerBuilder constructBeanSerializerBuilder(BasicBeanDescription beanDesc) { + return new BeanSerializerBuilder(beanDesc); + } + + /** + * Method called to find filter that is configured to be used with bean + * serializer being built, if any. + * + * @since 1.7 + */ + protected Object findFilterId(SerializationConfig config, BasicBeanDescription beanDesc) + { + return config.getAnnotationIntrospector().findFilterId(beanDesc.getClassInfo()); + } + + /* + /********************************************************** + /* Overridable non-public introspection methods + /********************************************************** + */ + + /** + * Helper method used to skip processing for types that we know + * can not be (i.e. are never consider to be) beans: + * things like primitives, Arrays, Enums, and proxy types. + *<p> + * Note that usually we shouldn't really be getting these sort of + * types anyway; but better safe than sorry. + */ + protected boolean isPotentialBeanType(Class<?> type) + { + return (ClassUtil.canBeABeanType(type) == null) && !ClassUtil.isProxyType(type); + } + + /** + * Method used to collect all actual serializable properties. + * Can be overridden to implement custom detection schemes. + */ + protected List<BeanPropertyWriter> findBeanProperties(SerializationConfig config, BasicBeanDescription beanDesc) + throws JsonMappingException + { + List<BeanPropertyDefinition> properties = beanDesc.findProperties(); + AnnotationIntrospector intr = config.getAnnotationIntrospector(); + + // [JACKSON-429]: ignore specified types + removeIgnorableTypes(config, beanDesc, properties); + + // and possibly remove ones without matching mutator... + if (config.isEnabled(SerializationConfig.Feature.REQUIRE_SETTERS_FOR_GETTERS)) { + removeSetterlessGetters(config, beanDesc, properties); + } + + // nothing? can't proceed (caller may or may not throw an exception) + if (properties.isEmpty()) { + return null; + } + + // null is for value type serializer, which we don't have access to from here (ditto for bean prop) + boolean staticTyping = usesStaticTyping(config, beanDesc, null, null); + PropertyBuilder pb = constructPropertyBuilder(config, beanDesc); + + ArrayList<BeanPropertyWriter> result = new ArrayList<BeanPropertyWriter>(properties.size()); + TypeBindings typeBind = beanDesc.bindingsForBeanType(); + // [JACKSON-98]: start with field properties, if any + for (BeanPropertyDefinition property : properties) { + AnnotatedMember accessor = property.getAccessor(); + // [JACKSON-235]: suppress writing of back references + AnnotationIntrospector.ReferenceProperty prop = intr.findReferenceType(accessor); + if (prop != null && prop.isBackReference()) { + continue; + } + String name = property.getName(); + if (accessor instanceof AnnotatedMethod) { + result.add(_constructWriter(config, typeBind, pb, staticTyping, name, (AnnotatedMethod) accessor)); + } else { + result.add(_constructWriter(config, typeBind, pb, staticTyping, name, (AnnotatedField) accessor)); + } + } + return result; + } + + /* + /********************************************************** + /* Overridable non-public methods for manipulating bean properties + /********************************************************** + */ + + /** + * Overridable method that can filter out properties. Default implementation + * checks annotations class may have. + */ + protected List<BeanPropertyWriter> filterBeanProperties(SerializationConfig config, + BasicBeanDescription beanDesc, List<BeanPropertyWriter> props) + { + AnnotationIntrospector intr = config.getAnnotationIntrospector(); + AnnotatedClass ac = beanDesc.getClassInfo(); + String[] ignored = intr.findPropertiesToIgnore(ac); + if (ignored != null && ignored.length > 0) { + HashSet<String> ignoredSet = ArrayBuilders.arrayToSet(ignored); + Iterator<BeanPropertyWriter> it = props.iterator(); + while (it.hasNext()) { + if (ignoredSet.contains(it.next().getName())) { + it.remove(); + } + } + } + return props; + } + + /** + * Overridable method that will impose given partial ordering on + * list of discovered propertied. Method can be overridden to + * provide custom ordering of properties, beyond configurability + * offered by annotations (whic allow alphabetic ordering, as + * well as explicit ordering by providing array of property names). + *<p> + * By default Creator properties will be ordered before other + * properties. Explicit custom ordering will override this implicit + * default ordering. + */ + /** + * Method that used to be called (pre-1.9) to impose configured + * ordering on list of discovered properties. + * With 1.9 it is not needed any more as ordering is done earlier. + * + * @deprecated Since 1.9 this method does nothing, so there is no + * benefit from overriding it; it will be removed from 2.0. + */ + @Deprecated + protected List<BeanPropertyWriter> sortBeanProperties(SerializationConfig config, + BasicBeanDescription beanDesc, List<BeanPropertyWriter> props) + { + return props; + } + + /** + * Method called to handle view information for constructed serializer, + * based on bean property writers. + *<p> + * Note that this method is designed to be overridden by sub-classes + * if they want to provide custom view handling. As such it is not + * considered an internal implementation detail, and will be supported + * as part of API going forward. + *<p> + * NOTE: signature of this method changed in 1.7, due to other significant + * changes (esp. use of builder for serializer construction). + */ + protected void processViews(SerializationConfig config, BeanSerializerBuilder builder) + { + // [JACKSON-232]: whether non-annotated fields are included by default or not is configurable + List<BeanPropertyWriter> props = builder.getProperties(); + boolean includeByDefault = config.isEnabled(SerializationConfig.Feature.DEFAULT_VIEW_INCLUSION); + final int propCount = props.size(); + int viewsFound = 0; + BeanPropertyWriter[] filtered = new BeanPropertyWriter[propCount]; + // Simple: view information is stored within individual writers, need to combine: + for (int i = 0; i < propCount; ++i) { + BeanPropertyWriter bpw = props.get(i); + Class<?>[] views = bpw.getViews(); + if (views == null) { // no view info? include or exclude by default? + if (includeByDefault) { + filtered[i] = bpw; + } + } else { + ++viewsFound; + filtered[i] = constructFilteredBeanWriter(bpw, views); + } + } + // minor optimization: if no view info, include-by-default, can leave out filtering info altogether: + if (includeByDefault && viewsFound == 0) { + return; + } + builder.setFilteredProperties(filtered); + } + + /** + * Method that will apply by-type limitations (as per [JACKSON-429]); + * by default this is based on {@link org.codehaus.jackson.annotate.JsonIgnoreType} annotation but + * can be supplied by module-provided introspectors too. + */ + protected void removeIgnorableTypes(SerializationConfig config, BasicBeanDescription beanDesc, + List<BeanPropertyDefinition> properties) + { + AnnotationIntrospector intr = config.getAnnotationIntrospector(); + HashMap<Class<?>,Boolean> ignores = new HashMap<Class<?>,Boolean>(); + Iterator<BeanPropertyDefinition> it = properties.iterator(); + while (it.hasNext()) { + BeanPropertyDefinition property = it.next(); + AnnotatedMember accessor = property.getAccessor(); + if (accessor == null) { + it.remove(); + continue; + } + Class<?> type = accessor.getRawType(); + Boolean result = ignores.get(type); + if (result == null) { + BasicBeanDescription desc = config.introspectClassAnnotations(type); + AnnotatedClass ac = desc.getClassInfo(); + result = intr.isIgnorableType(ac); + // default to false, non-ignorable + if (result == null) { + result = Boolean.FALSE; + } + ignores.put(type, result); + } + // lotsa work, and yes, it is ignorable type, so: + if (result.booleanValue()) { + it.remove(); + } + } + } + + /** + * Helper method that will remove all properties that do not have a + * mutator. + * + * @since 1.9 + */ + protected void removeSetterlessGetters(SerializationConfig config, BasicBeanDescription beanDesc, + List<BeanPropertyDefinition> properties) + { + Iterator<BeanPropertyDefinition> it = properties.iterator(); + while (it.hasNext()) { + BeanPropertyDefinition property = it.next(); + // one caveat: as per [JACKSON-806], only remove implicit properties; + // explicitly annotated ones should remain + if (!property.couldDeserialize() && !property.isExplicitlyIncluded()) { + it.remove(); + } + } + } + + /* + /********************************************************** + /* Internal helper methods + /********************************************************** + */ + + /** + * Secondary helper method for constructing {@link BeanPropertyWriter} for + * given member (field or method). + */ + protected BeanPropertyWriter _constructWriter(SerializationConfig config, TypeBindings typeContext, + PropertyBuilder pb, boolean staticTyping, String name, AnnotatedMember accessor) + throws JsonMappingException + { + if (config.isEnabled(SerializationConfig.Feature.CAN_OVERRIDE_ACCESS_MODIFIERS)) { + accessor.fixAccess(); + } + JavaType type = accessor.getType(typeContext); + BeanProperty.Std property = new BeanProperty.Std(name, type, pb.getClassAnnotations(), accessor); + + // Does member specify a serializer? If so, let's use it. + JsonSerializer<Object> annotatedSerializer = findSerializerFromAnnotation(config, accessor, property); + // And how about polymorphic typing? First special to cover JAXB per-field settings: + TypeSerializer contentTypeSer = null; + if (ClassUtil.isCollectionMapOrArray(type.getRawClass())) { + contentTypeSer = findPropertyContentTypeSerializer(type, config, accessor, property); + } + + // and if not JAXB collection/array with annotations, maybe regular type info? + TypeSerializer typeSer = findPropertyTypeSerializer(type, config, accessor, property); + BeanPropertyWriter pbw = pb.buildWriter(name, type, annotatedSerializer, + typeSer, contentTypeSer, accessor, staticTyping); + // how about views? (1.4+) + AnnotationIntrospector intr = config.getAnnotationIntrospector(); + pbw.setViews(intr.findSerializationViews(accessor)); + return pbw; + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/BeanSerializerModifier.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/BeanSerializerModifier.java new file mode 100644 index 0000000..9116cb8 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/BeanSerializerModifier.java
@@ -0,0 +1,95 @@ +package org.codehaus.jackson.map.ser; + +import java.util.List; + +import org.codehaus.jackson.map.JsonSerializer; +import org.codehaus.jackson.map.SerializationConfig; +import org.codehaus.jackson.map.introspect.BasicBeanDescription; + +/** + * Abstract class that defines API for objects that can be registered (for {@link BeanSerializerFactory} + * to participate in constructing {@link BeanSerializer} instances. + * This is typically done by modules that want alter some aspects of serialization + * process; and is preferable to sub-classing of {@link BeanSerializerFactory}. + *<p> + * Sequence in which callback methods are called is as follows: + * <ol> + * <li>After factory has collected tentative set of properties (instances of + * <code>BeanPropertyWriter</code>) is sent for modification via + * {@link #changeProperties}. Changes can include removal, addition and + * replacement of suggested properties. + * <li>Resulting set of properties are ordered (sorted) by factory, as per + * configuration, and then {@link #orderProperties} is called to allow + * modifiers to alter ordering. + * <li>After all bean properties and related information is accumulated, + * {@link #updateBuilder} is called with builder, to allow builder state + * to be modified (including possibly replacing builder itself if necessary) + * <li>Once all bean information has been determined, + * factory creates default {@link BeanSerializer} instance and passes + * it to modifiers using {@link #modifySerializer}, for possible + * modification or replacement (by any {@link org.codehaus.jackson.map.JsonSerializer} instance) + * </ol> + *<p> + * Default method implementations are "no-op"s, meaning that methods are implemented + * but have no effect. + * + * @since 1.7 + */ +public abstract class BeanSerializerModifier +{ + /** + * Method called by {@link BeanSerializerFactory} with tentative set + * of discovered properties. + * Implementations can add, remove or replace any of passed properties. + * + * Properties <code>List</code> passed as argument is modifiable, and returned List must + * likewise be modifiable as it may be passed to multiple registered + * modifiers. + */ + public List<BeanPropertyWriter> changeProperties(SerializationConfig config, + BasicBeanDescription beanDesc, List<BeanPropertyWriter> beanProperties) { + return beanProperties; + } + + /** + * Method called by {@link BeanSerializerFactory} with set of properties + * to serialize, in default ordering (based on defaults as well as + * possible type annotations). + * Implementations can change ordering any way they like. + * + * Properties <code>List</code> passed as argument is modifiable, and returned List must + * likewise be modifiable as it may be passed to multiple registered + * modifiers. + */ + public List<BeanPropertyWriter> orderProperties(SerializationConfig config, + BasicBeanDescription beanDesc, List<BeanPropertyWriter> beanProperties) { + return beanProperties; + } + + /** + * Method called by {@link BeanSerializerFactory} after collecting all information + * regarding POJO to serialize and updating builder with it, but before constructing + * serializer. + * Implementations may choose to modify state of builder (to affect serializer being + * built), or even completely replace it (if they want to build different kind of + * serializer). Typically, however, passed-in builder is returned, possibly with + * some modifications. + */ + public BeanSerializerBuilder updateBuilder(SerializationConfig config, + BasicBeanDescription beanDesc, BeanSerializerBuilder builder) { + return builder; + } + + /** + * Method called by {@link BeanSerializerFactory} after constructing default + * bean serializer instance with properties collected and ordered earlier. + * Implementations can modify or replace given serializer and return serializer + * to use. Note that although initial serializer being passed is of type + * {@link BeanSerializer}, modifiers may return serializers of other types; + * and this is why implementations must check for type before casting. + */ + public JsonSerializer<?> modifySerializer(SerializationConfig config, + BasicBeanDescription beanDesc, JsonSerializer<?> serializer) { + return serializer; + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/ContainerSerializers.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/ContainerSerializers.java new file mode 100644 index 0000000..8f13ff7 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/ContainerSerializers.java
@@ -0,0 +1,8 @@ +package org.codehaus.jackson.map.ser; + +/** + * @deprecated Since 1.9 use {@link org.codehaus.jackson.map.ser.std.StdContainerSerializers} instead + */ +@Deprecated +public class ContainerSerializers + extends org.codehaus.jackson.map.ser.std.StdContainerSerializers { }
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/CustomSerializerFactory.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/CustomSerializerFactory.java new file mode 100644 index 0000000..0e3762c --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/CustomSerializerFactory.java
@@ -0,0 +1,293 @@ +package org.codehaus.jackson.map.ser; + +import java.lang.reflect.Modifier; +import java.util.*; + +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.type.ClassKey; +import org.codehaus.jackson.type.JavaType; + +/** + * Serializer factory implementation that allows for configuring + * mapping between types (classes) and serializers to use, by using + * multiple types of overrides. Existing mappings established by + * {@link BeanSerializerFactory} (and its super class, + * {@link BasicSerializerFactory}) are used if no overrides are + * defined. + *<p> + * Unlike base serializer factories ({@link BasicSerializerFactory}, + * {@link BeanSerializerFactory}), this factory is stateful because + * of configuration settings. It is thread-safe, however, as long as + * all configuration as done before using the factory -- a single + * instance can be shared between providers and mappers. + *<p> + * Configurations currently available are: + *<ul> + * <li>Ability to define explicit mappings between classes and interfaces + * and serializers to use. These can be either specific ones (class must + * match exactly) or generic ones (any sub-class or class implementing + * the interface); specific ones have precedence over generic ones (and + * precedence between generic ones is not defined). + * </li> + * <li>Ability to define a single generic base serializer for all Enum + * types (precedence below specific serializer mapping) + * </li> + *</ul> + *<p> + * Note: as of version 1.7, this class is not as useful as it used to + * be, due to addition of "modules", which allow simpler addition + * of custom serializers and deserializers. In fact, use of module system + * is recommended even when not exposing serializers or deserializers + * as a pluggable library (just using them locally). + */ +public class CustomSerializerFactory + extends BeanSerializerFactory +{ + /* + /********************************************************** + /* Configuration, direct/special mappings + /********************************************************** + */ + + /** + * Direct mappings that are only used for exact class type + * matches, but not for sub-class checks. + */ + protected HashMap<ClassKey,JsonSerializer<?>> _directClassMappings = null; + + /** + * And for Enum handling we may specify a single default + * serializer to use, regardless of actual enumeration. + * Usually used to provide "toString - serializer". + */ + protected JsonSerializer<?> _enumSerializerOverride; + + /* + /********************************************************** + /* Configuration, generic (interface, super-class) mappings + /********************************************************** + */ + + /** + * And then class-based mappings that are used both for exact and + * sub-class matches. + */ + protected HashMap<ClassKey,JsonSerializer<?>> _transitiveClassMappings = null; + + /** + * And finally interface-based matches. + */ + protected HashMap<ClassKey,JsonSerializer<?>> _interfaceMappings = null; + + /* + /********************************************************** + /* Life-cycle, constructors + /********************************************************** + */ + + public CustomSerializerFactory() { + this(null); + } + + public CustomSerializerFactory(Config config) { + super(config); + } + + @Override + public SerializerFactory withConfig(Config config) + { + /* 22-Nov-2010, tatu: As with BeanSerializerFactory, must ensure type won't change + * with this method, so: + */ + if (getClass() != CustomSerializerFactory.class) { + throw new IllegalStateException("Subtype of CustomSerializerFactory ("+getClass().getName() + +") has not properly overridden method 'withAdditionalSerializers': can not instantiate subtype with " + +"additional serializer definitions"); + } + return new CustomSerializerFactory(config); + } + + /* + /********************************************************** + /* Configuration: type-to-serializer mappings + /********************************************************** + */ + + /** + * Method used to add a generic (transitive) mapping from specified + * class or its sub-classes into a serializer. + * When resolving a type into a serializer, explicit class is checked + * first, then immediate super-class, and so forth along inheritance + * chain. But if this fails, implemented interfaces are checked; + * ordering is done such that first interfaces implemented by + * the exact type are checked (in order returned by + * {@link Class#getInterfaces}), then super-type's and so forth. + *<p> + * Note that adding generic mappings may lead to problems with + * sub-classing: if sub-classes add new properties, these may not + * get properly serialized. + * + * @param type Class for which specified serializer is to be + * used. May be more specific type than what serializer indicates, + * but must be compatible (same or sub-class) + */ + public <T> void addGenericMapping(Class<? extends T> type, JsonSerializer<T> ser) + { + // Interface to match? + ClassKey key = new ClassKey(type); + if (type.isInterface()) { + if (_interfaceMappings == null) { + _interfaceMappings = new HashMap<ClassKey,JsonSerializer<?>>(); + } + _interfaceMappings.put(key, ser); + } else { // nope, class: + if (_transitiveClassMappings == null) { + _transitiveClassMappings = new HashMap<ClassKey,JsonSerializer<?>>(); + } + _transitiveClassMappings.put(key, ser); + } + } + + /** + * Method used to add a mapping from specific type -- and only that + * type -- to specified serializer. This means that binding is not + * used for sub-types. It also means that no such mappings are to + * be defined for abstract classes or interfaces: and if an attempt + * is made, {@link IllegalArgumentException} will be thrown to + * indicate caller error. + * + * @param forClass Class for which specified serializer is to be + * used. May be more specific type than what serializer indicates, + * but must be compatible (same or sub-class) + */ + public <T> void addSpecificMapping(Class<? extends T> forClass, JsonSerializer<T> ser) + { + ClassKey key = new ClassKey(forClass); + + /* First, let's ensure it's not an interface or abstract class: + * as those can not be instantiated, such mappings would never + * get used. + */ + if (forClass.isInterface()) { + throw new IllegalArgumentException("Can not add specific mapping for an interface ("+forClass.getName()+")"); + } + if (Modifier.isAbstract(forClass.getModifiers())) { + throw new IllegalArgumentException("Can not add specific mapping for an abstract class ("+forClass.getName()+")"); + } + + if (_directClassMappings == null) { + _directClassMappings = new HashMap<ClassKey,JsonSerializer<?>>(); + } + _directClassMappings.put(key, ser); + } + + /** + * Method that can be used to force specified serializer to be used for + * serializing all Enum instances. This is most commonly used to specify + * serializers that call either <code>enum.toString()</code>, or modify + * value returned by <code>enum.name()</code> (such as upper- or + * lower-casing it). + *<p> + * Note: this serializer has lower precedence than that of specific + * types; so if a specific serializer is assigned to an Enum type, + * this serializer will NOT be used. It has higher precedence than + * generic mappings have however. + */ + public void setEnumSerializer(JsonSerializer<?> enumSer) + { + _enumSerializerOverride = enumSer; + } + + /* + /********************************************************** + /* JsonSerializerFactory impl + /********************************************************** + */ + + @Override + @SuppressWarnings("unchecked") + public JsonSerializer<Object> createSerializer(SerializationConfig config, JavaType type, + BeanProperty property) + throws JsonMappingException + { + JsonSerializer<?> ser = findCustomSerializer(type.getRawClass(), config); + if (ser != null) { + return (JsonSerializer<Object>) ser; + } + return super.createSerializer(config, type, property); + } + + /* + /********************************************************** + /* Internal methods + /********************************************************** + */ + + protected JsonSerializer<?> findCustomSerializer(Class<?> type, SerializationConfig config) + { + JsonSerializer<?> ser = null; + ClassKey key = new ClassKey(type); + + // First: exact matches + if (_directClassMappings != null) { + ser = _directClassMappings.get(key); + if (ser != null) { + return ser; + } + } + + // No match? Perhaps we can use the enum serializer? + if (type.isEnum()) { + if (_enumSerializerOverride != null) { + return _enumSerializerOverride; + } + } + + // Still no match? How about more generic ones? + // Mappings for super-classes? + if (_transitiveClassMappings != null) { + for (Class<?> curr = type; (curr != null); curr = curr.getSuperclass()) { + key.reset(curr); + ser = _transitiveClassMappings.get(key); + if (ser != null) { + return ser; + } + } + } + + // And if still no match, how about interfaces? + if (_interfaceMappings != null) { + // as per [JACKSON-327], better check actual interface first too... + key.reset(type); + ser = _interfaceMappings.get(key); + if (ser != null) { + return ser; + } + for (Class<?> curr = type; (curr != null); curr = curr.getSuperclass()) { + ser = _findInterfaceMapping(curr, key); + if (ser != null) { + return ser; + } + } + } + return null; + } + + protected JsonSerializer<?> _findInterfaceMapping(Class<?> cls, ClassKey key) + { + for (Class<?> iface : cls.getInterfaces()) { + key.reset(iface); + JsonSerializer<?> ser = _interfaceMappings.get(key); + if (ser != null) { + return ser; + } + // [JACKSON-373] need to also check super-interfaces + ser = _findInterfaceMapping(iface, key); + if (ser != null) { + return ser; + } + } + return null; + } +} +
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/EnumSerializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/EnumSerializer.java new file mode 100644 index 0000000..d868f12 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/EnumSerializer.java
@@ -0,0 +1,17 @@ +package org.codehaus.jackson.map.ser; + +import org.codehaus.jackson.map.annotate.JacksonStdImpl; +import org.codehaus.jackson.map.util.EnumValues; + +/** + * @deprecated Since 1.9 use {@link org.codehaus.jackson.map.ser.std.EnumSerializer} + */ +@Deprecated +@JacksonStdImpl +public class EnumSerializer + extends org.codehaus.jackson.map.ser.std.EnumSerializer +{ + public EnumSerializer(EnumValues v) { + super(v); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/FilterProvider.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/FilterProvider.java new file mode 100644 index 0000000..03417c2 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/FilterProvider.java
@@ -0,0 +1,23 @@ +package org.codehaus.jackson.map.ser; + +/** + * Interface for objects that providers instances of {@link BeanPropertyFilter} + * that match given ids. A provider is configured to be used during serialization, + * to find filter to used based on id specified by {@link org.codehaus.jackson.map.annotate.JsonFilter} + * annotation on bean class. + * + * @since 1.7 + */ +public abstract class FilterProvider +{ + /** + * Lookup method used to find {@link BeanPropertyFilter} that has specified id. + * Note that id is typically a {@link java.lang.String}, but is not necessarily + * limited to that; that is, while standard components use String, custom + * implementation can choose other kinds of keys. + * + * @return Filter registered with specified id, if one defined; null if + * none found. + */ + public abstract BeanPropertyFilter findFilter(Object filterId); +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/FilteredBeanPropertyWriter.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/FilteredBeanPropertyWriter.java new file mode 100644 index 0000000..db474d2 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/FilteredBeanPropertyWriter.java
@@ -0,0 +1,96 @@ +package org.codehaus.jackson.map.ser; + +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.map.JsonSerializer; +import org.codehaus.jackson.map.SerializerProvider; + +/** + * Decorated {@link BeanPropertyWriter} that will filter out + * properties that are not to be included in currently active + * JsonView. + * + * @since 1.4 + */ +public abstract class FilteredBeanPropertyWriter +{ + public static BeanPropertyWriter constructViewBased(BeanPropertyWriter base, Class<?>[] viewsToIncludeIn) + { + if (viewsToIncludeIn.length == 1) { + return new SingleView(base, viewsToIncludeIn[0]); + } + return new MultiView(base, viewsToIncludeIn); + } + + /* + /********************************************************** + /* Concrete sub-classes + /********************************************************** + */ + + private final static class SingleView + extends BeanPropertyWriter + { + protected final BeanPropertyWriter _delegate; + + protected final Class<?> _view; + + protected SingleView(BeanPropertyWriter delegate, Class<?> view) + { + super(delegate); + _delegate = delegate; + _view = view; + } + + @Override + public BeanPropertyWriter withSerializer(JsonSerializer<Object> ser) { + return new SingleView(_delegate.withSerializer(ser), _view); + } + + @Override + public void serializeAsField(Object bean, JsonGenerator jgen, SerializerProvider prov) + throws Exception + { + Class<?> activeView = prov.getSerializationView(); + if (activeView == null || _view.isAssignableFrom(activeView)) { + _delegate.serializeAsField(bean, jgen, prov); + } + } + } + + private final static class MultiView + extends BeanPropertyWriter + { + protected final BeanPropertyWriter _delegate; + + protected final Class<?>[] _views; + + protected MultiView(BeanPropertyWriter delegate, Class<?>[] views) { + super(delegate); + _delegate = delegate; + _views = views; + } + + @Override + public BeanPropertyWriter withSerializer(JsonSerializer<Object> ser) { + return new MultiView(_delegate.withSerializer(ser), _views); + } + + @Override + public void serializeAsField(Object bean, JsonGenerator jgen, SerializerProvider prov) + throws Exception + { + final Class<?> activeView = prov.getSerializationView(); + if (activeView != null) { + int i = 0, len = _views.length; + for (; i < len; ++i) { + if (_views[i].isAssignableFrom(activeView)) break; + } + // not included, bail out: + if (i == len) { + return; + } + } + _delegate.serializeAsField(bean, jgen, prov); + } + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/JdkSerializers.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/JdkSerializers.java new file mode 100644 index 0000000..9b79a98 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/JdkSerializers.java
@@ -0,0 +1,11 @@ +package org.codehaus.jackson.map.ser; + +/** + * @deprecated Since 1.9 use {@link org.codehaus.jackson.map.ser.std.StdJdkSerializers} + */ +@Deprecated +public class JdkSerializers + extends org.codehaus.jackson.map.ser.std.StdJdkSerializers +{ + +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/MapSerializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/MapSerializer.java new file mode 100644 index 0000000..67c0baf --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/MapSerializer.java
@@ -0,0 +1,58 @@ +package org.codehaus.jackson.map.ser; + +import java.util.HashSet; + +import org.codehaus.jackson.map.BeanProperty; +import org.codehaus.jackson.map.JsonSerializer; +import org.codehaus.jackson.map.TypeSerializer; +import org.codehaus.jackson.map.annotate.JacksonStdImpl; +import org.codehaus.jackson.type.JavaType; + +/** + * @deprecated Since 1.9 use {@link org.codehaus.jackson.map.ser.std.MapSerializer} + */ +@Deprecated +@JacksonStdImpl +public class MapSerializer + extends org.codehaus.jackson.map.ser.std.MapSerializer +{ + protected MapSerializer() { + this((HashSet<String>)null, null, null, false, null, null, null, null); + } + + /** + * Legacy constructor (as of 1.7) + * + * @deprecated Use variant that takes Key type and property information + */ + @Deprecated + protected MapSerializer(HashSet<String> ignoredEntries, + JavaType valueType, boolean valueTypeIsStatic, + TypeSerializer vts) + { + super(ignoredEntries, UNSPECIFIED_TYPE, valueType, valueTypeIsStatic, vts, null, null, null); + } + + /** + * Legacy constructor (as of 1.8) + * + * @deprecated As of 1.8, use version that takes valueSerializer + */ + @Deprecated + protected MapSerializer(HashSet<String> ignoredEntries, + JavaType keyType, JavaType valueType, boolean valueTypeIsStatic, + TypeSerializer vts, JsonSerializer<Object> keySerializer, BeanProperty property) + { + super(ignoredEntries, keyType, valueType, valueTypeIsStatic, vts, keySerializer, null, property); + } + + protected MapSerializer(HashSet<String> ignoredEntries, + JavaType keyType, JavaType valueType, boolean valueTypeIsStatic, + TypeSerializer vts, + JsonSerializer<Object> keySerializer, JsonSerializer<Object> valueSerializer, + BeanProperty property) + { + super(ignoredEntries, keyType, valueType, valueTypeIsStatic, + vts, keySerializer, valueSerializer, property); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/PropertyBuilder.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/PropertyBuilder.java new file mode 100644 index 0000000..a1ff0f0 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/PropertyBuilder.java
@@ -0,0 +1,372 @@ +package org.codehaus.jackson.map.ser; + +import java.lang.reflect.Array; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.Collection; +import java.util.Map; + +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.JsonSerialize; +import org.codehaus.jackson.map.annotate.JsonSerialize.Inclusion; +import org.codehaus.jackson.map.introspect.*; +import org.codehaus.jackson.map.util.*; +import org.codehaus.jackson.type.JavaType; + +/** + * Helper class for {@link BeanSerializerFactory} that is used to + * construct {@link BeanPropertyWriter} instances. Can be sub-classed + * to change behavior. + */ +public class PropertyBuilder +{ + final protected SerializationConfig _config; + final protected BasicBeanDescription _beanDesc; + final protected JsonSerialize.Inclusion _outputProps; + + final protected AnnotationIntrospector _annotationIntrospector; + + /** + * If a property has serialization inclusion value of + * {@link Inclusion#ALWAYS}, we need to know the default + * value of the bean, to know if property value equals default + * one. + */ + protected Object _defaultBean; + + public PropertyBuilder(SerializationConfig config, BasicBeanDescription beanDesc) + { + _config = config; + _beanDesc = beanDesc; + _outputProps = beanDesc.findSerializationInclusion(config.getSerializationInclusion()); + _annotationIntrospector = _config.getAnnotationIntrospector(); + } + + /* + /********************************************************** + /* Public API + /********************************************************** + */ + + public Annotations getClassAnnotations() { + return _beanDesc.getClassAnnotations(); + } + + /** + * @param contentTypeSer Optional explicit type information serializer + * to use for contained values (only used for properties that are + * of container type) + */ + protected BeanPropertyWriter buildWriter(String name, JavaType declaredType, + JsonSerializer<Object> ser, + TypeSerializer typeSer, TypeSerializer contentTypeSer, + AnnotatedMember am, boolean defaultUseStaticTyping) + { + Field f; + Method m; + if (am instanceof AnnotatedField) { + m = null; + f = ((AnnotatedField) am).getAnnotated(); + } else { + m = ((AnnotatedMethod) am).getAnnotated(); + f = null; + } + + // do we have annotation that forces type to use (to declared type or its super type)? + JavaType serializationType = findSerializationType(am, defaultUseStaticTyping, declaredType); + + // Container types can have separate type serializers for content (value / element) type + if (contentTypeSer != null) { + /* 04-Feb-2010, tatu: Let's force static typing for collection, if there is + * type information for contents. Should work well (for JAXB case); can be + * revisited if this causes problems. + */ + if (serializationType == null) { +// serializationType = TypeFactory.type(am.getGenericType(), _beanDesc.getType()); + serializationType = declaredType; + } + JavaType ct = serializationType.getContentType(); + /* 03-Sep-2010, tatu: This is somehow related to [JACKSON-356], but I don't completely + * yet understand how pieces fit together. Still, better be explicit than rely on + * NPE to indicate an issue... + */ + if (ct == null) { + throw new IllegalStateException("Problem trying to create BeanPropertyWriter for property '" + +name+"' (of type "+_beanDesc.getType()+"); serialization type "+serializationType+" has no content"); + } + serializationType = serializationType.withContentTypeHandler(contentTypeSer); + ct = serializationType.getContentType(); + } + + Object valueToSuppress = null; + boolean suppressNulls = false; + + JsonSerialize.Inclusion methodProps = _annotationIntrospector.findSerializationInclusion(am, _outputProps); + + if (methodProps != null) { + switch (methodProps) { + case NON_DEFAULT: + valueToSuppress = getDefaultValue(name, m, f); + if (valueToSuppress == null) { + suppressNulls = true; + } else { + // [JACKSON-531]: Allow comparison of arrays too... + if (valueToSuppress.getClass().isArray()) { + valueToSuppress = Comparators.getArrayComparator(valueToSuppress); + } + } + break; + case NON_EMPTY: + // always suppress nulls + suppressNulls = true; + // but possibly also 'empty' values: + valueToSuppress = getEmptyValueChecker(name, declaredType); + break; + case NON_NULL: + suppressNulls = true; + // fall through + case ALWAYS: // default + // we may still want to suppress empty collections, as per [JACKSON-254]: + if (declaredType.isContainerType()) { + valueToSuppress = getContainerValueChecker(name, declaredType); + } + break; + } + } + + BeanPropertyWriter bpw = new BeanPropertyWriter(am, _beanDesc.getClassAnnotations(), name, declaredType, + ser, typeSer, serializationType, m, f, suppressNulls, valueToSuppress); + + // [JACKSON-132]: Unwrapping + Boolean unwrapped = _annotationIntrospector.shouldUnwrapProperty(am); + if (unwrapped != null && unwrapped.booleanValue()) { + bpw = bpw.unwrappingWriter(); + } + return bpw; + } + + /* + /********************************************************** + /* Helper methods; annotation access + /********************************************************** + */ + + /** + * Method that will try to determine statically defined type of property + * being serialized, based on annotations (for overrides), and alternatively + * declared type (if static typing for serialization is enabled). + * If neither can be used (no annotations, dynamic typing), returns null. + */ + protected JavaType findSerializationType(Annotated a, boolean useStaticTyping, JavaType declaredType) + { + // [JACKSON-120]: Check to see if serialization type is fixed + Class<?> serClass = _annotationIntrospector.findSerializationType(a); + if (serClass != null) { + // Must be a super type to be usable + Class<?> rawDeclared = declaredType.getRawClass(); + if (serClass.isAssignableFrom(rawDeclared)) { + declaredType = declaredType.widenBy(serClass); + } else { + /* 18-Nov-2010, tatu: Related to fixing [JACKSON-416], an issue with such + * check is that for deserialization more specific type makes sense; + * and for serialization more generic. But alas JAXB uses but a single + * annotation to do both... Hence, we must just discard type, as long as + * types are related + */ + if (!rawDeclared.isAssignableFrom(serClass)) { + throw new IllegalArgumentException("Illegal concrete-type annotation for method '"+a.getName()+"': class "+serClass.getName()+" not a super-type of (declared) class "+rawDeclared.getName()); + } + /* 03-Dec-2010, tatu: Actually, ugh, to resolve [JACKSON-415] may further relax this + * and actually accept subtypes too for serialization. Bit dangerous in theory + * but need to trust user here... + */ + declaredType = _config.constructSpecializedType(declaredType, serClass); + } + useStaticTyping = true; + } + + JavaType secondary = BeanSerializerFactory.modifySecondaryTypesByAnnotation(_config, a, declaredType); + if (secondary != declaredType) { + useStaticTyping = true; + declaredType = secondary; + } + + /* [JACKSON-114]: if using static typing, declared type is known + * to be the type... + */ + if (!useStaticTyping) { + JsonSerialize.Typing typing = _annotationIntrospector.findSerializationTyping(a); + if (typing != null) { + useStaticTyping = (typing == JsonSerialize.Typing.STATIC); + } + } + return useStaticTyping ? declaredType : null; + } + + /* + /********************************************************** + /* Helper methods for default value handling + /********************************************************** + */ + + protected Object getDefaultBean() + { + if (_defaultBean == null) { + /* If we can fix access rights, we should; otherwise non-public + * classes or default constructor will prevent instantiation + */ + _defaultBean = _beanDesc.instantiateBean(_config.isEnabled(SerializationConfig.Feature.CAN_OVERRIDE_ACCESS_MODIFIERS)); + if (_defaultBean == null) { + Class<?> cls = _beanDesc.getClassInfo().getAnnotated(); + throw new IllegalArgumentException("Class "+cls.getName()+" has no default constructor; can not instantiate default bean value to support 'properties=JsonSerialize.Inclusion.NON_DEFAULT' annotation"); + } + } + return _defaultBean; + } + + protected Object getDefaultValue(String name, Method m, Field f) + { + Object defaultBean = getDefaultBean(); + try { + if (m != null) { + return m.invoke(defaultBean); + } + return f.get(defaultBean); + } catch (Exception e) { + return _throwWrapped(e, name, defaultBean); + } + } + + /** + * Helper method called to see if we need a comparator Object to check if values + * of a container (Collection, array) property should be suppressed. + * This is usually + * + * @param propertyName Name of property to handle + * @param propertyType Declared type of values of the property to handle + * @return Object whose <code>equals()</code> method is called to check if given value + * is "empty Collection" value to suppress; or null if no such check should be done + * (declared type not Collection or array) + * + * @since 1.9 + */ + protected Object getContainerValueChecker(String propertyName, JavaType propertyType) + { + // currently we will only check for certain kinds of empty containers: + if (!_config.isEnabled(SerializationConfig.Feature.WRITE_EMPTY_JSON_ARRAYS)) { + if (propertyType.isArrayType()) { + return new EmptyArrayChecker(); + } + if (Collection.class.isAssignableFrom(propertyType.getRawClass())) { + return new EmptyCollectionChecker(); + } + } + return null; + } + + + /** + * Helper method called to see if we need a comparator Object to check if values + * of specified type are consider empty. + * If type has such concept, will build a comparator; otherwise return null, and + * in latter case, only null values are considered 'empty'. + * + * @param propertyName Name of property to handle + * @param propertyType Declared type of values of the property to handle + * @return Object whose <code>equals()</code> method is called to check if given value + * is "empty Collection" value to suppress; or null if no such check should be done + * (declared type not Collection or array) + * + * @since 1.9 + */ + protected Object getEmptyValueChecker(String propertyName, JavaType propertyType) + { + Class<?> rawType = propertyType.getRawClass(); + if (rawType == String.class) { + return new EmptyStringChecker(); + } + if (propertyType.isArrayType()) { + return new EmptyArrayChecker(); + } + if (Collection.class.isAssignableFrom(rawType)) { + return new EmptyCollectionChecker(); + } + if (Map.class.isAssignableFrom(rawType)) { + return new EmptyMapChecker(); + } + return null; + } + + /* + /********************************************************** + /* Helper methods for exception handling + /********************************************************** + */ + + protected Object _throwWrapped(Exception e, String propName, Object defaultBean) + { + Throwable t = e; + while (t.getCause() != null) { + t = t.getCause(); + } + if (t instanceof Error) throw (Error) t; + if (t instanceof RuntimeException) throw (RuntimeException) t; + throw new IllegalArgumentException("Failed to get property '"+propName+"' of default "+defaultBean.getClass().getName()+" instance"); + } + + /* + /********************************************************** + /* Helper classes + /********************************************************** + */ + + /** + * Helper object used to check if given Collection object is null or empty + * + * @since 1.9 + */ + public static class EmptyCollectionChecker + { + @Override public boolean equals(Object other) { + return (other == null) || ((Collection<?>) other).size() == 0; + } + } + + /** + * Helper object used to check if given Map object is null or empty + * + * @since 1.9 + */ + public static class EmptyMapChecker + { + @Override public boolean equals(Object other) { + return (other == null) || ((Map<?,?>) other).size() == 0; + } + } + + /** + * Helper object used to check if given array object is null or empty + * + * @since 1.9 + */ + public static class EmptyArrayChecker + { + @Override + public boolean equals(Object other) { + return (other == null) || Array.getLength(other) == 0; + } + } + + /** + * Helper object used to check if given String object is null or empty + * + * @since 1.9 + */ + public static class EmptyStringChecker + { + @Override + public boolean equals(Object other) { + return (other == null) || ((String) other).length() == 0; + } + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/ScalarSerializerBase.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/ScalarSerializerBase.java new file mode 100644 index 0000000..4ae9955 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/ScalarSerializerBase.java
@@ -0,0 +1,18 @@ +package org.codehaus.jackson.map.ser; + +/** + * @deprecated Since 1.9 use {@link org.codehaus.jackson.map.ser.std.SerializerBase} instead. + */ +@Deprecated +public abstract class ScalarSerializerBase<T> + extends org.codehaus.jackson.map.ser.std.SerializerBase<T> +{ + protected ScalarSerializerBase(Class<T> t) { + super(t); + } + + @SuppressWarnings("unchecked") + protected ScalarSerializerBase(Class<?> t, boolean dummy) { + super((Class<T>) t); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/SerializerBase.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/SerializerBase.java new file mode 100644 index 0000000..d67ff21 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/SerializerBase.java
@@ -0,0 +1,23 @@ +package org.codehaus.jackson.map.ser; + +import org.codehaus.jackson.type.JavaType; + +/** + * @deprecated Since 1.9 use {@link org.codehaus.jackson.map.ser.std.SerializerBase} + */ +@Deprecated +public abstract class SerializerBase<T> + extends org.codehaus.jackson.map.ser.std.SerializerBase<T> +{ + protected SerializerBase(Class<T> t) { + super(t); + } + + protected SerializerBase(JavaType type) { + super(type); + } + + protected SerializerBase(Class<?> t, boolean dummy) { + super(t, dummy); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/StdKeySerializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/StdKeySerializer.java new file mode 100644 index 0000000..d69bbda --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/StdKeySerializer.java
@@ -0,0 +1,11 @@ +package org.codehaus.jackson.map.ser; + +/** + * @deprecated Since 1.9 use {@link org.codehaus.jackson.map.ser.std.StdKeySerializer} instead + */ +@Deprecated +public final class StdKeySerializer + extends org.codehaus.jackson.map.ser.std.StdKeySerializer +{ + final static StdKeySerializer instace = new StdKeySerializer(); +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/StdSerializerProvider.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/StdSerializerProvider.java new file mode 100644 index 0000000..df67f13 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/StdSerializerProvider.java
@@ -0,0 +1,852 @@ +package org.codehaus.jackson.map.ser; + +import java.io.IOException; +import java.text.DateFormat; +import java.util.Date; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.ser.impl.FailingSerializer; +import org.codehaus.jackson.map.ser.impl.ReadOnlyClassToSerializerMap; +import org.codehaus.jackson.map.ser.impl.SerializerCache; +import org.codehaus.jackson.map.ser.impl.UnknownSerializer; +import org.codehaus.jackson.map.ser.std.NullSerializer; +import org.codehaus.jackson.map.ser.std.StdKeySerializer; +import org.codehaus.jackson.map.ser.std.StdKeySerializers; +import org.codehaus.jackson.map.util.ClassUtil; +import org.codehaus.jackson.map.util.RootNameLookup; +import org.codehaus.jackson.node.ObjectNode; +import org.codehaus.jackson.schema.JsonSchema; +import org.codehaus.jackson.schema.SchemaAware; +import org.codehaus.jackson.type.JavaType; + +import org.codehaus.jackson.map.*; + +/** + * Default {@link SerializerProvider} implementation. Handles + * caching aspects of serializer handling; all construction details + * are delegated to {@link SerializerFactory} instance. + *<p> + * One note about implementation: the main instance constructed will + * be so-called "blueprint" object, and will NOT be used during actual + * serialization. Rather, an "instance" instance is created so that + * state can be carried along, as well as to avoid synchronization + * during serializer access. Because of this, if sub-classing, one + * must override method {@link #createInstance}: if this is not done, + * an exception will get thrown as base class verifies that the + * instance has same class as the blueprint + * (<code>instance.getClass() == blueprint.getClass()</code>). + * Check is done to prevent weird bugs that would otherwise occur. + *<p> + * Starting with version 1.5, provider is also responsible for + * some parts of type serialization; specifically for locating + * proper type serializers to use for types. + */ +public class StdSerializerProvider + extends SerializerProvider +{ + /** + * Setting for determining whether mappings for "unknown classes" should be + * cached for faster resolution. Usually this isn't needed, but maybe it + * is in some cases? + */ + final static boolean CACHE_UNKNOWN_MAPPINGS = false; + + public final static JsonSerializer<Object> DEFAULT_NULL_KEY_SERIALIZER = + new FailingSerializer("Null key for a Map not allowed in JSON (use a converting NullKeySerializer?)"); + + /** + * @deprecated Since 1.9, use {@link StdKeySerializers} instead + */ + @Deprecated + public final static JsonSerializer<Object> DEFAULT_KEY_SERIALIZER = new StdKeySerializer(); + + public final static JsonSerializer<Object> DEFAULT_UNKNOWN_SERIALIZER = new UnknownSerializer(); + + /* + /********************************************************** + /* Configuration, factories + /********************************************************** + */ + + final protected SerializerFactory _serializerFactory; + + /** + * Cache for doing type-to-value-serializer lookups. + */ + final protected SerializerCache _serializerCache; + + /** + * Helper object for keeping track of introspected root names + */ + final protected RootNameLookup _rootNames; + + /* + /********************************************************** + /* Configuration, specialized serializers + /********************************************************** + */ + + /** + * Serializer that gets called for values of types for which no + * serializers can be constructed. + *<p> + * The default serializer will simply thrown an exception; a possible + * alternative that can be used would be + * {@link ToStringSerializer}. + */ + protected JsonSerializer<Object> _unknownTypeSerializer = DEFAULT_UNKNOWN_SERIALIZER; + + /** + * Serializer used to output non-null keys of Maps (which will get + * output as JSON Objects), if not null; if null, us the standard + * default key serializer. + */ + protected JsonSerializer<Object> _keySerializer; + + /** + * Serializer used to output a null value. Default implementation + * writes nulls using {@link JsonGenerator#writeNull}. + */ + protected JsonSerializer<Object> _nullValueSerializer = NullSerializer.instance; + + /** + * Serializer used to (try to) output a null key, due to an entry of + * {@link java.util.Map} having null key. + * The default implementation will throw an exception if this happens; + * alternative implementation (like one that would write an Empty String) + * can be defined. + */ + protected JsonSerializer<Object> _nullKeySerializer = DEFAULT_NULL_KEY_SERIALIZER; + + /* + /********************************************************** + /* State, for non-blueprint instances + /********************************************************** + */ + + /** + * For fast lookups, we will have a local non-shared read-only + * map that contains serializers previously fetched. + */ + protected final ReadOnlyClassToSerializerMap _knownSerializers; + + /** + * Lazily acquired and instantiated formatter object: initialized + * first time it is needed, reused afterwards. Used via instances + * (not blueprints), so that access need not be thread-safe. + */ + protected DateFormat _dateFormat; + + /* + /********************************************************** + /* Life-cycle + /********************************************************** + */ + + /** + * Constructor for creating master (or "blue-print") provider object, + * which is only used as the template for constructing per-binding + * instances. + */ + public StdSerializerProvider() + { + super(null); + _serializerFactory = null; + _serializerCache = new SerializerCache(); + // Blueprints doesn't have access to any serializers... + _knownSerializers = null; + _rootNames = new RootNameLookup(); + } + + /** + * "Copy-constructor", used from {@link #createInstance} (or by + * sub-classes) + * + * @param src Blueprint object used as the baseline for this instance + */ + protected StdSerializerProvider(SerializationConfig config, + StdSerializerProvider src, SerializerFactory f) + { + super(config); + if (config == null) { + throw new NullPointerException(); + } + _serializerFactory = f; + + _serializerCache = src._serializerCache; + _unknownTypeSerializer = src._unknownTypeSerializer; + _keySerializer = src._keySerializer; + _nullValueSerializer = src._nullValueSerializer; + _nullKeySerializer = src._nullKeySerializer; + _rootNames = src._rootNames; + + /* Non-blueprint instances do have a read-only map; one that doesn't + * need synchronization for lookups. + */ + _knownSerializers = _serializerCache.getReadOnlyLookupMap(); + } + + /** + * Overridable method, used to create a non-blueprint instances from the blueprint. + * This is needed to retain state during serialization. + */ + protected StdSerializerProvider createInstance(SerializationConfig config, SerializerFactory jsf) + { + return new StdSerializerProvider(config, this, jsf); + } + + /* + /********************************************************** + /* Configuration methods + /********************************************************** + */ + + @Override + public void setDefaultKeySerializer(JsonSerializer<Object> ks) + { + if (ks == null) { + throw new IllegalArgumentException("Can not pass null JsonSerializer"); + } + _keySerializer = ks; + } + + @Override + public void setNullValueSerializer(JsonSerializer<Object> nvs) + { + if (nvs == null) { + throw new IllegalArgumentException("Can not pass null JsonSerializer"); + } + _nullValueSerializer = nvs; + } + + @Override + public void setNullKeySerializer(JsonSerializer<Object> nks) + { + if (nks == null) { + throw new IllegalArgumentException("Can not pass null JsonSerializer"); + } + _nullKeySerializer = nks; + } + + /* + /********************************************************** + /* Methods to be called by ObjectMapper + /********************************************************** + */ + + @Override + public final void serializeValue(SerializationConfig config, + JsonGenerator jgen, Object value, SerializerFactory jsf) + throws IOException, JsonGenerationException + { + if (jsf == null) { + throw new IllegalArgumentException("Can not pass null serializerFactory"); + } + + /* First: we need a separate instance, which will hold a copy of the + * non-shared ("local") read-only lookup Map for fast + * class-to-serializer lookup + */ + StdSerializerProvider inst = createInstance(config, jsf); + // sanity check to avoid weird errors; to ensure sub-classes do override createInstance + if (inst.getClass() != getClass()) { + throw new IllegalStateException("Broken serializer provider: createInstance returned instance of type "+inst.getClass()+"; blueprint of type "+getClass()); + } + // And then we can do actual serialization, through the instance + inst._serializeValue(jgen, value); + } + + @Override + public final void serializeValue(SerializationConfig config, JsonGenerator jgen, + Object value, JavaType rootType, SerializerFactory jsf) + throws IOException, JsonGenerationException + { + if (jsf == null) { + throw new IllegalArgumentException("Can not pass null serializerFactory"); + } + StdSerializerProvider inst = createInstance(config, jsf); + if (inst.getClass() != getClass()) { + throw new IllegalStateException("Broken serializer provider: createInstance returned instance of type "+inst.getClass()+"; blueprint of type "+getClass()); + } + inst._serializeValue(jgen, value, rootType); + } + + @Override + public JsonSchema generateJsonSchema(Class<?> type, SerializationConfig config, SerializerFactory jsf) + throws JsonMappingException + { + if (type == null) { + throw new IllegalArgumentException("A class must be provided"); + } + + /* First: we need a separate instance, which will hold a copy of the + * non-shared ("local") read-only lookup Map for fast + * class-to-serializer lookup + */ + StdSerializerProvider inst = createInstance(config, jsf); + // sanity check to avoid weird errors; to ensure sub-classes do override createInstance + if (inst.getClass() != getClass()) { + throw new IllegalStateException("Broken serializer provider: createInstance returned instance of type "+inst.getClass()+"; blueprint of type "+getClass()); + } + /* no need for embedded type information for JSON schema generation (all + * type information it needs is accessible via "untyped" serializer) + */ + JsonSerializer<Object> ser = inst.findValueSerializer(type, null); + JsonNode schemaNode = (ser instanceof SchemaAware) ? + ((SchemaAware) ser).getSchema(inst, null) : + JsonSchema.getDefaultSchemaNode(); + if (!(schemaNode instanceof ObjectNode)) { + throw new IllegalArgumentException("Class " + type.getName() + + " would not be serialized as a JSON object and therefore has no schema"); + } + + return new JsonSchema((ObjectNode) schemaNode); + } + + @Override + public boolean hasSerializerFor(SerializationConfig config, + Class<?> cls, SerializerFactory jsf) + { + return createInstance(config, jsf)._findExplicitUntypedSerializer(cls, null) != null; + } + + @Override + public int cachedSerializersCount() { + return _serializerCache.size(); + } + + @Override + public void flushCachedSerializers() { + _serializerCache.flush(); + } + + /* + /********************************************************** + /* Abstract method implementations, value/type serializers + /********************************************************** + */ + + @Override + public JsonSerializer<Object> findValueSerializer(Class<?> valueType, + BeanProperty property) + throws JsonMappingException + { + // Fast lookup from local lookup thingy works? + JsonSerializer<Object> ser = _knownSerializers.untypedValueSerializer(valueType); + if (ser == null) { + // If not, maybe shared map already has it? + ser = _serializerCache.untypedValueSerializer(valueType); + if (ser == null) { + // ... possibly as fully typed? + ser = _serializerCache.untypedValueSerializer(_config.constructType(valueType)); + if (ser == null) { + // If neither, must create + ser = _createAndCacheUntypedSerializer(valueType, property); + // Not found? Must use the unknown type serializer + /* Couldn't create? Need to return the fallback serializer, which + * most likely will report an error: but one question is whether + * we should cache it? + */ + if (ser == null) { + ser = getUnknownTypeSerializer(valueType); + // Should this be added to lookups? + if (CACHE_UNKNOWN_MAPPINGS) { + _serializerCache.addAndResolveNonTypedSerializer(valueType, ser, this); + } + return ser; + } + } + } + } + return _handleContextualResolvable(ser, property); + } + + /** + * This variant was added in 1.5, to allow for efficient access using full + * structured types, not just classes. This is necessary for accurate + * handling of external type information, to handle polymorphic types. + */ + @Override + public JsonSerializer<Object> findValueSerializer(JavaType valueType, BeanProperty property) + throws JsonMappingException + { + // Fast lookup from local lookup thingy works? + JsonSerializer<Object> ser = _knownSerializers.untypedValueSerializer(valueType); + if (ser == null) { + // If not, maybe shared map already has it? + ser = _serializerCache.untypedValueSerializer(valueType); + if (ser == null) { + // If neither, must create + ser = _createAndCacheUntypedSerializer(valueType, property); + // Not found? Must use the unknown type serializer + /* Couldn't create? Need to return the fallback serializer, which + * most likely will report an error: but one question is whether + * we should cache it? + */ + if (ser == null) { + ser = getUnknownTypeSerializer(valueType.getRawClass()); + // Should this be added to lookups? + if (CACHE_UNKNOWN_MAPPINGS) { + _serializerCache.addAndResolveNonTypedSerializer(valueType, ser, this); + } + return ser; + } + } + } + return _handleContextualResolvable(ser, property); + } + + /** + * @param cache Whether resulting value serializer should be cached or not; this is just + * a hint + */ + @Override + public JsonSerializer<Object> findTypedValueSerializer(Class<?> valueType, boolean cache, + BeanProperty property) + throws JsonMappingException + { + // Two-phase lookups; local non-shared cache, then shared: + JsonSerializer<Object> ser = _knownSerializers.typedValueSerializer(valueType); + if (ser != null) { + return ser; + } + // If not, maybe shared map already has it? + ser = _serializerCache.typedValueSerializer(valueType); + if (ser != null) { + return ser; + } + + // Well, let's just compose from pieces: + ser = findValueSerializer(valueType, property); + TypeSerializer typeSer = _serializerFactory.createTypeSerializer(_config, + _config.constructType(valueType), property); + if (typeSer != null) { + ser = new WrappedSerializer(typeSer, ser); + } + if (cache) { + _serializerCache.addTypedSerializer(valueType, ser); + } + return ser; + } + + @Override + public JsonSerializer<Object> findTypedValueSerializer(JavaType valueType, boolean cache, + BeanProperty property) + throws JsonMappingException + { + // Two-phase lookups; local non-shared cache, then shared: + JsonSerializer<Object> ser = _knownSerializers.typedValueSerializer(valueType); + if (ser != null) { + return ser; + } + // If not, maybe shared map already has it? + ser = _serializerCache.typedValueSerializer(valueType); + if (ser != null) { + return ser; + } + + // Well, let's just compose from pieces: + ser = findValueSerializer(valueType, property); + TypeSerializer typeSer = _serializerFactory.createTypeSerializer(_config, valueType, property); + if (typeSer != null) { + ser = new WrappedSerializer(typeSer, ser); + } + if (cache) { + _serializerCache.addTypedSerializer(valueType, ser); + } + return ser; + } + + /* + /********************************************************** + /* Abstract method implementations, other serializers + /********************************************************** + */ + + @SuppressWarnings("unchecked") + @Override + public JsonSerializer<Object> findKeySerializer(JavaType keyType, BeanProperty property) + throws JsonMappingException + { + JsonSerializer<Object> ser = _serializerFactory.createKeySerializer(_config, keyType, property); + + // First things first: maybe there are registered custom implementations + // if not, use default one: + if (ser == null) { + if (_keySerializer == null) { + ser = StdKeySerializers.getStdKeySerializer(keyType); + } else { + ser = _keySerializer; + } + } + // 25-Feb-2011, tatu: As per [JACKSON-519], need to ensure contextuality works here, too + if (ser instanceof ContextualSerializer<?>) { + ContextualSerializer<?> contextual = (ContextualSerializer<?>) ser; + ser = (JsonSerializer<Object>)contextual.createContextual(_config, property); + } + return ser; + } + + @Override + public JsonSerializer<Object> getNullKeySerializer() { + return _nullKeySerializer; + } + + @Override + public JsonSerializer<Object> getNullValueSerializer() { + return _nullValueSerializer; + } + + @Override + public JsonSerializer<Object> getUnknownTypeSerializer(Class<?> unknownType) { + return _unknownTypeSerializer; + } + + /* + /********************************************************** + /* Abstract method impls, convenience methods + /********************************************************** + */ + + /** + * @param timestamp Millisecond timestamp that defines date, if available; + */ + @Override + public final void defaultSerializeDateValue(long timestamp, JsonGenerator jgen) + throws IOException, JsonProcessingException + { + // [JACKSON-87]: Support both numeric timestamps and textual + if (isEnabled(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS)) { + jgen.writeNumber(timestamp); + } else { + if (_dateFormat == null) { + // must create a clone since Formats are not thread-safe: + _dateFormat = (DateFormat)_config.getDateFormat().clone(); + } + jgen.writeString(_dateFormat.format(new Date(timestamp))); + } + } + + @Override + public final void defaultSerializeDateValue(Date date, JsonGenerator jgen) + throws IOException, JsonProcessingException + { + // [JACKSON-87]: Support both numeric timestamps and textual + if (isEnabled(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS)) { + jgen.writeNumber(date.getTime()); + } else { + if (_dateFormat == null) { + DateFormat blueprint = _config.getDateFormat(); + // must create a clone since Formats are not thread-safe: + _dateFormat = (DateFormat)blueprint.clone(); + } + jgen.writeString(_dateFormat.format(date)); + } + } + + @Override + public void defaultSerializeDateKey(long timestamp, JsonGenerator jgen) + throws IOException, JsonProcessingException + { + if (isEnabled(SerializationConfig.Feature.WRITE_DATE_KEYS_AS_TIMESTAMPS)) { + jgen.writeFieldName(String.valueOf(timestamp)); + } else { + if (_dateFormat == null) { + DateFormat blueprint = _config.getDateFormat(); + // must create a clone since Formats are not thread-safe: + _dateFormat = (DateFormat)blueprint.clone(); + } + jgen.writeFieldName(_dateFormat.format(new Date(timestamp))); + } + } + + @Override + public void defaultSerializeDateKey(Date date, JsonGenerator jgen) + throws IOException, JsonProcessingException + { + if (isEnabled(SerializationConfig.Feature.WRITE_DATE_KEYS_AS_TIMESTAMPS)) { + jgen.writeFieldName(String.valueOf(date.getTime())); + } else { + if (_dateFormat == null) { + DateFormat blueprint = _config.getDateFormat(); + // must create a clone since Formats are not thread-safe: + _dateFormat = (DateFormat)blueprint.clone(); + } + jgen.writeFieldName(_dateFormat.format(date)); + } + } + + /* + /********************************************************** + /* Helper methods: can be overridden by sub-classes + /********************************************************** + */ + + /** + * Method called on the actual non-blueprint provider instance object, + * to kick off the serialization. + */ + protected void _serializeValue(JsonGenerator jgen, Object value) + throws IOException, JsonProcessingException + { + JsonSerializer<Object> ser; + boolean wrap; + + if (value == null) { + ser = getNullValueSerializer(); + wrap = false; // no name to use for wrapping; can't do! + } else { + Class<?> cls = value.getClass(); + // true, since we do want to cache root-level typed serializers (ditto for null property) + ser = findTypedValueSerializer(cls, true, null); + // [JACKSON-163] + wrap = _config.isEnabled(SerializationConfig.Feature.WRAP_ROOT_VALUE); + if (wrap) { + jgen.writeStartObject(); + jgen.writeFieldName(_rootNames.findRootName(value.getClass(), _config)); + } + } + try { + ser.serialize(value, jgen, this); + if (wrap) { + jgen.writeEndObject(); + } + } catch (IOException ioe) { + /* As per [JACKSON-99], should not wrap IOException or its + * sub-classes (like JsonProcessingException, JsonMappingException) + */ + throw ioe; + } catch (Exception e) { + // but others are wrapped + String msg = e.getMessage(); + if (msg == null) { + msg = "[no message for "+e.getClass().getName()+"]"; + } + throw new JsonMappingException(msg, e); + } + } + + /** + * Method called on the actual non-blueprint provider instance object, + * to kick off the serialization, when root type is explicitly + * specified and not determined from value. + */ + protected void _serializeValue(JsonGenerator jgen, Object value, JavaType rootType) + throws IOException, JsonProcessingException + { + // [JACKSON-163] + boolean wrap; + + JsonSerializer<Object> ser; + if (value == null) { + ser = getNullValueSerializer(); + wrap = false; + } else { + // Let's ensure types are compatible at this point + if (!rootType.getRawClass().isAssignableFrom(value.getClass())) { + _reportIncompatibleRootType(value, rootType); + } + // root value, not reached via property: + ser = findTypedValueSerializer(rootType, true, null); + // [JACKSON-163] + wrap = _config.isEnabled(SerializationConfig.Feature.WRAP_ROOT_VALUE); + if (wrap) { + jgen.writeStartObject(); + jgen.writeFieldName(_rootNames.findRootName(rootType, _config)); + } + } + try { + ser.serialize(value, jgen, this); + if (wrap) { + jgen.writeEndObject(); + } + } catch (IOException ioe) { // no wrapping for IO (and derived) + throw ioe; + } catch (Exception e) { // but others do need to be, to get path etc + String msg = e.getMessage(); + if (msg == null) { + msg = "[no message for "+e.getClass().getName()+"]"; + } + throw new JsonMappingException(msg, e); + } + } + + protected void _reportIncompatibleRootType(Object value, JavaType rootType) + throws IOException, JsonProcessingException + { + /* 07-Jan-2010, tatu: As per [JACKSON-456] better handle distinction between wrapper types, + * primitives + */ + if (rootType.isPrimitive()) { + Class<?> wrapperType = ClassUtil.wrapperType(rootType.getRawClass()); + // If it's just difference between wrapper, primitive, let it slide + if (wrapperType.isAssignableFrom(value.getClass())) { + return; + } + } + throw new JsonMappingException("Incompatible types: declared root type ("+rootType+") vs " + +value.getClass().getName()); + } + + /** + * Method that will try to find a serializer, either from cache + * or by constructing one; but will not return an "unknown" serializer + * if this can not be done but rather returns null. + * + * @return Serializer if one can be found, null if not. + */ + protected JsonSerializer<Object> _findExplicitUntypedSerializer(Class<?> runtimeType, + BeanProperty property) + { + // Fast lookup from local lookup thingy works? + JsonSerializer<Object> ser = _knownSerializers.untypedValueSerializer(runtimeType); + if (ser != null) { + return ser; + } + // If not, maybe shared map already has it? + ser = _serializerCache.untypedValueSerializer(runtimeType); + if (ser != null) { + return ser; + } + try { + return _createAndCacheUntypedSerializer(runtimeType, property); + } catch (Exception e) { + return null; + } + } + + /* + /********************************************************** + /* Low-level methods for actually constructing and initializing + /* serializers + /********************************************************** + */ + + /** + * Method that will try to construct a value serializer; and if + * one is successfully created, cache it for reuse. + */ + protected JsonSerializer<Object> _createAndCacheUntypedSerializer(Class<?> type, + BeanProperty property) + throws JsonMappingException + { + JsonSerializer<Object> ser; + try { + ser = _createUntypedSerializer(_config.constructType(type), property); + } catch (IllegalArgumentException iae) { + /* We better only expose checked exceptions, since those + * are what caller is expected to handle + */ + throw new JsonMappingException(iae.getMessage(), null, iae); + } + + if (ser != null) { + _serializerCache.addAndResolveNonTypedSerializer(type, ser, this); + } + return ser; + } + + /** + * @since 1.5 +] */ + protected JsonSerializer<Object> _createAndCacheUntypedSerializer(JavaType type, + BeanProperty property) + throws JsonMappingException + { + JsonSerializer<Object> ser; + try { + ser = _createUntypedSerializer(type, property); + } catch (IllegalArgumentException iae) { + /* We better only expose checked exceptions, since those + * are what caller is expected to handle + */ + throw new JsonMappingException(iae.getMessage(), null, iae); + } + + if (ser != null) { + _serializerCache.addAndResolveNonTypedSerializer(type, ser, this); + } + return ser; + } + + protected JsonSerializer<Object> _createUntypedSerializer(JavaType type, + BeanProperty property) + throws JsonMappingException + { + /* 10-Dec-2008, tatu: Is there a possibility of infinite loops + * here? Shouldn't be, given that we do not pass back-reference + * to this provider. But if there is, we'd need to sync calls, + * and keep track of creation chain to look for loops -- fairly + * easy to do, but won't add yet since it seems unnecessary. + */ + return (JsonSerializer<Object>)_serializerFactory.createSerializer(_config, type, property); + } + + /** + * @since 1.8.5 + */ + @SuppressWarnings("unchecked") + protected JsonSerializer<Object> _handleContextualResolvable(JsonSerializer<Object> ser, + BeanProperty property) + throws JsonMappingException + { + if (!(ser instanceof ContextualSerializer<?>)) { + return ser; + } + JsonSerializer<Object> ctxtSer = ((ContextualSerializer<Object>) ser).createContextual(_config, property); + if (ctxtSer != ser) { + // need to re-resolve? + if (ctxtSer instanceof ResolvableSerializer) { + ((ResolvableSerializer) ctxtSer).resolve(this); + } + ser = ctxtSer; + } + return ser; + } + + /* + /********************************************************** + /* Helper classes + /********************************************************** + */ + + /** + * Simple serializer that will call configured type serializer, passing + * in configured data serializer, and exposing it all as a simple + * serializer. + */ + private final static class WrappedSerializer + extends JsonSerializer<Object> + { + final protected TypeSerializer _typeSerializer; + final protected JsonSerializer<Object> _serializer; + + public WrappedSerializer(TypeSerializer typeSer, JsonSerializer<Object> ser) + { + super(); + _typeSerializer = typeSer; + _serializer = ser; + } + + @Override + public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonProcessingException + { + _serializer.serializeWithType(value, jgen, provider, _typeSerializer); + } + + @Override + public void serializeWithType(Object value, JsonGenerator jgen, SerializerProvider provider, + TypeSerializer typeSer) + throws IOException, JsonProcessingException + { + /* Is this an erroneous call? For now, let's assume it is not, and + * that type serializer is just overridden if so + */ + _serializer.serializeWithType(value, jgen, provider, typeSer); + } + + @Override + public Class<Object> handledType() { return Object.class; } + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/StdSerializers.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/StdSerializers.java new file mode 100644 index 0000000..8ca3889 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/StdSerializers.java
@@ -0,0 +1,372 @@ +package org.codehaus.jackson.map.ser; + +import java.io.IOException; +import java.lang.reflect.Type; +import java.math.BigDecimal; +import java.math.BigInteger; + +import org.codehaus.jackson.JsonGenerationException; +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.JacksonStdImpl; +import org.codehaus.jackson.map.ser.std.NonTypedScalarSerializerBase; +import org.codehaus.jackson.map.ser.std.ScalarSerializerBase; + +/** + * Container class for serializers used for handling standard JDK-provided types. + * + * @since 1.5 + */ +public class StdSerializers +{ + protected StdSerializers() { } + + /* + /********************************************************** + /* Concrete serializers, non-numeric primitives, Strings, Classes + /********************************************************** + */ + + /** + * Serializer used for primitive boolean, as well as java.util.Boolean + * wrapper type. + *<p> + * Since this is one of "native" types, no type information is ever + * included on serialization (unlike for most scalar types as of 1.5) + */ + @JacksonStdImpl + public final static class BooleanSerializer + extends NonTypedScalarSerializerBase<Boolean> + { + /** + * Whether type serialized is primitive (boolean) or wrapper + * (java.lang.Boolean); if true, former, if false, latter. + */ + final boolean _forPrimitive; + + public BooleanSerializer(boolean forPrimitive) + { + super(Boolean.class); + _forPrimitive = forPrimitive; + } + + @Override + public void serialize(Boolean value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + jgen.writeBoolean(value.booleanValue()); + } + + @Override + public JsonNode getSchema(SerializerProvider provider, Type typeHint) + { + /*(ryan) it may not, in fact, be optional, but there's no way + * to tell whether we're referencing a boolean or java.lang.Boolean. + */ + /* 27-Jun-2009, tatu: Now we can tell, after passing + * 'forPrimitive' flag... + */ + return createSchemaNode("boolean", !_forPrimitive); + } + } + + /** + * @deprecated Since 1.9, use {@link org.codehaus.jackson.map.ser.std.StringSerializer} instead + */ + @Deprecated + @JacksonStdImpl + public final static class StringSerializer + extends NonTypedScalarSerializerBase<String> + { + public StringSerializer() { super(String.class); } + + @Override + public void serialize(String value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + jgen.writeString(value); + } + + @Override + public JsonNode getSchema(SerializerProvider provider, Type typeHint) + { + return createSchemaNode("string", true); + } + } + + /* + /********************************************************** + /* Concrete serializers, numerics + /********************************************************** + */ + + /** + * This is the special serializer for regular {@link java.lang.Integer}s + * (and primitive ints) + *<p> + * Since this is one of "native" types, no type information is ever + * included on serialization (unlike for most scalar types as of 1.5) + */ + @JacksonStdImpl + public final static class IntegerSerializer + extends NonTypedScalarSerializerBase<Integer> + { + public IntegerSerializer() { super(Integer.class); } + + @Override + public void serialize(Integer value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + jgen.writeNumber(value.intValue()); + } + + @Override + public JsonNode getSchema(SerializerProvider provider, Type typeHint) + { + return createSchemaNode("integer", true); + } + } + + /** + * Similar to {@link IntegerSerializer}, but will not cast to Integer: + * instead, cast is to {@link java.lang.Number}, and conversion is + * by calling {@link java.lang.Number#intValue}. + */ + @JacksonStdImpl + public final static class IntLikeSerializer + extends ScalarSerializerBase<Number> + { + final static IntLikeSerializer instance = new IntLikeSerializer(); + + public IntLikeSerializer() { super(Number.class); } + + @Override + public void serialize(Number value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + jgen.writeNumber(value.intValue()); + } + + @Override + public JsonNode getSchema(SerializerProvider provider, Type typeHint) + { + return createSchemaNode("integer", true); + } + } + + @JacksonStdImpl + public final static class LongSerializer + extends ScalarSerializerBase<Long> + { + final static LongSerializer instance = new LongSerializer(); + + public LongSerializer() { super(Long.class); } + + @Override + public void serialize(Long value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + jgen.writeNumber(value.longValue()); + } + + @Override + public JsonNode getSchema(SerializerProvider provider, Type typeHint) + { + return createSchemaNode("number", true); + } + } + + @JacksonStdImpl + public final static class FloatSerializer + extends ScalarSerializerBase<Float> + { + final static FloatSerializer instance = new FloatSerializer(); + + public FloatSerializer() { super(Float.class); } + + @Override + public void serialize(Float value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + jgen.writeNumber(value.floatValue()); + } + + @Override + public JsonNode getSchema(SerializerProvider provider, Type typeHint) + { + return createSchemaNode("number", true); + } + } + + /** + * This is the special serializer for regular {@link java.lang.Double}s + * (and primitive doubles) + *<p> + * Since this is one of "native" types, no type information is ever + * included on serialization (unlike for most scalar types as of 1.5) + */ + @JacksonStdImpl + public final static class DoubleSerializer + extends NonTypedScalarSerializerBase<Double> + { + final static DoubleSerializer instance = new DoubleSerializer(); + + public DoubleSerializer() { super(Double.class); } + + @Override + public void serialize(Double value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + jgen.writeNumber(value.doubleValue()); + } + + @Override + public JsonNode getSchema(SerializerProvider provider, Type typeHint) + { + return createSchemaNode("number", true); + } + } + + /** + * As a fallback, we may need to use this serializer for other + * types of {@link Number}s (custom types). + */ + @JacksonStdImpl + public final static class NumberSerializer + extends ScalarSerializerBase<Number> + { + public final static NumberSerializer instance = new NumberSerializer(); + + public NumberSerializer() { super(Number.class); } + + @Override + public void serialize(Number value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + // As per [JACKSON-423], handling for BigInteger and BigDecimal was missing! + if (value instanceof BigDecimal) { + jgen.writeNumber((BigDecimal) value); + } else if (value instanceof BigInteger) { + jgen.writeNumber((BigInteger) value); + + /* These shouldn't match (as there are more specific ones), + * but just to be sure: + */ + } else if (value instanceof Integer) { + jgen.writeNumber(value.intValue()); + } else if (value instanceof Long) { + jgen.writeNumber(value.longValue()); + } else if (value instanceof Double) { + jgen.writeNumber(value.doubleValue()); + } else if (value instanceof Float) { + jgen.writeNumber(value.floatValue()); + } else if ((value instanceof Byte) || (value instanceof Short)) { + jgen.writeNumber(value.intValue()); // doesn't need to be cast to smaller numbers + } else { + // We'll have to use fallback "untyped" number write method + jgen.writeNumber(value.toString()); + } + } + + @Override + public JsonNode getSchema(SerializerProvider provider, Type typeHint) + { + return createSchemaNode("number", true); + } + } + + /* + /********************************************************** + /* Serializers for JDK date/time data types + /********************************************************** + */ + + /** + * @deprecated Since 1.9, use {@link org.codehaus.jackson.map.ser.std.DateSerializer} instead + */ + @JacksonStdImpl + @Deprecated + public final static class CalendarSerializer + extends org.codehaus.jackson.map.ser.std.CalendarSerializer { } + + /** + * @deprecated Since 1.9, use {@link org.codehaus.jackson.map.ser.std.DateSerializer} instead + */ + @Deprecated + @JacksonStdImpl + public final static class UtilDateSerializer + extends org.codehaus.jackson.map.ser.std.DateSerializer { + + } + + /** + * Compared to regular {@link UtilDateSerializer}, we do use String + * representation here. Why? Basically to truncate of time part, since + * that should not be used by plain SQL date. + */ + @JacksonStdImpl + public final static class SqlDateSerializer + extends ScalarSerializerBase<java.sql.Date> + { + public SqlDateSerializer() { super(java.sql.Date.class); } + + @Override + public void serialize(java.sql.Date value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + jgen.writeString(value.toString()); + } + + @Override + public JsonNode getSchema(SerializerProvider provider, Type typeHint) + { + //todo: (ryan) add a format for the date in the schema? + return createSchemaNode("string", true); + } + } + + @JacksonStdImpl + public final static class SqlTimeSerializer + extends ScalarSerializerBase<java.sql.Time> + { + public SqlTimeSerializer() { super(java.sql.Time.class); } + + @Override + public void serialize(java.sql.Time value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + jgen.writeString(value.toString()); + } + + @Override + public JsonNode getSchema(SerializerProvider provider, Type typeHint) + { + return createSchemaNode("string", true); + } + } + + + /* + /********************************************************** + / Other serializers + /********************************************************** + */ + + /** + * @deprecated Since 1.9, use {@link org.codehaus.jackson.map.ser.std.DateSerializer} instead + */ + @Deprecated + @JacksonStdImpl + public final static class SerializableSerializer + extends org.codehaus.jackson.map.ser.std.SerializableSerializer { } + + /** + * @deprecated Since 1.9, use {@link org.codehaus.jackson.map.ser.std.DateSerializer} instead + */ + @Deprecated + @JacksonStdImpl + public final static class SerializableWithTypeSerializer + extends org.codehaus.jackson.map.ser.std.SerializableWithTypeSerializer { + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/ToStringSerializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/ToStringSerializer.java new file mode 100644 index 0000000..754584d --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/ToStringSerializer.java
@@ -0,0 +1,14 @@ +package org.codehaus.jackson.map.ser; + +import org.codehaus.jackson.map.annotate.JacksonStdImpl; + +/** + * @deprecated Since 1.9 use {@link org.codehaus.jackson.map.ser.std.ToStringSerializer} + */ +@Deprecated +@JacksonStdImpl +public final class ToStringSerializer + extends org.codehaus.jackson.map.ser.std.ToStringSerializer +{ + public final static ToStringSerializer instance = new ToStringSerializer(); +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/impl/FailingSerializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/impl/FailingSerializer.java new file mode 100644 index 0000000..f2508b7 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/impl/FailingSerializer.java
@@ -0,0 +1,43 @@ +package org.codehaus.jackson.map.ser.impl; + +import java.io.IOException; +import java.lang.reflect.Type; + +import org.codehaus.jackson.JsonGenerationException; +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.map.JsonMappingException; +import org.codehaus.jackson.map.SerializerProvider; +import org.codehaus.jackson.map.ser.std.SerializerBase; + +/** + * Special bogus "serializer" that will throw + * {@link JsonGenerationException} if its {@link #serialize} + * gets invoked. Most commonly registered as handler for unknown types, + * as well as for catching unintended usage (like trying to use null + * as Map/Object key). + */ +public final class FailingSerializer + extends SerializerBase<Object> +{ + final String _msg; + + public FailingSerializer(String msg) { + super(Object.class); + _msg = msg; + } + + @Override + public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + throw new JsonGenerationException(_msg); + } + + @Override + public JsonNode getSchema(SerializerProvider provider, Type typeHint) + throws JsonMappingException + { + return null; + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/impl/JsonSerializerMap.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/impl/JsonSerializerMap.java new file mode 100644 index 0000000..14eae9a --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/impl/JsonSerializerMap.java
@@ -0,0 +1,93 @@ +package org.codehaus.jackson.map.ser.impl; + +import java.util.Map; + +import org.codehaus.jackson.map.JsonSerializer; +import org.codehaus.jackson.map.ser.impl.SerializerCache.TypeKey; + +/** + * Specialized read-only map used for storing and accessing serializers by type. + * + * @since 1.7 + */ +public class JsonSerializerMap +{ + private final Bucket[] _buckets; + + private final int _size; + + public JsonSerializerMap(Map<TypeKey,JsonSerializer<Object>> serializers) + { + int size = findSize(serializers.size()); + _size = size; + int hashMask = (size-1); + Bucket[] buckets = new Bucket[size]; + for (Map.Entry<TypeKey,JsonSerializer<Object>> entry : serializers.entrySet()) { + TypeKey key = entry.getKey(); + int index = key.hashCode() & hashMask; + buckets[index] = new Bucket(buckets[index], key, entry.getValue()); + } + _buckets = buckets; + } + + private final static int findSize(int size) + { + // For small enough results (64 or less), we'll require <= 50% fill rate; otherwise 80% + int needed = (size <= 64) ? (size + size) : (size + (size >> 2)); + int result = 8; + while (result < needed) { + result += result; + } + return result; + } + + /* + /********************************************************** + /* Public API + /********************************************************** + */ + + public int size() { return _size; } + + public JsonSerializer<Object> find(TypeKey key) + { + int index = key.hashCode() & (_buckets.length-1); + Bucket bucket = _buckets[index]; + /* Ok let's actually try unrolling loop slightly as this shows up in profiler; + * and also because in vast majority of cases first entry is either null + * or matches. + */ + if (bucket == null) { + return null; + } + if (key.equals(bucket.key)) { + return bucket.value; + } + while ((bucket = bucket.next) != null) { + if (key.equals(bucket.key)) { + return bucket.value; + } + } + return null; + } + + /* + /********************************************************** + /* Helper beans + /********************************************************** + */ + + private final static class Bucket + { + public final TypeKey key; + public final JsonSerializer<Object> value; + public final Bucket next; + + public Bucket(Bucket next, TypeKey key, JsonSerializer<Object> value) + { + this.next = next; + this.key = key; + this.value = value; + } + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/impl/PropertySerializerMap.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/impl/PropertySerializerMap.java new file mode 100644 index 0000000..821de5d --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/impl/PropertySerializerMap.java
@@ -0,0 +1,231 @@ +package org.codehaus.jackson.map.ser.impl; + +import org.codehaus.jackson.map.BeanProperty; +import org.codehaus.jackson.map.JsonMappingException; +import org.codehaus.jackson.map.JsonSerializer; +import org.codehaus.jackson.map.SerializerProvider; +import org.codehaus.jackson.type.JavaType; + +/** + * Helper container used for resolving serializers for dynamic (possibly but not + * necessarily polymorphic) properties: properties whose type is not forced + * to use dynamic (declared) type and that are not final. + * If so, serializer to use can only be established once actual value type is known. + * Since this happens a lot unless static typing is forced (or types are final) + * this implementation is optimized for efficiency. + * Instances are immutable; new instances are created with factory methods: this + * is important to ensure correct multi-threaded access. + * + * @since 1.7 + */ +public abstract class PropertySerializerMap +{ + /** + * Main lookup method. Takes a "raw" type since usage is always from + * place where parameterization is fixed such that there can not be + * type-parametric variations. + */ + public abstract JsonSerializer<Object> serializerFor(Class<?> type); + + /** + * Method called if initial lookup fails; will both find serializer + * and construct new map instance if warranted, and return both + * @throws JsonMappingException + */ + public final SerializerAndMapResult findAndAddSerializer(Class<?> type, + SerializerProvider provider, BeanProperty property) + throws JsonMappingException + { + JsonSerializer<Object> serializer = provider.findValueSerializer(type, property); + return new SerializerAndMapResult(serializer, newWith(type, serializer)); + } + + public final SerializerAndMapResult findAndAddSerializer(JavaType type, + SerializerProvider provider, BeanProperty property) + throws JsonMappingException + { + JsonSerializer<Object> serializer = provider.findValueSerializer(type, property); + return new SerializerAndMapResult(serializer, newWith(type.getRawClass(), serializer)); + } + + public abstract PropertySerializerMap newWith(Class<?> type, JsonSerializer<Object> serializer); + + public static PropertySerializerMap emptyMap() { + return Empty.instance; + } + + /* + /********************************************************** + /* Helper classes + /********************************************************** + */ + + /** + * Value class used for returning tuple that has both serializer + * that was retrieved and new map instance + */ + public final static class SerializerAndMapResult + { + public final JsonSerializer<Object> serializer; + public final PropertySerializerMap map; + + public SerializerAndMapResult(JsonSerializer<Object> serializer, + PropertySerializerMap map) + { + this.serializer = serializer; + this.map = map; + } + } + + /** + * Trivial container for bundling type + serializer entries. + */ + private final static class TypeAndSerializer + { + public final Class<?> type; + public final JsonSerializer<Object> serializer; + + public TypeAndSerializer(Class<?> type, JsonSerializer<Object> serializer) { + this.type = type; + this.serializer = serializer; + } + } + + /* + /********************************************************** + /* Implementations + /********************************************************** + */ + + /** + * Bogus instance that contains no serializers; used as the default + * map with new serializers. + */ + private final static class Empty extends PropertySerializerMap + { + protected final static Empty instance = new Empty(); + + @Override + public JsonSerializer<Object> serializerFor(Class<?> type) { + return null; // empty, nothing to find + } + + @Override + public PropertySerializerMap newWith(Class<?> type, JsonSerializer<Object> serializer) { + return new Single(type, serializer); + } + } + + /** + * Map that contains a single serializer; although seemingly silly + * this is probably the most commonly used variant because many + * theoretically dynamic or polymorphic types just have single + * actual type. + */ + private final static class Single extends PropertySerializerMap + { + private final Class<?> _type; + private final JsonSerializer<Object> _serializer; + + public Single(Class<?> type, JsonSerializer<Object> serializer) { + _type = type; + _serializer = serializer; + } + + @Override + public JsonSerializer<Object> serializerFor(Class<?> type) + { + if (type == _type) { + return _serializer; + } + return null; + } + + @Override + public PropertySerializerMap newWith(Class<?> type, JsonSerializer<Object> serializer) { + return new Double(_type, _serializer, type, serializer); + } + } + + private final static class Double extends PropertySerializerMap + { + private final Class<?> _type1, _type2; + private final JsonSerializer<Object> _serializer1, _serializer2; + + public Double(Class<?> type1, JsonSerializer<Object> serializer1, + Class<?> type2, JsonSerializer<Object> serializer2) + { + _type1 = type1; + _serializer1 = serializer1; + _type2 = type2; + _serializer2 = serializer2; + } + + @Override + public JsonSerializer<Object> serializerFor(Class<?> type) + { + if (type == _type1) { + return _serializer1; + } + if (type == _type2) { + return _serializer2; + } + return null; + } + + @Override + public PropertySerializerMap newWith(Class<?> type, JsonSerializer<Object> serializer) { + // Ok: let's just create generic one + TypeAndSerializer[] ts = new TypeAndSerializer[2]; + ts[0] = new TypeAndSerializer(_type1, _serializer1); + ts[1] = new TypeAndSerializer(_type2, _serializer2); + return new Multi(ts); + } + } + + private final static class Multi extends PropertySerializerMap + { + /** + * Let's limit number of serializers we actually cache; linear + * lookup won't scale too well beyond smallish number, and if + * we really want to support larger collections should use + * a hash map. But it seems unlikely this is a common use + * case so for now let's just stop building after hard-coded + * limit. 8 sounds like a reasonable stab for now. + */ + private final static int MAX_ENTRIES = 8; + + private final TypeAndSerializer[] _entries; + + public Multi(TypeAndSerializer[] entries) { + _entries = entries; + } + + @Override + public JsonSerializer<Object> serializerFor(Class<?> type) + { + for (int i = 0, len = _entries.length; i < len; ++i) { + TypeAndSerializer entry = _entries[i]; + if (entry.type == type) { + return entry.serializer; + } + } + return null; + } + + @Override + public PropertySerializerMap newWith(Class<?> type, JsonSerializer<Object> serializer) + { + int len = _entries.length; + // Will only grow up to N entries + if (len == MAX_ENTRIES) { + return this; + } + // 1.6 has nice resize methods but we are still 1.5 + TypeAndSerializer[] entries = new TypeAndSerializer[len+1]; + System.arraycopy(_entries, 0, entries, 0, len); + entries[len] = new TypeAndSerializer(type, serializer); + return new Multi(entries); + } + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/impl/ReadOnlyClassToSerializerMap.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/impl/ReadOnlyClassToSerializerMap.java new file mode 100644 index 0000000..d69b54e --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/impl/ReadOnlyClassToSerializerMap.java
@@ -0,0 +1,73 @@ +package org.codehaus.jackson.map.ser.impl; + +import java.util.*; + +import org.codehaus.jackson.type.JavaType; +import org.codehaus.jackson.map.JsonSerializer; +import org.codehaus.jackson.map.ser.impl.SerializerCache.TypeKey; + +/** + * Optimized lookup table for accessing two types of serializers; typed + * and non-typed. Only accessed from a single thread, so no synchronization + * needed for accessors. + * + * @since 1.7 + */ +public final class ReadOnlyClassToSerializerMap +{ + /** + * Actual mappings from type key to serializers + */ + protected final JsonSerializerMap _map; + + /** + * We'll reuse key class to avoid unnecessary instantiations; since + * this is not shared between threads, we can just reuse single + * instance. + */ + protected final TypeKey _cacheKey = new TypeKey(getClass(), false); + + private ReadOnlyClassToSerializerMap(JsonSerializerMap map) + { + _map = map; + } + + public ReadOnlyClassToSerializerMap instance() + { + return new ReadOnlyClassToSerializerMap(_map); + } + + /** + * Factory method for creating the "blueprint" lookup map. Such map + * can not be used as is but just shared: to get an actual usable + * instance, {@link #instance} has to be called first. + */ + public static ReadOnlyClassToSerializerMap from(HashMap<TypeKey, JsonSerializer<Object>> src) + { + return new ReadOnlyClassToSerializerMap(new JsonSerializerMap(src)); + } + + public JsonSerializer<Object> typedValueSerializer(JavaType type) + { + _cacheKey.resetTyped(type); + return _map.find(_cacheKey); + } + + public JsonSerializer<Object> typedValueSerializer(Class<?> cls) + { + _cacheKey.resetTyped(cls); + return _map.find(_cacheKey); + } + + public JsonSerializer<Object> untypedValueSerializer(Class<?> cls) + { + _cacheKey.resetUntyped(cls); + return _map.find(_cacheKey); + } + + public JsonSerializer<Object> untypedValueSerializer(JavaType type) + { + _cacheKey.resetUntyped(type); + return _map.find(_cacheKey); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/impl/SerializerCache.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/impl/SerializerCache.java new file mode 100644 index 0000000..d4fb875 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/impl/SerializerCache.java
@@ -0,0 +1,304 @@ +package org.codehaus.jackson.map.ser.impl; + +import java.util.*; + +import org.codehaus.jackson.type.JavaType; +import org.codehaus.jackson.map.JsonMappingException; +import org.codehaus.jackson.map.JsonSerializer; +import org.codehaus.jackson.map.ResolvableSerializer; +import org.codehaus.jackson.map.SerializerProvider; + +/** + * Simple cache object that allows for doing 2-level lookups: first level is + * by "local" read-only lookup Map (used without locking) + * and second backup level is by a shared modifiable HashMap. + * The idea is that after a while, most serializers are found from the + * local Map (to optimize performance, reduce lock contention), + * but that during buildup we can use a shared map to reduce both + * number of distinct read-only maps constructed, and number of + * serializers constructed. + *<p> + * Since version 1.5 cache will actually contain three kinds of entries, + * based on combination of class pair key. First class in key is for the + * type to serialize, and second one is type used for determining how + * to resolve value type. One (but not both) of entries can be null. + */ +public final class SerializerCache +{ + /** + * Shared, modifiable map; all access needs to be through synchronized blocks. + *<p> + * NOTE: keys are of various types (see below for key types), in addition to + * basic {@link JavaType} used for "untyped" serializers. + */ + private HashMap<TypeKey, JsonSerializer<Object>> _sharedMap = new HashMap<TypeKey, JsonSerializer<Object>>(64); + + /** + * Most recent read-only instance, created from _sharedMap, if any. + */ + private ReadOnlyClassToSerializerMap _readOnlyMap = null; + + public SerializerCache() { + } + + /** + * Method that can be called to get a read-only instance populated from the + * most recent version of the shared lookup Map. + */ + public ReadOnlyClassToSerializerMap getReadOnlyLookupMap() + { + ReadOnlyClassToSerializerMap m; + synchronized (this) { + m = _readOnlyMap; + if (m == null) { + _readOnlyMap = m = ReadOnlyClassToSerializerMap.from(_sharedMap); + } + } + return m.instance(); + } + + /* + /********************************************************** + /* Lookup methods for accessing shared (slow) cache + /********************************************************** + */ + + /** + * @since 1.4 + */ + public synchronized int size() { + return _sharedMap.size(); + } + + /** + * Method that checks if the shared (and hence, synchronized) lookup Map might have + * untyped serializer for given type. + */ + public JsonSerializer<Object> untypedValueSerializer(Class<?> type) + { + synchronized (this) { + return _sharedMap.get(new TypeKey(type, false)); + } + } + + /** + * @since 1.5 + */ + public JsonSerializer<Object> untypedValueSerializer(JavaType type) + { + synchronized (this) { + return _sharedMap.get(new TypeKey(type, false)); + } + } + + public JsonSerializer<Object> typedValueSerializer(JavaType type) + { + synchronized (this) { + return _sharedMap.get(new TypeKey(type, true)); + } + } + + public JsonSerializer<Object> typedValueSerializer(Class<?> cls) + { + synchronized (this) { + return _sharedMap.get(new TypeKey(cls, true)); + } + } + + /* + /********************************************************** + /* Methods for adding shared serializer instances + /********************************************************** + */ + + /** + * Method called if none of lookups succeeded, and caller had to construct + * a serializer. If so, we will update the shared lookup map so that it + * can be resolved via it next time. + */ + public void addTypedSerializer(JavaType type, JsonSerializer<Object> ser) + { + synchronized (this) { + if (_sharedMap.put(new TypeKey(type, true), ser) == null) { + // let's invalidate the read-only copy, too, to get it updated + _readOnlyMap = null; + } + } + } + + public void addTypedSerializer(Class<?> cls, JsonSerializer<Object> ser) + { + synchronized (this) { + if (_sharedMap.put(new TypeKey(cls, true), ser) == null) { + // let's invalidate the read-only copy, too, to get it updated + _readOnlyMap = null; + } + } + } + + /** + * @since 1.8 + */ + public void addAndResolveNonTypedSerializer(Class<?> type, JsonSerializer<Object> ser, + SerializerProvider provider) + throws JsonMappingException + { + synchronized (this) { + if (_sharedMap.put(new TypeKey(type, false), ser) == null) { + // let's invalidate the read-only copy, too, to get it updated + _readOnlyMap = null; + } + /* Finally: some serializers want to do post-processing, after + * getting registered (to handle cyclic deps). + */ + /* 14-May-2011, tatu: As per [JACKSON-570], resolving needs to be done + * in synchronized manner; this because while we do need to register + * instance first, we also must keep lock until resolution is complete + */ + if (ser instanceof ResolvableSerializer) { + ((ResolvableSerializer) ser).resolve(provider); + } + } + } + + /** + * @since 1.8 + */ + public void addAndResolveNonTypedSerializer(JavaType type, JsonSerializer<Object> ser, + SerializerProvider provider) + throws JsonMappingException + { + synchronized (this) { + if (_sharedMap.put(new TypeKey(type, false), ser) == null) { + // let's invalidate the read-only copy, too, to get it updated + _readOnlyMap = null; + } + /* Finally: some serializers want to do post-processing, after + * getting registered (to handle cyclic deps). + */ + /* 14-May-2011, tatu: As per [JACKSON-570], resolving needs to be done + * in synchronized manner; this because while we do need to register + * instance first, we also must keep lock until resolution is complete + */ + if (ser instanceof ResolvableSerializer) { + ((ResolvableSerializer) ser).resolve(provider); + } + } + } + + /** + * Method called by StdSerializerProvider#flushCachedSerializers() to + * clear all cached serializers + */ + public synchronized void flush() { + _sharedMap.clear(); + } + + /* + /************************************************************** + /* Helper class(es) + /************************************************************** + */ + + /** + * Key that offers two "modes"; one with raw class, as used for + * cases were raw class type is available (for example, when using + * runtime type); and one with full generics-including. + */ + public final static class TypeKey + { + protected int _hashCode; + + protected Class<?> _class; + + protected JavaType _type; + + /** + * Indicator of whether serializer stored has a type serializer + * wrapper around it or not; if not, it is "untyped" serializer; + * if it has, it is "typed" + */ + protected boolean _isTyped; + + public TypeKey(Class<?> key, boolean typed) { + _class = key; + _type = null; + _isTyped = typed; + _hashCode = hash(key, typed); + } + + public TypeKey(JavaType key, boolean typed) { + _type = key; + _class = null; + _isTyped = typed; + _hashCode = hash(key, typed); + } + + private final static int hash(Class<?> cls, boolean typed) { + int hash = cls.getName().hashCode(); + if (typed) { + ++hash; + } + return hash; + } + + private final static int hash(JavaType type, boolean typed) { + int hash = type.hashCode() - 1; + if (typed) { + --hash; + } + return hash; + } + + public void resetTyped(Class<?> cls) { + _type = null; + _class = cls; + _isTyped = true; + _hashCode = hash(cls, true); + } + + public void resetUntyped(Class<?> cls) { + _type = null; + _class = cls; + _isTyped = false; + _hashCode = hash(cls, false); + } + + public void resetTyped(JavaType type) { + _type = type; + _class = null; + _isTyped = true; + _hashCode = hash(type, true); + } + + public void resetUntyped(JavaType type) { + _type = type; + _class = null; + _isTyped = false; + _hashCode = hash(type, false); + } + + @Override public final int hashCode() { return _hashCode; } + + @Override public final String toString() { + if (_class != null) { + return "{class: "+_class.getName()+", typed? "+_isTyped+"}"; + } + return "{type: "+_type+", typed? "+_isTyped+"}"; + } + + // note: we assume key is never used for anything other than as map key, so: + @Override public final boolean equals(Object o) + { + if (o == this) return true; + TypeKey other = (TypeKey) o; + if (other._isTyped == _isTyped) { + if (_class != null) { + return other._class == _class; + } + return _type.equals(other._type); + } + return false; + } + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/impl/SimpleBeanPropertyFilter.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/impl/SimpleBeanPropertyFilter.java new file mode 100644 index 0000000..d517db6 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/impl/SimpleBeanPropertyFilter.java
@@ -0,0 +1,109 @@ +package org.codehaus.jackson.map.ser.impl; + +import java.util.*; + +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.ser.BeanPropertyFilter; +import org.codehaus.jackson.map.ser.BeanPropertyWriter; + +/** + * Simple {@link BeanPropertyFilter} implementation that only uses property name + * to determine whether to serialize property as is, or to filter it out. + * + * @since 1.7 + */ +public abstract class SimpleBeanPropertyFilter implements BeanPropertyFilter +{ + /* + /********************************************************** + /* Life-cycle + /********************************************************** + */ + + protected SimpleBeanPropertyFilter() { } + + /** + * Factory method to construct filter that filters out all properties <b>except</b> + * ones includes in set + */ + public static SimpleBeanPropertyFilter filterOutAllExcept(Set<String> properties) { + return new FilterExceptFilter(properties); + } + + public static SimpleBeanPropertyFilter filterOutAllExcept(String... propertyArray) { + HashSet<String> properties = new HashSet<String>(propertyArray.length); + Collections.addAll(properties, propertyArray); + return new FilterExceptFilter(properties); + } + + public static SimpleBeanPropertyFilter serializeAllExcept(Set<String> properties) { + return new SerializeExceptFilter(properties); + } + + public static SimpleBeanPropertyFilter serializeAllExcept(String... propertyArray) { + HashSet<String> properties = new HashSet<String>(propertyArray.length); + Collections.addAll(properties, propertyArray); + return new SerializeExceptFilter(properties); + } + + /* + /********************************************************** + /* Sub-classes + /********************************************************** + */ + + /** + * Filter implementation which defaults to filtering out unknown + * properties and only serializes ones explicitly listed. + */ + public static class FilterExceptFilter + extends SimpleBeanPropertyFilter + { + /** + * Set of property names to serialize. + */ + protected final Set<String> _propertiesToInclude; + + public FilterExceptFilter(Set<String> properties) { + _propertiesToInclude = properties; + } + + @Override + public void serializeAsField(Object bean, JsonGenerator jgen, + SerializerProvider provider, BeanPropertyWriter writer) + throws Exception + { + if (_propertiesToInclude.contains(writer.getName())) { + writer.serializeAsField(bean, jgen, provider); + } + } + } + + /** + * Filter implementation which defaults to serializing all + * properties, except for ones explicitly listed to be filtered out. + */ + public static class SerializeExceptFilter + extends SimpleBeanPropertyFilter + { + /** + * Set of property names to filter out. + */ + protected final Set<String> _propertiesToExclude; + + public SerializeExceptFilter(Set<String> properties) { + _propertiesToExclude = properties; + } + + @Override + public void serializeAsField(Object bean, JsonGenerator jgen, + SerializerProvider provider, BeanPropertyWriter writer) + throws Exception + { + if (!_propertiesToExclude.contains(writer.getName())) { + writer.serializeAsField(bean, jgen, provider); + } + } + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/impl/SimpleFilterProvider.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/impl/SimpleFilterProvider.java new file mode 100644 index 0000000..9909a70 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/impl/SimpleFilterProvider.java
@@ -0,0 +1,114 @@ +package org.codehaus.jackson.map.ser.impl; + +import java.util.*; + +import org.codehaus.jackson.map.ser.*; + +/** + * Simple {@link FilterProvider} implementation that just stores + * direct id-to-filter mapping. + */ +public class SimpleFilterProvider extends FilterProvider +{ + /** + * Mappings from ids to filters. + */ + protected final Map<String,BeanPropertyFilter> _filtersById; + + /** + * This is the filter we return in case no mapping was found for + * given id; default is 'null' (in which case caller typically + * reports an error), but can be set to an explicit filter. + */ + protected BeanPropertyFilter _defaultFilter; + + /** + * Flag that indicates whether request for an unknown filter id should + * result an exception (default) or not. + * Note that this is only relevant if no default filter has been + * configured. + * + * @since 1.9 + */ + protected boolean _cfgFailOnUnknownId = true; + + /* + /********************************************************** + /* Life-cycle: constructing, configuring + /********************************************************** + */ + + public SimpleFilterProvider() { + this(new HashMap<String,BeanPropertyFilter>()); + } + + /** + * @param mapping Mapping from id to filter; used as is, no copy is made. + */ + public SimpleFilterProvider(Map<String,BeanPropertyFilter> mapping) { + _filtersById = mapping; + } + + /** + * Method for defining filter to return for "unknown" filters; cases + * where there is no mapping from given id to an explicit filter. + * + * @param f Filter to return when no filter is found for given id + */ + public SimpleFilterProvider setDefaultFilter(BeanPropertyFilter f) + { + _defaultFilter = f; + return this; + } + + /** + * @since 1.9 + */ + public BeanPropertyFilter getDefaultFilter() { + return _defaultFilter; + } + + /** + * @since 1.9 + */ + public SimpleFilterProvider setFailOnUnknownId(boolean state) { + _cfgFailOnUnknownId = state; + return this; + } + + /** + * @since 1.9 + */ + public boolean willFailOnUnknownId() { + return _cfgFailOnUnknownId; + } + + public SimpleFilterProvider addFilter(String id, BeanPropertyFilter filter) { + _filtersById.put(id, filter); + return this; + } + + public BeanPropertyFilter removeFilter(String id) { + return _filtersById.remove(id); + } + + /* + /********************************************************** + /* Public lookup API + /********************************************************** + */ + + @Override + public BeanPropertyFilter findFilter(Object filterId) + { + BeanPropertyFilter f = _filtersById.get(filterId); + if (f == null) { + f = _defaultFilter; + if (f == null && _cfgFailOnUnknownId) { + throw new IllegalArgumentException("No filter configured with id '"+filterId+"' (type " + +filterId.getClass().getName()+")"); + } + } + return f; + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/impl/UnknownSerializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/impl/UnknownSerializer.java new file mode 100644 index 0000000..5e3cda6 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/impl/UnknownSerializer.java
@@ -0,0 +1,54 @@ +package org.codehaus.jackson.map.ser.impl; + +import java.io.IOException; +import java.lang.reflect.Type; + +import org.codehaus.jackson.JsonGenerationException; +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.ser.std.SerializerBase; + +public class UnknownSerializer + extends SerializerBase<Object> +{ + public UnknownSerializer() { + super(Object.class); + } + + @Override + public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonMappingException + { + // 27-Nov-2009, tatu: As per [JACKSON-201] may or may not fail... + if (provider.isEnabled(SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS)) { + failForEmpty(value); + } + // But if it's fine, we'll just output empty JSON Object: + jgen.writeStartObject(); + jgen.writeEndObject(); + } + + // since 1.6.2; needed to retain type information + @Override + public final void serializeWithType(Object value, JsonGenerator jgen, SerializerProvider provider, + TypeSerializer typeSer) + throws IOException, JsonGenerationException + { + if (provider.isEnabled(SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS)) { + failForEmpty(value); + } + typeSer.writeTypePrefixForObject(value, jgen); + typeSer.writeTypeSuffixForObject(value, jgen); + } + + @Override + public JsonNode getSchema(SerializerProvider provider, Type typeHint) throws JsonMappingException { + return null; + } + + protected void failForEmpty(Object value) throws JsonMappingException + { + throw new JsonMappingException("No serializer found for class "+value.getClass().getName()+" and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS) )"); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/impl/UnwrappingBeanPropertyWriter.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/impl/UnwrappingBeanPropertyWriter.java new file mode 100644 index 0000000..63c3796 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/impl/UnwrappingBeanPropertyWriter.java
@@ -0,0 +1,99 @@ +package org.codehaus.jackson.map.ser.impl; + +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.map.JsonMappingException; +import org.codehaus.jackson.map.JsonSerializer; +import org.codehaus.jackson.map.SerializerProvider; +import org.codehaus.jackson.map.ser.*; +import org.codehaus.jackson.type.JavaType; + +/** + * Variant of {@link BeanPropertyWriter} which will handle unwrapping + * of JSON Object (including of properties of Object within surrounding + * JSON object, and not as sub-object). + * + * @since 1.9 + */ +public class UnwrappingBeanPropertyWriter + extends BeanPropertyWriter +{ + public UnwrappingBeanPropertyWriter(BeanPropertyWriter base) { + super(base); + } + + public UnwrappingBeanPropertyWriter(BeanPropertyWriter base, JsonSerializer<Object> ser) { + super(base, ser); + } + + @Override + public BeanPropertyWriter withSerializer(JsonSerializer<Object> ser) + { + if (getClass() != UnwrappingBeanPropertyWriter.class) { + throw new IllegalStateException("UnwrappingBeanPropertyWriter sub-class does not override 'withSerializer()'; needs to!"); + } + // better try to create unwrapping instance + if (!ser.isUnwrappingSerializer()) { + ser = ser.unwrappingSerializer(); + } + return new UnwrappingBeanPropertyWriter(this, ser); + } + + @Override + public void serializeAsField(Object bean, JsonGenerator jgen, SerializerProvider prov) + throws Exception + { + Object value = get(bean); + if (value == null) { + /* Hmmh. I assume we MUST pretty much suppress nulls, since we + * can't really unwrap it... + */ + return; + } + // For non-nulls, first: simple check for direct cycles + if (value == bean) { + _reportSelfReference(bean); + } + if (_suppressableValue != null && _suppressableValue.equals(value)) { + return; + } + JsonSerializer<Object> ser = _serializer; + if (ser == null) { + Class<?> cls = value.getClass(); + PropertySerializerMap map = _dynamicSerializers; + ser = map.serializerFor(cls); + if (ser == null) { + ser = _findAndAddDynamic(map, cls, prov); + } + } + + // note: must verify we are using unwrapping serializer; if not, will write field name + if (!ser.isUnwrappingSerializer()) { + jgen.writeFieldName(_name); + } + + if (_typeSerializer == null) { + ser.serialize(value, jgen, prov); + } else { + ser.serializeWithType(value, jgen, prov, _typeSerializer); + } + } + + // need to override as we must get unwrapping instance... + @Override + protected JsonSerializer<Object> _findAndAddDynamic(PropertySerializerMap map, + Class<?> type, SerializerProvider provider) throws JsonMappingException + { + JsonSerializer<Object> serializer; + if (_nonTrivialBaseType != null) { + JavaType subtype = provider.constructSpecializedType(_nonTrivialBaseType, type); + serializer = provider.findValueSerializer(subtype, this); + } else { + serializer = provider.findValueSerializer(type, this); + } + if (!serializer.isUnwrappingSerializer()) { + serializer = serializer.unwrappingSerializer(); + } + _dynamicSerializers = _dynamicSerializers.newWith(type, serializer); + return serializer; + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/impl/UnwrappingBeanSerializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/impl/UnwrappingBeanSerializer.java new file mode 100644 index 0000000..8fd5adf --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/impl/UnwrappingBeanSerializer.java
@@ -0,0 +1,76 @@ +package org.codehaus.jackson.map.ser.impl; + +import java.io.IOException; + +import org.codehaus.jackson.JsonGenerationException; +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.ser.*; +import org.codehaus.jackson.map.ser.std.BeanSerializerBase; + +public class UnwrappingBeanSerializer + extends BeanSerializerBase +{ + /* + /********************************************************** + /* Life-cycle: constructors + /********************************************************** + */ + + /** + * Constructor used for creating unwrapping instance of a + * standard <code>BeanSerializer</code> + */ + public UnwrappingBeanSerializer(BeanSerializerBase src) { + super(src); + } + + /* + /********************************************************** + /* Life-cycle: factory methods, fluent factories + /********************************************************** + */ + + @Override + public JsonSerializer<Object> unwrappingSerializer() { + // already unwrapping, nothing more to do: + return this; + } + + @Override + public boolean isUnwrappingSerializer() { + return true; // sure is + } + + /* + /********************************************************** + /* JsonSerializer implementation that differs between impls + /********************************************************** + */ + + /** + * Main serialization method that will delegate actual output to + * configured + * {@link BeanPropertyWriter} instances. + */ + @Override + public final void serialize(Object bean, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + if (_propertyFilterId != null) { + serializeFieldsFiltered(bean, jgen, provider); + } else { + serializeFields(bean, jgen, provider); + } + } + + /* + /********************************************************** + /* Standard methods + /********************************************************** + */ + + @Override public String toString() { + return "UnwrappingBeanSerializer for "+handledType().getName(); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/impl/package-info.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/impl/package-info.java new file mode 100644 index 0000000..90cdfc7 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/impl/package-info.java
@@ -0,0 +1,5 @@ +/** + * Contains implementation classes of serialization part of + * data binding. + */ +package org.codehaus.jackson.map.ser.impl;
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/package-info.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/package-info.java new file mode 100644 index 0000000..fba34ea --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/package-info.java
@@ -0,0 +1,5 @@ +/** + * Contains implementation classes of serialization part of + * data binding. + */ +package org.codehaus.jackson.map.ser;
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/AsArraySerializerBase.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/AsArraySerializerBase.java new file mode 100644 index 0000000..092462e --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/AsArraySerializerBase.java
@@ -0,0 +1,185 @@ +package org.codehaus.jackson.map.ser.std; + +import java.io.IOException; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; + +import org.codehaus.jackson.JsonGenerationException; +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.ser.impl.PropertySerializerMap; +import org.codehaus.jackson.node.ObjectNode; +import org.codehaus.jackson.schema.JsonSchema; +import org.codehaus.jackson.schema.SchemaAware; +import org.codehaus.jackson.type.JavaType; + +/** + * Base class for serializers that will output contents as JSON + * arrays; typically serializers used for {@link java.util.Collection} + * and array types. + */ +public abstract class AsArraySerializerBase<T> + extends ContainerSerializerBase<T> + implements ResolvableSerializer +{ + protected final boolean _staticTyping; + + protected final JavaType _elementType; + + /** + * Type serializer used for values, if any. + */ + protected final TypeSerializer _valueTypeSerializer; + + /** + * Value serializer to use, if it can be statically determined + * + * @since 1.5 + */ + protected JsonSerializer<Object> _elementSerializer; + + /** + * Collection-valued property being serialized with this instance + * + * @since 1.7 + */ + protected final BeanProperty _property; + + /** + * If element type can not be statically determined, mapping from + * runtime type to serializer is handled using this object + * + * @since 1.7 + */ + protected PropertySerializerMap _dynamicSerializers; + + /** + * @deprecated since 1.8 + */ + @Deprecated + protected AsArraySerializerBase(Class<?> cls, JavaType et, boolean staticTyping, + TypeSerializer vts, BeanProperty property) + { + this(cls, et, staticTyping, vts, property, null); + } + + protected AsArraySerializerBase(Class<?> cls, JavaType et, boolean staticTyping, + TypeSerializer vts, BeanProperty property, JsonSerializer<Object> elementSerializer) + { + // typing with generics is messy... have to resort to this: + super(cls, false); + _elementType = et; + // static if explicitly requested, or if element type is final + _staticTyping = staticTyping || (et != null && et.isFinal()); + _valueTypeSerializer = vts; + _property = property; + _elementSerializer = elementSerializer; + _dynamicSerializers = PropertySerializerMap.emptyMap(); + } + + @Override + public final void serialize(T value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + jgen.writeStartArray(); + serializeContents(value, jgen, provider); + jgen.writeEndArray(); + } + + @Override + public final void serializeWithType(T value, JsonGenerator jgen, SerializerProvider provider, + TypeSerializer typeSer) + throws IOException, JsonGenerationException + { + typeSer.writeTypePrefixForArray(value, jgen); + serializeContents(value, jgen, provider); + typeSer.writeTypeSuffixForArray(value, jgen); + } + + protected abstract void serializeContents(T value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException; + + @Override + public JsonNode getSchema(SerializerProvider provider, Type typeHint) + throws JsonMappingException + { + /* 15-Jan-2010, tatu: This should probably be rewritten, given that + * more information about content type is actually being explicitly + * passed. So there should be less need to try to re-process that + * information. + */ + ObjectNode o = createSchemaNode("array", true); + JavaType contentType = null; + if (typeHint != null) { + JavaType javaType = provider.constructType(typeHint); + contentType = javaType.getContentType(); + if (contentType == null) { // could still be parametrized (Iterators) + if (typeHint instanceof ParameterizedType) { + Type[] typeArgs = ((ParameterizedType) typeHint).getActualTypeArguments(); + if (typeArgs.length == 1) { + contentType = provider.constructType(typeArgs[0]); + } + } + } + } + if (contentType == null && _elementType != null) { + contentType = _elementType; + } + if (contentType != null) { + JsonNode schemaNode = null; + // 15-Oct-2010, tatu: We can't serialize plain Object.class; but what should it produce here? Untyped? + if (contentType.getRawClass() != Object.class) { + JsonSerializer<Object> ser = provider.findValueSerializer(contentType, _property); + if (ser instanceof SchemaAware) { + schemaNode = ((SchemaAware) ser).getSchema(provider, null); + } + } + if (schemaNode == null) { + schemaNode = JsonSchema.getDefaultSchemaNode(); + } + o.put("items", schemaNode); + } + return o; + } + + /** + * Need to get callback to resolve value serializer, if static typing + * is used (either being forced, or because value type is final) + */ + @Override + public void resolve(SerializerProvider provider) + throws JsonMappingException + { + if (_staticTyping && _elementType != null && _elementSerializer == null) { + _elementSerializer = provider.findValueSerializer(_elementType, _property); + } + } + + /** + * @since 1.7 + */ + protected final JsonSerializer<Object> _findAndAddDynamic(PropertySerializerMap map, + Class<?> type, SerializerProvider provider) throws JsonMappingException + { + PropertySerializerMap.SerializerAndMapResult result = map.findAndAddSerializer(type, provider, _property); + // did we get a new map of serializers? If so, start using it + if (map != result.map) { + _dynamicSerializers = result.map; + } + return result.serializer; + } + + /** + * @since 1.8 + */ + protected final JsonSerializer<Object> _findAndAddDynamic(PropertySerializerMap map, + JavaType type, SerializerProvider provider) throws JsonMappingException + { + PropertySerializerMap.SerializerAndMapResult result = map.findAndAddSerializer(type, provider, _property); + if (map != result.map) { + _dynamicSerializers = result.map; + } + return result.serializer; + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/BeanSerializerBase.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/BeanSerializerBase.java new file mode 100644 index 0000000..8af9d58 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/BeanSerializerBase.java
@@ -0,0 +1,340 @@ +package org.codehaus.jackson.map.ser.std; + +import java.io.IOException; +import java.lang.reflect.Type; + +import org.codehaus.jackson.JsonGenerationException; +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.ser.*; +import org.codehaus.jackson.node.ObjectNode; +import org.codehaus.jackson.schema.JsonSchema; +import org.codehaus.jackson.schema.SchemaAware; +import org.codehaus.jackson.type.JavaType; + +/** + * Base class both for the standard bean serializer, and couple + * of variants that only differ in small details. + * Can be used for custom bean serializers as well, although that + * is not the primary design goal. + * + * @since 1.9 + */ +public abstract class BeanSerializerBase + extends SerializerBase<Object> + implements ResolvableSerializer, SchemaAware +{ + final protected static BeanPropertyWriter[] NO_PROPS = new BeanPropertyWriter[0]; + + /* + /********************************************************** + /* Configuration + /********************************************************** + */ + + /** + * Writers used for outputting actual property values + */ + final protected BeanPropertyWriter[] _props; + + /** + * Optional filters used to suppress output of properties that + * are only to be included in certain views + */ + final protected BeanPropertyWriter[] _filteredProps; + + /** + * Handler for {@link org.codehaus.jackson.annotate.JsonAnyGetter} + * annotated properties + * + * @since 1.6 + */ + final protected AnyGetterWriter _anyGetterWriter; + + /** + * Id of the bean property filter to use, if any; null if none. + */ + final protected Object _propertyFilterId; + + /* + /********************************************************** + /* Life-cycle: constructors + /********************************************************** + */ + + /** + * @param type Nominal type of values handled by this serializer + * @param properties Property writers used for actual serialization + */ + protected BeanSerializerBase(JavaType type, + BeanPropertyWriter[] properties, BeanPropertyWriter[] filteredProperties, + AnyGetterWriter anyGetterWriter, + Object filterId) + { + super(type); + _props = properties; + _filteredProps = filteredProperties; + _anyGetterWriter = anyGetterWriter; + _propertyFilterId = filterId; + } + + @SuppressWarnings("unchecked") + public BeanSerializerBase(Class<?> rawType, + BeanPropertyWriter[] properties, BeanPropertyWriter[] filteredProperties, + AnyGetterWriter anyGetterWriter, + Object filterId) + { + super((Class<Object>) rawType); + _props = properties; + _filteredProps = filteredProperties; + _anyGetterWriter = anyGetterWriter; + _propertyFilterId = filterId; + } + + /** + * Copy-constructor that is useful for sub-classes that just want to + * copy all super-class properties without modifications. + */ + protected BeanSerializerBase(BeanSerializerBase src) { + this(src._handledType, + src._props, src._filteredProps, src._anyGetterWriter, src._propertyFilterId); + } + + /* + /********************************************************** + /* Partial JsonSerializer implementation + /********************************************************** + */ + + // Main serialization method left unimplemented + @Override + public abstract void serialize(Object bean, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException; + + // Type-info-augmented case implemented as it does not usually differ between impls + @Override + public void serializeWithType(Object bean, JsonGenerator jgen, SerializerProvider provider, + TypeSerializer typeSer) + throws IOException, JsonGenerationException + { + typeSer.writeTypePrefixForObject(bean, jgen); + if (_propertyFilterId != null) { + serializeFieldsFiltered(bean, jgen, provider); + } else { + serializeFields(bean, jgen, provider); + } + typeSer.writeTypeSuffixForObject(bean, jgen); + } + + /* + /********************************************************** + /* Field serialization methods + /********************************************************** + */ + + protected void serializeFields(Object bean, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + final BeanPropertyWriter[] props; + if (_filteredProps != null && provider.getSerializationView() != null) { + props = _filteredProps; + } else { + props = _props; + } + int i = 0; + try { + for (final int len = props.length; i < len; ++i) { + BeanPropertyWriter prop = props[i]; + if (prop != null) { // can have nulls in filtered list + prop.serializeAsField(bean, jgen, provider); + } + } + if (_anyGetterWriter != null) { + _anyGetterWriter.getAndSerialize(bean, jgen, provider); + } + } catch (Exception e) { + String name = (i == props.length) ? "[anySetter]" : props[i].getName(); + wrapAndThrow(provider, e, bean, name); + } catch (StackOverflowError e) { + /* 04-Sep-2009, tatu: Dealing with this is tricky, since we do not + * have many stack frames to spare... just one or two; can't + * make many calls. + */ + JsonMappingException mapE = new JsonMappingException("Infinite recursion (StackOverflowError)", e); + String name = (i == props.length) ? "[anySetter]" : props[i].getName(); + mapE.prependPath(new JsonMappingException.Reference(bean, name)); + throw mapE; + } + } + + /** + * Alternative serialization method that gets called when there is a + * {@link BeanPropertyFilter} that needs to be called to determine + * which properties are to be serialized (and possibly how) + * + * @since 1.7 + */ + protected void serializeFieldsFiltered(Object bean, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + /* note: almost verbatim copy of "serializeFields"; copied (instead of merged) + * so that old method need not add check for existence of filter. + */ + + final BeanPropertyWriter[] props; + if (_filteredProps != null && provider.getSerializationView() != null) { + props = _filteredProps; + } else { + props = _props; + } + final BeanPropertyFilter filter = findFilter(provider); + // better also allow missing filter actually.. + if (filter == null) { + serializeFields(bean, jgen, provider); + return; + } + + int i = 0; + try { + for (final int len = props.length; i < len; ++i) { + BeanPropertyWriter prop = props[i]; + if (prop != null) { // can have nulls in filtered list + filter.serializeAsField(bean, jgen, provider, prop); + } + } + if (_anyGetterWriter != null) { + _anyGetterWriter.getAndSerialize(bean, jgen, provider); + } + } catch (Exception e) { + String name = (i == props.length) ? "[anySetter]" : props[i].getName(); + wrapAndThrow(provider, e, bean, name); + } catch (StackOverflowError e) { + JsonMappingException mapE = new JsonMappingException("Infinite recursion (StackOverflowError)", e); + String name = (i == props.length) ? "[anySetter]" : props[i].getName(); + mapE.prependPath(new JsonMappingException.Reference(bean, name)); + throw mapE; + } + } + + /** + * Helper method used to locate filter that is needed, based on filter id + * this serializer was constructed with. + * + * @since 1.7 + */ + protected BeanPropertyFilter findFilter(SerializerProvider provider) + throws JsonMappingException + { + final Object filterId = _propertyFilterId; + FilterProvider filters = provider.getFilterProvider(); + // Not ok to miss the provider, if a filter is declared to be needed. + if (filters == null) { + throw new JsonMappingException("Can not resolve BeanPropertyFilter with id '"+filterId+"'; no FilterProvider configured"); + } + BeanPropertyFilter filter = filters.findFilter(filterId); + // But whether unknown ids are ok just depends on filter provider; if we get null that's fine + return filter; + } + + @Override + public JsonNode getSchema(SerializerProvider provider, Type typeHint) + throws JsonMappingException + { + ObjectNode o = createSchemaNode("object", true); + //todo: should the classname go in the title? + //o.put("title", _className); + ObjectNode propertiesNode = o.objectNode(); + for (int i = 0; i < _props.length; i++) { + BeanPropertyWriter prop = _props[i]; + JavaType propType = prop.getSerializationType(); + // 03-Dec-2010, tatu: SchemaAware REALLY should use JavaType, but alas it doesn't... + Type hint = (propType == null) ? prop.getGenericPropertyType() : propType.getRawClass(); + // Maybe it already has annotated/statically configured serializer? + JsonSerializer<Object> ser = prop.getSerializer(); + if (ser == null) { // nope + Class<?> serType = prop.getRawSerializationType(); + if (serType == null) { + serType = prop.getPropertyType(); + } + ser = provider.findValueSerializer(serType, prop); + } + JsonNode schemaNode = (ser instanceof SchemaAware) ? + ((SchemaAware) ser).getSchema(provider, hint) : + JsonSchema.getDefaultSchemaNode(); + propertiesNode.put(prop.getName(), schemaNode); + } + o.put("properties", propertiesNode); + return o; + } + + /* + /********************************************************** + /* ResolvableSerializer impl + /********************************************************** + */ + + @Override + public void resolve(SerializerProvider provider) + throws JsonMappingException + { + int filteredCount = (_filteredProps == null) ? 0 : _filteredProps.length; + for (int i = 0, len = _props.length; i < len; ++i) { + BeanPropertyWriter prop = _props[i]; + if (prop.hasSerializer()) { + continue; + } + // Was the serialization type hard-coded? If so, use it + JavaType type = prop.getSerializationType(); + + /* It not, we can use declared return type if and only if + * declared type is final -- if not, we don't really know + * the actual type until we get the instance. + */ + if (type == null) { + type = provider.constructType(prop.getGenericPropertyType()); + if (!type.isFinal()) { + /* 18-Feb-2010, tatus: But even if it is non-final, we may + * need to retain some of type information so that we can + * accurately handle contained types + */ + if (type.isContainerType() || type.containedTypeCount() > 0) { + prop.setNonTrivialBaseType(type); + } + continue; + } + } + JsonSerializer<Object> ser = provider.findValueSerializer(type, prop); + /* 04-Feb-2010, tatu: We may have stashed type serializer for content types + * too, earlier; if so, it's time to connect the dots here: + */ + if (type.isContainerType()) { + TypeSerializer typeSer = type.getContentType().getTypeHandler(); + if (typeSer != null) { + // for now, can do this only for standard containers... + if (ser instanceof ContainerSerializerBase<?>) { + // ugly casts... but necessary + @SuppressWarnings("unchecked") + JsonSerializer<Object> ser2 = (JsonSerializer<Object>)((ContainerSerializerBase<?>) ser).withValueTypeSerializer(typeSer); + ser = ser2; + } + } + } + prop = prop.withSerializer(ser); + _props[i] = prop; + // and maybe replace filtered property too? (see [JACKSON-364]) + if (i < filteredCount) { + BeanPropertyWriter w2 = _filteredProps[i]; + if (w2 != null) { + _filteredProps[i] = w2.withSerializer(ser); + } + } + } + + // also, any-getter may need to be resolved + if (_anyGetterWriter != null) { + _anyGetterWriter.resolve(provider); + } + } + +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/CalendarSerializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/CalendarSerializer.java new file mode 100644 index 0000000..a059d13 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/CalendarSerializer.java
@@ -0,0 +1,43 @@ +package org.codehaus.jackson.map.ser.std; + +import java.io.IOException; +import java.lang.reflect.Type; +import java.util.Calendar; + +import org.codehaus.jackson.JsonGenerationException; +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.map.SerializationConfig; +import org.codehaus.jackson.map.SerializerProvider; +import org.codehaus.jackson.map.annotate.JacksonStdImpl; + +/** + * Standard serializer for {@link java.util.Calendar}. + * As with other time/date types, is configurable to produce timestamps + * (standard Java 64-bit timestamp) or textual formats (usually ISO-8601). + * + * @since 1.9 (moved from 'org.codehaus.jackson.map.ser.StdSerializers#CalendarSerializer} + */ +@JacksonStdImpl +public class CalendarSerializer + extends ScalarSerializerBase<Calendar> +{ + public static CalendarSerializer instance = new CalendarSerializer(); + + public CalendarSerializer() { super(Calendar.class); } + + @Override + public void serialize(Calendar value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + provider.defaultSerializeDateValue(value.getTimeInMillis(), jgen); + } + + @Override + public JsonNode getSchema(SerializerProvider provider, Type typeHint) + { + //TODO: (ryan) add a format for the date in the schema? + return createSchemaNode(provider.isEnabled(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS) + ? "number" : "string", true); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/CollectionSerializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/CollectionSerializer.java new file mode 100644 index 0000000..31bad2d --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/CollectionSerializer.java
@@ -0,0 +1,113 @@ +package org.codehaus.jackson.map.ser.std; + +import java.io.IOException; +import java.util.Collection; +import java.util.Iterator; + +import org.codehaus.jackson.JsonGenerationException; +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.map.BeanProperty; +import org.codehaus.jackson.map.JsonSerializer; +import org.codehaus.jackson.map.SerializerProvider; +import org.codehaus.jackson.map.TypeSerializer; +import org.codehaus.jackson.map.ser.impl.PropertySerializerMap; +import org.codehaus.jackson.type.JavaType; + +/** + * Fallback serializer for cases where Collection is not known to be + * of type for which more specializer serializer exists (such as + * index-accessible List). + * If so, we will just construct an {@link java.util.Iterator} + * to iterate over elements. + */ +public class CollectionSerializer + extends AsArraySerializerBase<Collection<?>> +{ + public CollectionSerializer(JavaType elemType, boolean staticTyping, TypeSerializer vts, + BeanProperty property, JsonSerializer<Object> valueSerializer) + { + super(Collection.class, elemType, staticTyping, vts, property, valueSerializer); + } + + @Override + public ContainerSerializerBase<?> _withValueTypeSerializer(TypeSerializer vts) { + return new CollectionSerializer(_elementType, _staticTyping, vts, _property, _elementSerializer); + } + + @Override + public void serializeContents(Collection<?> value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + if (_elementSerializer != null) { + serializeContentsUsing(value, jgen, provider, _elementSerializer); + return; + } + Iterator<?> it = value.iterator(); + if (!it.hasNext()) { + return; + } + PropertySerializerMap serializers = _dynamicSerializers; + final TypeSerializer typeSer = _valueTypeSerializer; + + int i = 0; + try { + do { + Object elem = it.next(); + if (elem == null) { + provider.defaultSerializeNull(jgen); + } else { + Class<?> cc = elem.getClass(); + JsonSerializer<Object> serializer = serializers.serializerFor(cc); + if (serializer == null) { + // To fix [JACKSON-508] + if (_elementType.hasGenericTypes()) { + serializer = _findAndAddDynamic(serializers, + provider.constructSpecializedType(_elementType, cc), provider); + } else { + serializer = _findAndAddDynamic(serializers, cc, provider); + } + serializers = _dynamicSerializers; + } + if (typeSer == null) { + serializer.serialize(elem, jgen, provider); + } else { + serializer.serializeWithType(elem, jgen, provider, typeSer); + } + } + ++i; + } while (it.hasNext()); + } catch (Exception e) { + // [JACKSON-55] Need to add reference information + wrapAndThrow(provider, e, value, i); + } + } + + public void serializeContentsUsing(Collection<?> value, JsonGenerator jgen, SerializerProvider provider, + JsonSerializer<Object> ser) + throws IOException, JsonGenerationException + { + Iterator<?> it = value.iterator(); + if (it.hasNext()) { + TypeSerializer typeSer = _valueTypeSerializer; + int i = 0; + do { + Object elem = it.next(); + try { + if (elem == null) { + provider.defaultSerializeNull(jgen); + } else { + if (typeSer == null) { + ser.serialize(elem, jgen, provider); + } else { + ser.serializeWithType(elem, jgen, provider, typeSer); + } + } + ++i; + } catch (Exception e) { + // [JACKSON-55] Need to add reference information + wrapAndThrow(provider, e, value, i); + } + } while (it.hasNext()); + } + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/ContainerSerializerBase.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/ContainerSerializerBase.java new file mode 100644 index 0000000..91d348f --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/ContainerSerializerBase.java
@@ -0,0 +1,51 @@ +package org.codehaus.jackson.map.ser.std; + +import org.codehaus.jackson.map.TypeSerializer; + +/** + * Intermediate base class for types that contain element(s) of + * other types. Used for example for List, Map, Object array and + * Iterator serializers. + * + * @since 1.5 + */ +public abstract class ContainerSerializerBase<T> + extends SerializerBase<T> +{ + /* + /********************************************************** + /* Construction, initialization + /********************************************************** + */ + + protected ContainerSerializerBase(Class<T> t) { + super(t); + } + + /** + * Alternate constructor that is (alas!) needed to work + * around kinks of generic type handling + * + * @param t + */ + protected ContainerSerializerBase(Class<?> t, boolean dummy) { + super(t, dummy); + } + + /** + * Factory(-like) method that can be used to construct a new container + * serializer that uses specified {@link TypeSerializer} for decorating + * contained values with additional type information. + * + * @param vts Type serializer to use for contained values; can be null, + * in which case 'this' serializer is returned as is + * @return Serializer instance that uses given type serializer for values if + * that is possible (or if not, just 'this' serializer) + */ + public ContainerSerializerBase<?> withValueTypeSerializer(TypeSerializer vts) { + if (vts == null) return this; + return _withValueTypeSerializer(vts); + } + + public abstract ContainerSerializerBase<?> _withValueTypeSerializer(TypeSerializer vts); +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/DateSerializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/DateSerializer.java new file mode 100644 index 0000000..fe5ded3 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/DateSerializer.java
@@ -0,0 +1,42 @@ +package org.codehaus.jackson.map.ser.std; + +import java.io.IOException; +import java.lang.reflect.Type; +import java.util.Date; + +import org.codehaus.jackson.JsonGenerationException; +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.map.SerializationConfig; +import org.codehaus.jackson.map.SerializerProvider; +import org.codehaus.jackson.map.annotate.JacksonStdImpl; + +/** + * For efficiency, we will serialize Dates as longs, instead of + * potentially more readable Strings. + *<p> + * @since 1.9 (moved from 'org.codehaus.jackson.map.ser.StdSerializers#UtilDateSerializer} + */ +@JacksonStdImpl +public class DateSerializer + extends ScalarSerializerBase<java.util.Date> +{ + public static DateSerializer instance = new DateSerializer(); + + public DateSerializer() { super(Date.class); } + + @Override + public void serialize(Date value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + provider.defaultSerializeDateValue(value, jgen); + } + + @Override + public JsonNode getSchema(SerializerProvider provider, Type typeHint) + { + //todo: (ryan) add a format for the date in the schema? + return createSchemaNode(provider.isEnabled(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS) + ? "number" : "string", true); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/EnumMapSerializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/EnumMapSerializer.java new file mode 100644 index 0000000..c29d5f3 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/EnumMapSerializer.java
@@ -0,0 +1,218 @@ +package org.codehaus.jackson.map.ser.std; + +import java.io.IOException; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.JacksonStdImpl; +import org.codehaus.jackson.map.util.EnumValues; +import org.codehaus.jackson.type.JavaType; +import org.codehaus.jackson.node.JsonNodeFactory; +import org.codehaus.jackson.node.ObjectNode; +import org.codehaus.jackson.schema.JsonSchema; +import org.codehaus.jackson.schema.SchemaAware; + +/** + * Specialized serializer for {@link EnumMap}s. Somewhat tricky to + * implement because actual Enum value type may not be available; + * and if not, it can only be gotten from actual instance. + */ +@JacksonStdImpl +public class EnumMapSerializer + extends ContainerSerializerBase<EnumMap<? extends Enum<?>, ?>> + implements ResolvableSerializer +{ + protected final boolean _staticTyping; + + /** + * If we know enumeration used as key, this will contain + * value set to use for serialization + */ + protected final EnumValues _keyEnums; + + protected final JavaType _valueType; + + /** + * Property being serialized with this instance + * + * @since 1.7 + */ + protected final BeanProperty _property; + + /** + * Value serializer to use, if it can be statically determined + * + * @since 1.5 + */ + protected JsonSerializer<Object> _valueSerializer; + + /** + * Type serializer used for values, if any. + */ + protected final TypeSerializer _valueTypeSerializer; + + /** + * @deprecated Since 1.8, use variant that takes value serializer + */ + @Deprecated + public EnumMapSerializer(JavaType valueType, boolean staticTyping, EnumValues keyEnums, + TypeSerializer vts, BeanProperty property) + { + this(valueType, staticTyping, keyEnums, vts, property, null); + } + + public EnumMapSerializer(JavaType valueType, boolean staticTyping, EnumValues keyEnums, + TypeSerializer vts, BeanProperty property, JsonSerializer<Object> valueSerializer) + { + super(EnumMap.class, false); + _staticTyping = staticTyping || (valueType != null && valueType.isFinal()); + _valueType = valueType; + _keyEnums = keyEnums; + _valueTypeSerializer = vts; + _property = property; + _valueSerializer = valueSerializer; + } + + @Override + public ContainerSerializerBase<?> _withValueTypeSerializer(TypeSerializer vts) + { + return new EnumMapSerializer(_valueType, _staticTyping, _keyEnums, vts, _property, _valueSerializer); + } + + @Override + public void serialize(EnumMap<? extends Enum<?>,?> value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + jgen.writeStartObject(); + if (!value.isEmpty()) { + serializeContents(value, jgen, provider); + } + jgen.writeEndObject(); + } + + @Override + public void serializeWithType(EnumMap<? extends Enum<?>,?> value, JsonGenerator jgen, SerializerProvider provider, + TypeSerializer typeSer) + throws IOException, JsonGenerationException + { + typeSer.writeTypePrefixForObject(value, jgen); + if (!value.isEmpty()) { + serializeContents(value, jgen, provider); + } + typeSer.writeTypeSuffixForObject(value, jgen); + } + + protected void serializeContents(EnumMap<? extends Enum<?>,?> value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + if (_valueSerializer != null) { + serializeContentsUsing(value, jgen, provider, _valueSerializer); + return; + } + JsonSerializer<Object> prevSerializer = null; + Class<?> prevClass = null; + EnumValues keyEnums = _keyEnums; + + for (Map.Entry<? extends Enum<?>,?> entry : value.entrySet()) { + // First, serialize key + Enum<?> key = entry.getKey(); + if (keyEnums == null) { + /* 15-Oct-2009, tatu: This is clumsy, but still the simplest efficient + * way to do it currently, as Serializers get cached. (it does assume we'll always use + * default serializer tho -- so ideally code should be rewritten) + */ + // ... and lovely two-step casting process too... + SerializerBase<?> ser = (SerializerBase<?>) provider.findValueSerializer( + key.getDeclaringClass(), _property); + keyEnums = ((EnumSerializer) ser).getEnumValues(); + } + jgen.writeFieldName(keyEnums.serializedValueFor(key)); + // And then value + Object valueElem = entry.getValue(); + if (valueElem == null) { + provider.defaultSerializeNull(jgen); + } else { + Class<?> cc = valueElem.getClass(); + JsonSerializer<Object> currSerializer; + if (cc == prevClass) { + currSerializer = prevSerializer; + } else { + currSerializer = provider.findValueSerializer(cc, _property); + prevSerializer = currSerializer; + prevClass = cc; + } + try { + currSerializer.serialize(valueElem, jgen, provider); + } catch (Exception e) { + // [JACKSON-55] Need to add reference information + wrapAndThrow(provider, e, value, entry.getKey().name()); + } + } + } + } + + protected void serializeContentsUsing(EnumMap<? extends Enum<?>,?> value, JsonGenerator jgen, SerializerProvider provider, + JsonSerializer<Object> valueSer) + throws IOException, JsonGenerationException + { + EnumValues keyEnums = _keyEnums; + for (Map.Entry<? extends Enum<?>,?> entry : value.entrySet()) { + Enum<?> key = entry.getKey(); + if (keyEnums == null) { + // clumsy, but has to do for now: + SerializerBase<?> ser = (SerializerBase<?>) provider.findValueSerializer(key.getDeclaringClass(), + _property); + keyEnums = ((EnumSerializer) ser).getEnumValues(); + } + jgen.writeFieldName(keyEnums.serializedValueFor(key)); + Object valueElem = entry.getValue(); + if (valueElem == null) { + provider.defaultSerializeNull(jgen); + } else { + try { + valueSer.serialize(valueElem, jgen, provider); + } catch (Exception e) { + wrapAndThrow(provider, e, value, entry.getKey().name()); + } + } + } + } + + @Override + public void resolve(SerializerProvider provider) + throws JsonMappingException + { + if (_staticTyping && _valueSerializer == null) { + _valueSerializer = provider.findValueSerializer(_valueType, _property); + } + } + + @SuppressWarnings("unchecked") + @Override + public JsonNode getSchema(SerializerProvider provider, Type typeHint) + throws JsonMappingException + { + ObjectNode o = createSchemaNode("object", true); + if (typeHint instanceof ParameterizedType) { + Type[] typeArgs = ((ParameterizedType) typeHint).getActualTypeArguments(); + if (typeArgs.length == 2) { + JavaType enumType = provider.constructType(typeArgs[0]); + JavaType valueType = provider.constructType(typeArgs[1]); + ObjectNode propsNode = JsonNodeFactory.instance.objectNode(); + Class<Enum<?>> enumClass = (Class<Enum<?>>) enumType.getRawClass(); + for (Enum<?> enumValue : enumClass.getEnumConstants()) { + JsonSerializer<Object> ser = provider.findValueSerializer(valueType.getRawClass(), _property); + JsonNode schemaNode = (ser instanceof SchemaAware) ? + ((SchemaAware) ser).getSchema(provider, null) : + JsonSchema.getDefaultSchemaNode(); + propsNode.put(provider.getConfig().getAnnotationIntrospector().findEnumValue((Enum<?>)enumValue), schemaNode); + } + o.put("properties", propsNode); + } + } + return o; + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/EnumSerializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/EnumSerializer.java new file mode 100644 index 0000000..32fabf9 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/EnumSerializer.java
@@ -0,0 +1,84 @@ +package org.codehaus.jackson.map.ser.std; + +import java.io.IOException; +import java.lang.reflect.Type; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.io.SerializedString; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.JacksonStdImpl; +import org.codehaus.jackson.map.introspect.BasicBeanDescription; +import org.codehaus.jackson.map.util.EnumValues; +import org.codehaus.jackson.node.ObjectNode; +import org.codehaus.jackson.node.ArrayNode; +import org.codehaus.jackson.type.JavaType; + +/** + * Standard serializer used for {@link java.lang.Enum} types. + *<p> + * Based on {@link ScalarSerializerBase} since the JSON value is + * scalar (String). + * + * @author tatu + */ +@JacksonStdImpl +public class EnumSerializer + extends ScalarSerializerBase<Enum<?>> +{ + /** + * This map contains pre-resolved values (since there are ways + * to customize actual String constants to use) to use as + * serializations. + */ + protected final EnumValues _values; + + public EnumSerializer(EnumValues v) { + super(Enum.class, false); + _values = v; + } + + public static EnumSerializer construct(Class<Enum<?>> enumClass, SerializationConfig config, + BasicBeanDescription beanDesc) + { + // [JACKSON-212]: If toString() is to be used instead, leave EnumValues null + AnnotationIntrospector intr = config.getAnnotationIntrospector(); + EnumValues v = config.isEnabled(SerializationConfig.Feature.WRITE_ENUMS_USING_TO_STRING) + ? EnumValues.constructFromToString(enumClass, intr) : EnumValues.constructFromName(enumClass, intr); + return new EnumSerializer(v); + } + + @Override + public final void serialize(Enum<?> en, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + // [JACKSON-684]: serialize as index? + if (provider.isEnabled(SerializationConfig.Feature.WRITE_ENUMS_USING_INDEX)) { + jgen.writeNumber(en.ordinal()); + return; + } + jgen.writeString(_values.serializedValueFor(en)); + } + + @Override + public JsonNode getSchema(SerializerProvider provider, Type typeHint) + { + // [JACKSON-684]: serialize as index? + if (provider.isEnabled(SerializationConfig.Feature.WRITE_ENUMS_USING_INDEX)) { + return createSchemaNode("integer", true); + } + ObjectNode objectNode = createSchemaNode("string", true); + if (typeHint != null) { + JavaType type = provider.constructType(typeHint); + if (type.isEnumType()) { + ArrayNode enumNode = objectNode.putArray("enum"); + for (SerializedString value : _values.values()) { + enumNode.add(value.getValue()); + } + } + } + return objectNode; + } + + public EnumValues getEnumValues() { return _values; } +} +
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/EnumSetSerializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/EnumSetSerializer.java new file mode 100644 index 0000000..f5870ff --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/EnumSetSerializer.java
@@ -0,0 +1,47 @@ +package org.codehaus.jackson.map.ser.std; + +import java.io.IOException; +import java.util.EnumSet; + +import org.codehaus.jackson.JsonGenerationException; +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.map.BeanProperty; +import org.codehaus.jackson.map.JsonSerializer; +import org.codehaus.jackson.map.SerializerProvider; +import org.codehaus.jackson.map.TypeSerializer; +import org.codehaus.jackson.type.JavaType; + +public class EnumSetSerializer + extends AsArraySerializerBase<EnumSet<? extends Enum<?>>> +{ + public EnumSetSerializer(JavaType elemType, BeanProperty property) + { + super(EnumSet.class, elemType, true, null, property, null); + } + + @Override + public ContainerSerializerBase<?> _withValueTypeSerializer(TypeSerializer vts) { + // no typing for enums (always "hard" type) + return this; + } + + @Override + public void serializeContents(EnumSet<? extends Enum<?>> value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + JsonSerializer<Object> enumSer = _elementSerializer; + /* Need to dynamically find instance serializer; unfortunately + * that seems to be the only way to figure out type (no accessors + * to the enum class that set knows) + */ + for (Enum<?> en : value) { + if (enumSer == null) { + /* 12-Jan-2010, tatu: Since enums can not be polymorphic, let's + * not bother with typed serializer variant here + */ + enumSer = provider.findValueSerializer(en.getDeclaringClass(), _property); + } + enumSer.serialize(en, jgen, provider); + } + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/IndexedStringListSerializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/IndexedStringListSerializer.java new file mode 100644 index 0000000..af53043 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/IndexedStringListSerializer.java
@@ -0,0 +1,122 @@ +package org.codehaus.jackson.map.ser.std; + +import java.io.IOException; +import java.util.*; + +import org.codehaus.jackson.JsonGenerationException; +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.map.BeanProperty; +import org.codehaus.jackson.map.JsonMappingException; +import org.codehaus.jackson.map.JsonSerializer; +import org.codehaus.jackson.map.ResolvableSerializer; +import org.codehaus.jackson.map.SerializerProvider; +import org.codehaus.jackson.map.TypeSerializer; +import org.codehaus.jackson.map.annotate.JacksonStdImpl; + +/** + * Efficient implementation for serializing {@link List}s that contains Strings and are random-accessible. + * The only complexity is due to possibility that serializer for {@link String} + * may be overridde; because of this, logic is needed to ensure that the default + * serializer is in use to use fastest mode, or if not, to defer to custom + * String serializer. + */ +@JacksonStdImpl +public final class IndexedStringListSerializer + extends StaticListSerializerBase<List<String>> + implements ResolvableSerializer +{ + protected JsonSerializer<String> _serializer; + + public IndexedStringListSerializer(BeanProperty property) { + this(property, null); + } + + @SuppressWarnings("unchecked") + public IndexedStringListSerializer(BeanProperty property, JsonSerializer<?> ser) { + super(List.class, property); + _serializer = (JsonSerializer<String>) ser; + } + + @Override protected JsonNode contentSchema() { + return createSchemaNode("string", true); + } + + @SuppressWarnings("unchecked") + @Override + public void resolve(SerializerProvider provider) throws JsonMappingException + { + if (_serializer == null) { + JsonSerializer<?> ser = provider.findValueSerializer(String.class, _property); + if (!isDefaultSerializer(ser)) { + _serializer = (JsonSerializer<String>) ser; + } + } + } + + @Override + public void serialize(List<String> value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + jgen.writeStartArray(); + if (_serializer == null) { + serializeContents(value, jgen, provider); + } else { + serializeUsingCustom(value, jgen, provider); + } + jgen.writeEndArray(); + } + + @Override + public void serializeWithType(List<String> value, JsonGenerator jgen, SerializerProvider provider, + TypeSerializer typeSer) + throws IOException, JsonGenerationException + { + typeSer.writeTypePrefixForArray(value, jgen); + if (_serializer == null) { + serializeContents(value, jgen, provider); + } else { + serializeUsingCustom(value, jgen, provider); + } + typeSer.writeTypeSuffixForArray(value, jgen); + } + + private final void serializeContents(List<String> value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + int i = 0; + try { + final int len = value.size(); + for (; i < len; ++i) { + String str = value.get(i); + if (str == null) { + provider.defaultSerializeNull(jgen); + } else { + jgen.writeString(str); + } + } + } catch (Exception e) { + wrapAndThrow(provider, e, value, i); + } + } + + private final void serializeUsingCustom(List<String> value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + int i = 0; + try { + final int len = value.size(); + final JsonSerializer<String> ser = _serializer; + for (i = 0; i < len; ++i) { + String str = value.get(i); + if (str == null) { + provider.defaultSerializeNull(jgen); + } else { + ser.serialize(str, jgen, provider); + } + } + } catch (Exception e) { + wrapAndThrow(provider, e, value, i); + } + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/InetAddressSerializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/InetAddressSerializer.java new file mode 100644 index 0000000..12149de --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/InetAddressSerializer.java
@@ -0,0 +1,51 @@ +package org.codehaus.jackson.map.ser.std; + +import java.io.IOException; +import java.net.InetAddress; + +import org.codehaus.jackson.JsonGenerationException; +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.map.SerializerProvider; +import org.codehaus.jackson.map.TypeSerializer; + +/** + * Simple serializer for {@link java.net.InetAddress}. Main complexity is + * with registration, since same serializer is to be used for sub-classes. + * + * @since 1.8 + */ +public class InetAddressSerializer + extends ScalarSerializerBase<InetAddress> +{ + public final static InetAddressSerializer instance = new InetAddressSerializer(); + + public InetAddressSerializer() { super(InetAddress.class); } + + @Override + public void serialize(InetAddress value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + // Ok: get textual description; choose "more specific" part + String str = value.toString().trim(); + int ix = str.indexOf('/'); + if (ix >= 0) { + if (ix == 0) { // missing host name; use address + str = str.substring(1); + } else { // otherwise use name + str = str.substring(0, ix); + } + } + jgen.writeString(str); + } + + @Override + public void serializeWithType(InetAddress value, JsonGenerator jgen, SerializerProvider provider, + TypeSerializer typeSer) + throws IOException, JsonGenerationException + { + // Better ensure we don't use specific sub-classes... + typeSer.writeTypePrefixForScalar(value, jgen, InetAddress.class); + serialize(value, jgen, provider); + typeSer.writeTypeSuffixForScalar(value, jgen); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/IterableSerializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/IterableSerializer.java new file mode 100644 index 0000000..ea74f20 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/IterableSerializer.java
@@ -0,0 +1,63 @@ +package org.codehaus.jackson.map.ser.std; + +import java.io.IOException; +import java.util.Iterator; + +import org.codehaus.jackson.JsonGenerationException; +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.map.BeanProperty; +import org.codehaus.jackson.map.JsonSerializer; +import org.codehaus.jackson.map.SerializerProvider; +import org.codehaus.jackson.map.TypeSerializer; +import org.codehaus.jackson.map.annotate.JacksonStdImpl; +import org.codehaus.jackson.type.JavaType; + +@JacksonStdImpl +public class IterableSerializer + extends AsArraySerializerBase<Iterable<?>> +{ + public IterableSerializer(JavaType elemType, boolean staticTyping, TypeSerializer vts, BeanProperty property) + { + super(Iterable.class, elemType, staticTyping, vts, property, null); + } + + @Override + public ContainerSerializerBase<?> _withValueTypeSerializer(TypeSerializer vts) { + return new IterableSerializer(_elementType, _staticTyping, vts, _property); + } + + @Override + public void serializeContents(Iterable<?> value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + Iterator<?> it = value.iterator(); + if (it.hasNext()) { + final TypeSerializer typeSer = _valueTypeSerializer; + JsonSerializer<Object> prevSerializer = null; + Class<?> prevClass = null; + + do { + Object elem = it.next(); + if (elem == null) { + provider.defaultSerializeNull(jgen); + } else { + // Minor optimization to avoid most lookups: + Class<?> cc = elem.getClass(); + JsonSerializer<Object> currSerializer; + if (cc == prevClass) { + currSerializer = prevSerializer; + } else { + currSerializer = provider.findValueSerializer(cc, _property); + prevSerializer = currSerializer; + prevClass = cc; + } + if (typeSer == null) { + currSerializer.serialize(elem, jgen, provider); + } else { + currSerializer.serializeWithType(elem, jgen, provider, typeSer); + } + } + } while (it.hasNext()); + } + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/JsonValueSerializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/JsonValueSerializer.java new file mode 100644 index 0000000..b879e2c --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/JsonValueSerializer.java
@@ -0,0 +1,233 @@ +package org.codehaus.jackson.map.ser.std; + +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.Type; + +import org.codehaus.jackson.JsonGenerationException; +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.JacksonStdImpl; +import org.codehaus.jackson.map.ser.BeanSerializer; +import org.codehaus.jackson.schema.SchemaAware; +import org.codehaus.jackson.schema.JsonSchema; +import org.codehaus.jackson.type.JavaType; + +/** + * Serializer class that can serialize Object that have a + * {@link org.codehaus.jackson.annotate.JsonValue} annotation to + * indicate that serialization should be done by calling the method + * annotated, and serializing result it returns. + * <p/> + * Implementation note: we will post-process resulting serializer + * (much like what is done with {@link BeanSerializer}) + * to figure out actual serializers for final types. This must be + * done from {@link #resolve} method, and NOT from constructor; + * otherwise we could end up with an infinite loop. + */ +@JacksonStdImpl +public class JsonValueSerializer + extends SerializerBase<Object> + implements ResolvableSerializer, SchemaAware +{ + protected final Method _accessorMethod; + + protected JsonSerializer<Object> _valueSerializer; + + protected final BeanProperty _property; + + /** + * This is a flag that is set in rare (?) cases where this serializer + * is used for "natural" types (boolean, int, String, double); and where + * we actually must force type information wrapping, even though + * one would not normally be added. + * + * @since 1.7 + */ + protected boolean _forceTypeInformation; + + /** + * @param ser Explicit serializer to use, if caller knows it (which + * occurs if and only if the "value method" was annotated with + * {@link org.codehaus.jackson.map.annotate.JsonSerialize#using}), otherwise + * null + */ + public JsonValueSerializer(Method valueMethod, JsonSerializer<Object> ser, BeanProperty property) + { + super(Object.class); + _accessorMethod = valueMethod; + _valueSerializer = ser; + _property = property; + } + + @Override + public void serialize(Object bean, JsonGenerator jgen, SerializerProvider prov) + throws IOException, JsonGenerationException + { + try { + Object value = _accessorMethod.invoke(bean); + + if (value == null) { + prov.defaultSerializeNull(jgen); + return; + } + JsonSerializer<Object> ser = _valueSerializer; + if (ser == null) { + Class<?> c = value.getClass(); + /* 10-Mar-2010, tatu: Ideally we would actually separate out type + * serializer from value serializer; but, alas, there's no access + * to serializer factory at this point... + */ + // let's cache it, may be needed soon again + ser = prov.findTypedValueSerializer(c, true, _property); + } + ser.serialize(value, jgen, prov); + } catch (IOException ioe) { + throw ioe; + } catch (Exception e) { + Throwable t = e; + // Need to unwrap this specific type, to see infinite recursion... + while (t instanceof InvocationTargetException && t.getCause() != null) { + t = t.getCause(); + } + // Errors shouldn't be wrapped (and often can't, as well) + if (t instanceof Error) { + throw (Error) t; + } + // let's try to indicate the path best we can... + throw JsonMappingException.wrapWithPath(t, bean, _accessorMethod.getName() + "()"); + } + } + + @Override + public void serializeWithType(Object bean, JsonGenerator jgen, SerializerProvider provider, + TypeSerializer typeSer) + throws IOException, JsonProcessingException + { + // Regardless of other parts, first need to find value to serialize: + Object value = null; + try { + value = _accessorMethod.invoke(bean); + + // and if we got null, can also just write it directly + if (value == null) { + provider.defaultSerializeNull(jgen); + return; + } + JsonSerializer<Object> ser = _valueSerializer; + if (ser != null) { // already got a serializer? fabulous, that be easy... + /* 09-Dec-2010, tatu: To work around natural type's refusal to add type info, we do + * this (note: type is for the wrapper type, not enclosed value!) + */ + if (_forceTypeInformation) { + typeSer.writeTypePrefixForScalar(bean, jgen); + } + ser.serializeWithType(value, jgen, provider, typeSer); + if (_forceTypeInformation) { + typeSer.writeTypeSuffixForScalar(bean, jgen); + } + return; + } + // But if not, it gets tad trickier (copied from main serialize() method) + Class<?> c = value.getClass(); + ser = provider.findTypedValueSerializer(c, true, _property); + // note: now we have bundled type serializer, so should NOT call with typed version + ser.serialize(value, jgen, provider); + } catch (IOException ioe) { + throw ioe; + } catch (Exception e) { + Throwable t = e; + // Need to unwrap this specific type, to see infinite recursion... + while (t instanceof InvocationTargetException && t.getCause() != null) { + t = t.getCause(); + } + // Errors shouldn't be wrapped (and often can't, as well) + if (t instanceof Error) { + throw (Error) t; + } + // let's try to indicate the path best we can... + throw JsonMappingException.wrapWithPath(t, bean, _accessorMethod.getName() + "()"); + } + } + + @Override + public JsonNode getSchema(SerializerProvider provider, Type typeHint) + throws JsonMappingException + { + return (_valueSerializer instanceof SchemaAware) ? + ((SchemaAware) _valueSerializer).getSchema(provider, null) : + JsonSchema.getDefaultSchemaNode(); + } + + /* + /******************************************************* + /* ResolvableSerializer impl + /******************************************************* + */ + + /** + * We can try to find the actual serializer for value, if we can + * statically figure out what the result type must be. + */ + @Override + public void resolve(SerializerProvider provider) + throws JsonMappingException + { + if (_valueSerializer == null) { + /* Note: we can only assign serializer statically if the + * declared type is final -- if not, we don't really know + * the actual type until we get the instance. + */ + // 10-Mar-2010, tatu: Except if static typing is to be used + if (provider.isEnabled(SerializationConfig.Feature.USE_STATIC_TYPING) + || Modifier.isFinal(_accessorMethod.getReturnType().getModifiers())) { + JavaType t = provider.constructType(_accessorMethod.getGenericReturnType()); + // false -> no need to cache + /* 10-Mar-2010, tatu: Ideally we would actually separate out type + * serializer from value serializer; but, alas, there's no access + * to serializer factory at this point... + */ + _valueSerializer = provider.findTypedValueSerializer(t, false, _property); + /* 09-Dec-2010, tatu: Turns out we must add special handling for + * cases where "native" (aka "natural") type is being serialized, + * using standard serializer + */ + _forceTypeInformation = isNaturalTypeWithStdHandling(t, _valueSerializer); + } + } + } + + protected boolean isNaturalTypeWithStdHandling(JavaType type, JsonSerializer<?> ser) + { + Class<?> cls = type.getRawClass(); + // First: do we have a natural type being handled? + if (type.isPrimitive()) { + if (cls != Integer.TYPE && cls != Boolean.TYPE && cls != Double.TYPE) { + return false; + } + } else { + if (cls != String.class && + cls != Integer.class && cls != Boolean.class && cls != Double.class) { + return false; + } + } + // Second: and it's handled with standard serializer? + return (ser.getClass().getAnnotation(JacksonStdImpl.class)) != null; + } + + /* + /********************************************************** + /* Other methods + /********************************************************** + */ + + @Override + public String toString() + { + return "(@JsonValue serializer for method " + _accessorMethod.getDeclaringClass() + "#" + _accessorMethod.getName() + ")"; + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/MapSerializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/MapSerializer.java new file mode 100644 index 0000000..c2c447c --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/MapSerializer.java
@@ -0,0 +1,422 @@ +package org.codehaus.jackson.map.ser.std; + +import java.io.IOException; +import java.lang.reflect.Type; +import java.util.*; + +import org.codehaus.jackson.JsonGenerationException; +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.JacksonStdImpl; +import org.codehaus.jackson.map.ser.impl.PropertySerializerMap; +import org.codehaus.jackson.map.type.TypeFactory; +import org.codehaus.jackson.node.ObjectNode; +import org.codehaus.jackson.type.JavaType; + +/** + * Standard serializer implementation for serializing {link java.util.Map} types. + *<p> + * Note: about the only configurable setting currently is ability to filter out + * entries with specified names. + */ +@JacksonStdImpl +public class MapSerializer + extends ContainerSerializerBase<Map<?,?>> + implements ResolvableSerializer +{ + protected final static JavaType UNSPECIFIED_TYPE = TypeFactory.unknownType(); + + /** + * Map-valued property being serialized with this instance + * + * @since 1.7 + */ + protected final BeanProperty _property; + + /** + * Set of entries to omit during serialization, if any + */ + protected final HashSet<String> _ignoredEntries; + + /** + * Whether static types should be used for serialization of values + * or not (if not, dynamic runtime type is used) + */ + protected final boolean _valueTypeIsStatic; + + /** + * Declared type of keys + * + * @since 1.7 + */ + protected final JavaType _keyType; + + /** + * Declared type of contained values + */ + protected final JavaType _valueType; + + /** + * Key serializer to use, if it can be statically determined + * + * @since 1.7 + */ + protected JsonSerializer<Object> _keySerializer; + + /** + * Value serializer to use, if it can be statically determined + * + * @since 1.5 + */ + protected JsonSerializer<Object> _valueSerializer; + + /** + * Type identifier serializer used for values, if any. + */ + protected final TypeSerializer _valueTypeSerializer; + + /** + * If value type can not be statically determined, mapping from + * runtime value types to serializers are stored in this object. + * + * @since 1.8 + */ + protected PropertySerializerMap _dynamicValueSerializers; + + protected MapSerializer() { + this((HashSet<String>)null, null, null, false, null, null, null, null); + } + + protected MapSerializer(HashSet<String> ignoredEntries, + JavaType keyType, JavaType valueType, boolean valueTypeIsStatic, + TypeSerializer vts, + JsonSerializer<Object> keySerializer, JsonSerializer<Object> valueSerializer, + BeanProperty property) + { + super(Map.class, false); + _property = property; + _ignoredEntries = ignoredEntries; + _keyType = keyType; + _valueType = valueType; + _valueTypeIsStatic = valueTypeIsStatic; + _valueTypeSerializer = vts; + _keySerializer = keySerializer; + _valueSerializer = valueSerializer; + _dynamicValueSerializers = PropertySerializerMap.emptyMap(); + } + + @Override + public ContainerSerializerBase<?> _withValueTypeSerializer(TypeSerializer vts) + { + MapSerializer ms = new MapSerializer(_ignoredEntries, _keyType, _valueType, _valueTypeIsStatic, vts, + _keySerializer, _valueSerializer, _property); + if (_valueSerializer != null) { + ms._valueSerializer = _valueSerializer; + } + return ms; + } + + /** + * Factory method used to construct Map serializers. + * + * @param ignoredList Array of entry names that are to be filtered on + * serialization; null if none + * @param mapType Declared type information (needed for static typing) + * @param staticValueType Whether static typing should be used for the + * Map (which includes its contents) + * @param vts Type serializer to use for map entry values, if any + * + * @deprecated As of 1.8; use the variant with more arguments + */ + @Deprecated + public static MapSerializer construct(String[] ignoredList, JavaType mapType, + boolean staticValueType, TypeSerializer vts, BeanProperty property) + { + return construct(ignoredList, mapType, staticValueType, vts, property, null, null); + } + + public static MapSerializer construct(String[] ignoredList, JavaType mapType, + boolean staticValueType, TypeSerializer vts, BeanProperty property, + JsonSerializer<Object> keySerializer, JsonSerializer<Object> valueSerializer) + { + HashSet<String> ignoredEntries = toSet(ignoredList); + JavaType keyType, valueType; + + if (mapType == null) { + keyType = valueType = UNSPECIFIED_TYPE; + } else { + keyType = mapType.getKeyType(); + valueType = mapType.getContentType(); + } + // If value type is final, it's same as forcing static value typing: + if (!staticValueType) { + staticValueType = (valueType != null && valueType.isFinal()); + } + return new MapSerializer(ignoredEntries, keyType, valueType, staticValueType, vts, + keySerializer, valueSerializer, property); + } + + private static HashSet<String> toSet(String[] ignoredEntries) { + if (ignoredEntries == null || ignoredEntries.length == 0) { + return null; + } + HashSet<String> result = new HashSet<String>(ignoredEntries.length); + for (String prop : ignoredEntries) { + result.add(prop); + } + return result; + } + + /* + /********************************************************** + /* JsonSerializer implementation + /********************************************************** + */ + + @Override + public void serialize(Map<?,?> value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + jgen.writeStartObject(); + if (!value.isEmpty()) { + if (_valueSerializer != null) { + serializeFieldsUsing(value, jgen, provider, _valueSerializer); + } else { + serializeFields(value, jgen, provider); + } + } + jgen.writeEndObject(); + } + + @Override + public void serializeWithType(Map<?,?> value, JsonGenerator jgen, SerializerProvider provider, + TypeSerializer typeSer) + throws IOException, JsonGenerationException + { + typeSer.writeTypePrefixForObject(value, jgen); + if (!value.isEmpty()) { + if (_valueSerializer != null) { + serializeFieldsUsing(value, jgen, provider, _valueSerializer); + } else { + serializeFields(value, jgen, provider); + } + } + typeSer.writeTypeSuffixForObject(value, jgen); + } + + /* + /********************************************************** + /* JsonSerializer implementation + /********************************************************** + */ + + /** + * Method called to serialize fields, when the value type is not statically known. + */ + public void serializeFields(Map<?,?> value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + // If value type needs polymorphic type handling, some more work needed: + if (_valueTypeSerializer != null) { + serializeTypedFields(value, jgen, provider); + return; + } + final JsonSerializer<Object> keySerializer = _keySerializer; + + final HashSet<String> ignored = _ignoredEntries; + final boolean skipNulls = !provider.isEnabled(SerializationConfig.Feature.WRITE_NULL_MAP_VALUES); + + PropertySerializerMap serializers = _dynamicValueSerializers; + + for (Map.Entry<?,?> entry : value.entrySet()) { + Object valueElem = entry.getValue(); + // First, serialize key + Object keyElem = entry.getKey(); + if (keyElem == null) { + provider.getNullKeySerializer().serialize(null, jgen, provider); + } else { + // [JACKSON-314] skip entries with null values? + if (skipNulls && valueElem == null) continue; + // One twist: is entry ignorable? If so, skip + if (ignored != null && ignored.contains(keyElem)) continue; + keySerializer.serialize(keyElem, jgen, provider); + } + + // And then value + if (valueElem == null) { + provider.defaultSerializeNull(jgen); + } else { + Class<?> cc = valueElem.getClass(); + JsonSerializer<Object> serializer = serializers.serializerFor(cc); + if (serializer == null) { + if (_valueType.hasGenericTypes()) { + serializer = _findAndAddDynamic(serializers, + provider.constructSpecializedType(_valueType, cc), provider); + } else { + serializer = _findAndAddDynamic(serializers, cc, provider); + } + serializers = _dynamicValueSerializers; + } + try { + serializer.serialize(valueElem, jgen, provider); + } catch (Exception e) { + // [JACKSON-55] Need to add reference information + String keyDesc = ""+keyElem; + wrapAndThrow(provider, e, value, keyDesc); + } + } + } + } + + /** + * Method called to serialize fields, when the value type is statically known, + * so that value serializer is passed and does not need to be fetched from + * provider. + */ + protected void serializeFieldsUsing(Map<?,?> value, JsonGenerator jgen, SerializerProvider provider, + JsonSerializer<Object> ser) + throws IOException, JsonGenerationException + { + final JsonSerializer<Object> keySerializer = _keySerializer; + final HashSet<String> ignored = _ignoredEntries; + final TypeSerializer typeSer = _valueTypeSerializer; + final boolean skipNulls = !provider.isEnabled(SerializationConfig.Feature.WRITE_NULL_MAP_VALUES); + + for (Map.Entry<?,?> entry : value.entrySet()) { + Object valueElem = entry.getValue(); + Object keyElem = entry.getKey(); + if (keyElem == null) { + provider.getNullKeySerializer().serialize(null, jgen, provider); + } else { + // [JACKSON-314] also may need to skip entries with null values + if (skipNulls && valueElem == null) continue; + if (ignored != null && ignored.contains(keyElem)) continue; + keySerializer.serialize(keyElem, jgen, provider); + } + if (valueElem == null) { + provider.defaultSerializeNull(jgen); + } else { + try { + if (typeSer == null) { + ser.serialize(valueElem, jgen, provider); + } else { + ser.serializeWithType(valueElem, jgen, provider, typeSer); + } + } catch (Exception e) { + // [JACKSON-55] Need to add reference information + String keyDesc = ""+keyElem; + wrapAndThrow(provider, e, value, keyDesc); + } + } + } + } + + protected void serializeTypedFields(Map<?,?> value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + final JsonSerializer<Object> keySerializer = _keySerializer; + JsonSerializer<Object> prevValueSerializer = null; + Class<?> prevValueClass = null; + final HashSet<String> ignored = _ignoredEntries; + final boolean skipNulls = !provider.isEnabled(SerializationConfig.Feature.WRITE_NULL_MAP_VALUES); + + for (Map.Entry<?,?> entry : value.entrySet()) { + Object valueElem = entry.getValue(); + // First, serialize key + Object keyElem = entry.getKey(); + if (keyElem == null) { + provider.getNullKeySerializer().serialize(null, jgen, provider); + } else { + // [JACKSON-314] also may need to skip entries with null values + if (skipNulls && valueElem == null) continue; + // One twist: is entry ignorable? If so, skip + if (ignored != null && ignored.contains(keyElem)) continue; + keySerializer.serialize(keyElem, jgen, provider); + } + + // And then value + if (valueElem == null) { + provider.defaultSerializeNull(jgen); + } else { + Class<?> cc = valueElem.getClass(); + JsonSerializer<Object> currSerializer; + if (cc == prevValueClass) { + currSerializer = prevValueSerializer; + } else { + currSerializer = provider.findValueSerializer(cc, _property); + prevValueSerializer = currSerializer; + prevValueClass = cc; + } + try { + currSerializer.serializeWithType(valueElem, jgen, provider, _valueTypeSerializer); + } catch (Exception e) { + // [JACKSON-55] Need to add reference information + String keyDesc = ""+keyElem; + wrapAndThrow(provider, e, value, keyDesc); + } + } + } + } + + @Override + public JsonNode getSchema(SerializerProvider provider, Type typeHint) + { + ObjectNode o = createSchemaNode("object", true); + //(ryan) even though it's possible to statically determine the "value" type of the map, + // there's no way to statically determine the keys, so the "Entries" can't be determined. + return o; + } + + /** + * Need to get callback to resolve value serializer, if static typing + * is used (either being forced, or because value type is final) + */ + @Override + public void resolve(SerializerProvider provider) + throws JsonMappingException + { + if (_valueTypeIsStatic && _valueSerializer == null) { + _valueSerializer = provider.findValueSerializer(_valueType, _property); + } + /* 10-Dec-2010, tatu: Let's also fetch key serializer; and always assume we'll + * do that just by using static type information + */ + /* 25-Feb-2011, tatu: May need to reconsider this static checking (since it + * differs from value handling)... but for now, it's ok to ensure contextual + * aspects are handled; this is done by provider. + */ + if (_keySerializer == null) { + _keySerializer = provider.findKeySerializer(_keyType, _property); + } + } + + /* + /********************************************************** + /* Internal methods + /********************************************************** + */ + + protected final JsonSerializer<Object> _findAndAddDynamic(PropertySerializerMap map, + Class<?> type, SerializerProvider provider) throws JsonMappingException + { + PropertySerializerMap.SerializerAndMapResult result = map.findAndAddSerializer(type, provider, _property); + // did we get a new map of serializers? If so, start using it + if (map != result.map) { + _dynamicValueSerializers = result.map; + } + return result.serializer; + } + + protected final JsonSerializer<Object> _findAndAddDynamic(PropertySerializerMap map, + JavaType type, SerializerProvider provider) throws JsonMappingException + { + PropertySerializerMap.SerializerAndMapResult result = map.findAndAddSerializer(type, provider, _property); + if (map != result.map) { + _dynamicValueSerializers = result.map; + } + return result.serializer; + } + +} +
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/NonTypedScalarSerializerBase.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/NonTypedScalarSerializerBase.java new file mode 100644 index 0000000..240f502 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/NonTypedScalarSerializerBase.java
@@ -0,0 +1,34 @@ +package org.codehaus.jackson.map.ser.std; + +import java.io.IOException; + +import org.codehaus.jackson.JsonGenerationException; +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.map.SerializerProvider; +import org.codehaus.jackson.map.TypeSerializer; + +/** + * Intermediate base class for limited number of scalar types + * that should never include type information. These are "native" + * types that are default mappings for corresponding JSON scalar + * types: {@link java.lang.String}, {@link java.lang.Integer}, + * {@link java.lang.Double} and {@link java.lang.Boolean}. + * + * @since 1.9 (refactored from 'org.codehaus.jackson.map.StdSerializers#NontTypedScalarSerializer') + */ +public abstract class NonTypedScalarSerializerBase<T> + extends ScalarSerializerBase<T> +{ + protected NonTypedScalarSerializerBase(Class<T> t) { + super(t); + } + + @Override + public final void serializeWithType(T value, JsonGenerator jgen, SerializerProvider provider, + TypeSerializer typeSer) + throws IOException, JsonGenerationException + { + // no type info, just regular serialization + serialize(value, jgen, provider); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/NullSerializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/NullSerializer.java new file mode 100644 index 0000000..2b63e5e --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/NullSerializer.java
@@ -0,0 +1,38 @@ +package org.codehaus.jackson.map.ser.std; + +import java.lang.reflect.Type; +import java.io.IOException; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.JacksonStdImpl; + +/** + * This is a simple dummy serializer that will just output literal + * JSON null value whenever serialization is requested. + * Used as the default "null serializer" (which is used for serializing + * null object references unless overridden), as well as for some + * more exotic types (java.lang.Void). + */ +@JacksonStdImpl +public class NullSerializer + extends SerializerBase<Object> +{ + public final static NullSerializer instance = new NullSerializer(); + + private NullSerializer() { super(Object.class); } + + @Override + public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + jgen.writeNull(); + } + + @Override + public JsonNode getSchema(SerializerProvider provider, Type typeHint) + throws JsonMappingException + { + return createSchemaNode("null"); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/ObjectArraySerializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/ObjectArraySerializer.java new file mode 100644 index 0000000..ef93788 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/ObjectArraySerializer.java
@@ -0,0 +1,281 @@ +package org.codehaus.jackson.map.ser.std; + +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Type; + +import org.codehaus.jackson.JsonGenerationException; +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.map.BeanProperty; +import org.codehaus.jackson.map.JsonMappingException; +import org.codehaus.jackson.map.JsonSerializer; +import org.codehaus.jackson.map.ResolvableSerializer; +import org.codehaus.jackson.map.SerializerProvider; +import org.codehaus.jackson.map.TypeSerializer; +import org.codehaus.jackson.map.annotate.JacksonStdImpl; +import org.codehaus.jackson.map.ser.impl.PropertySerializerMap; +import org.codehaus.jackson.map.type.ArrayType; +import org.codehaus.jackson.node.ObjectNode; +import org.codehaus.jackson.schema.JsonSchema; +import org.codehaus.jackson.schema.SchemaAware; +import org.codehaus.jackson.type.JavaType; + +/** + * Generic serializer for Object arrays (<code>Object[]</code>). + * + * @since 1.9 (moved from 'org.codehaus.jackson.map.ser.impl.ObjectArraySerializer') + */ +@JacksonStdImpl +public class ObjectArraySerializer + extends StdArraySerializers.ArraySerializerBase<Object[]> + implements ResolvableSerializer +{ + /** + * Whether we are using static typing (using declared types, ignoring + * runtime type) or not for elements. + */ + protected final boolean _staticTyping; + + /** + * Declared type of element entries + */ + protected final JavaType _elementType; + + /** + * Value serializer to use, if it can be statically determined. + * + * @since 1.5 + */ + protected JsonSerializer<Object> _elementSerializer; + + /** + * If element type can not be statically determined, mapping from + * runtime type to serializer is handled using this object + * + * @since 1.7 + */ + protected PropertySerializerMap _dynamicSerializers; + + /** + * @deprecated since 1.8 + */ + @Deprecated + public ObjectArraySerializer(JavaType elemType, boolean staticTyping, + TypeSerializer vts, BeanProperty property) + { + this(elemType, staticTyping, vts, property, null); + } + + public ObjectArraySerializer(JavaType elemType, boolean staticTyping, + TypeSerializer vts, BeanProperty property, JsonSerializer<Object> elementSerializer) + { + super(Object[].class, vts, property); + _elementType = elemType; + _staticTyping = staticTyping; + _dynamicSerializers = PropertySerializerMap.emptyMap(); + _elementSerializer = elementSerializer; + } + + @Override + public ContainerSerializerBase<?> _withValueTypeSerializer(TypeSerializer vts) + { + return new ObjectArraySerializer(_elementType, _staticTyping, vts, _property, _elementSerializer); + } + + @Override + public void serializeContents(Object[] value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + final int len = value.length; + if (len == 0) { + return; + } + if (_elementSerializer != null) { + serializeContentsUsing(value, jgen, provider, _elementSerializer); + return; + } + if (_valueTypeSerializer != null) { + serializeTypedContents(value, jgen, provider); + return; + } + int i = 0; + Object elem = null; + try { + PropertySerializerMap serializers = _dynamicSerializers; + for (; i < len; ++i) { + elem = value[i]; + if (elem == null) { + provider.defaultSerializeNull(jgen); + continue; + } + Class<?> cc = elem.getClass(); + JsonSerializer<Object> serializer = serializers.serializerFor(cc); + if (serializer == null) { + // To fix [JACKSON-508] + if (_elementType.hasGenericTypes()) { + serializer = _findAndAddDynamic(serializers, + provider.constructSpecializedType(_elementType, cc), provider); + } else { + serializer = _findAndAddDynamic(serializers, cc, provider); + } + } + serializer.serialize(elem, jgen, provider); + } + } catch (IOException ioe) { + throw ioe; + } catch (Exception e) { + // [JACKSON-55] Need to add reference information + /* 05-Mar-2009, tatu: But one nasty edge is when we get + * StackOverflow: usually due to infinite loop. But that gets + * hidden within an InvocationTargetException... + */ + Throwable t = e; + while (t instanceof InvocationTargetException && t.getCause() != null) { + t = t.getCause(); + } + if (t instanceof Error) { + throw (Error) t; + } + throw JsonMappingException.wrapWithPath(t, elem, i); + } + } + + public void serializeContentsUsing(Object[] value, JsonGenerator jgen, SerializerProvider provider, + JsonSerializer<Object> ser) + throws IOException, JsonGenerationException + { + final int len = value.length; + final TypeSerializer typeSer = _valueTypeSerializer; + + int i = 0; + Object elem = null; + try { + for (; i < len; ++i) { + elem = value[i]; + if (elem == null) { + provider.defaultSerializeNull(jgen); + continue; + } + if (typeSer == null) { + ser.serialize(elem, jgen, provider); + } else { + ser.serializeWithType(elem, jgen, provider, typeSer); + } + } + } catch (IOException ioe) { + throw ioe; + } catch (Exception e) { + Throwable t = e; + while (t instanceof InvocationTargetException && t.getCause() != null) { + t = t.getCause(); + } + if (t instanceof Error) { + throw (Error) t; + } + throw JsonMappingException.wrapWithPath(t, elem, i); + } + } + + public void serializeTypedContents(Object[] value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + final int len = value.length; + final TypeSerializer typeSer = _valueTypeSerializer; + int i = 0; + Object elem = null; + try { + PropertySerializerMap serializers = _dynamicSerializers; + for (; i < len; ++i) { + elem = value[i]; + if (elem == null) { + provider.defaultSerializeNull(jgen); + continue; + } + Class<?> cc = elem.getClass(); + JsonSerializer<Object> serializer = serializers.serializerFor(cc); + if (serializer == null) { + serializer = _findAndAddDynamic(serializers, cc, provider); + } + serializer.serializeWithType(elem, jgen, provider, typeSer); + } + } catch (IOException ioe) { + throw ioe; + } catch (Exception e) { + Throwable t = e; + while (t instanceof InvocationTargetException && t.getCause() != null) { + t = t.getCause(); + } + if (t instanceof Error) { + throw (Error) t; + } + throw JsonMappingException.wrapWithPath(t, elem, i); + } + } + + @Override + public JsonNode getSchema(SerializerProvider provider, Type typeHint) + throws JsonMappingException + { + ObjectNode o = createSchemaNode("array", true); + if (typeHint != null) { + JavaType javaType = provider.constructType(typeHint); + if (javaType.isArrayType()) { + Class<?> componentType = ((ArrayType) javaType).getContentType().getRawClass(); + // 15-Oct-2010, tatu: We can't serialize plain Object.class; but what should it produce here? Untyped? + if (componentType == Object.class) { + o.put("items", JsonSchema.getDefaultSchemaNode()); + } else { + JsonSerializer<Object> ser = provider.findValueSerializer(componentType, _property); + JsonNode schemaNode = (ser instanceof SchemaAware) ? + ((SchemaAware) ser).getSchema(provider, null) : + JsonSchema.getDefaultSchemaNode(); + o.put("items", schemaNode); + } + } + } + return o; + } + + /** + * Need to get callback to resolve value serializer, if static typing + * is used (either being forced, or because value type is final) + */ + @Override + public void resolve(SerializerProvider provider) + throws JsonMappingException + { + if (_staticTyping && _elementSerializer == null) { + _elementSerializer = provider.findValueSerializer(_elementType, _property); + } + } + + /** + * @since 1.7 + */ + protected final JsonSerializer<Object> _findAndAddDynamic(PropertySerializerMap map, + Class<?> type, SerializerProvider provider) throws JsonMappingException + { + PropertySerializerMap.SerializerAndMapResult result = map.findAndAddSerializer(type, provider, _property); + // did we get a new map of serializers? If so, start using it + if (map != result.map) { + _dynamicSerializers = result.map; + } + return result.serializer; + } + + /** + * @since 1.8 + */ + protected final JsonSerializer<Object> _findAndAddDynamic(PropertySerializerMap map, + JavaType type, SerializerProvider provider) throws JsonMappingException + { + PropertySerializerMap.SerializerAndMapResult result = map.findAndAddSerializer(type, provider, _property); + // did we get a new map of serializers? If so, start using it + if (map != result.map) { + _dynamicSerializers = result.map; + } + return result.serializer; + } + +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/RawSerializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/RawSerializer.java new file mode 100644 index 0000000..c5ea2d6 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/RawSerializer.java
@@ -0,0 +1,52 @@ +package org.codehaus.jackson.map.ser.std; + +import java.lang.reflect.Type; +import java.io.IOException; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.JacksonStdImpl; + +/** + * This is a simple dummy serializer that will just output raw values by calling toString() + * on value to serialize. + * + * @since 1.7 + */ +@JacksonStdImpl +public class RawSerializer<T> + extends SerializerBase<T> +{ + /** + * Constructor takes in expected type of values; but since caller + * typically can not really provide actual type parameter, we will + * just take wild card and coerce type. + */ + public RawSerializer(Class<?> cls) { + super(cls, false); + } + + @Override + public void serialize(T value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + jgen.writeRawValue(value.toString()); + } + + @Override + public void serializeWithType(T value, JsonGenerator jgen, SerializerProvider provider, + TypeSerializer typeSer) + throws IOException, JsonProcessingException + { + typeSer.writeTypePrefixForScalar(value, jgen); + serialize(value, jgen, provider); + typeSer.writeTypeSuffixForScalar(value, jgen); + } + + @Override + public JsonNode getSchema(SerializerProvider provider, Type typeHint) + { + // type not really known, but since it is a JSON string: + return createSchemaNode("string", true); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/ScalarSerializerBase.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/ScalarSerializerBase.java new file mode 100644 index 0000000..3626915 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/ScalarSerializerBase.java
@@ -0,0 +1,52 @@ +package org.codehaus.jackson.map.ser.std; + +import java.io.IOException; +import java.lang.reflect.Type; + +import org.codehaus.jackson.JsonGenerationException; +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.map.JsonMappingException; +import org.codehaus.jackson.map.SerializerProvider; +import org.codehaus.jackson.map.TypeSerializer; + +public abstract class ScalarSerializerBase<T> + extends SerializerBase<T> +{ + protected ScalarSerializerBase(Class<T> t) { + super(t); + } + + /** + * Alternate constructor that is (alas!) needed to work + * around kinks of generic type handling + */ + @SuppressWarnings("unchecked") + protected ScalarSerializerBase(Class<?> t, boolean dummy) { + super((Class<T>) t); + } + + /** + * Default implementation will write type prefix, call regular serialization + * method (since assumption is that value itself does not need JSON + * Array or Object start/end markers), and then write type suffix. + * This should work for most cases; some sub-classes may want to + * change this behavior. + */ + @Override + public void serializeWithType(T value, JsonGenerator jgen, SerializerProvider provider, + TypeSerializer typeSer) + throws IOException, JsonGenerationException + { + typeSer.writeTypePrefixForScalar(value, jgen); + serialize(value, jgen, provider); + typeSer.writeTypeSuffixForScalar(value, jgen); + } + + @Override + public JsonNode getSchema(SerializerProvider provider, Type typeHint) + throws JsonMappingException + { + return createSchemaNode("string", true); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/SerializableSerializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/SerializableSerializer.java new file mode 100644 index 0000000..5336833 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/SerializableSerializer.java
@@ -0,0 +1,99 @@ +package org.codehaus.jackson.map.ser.std; + +import java.io.IOException; +import java.lang.reflect.Type; + +import org.codehaus.jackson.JsonGenerationException; +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.map.JsonMappingException; +import org.codehaus.jackson.map.JsonSerializable; +import org.codehaus.jackson.map.JsonSerializableWithType; +import org.codehaus.jackson.map.ObjectMapper; +import org.codehaus.jackson.map.SerializerProvider; +import org.codehaus.jackson.map.TypeSerializer; +import org.codehaus.jackson.map.annotate.JacksonStdImpl; +import org.codehaus.jackson.map.ser.SerializerBase; +import org.codehaus.jackson.map.type.TypeFactory; +import org.codehaus.jackson.node.ObjectNode; +import org.codehaus.jackson.schema.JsonSerializableSchema; + +/** + * Generic handler for types that implement {@link JsonSerializable}. + *<p> + * Note: given that this is used for anything that implements + * interface, can not be checked for direct class equivalence. + */ +@JacksonStdImpl +@SuppressWarnings("deprecation") +public class SerializableSerializer + extends SerializerBase<JsonSerializable> +{ + public final static SerializableSerializer instance = new SerializableSerializer(); + + protected SerializableSerializer() { super(JsonSerializable.class); } + + @Override + public void serialize(JsonSerializable value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + value.serialize(jgen, provider); + } + + @Override + public final void serializeWithType(JsonSerializable value, JsonGenerator jgen, SerializerProvider provider, + TypeSerializer typeSer) + throws IOException, JsonGenerationException + { + /* 24-Jan-2009, tatus: This is not quite optimal (perhaps we should + * just create separate serializer...), but works until 2.0 will + * deprecate non-typed interface + */ + if (value instanceof JsonSerializableWithType) { + ((JsonSerializableWithType) value).serializeWithType(jgen, provider, typeSer); + } else { + this.serialize(value, jgen, provider); + } + } + + @Override + public JsonNode getSchema(SerializerProvider provider, Type typeHint) + throws JsonMappingException + { + ObjectNode objectNode = createObjectNode(); + String schemaType = "any"; + String objectProperties = null; + String itemDefinition = null; + if (typeHint != null) { + Class<?> rawClass = TypeFactory.type(typeHint).getRawClass(); + if (rawClass.isAnnotationPresent(JsonSerializableSchema.class)) { + JsonSerializableSchema schemaInfo = rawClass.getAnnotation(JsonSerializableSchema.class); + schemaType = schemaInfo.schemaType(); + if (!"##irrelevant".equals(schemaInfo.schemaObjectPropertiesDefinition())) { + objectProperties = schemaInfo.schemaObjectPropertiesDefinition(); + } + if (!"##irrelevant".equals(schemaInfo.schemaItemDefinition())) { + itemDefinition = schemaInfo.schemaItemDefinition(); + } + } + } + objectNode.put("type", schemaType); + if (objectProperties != null) { + try { + objectNode.put("properties", new ObjectMapper().readValue(objectProperties, JsonNode.class)); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + if (itemDefinition != null) { + try { + objectNode.put("items", new ObjectMapper().readValue(itemDefinition, JsonNode.class)); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + // always optional, no need to specify: + //objectNode.put("required", false); + return objectNode; + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/SerializableWithTypeSerializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/SerializableWithTypeSerializer.java new file mode 100644 index 0000000..7321b82 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/SerializableWithTypeSerializer.java
@@ -0,0 +1,90 @@ +package org.codehaus.jackson.map.ser.std; + +import java.io.IOException; +import java.lang.reflect.Type; + +import org.codehaus.jackson.JsonGenerationException; +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.map.JsonMappingException; +import org.codehaus.jackson.map.JsonSerializableWithType; +import org.codehaus.jackson.map.ObjectMapper; +import org.codehaus.jackson.map.SerializerProvider; +import org.codehaus.jackson.map.TypeSerializer; +import org.codehaus.jackson.map.annotate.JacksonStdImpl; +import org.codehaus.jackson.map.type.TypeFactory; +import org.codehaus.jackson.node.ObjectNode; +import org.codehaus.jackson.schema.JsonSerializableSchema; + +/** + * Generic handler for types that implement {@link JsonSerializableWithType}. + *<p> + * Note: given that this is used for anything that implements + * interface, can not be checked for direct class equivalence. + */ +@JacksonStdImpl +public class SerializableWithTypeSerializer + extends SerializerBase<JsonSerializableWithType> +{ + public final static SerializableWithTypeSerializer instance = new SerializableWithTypeSerializer(); + + protected SerializableWithTypeSerializer() { super(JsonSerializableWithType.class); } + + @SuppressWarnings("deprecation") // why is this needed? + @Override + public void serialize(JsonSerializableWithType value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + value.serialize(jgen, provider); + } + + @Override + public final void serializeWithType(JsonSerializableWithType value, JsonGenerator jgen, SerializerProvider provider, + TypeSerializer typeSer) + throws IOException, JsonGenerationException + { + value.serializeWithType(jgen, provider, typeSer); + } + + // copied verbatim from "JsonSerializableSerializer" + @Override + public JsonNode getSchema(SerializerProvider provider, Type typeHint) + throws JsonMappingException + { + ObjectNode objectNode = createObjectNode(); + String schemaType = "any"; + String objectProperties = null; + String itemDefinition = null; + if (typeHint != null) { + Class<?> rawClass = TypeFactory.rawClass(typeHint); + if (rawClass.isAnnotationPresent(JsonSerializableSchema.class)) { + JsonSerializableSchema schemaInfo = rawClass.getAnnotation(JsonSerializableSchema.class); + schemaType = schemaInfo.schemaType(); + if (!"##irrelevant".equals(schemaInfo.schemaObjectPropertiesDefinition())) { + objectProperties = schemaInfo.schemaObjectPropertiesDefinition(); + } + if (!"##irrelevant".equals(schemaInfo.schemaItemDefinition())) { + itemDefinition = schemaInfo.schemaItemDefinition(); + } + } + } + objectNode.put("type", schemaType); + if (objectProperties != null) { + try { + objectNode.put("properties", new ObjectMapper().readValue(objectProperties, JsonNode.class)); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + if (itemDefinition != null) { + try { + objectNode.put("items", new ObjectMapper().readValue(itemDefinition, JsonNode.class)); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + // always optional, no need to specify: + //objectNode.put("required", false); + return objectNode; + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/SerializerBase.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/SerializerBase.java new file mode 100644 index 0000000..bc9eaea --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/SerializerBase.java
@@ -0,0 +1,184 @@ +package org.codehaus.jackson.map.ser.std; + +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Type; + +import org.codehaus.jackson.JsonGenerationException; +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.JacksonStdImpl; +import org.codehaus.jackson.node.JsonNodeFactory; +import org.codehaus.jackson.node.ObjectNode; +import org.codehaus.jackson.schema.SchemaAware; +import org.codehaus.jackson.type.JavaType; + +/** + * Base class used by all standard serializers. Provides some convenience + * methods for implementing {@link SchemaAware} + * + * @since 1.9 (renamed from 'org.codehaus.jackson.map.ser.SerializerBase') + */ +public abstract class SerializerBase<T> + extends JsonSerializer<T> + implements SchemaAware +{ + protected final Class<T> _handledType; + + protected SerializerBase(Class<T> t) { + _handledType = t; + } + + /** + * @since 1.7 + */ + @SuppressWarnings("unchecked") + protected SerializerBase(JavaType type) { + _handledType = (Class<T>) type.getRawClass(); + } + + /** + * Alternate constructor that is (alas!) needed to work + * around kinks of generic type handling + */ + @SuppressWarnings("unchecked") + protected SerializerBase(Class<?> t, boolean dummy) { + _handledType = (Class<T>) t; + } + + @Override + public final Class<T> handledType() { return _handledType; } + + @Override + public abstract void serialize(T value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException; + + /** + * Note: since Jackson 1.9, default implementation claims type is "string" + */ + @Override + public JsonNode getSchema(SerializerProvider provider, Type typeHint) + throws JsonMappingException + { + return createSchemaNode("string"); + } + + protected ObjectNode createObjectNode() { + return JsonNodeFactory.instance.objectNode(); + } + + protected ObjectNode createSchemaNode(String type) + { + ObjectNode schema = createObjectNode(); + schema.put("type", type); + return schema; + } + + protected ObjectNode createSchemaNode(String type, boolean isOptional) + { + ObjectNode schema = createSchemaNode(type); + // as per [JACKSON-563]. Note that 'required' defaults to false + if (!isOptional) { + schema.put("required", !isOptional); + } + return schema; + } + + /** + * Method that can be called to determine if given serializer is the default + * serializer Jackson uses; as opposed to a custom serializer installed by + * a module or calling application. Determination is done using + * {@link JacksonStdImpl} annotation on serializer class. + * + * @since 1.7 + */ + protected boolean isDefaultSerializer(JsonSerializer<?> serializer) + { + return (serializer != null && serializer.getClass().getAnnotation(JacksonStdImpl.class) != null); + } + + /** + * Method that will modify caught exception (passed in as argument) + * as necessary to include reference information, and to ensure it + * is a subtype of {@link IOException}, or an unchecked exception. + *<p> + * Rules for wrapping and unwrapping are bit complicated; essentially: + *<ul> + * <li>Errors are to be passed as is (if uncovered via unwrapping) + * <li>"Plain" IOExceptions (ones that are not of type + * {@link JsonMappingException} are to be passed as is + *</ul> + */ + public void wrapAndThrow(SerializerProvider provider, + Throwable t, Object bean, String fieldName) + throws IOException + { + /* 05-Mar-2009, tatu: But one nasty edge is when we get + * StackOverflow: usually due to infinite loop. But that + * usually gets hidden within an InvocationTargetException... + */ + while (t instanceof InvocationTargetException && t.getCause() != null) { + t = t.getCause(); + } + // Errors and "plain" IOExceptions to be passed as is + if (t instanceof Error) { + throw (Error) t; + } + // Ditto for IOExceptions... except for mapping exceptions! + boolean wrap = (provider == null) || provider.isEnabled(SerializationConfig.Feature.WRAP_EXCEPTIONS); + if (t instanceof IOException) { + if (!wrap || !(t instanceof JsonMappingException)) { + throw (IOException) t; + } + } else if (!wrap) { // [JACKSON-407] -- allow disabling wrapping for unchecked exceptions + if (t instanceof RuntimeException) { + throw (RuntimeException) t; + } + } + // [JACKSON-55] Need to add reference information + throw JsonMappingException.wrapWithPath(t, bean, fieldName); + } + + public void wrapAndThrow(SerializerProvider provider, + Throwable t, Object bean, int index) + throws IOException + { + while (t instanceof InvocationTargetException && t.getCause() != null) { + t = t.getCause(); + } + // Errors are to be passed as is + if (t instanceof Error) { + throw (Error) t; + } + // Ditto for IOExceptions... except for mapping exceptions! + boolean wrap = (provider == null) || provider.isEnabled(SerializationConfig.Feature.WRAP_EXCEPTIONS); + if (t instanceof IOException) { + if (!wrap || !(t instanceof JsonMappingException)) { + throw (IOException) t; + } + } else if (!wrap) { // [JACKSON-407] -- allow disabling wrapping for unchecked exceptions + if (t instanceof RuntimeException) { + throw (RuntimeException) t; + } + } + // [JACKSON-55] Need to add reference information + throw JsonMappingException.wrapWithPath(t, bean, index); + } + + /** + * @deprecated Use version that takes <code>SerializerProvider</code> instead. + */ + @Deprecated + public void wrapAndThrow(Throwable t, Object bean, String fieldName) throws IOException { + wrapAndThrow(null, t, bean, fieldName); + } + + /** + * @deprecated Use version that takes <code>SerializerProvider</code> instead. + */ + @Deprecated + public void wrapAndThrow(Throwable t, Object bean, int index) throws IOException { + wrapAndThrow(null, t, bean, index); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/StaticListSerializerBase.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/StaticListSerializerBase.java new file mode 100644 index 0000000..617e777 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/StaticListSerializerBase.java
@@ -0,0 +1,46 @@ +package org.codehaus.jackson.map.ser.std; + +import java.lang.reflect.Type; +import java.util.*; + +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.map.BeanProperty; +import org.codehaus.jackson.map.SerializerProvider; +import org.codehaus.jackson.node.ObjectNode; + +/** + * Intermediate base class for Lists, Collections and Arrays + * that contain static (non-dynamic) value types. + * + * @since 1.7 + */ +public abstract class StaticListSerializerBase<T extends Collection<?>> + extends SerializerBase<T> +{ + /** + * Property that contains String List to serialize, if known. + */ + protected final BeanProperty _property; + + protected StaticListSerializerBase(Class<?> cls, BeanProperty property) + { + super(cls, false); + _property = property; + } + + @Override + public JsonNode getSchema(SerializerProvider provider, Type typeHint) + { + ObjectNode o = createSchemaNode("array", true); + o.put("items", contentSchema()); + return o; + } + + /* + /********************************************************** + /* Abstract methods for sub-classes to implement + /********************************************************** + */ + + protected abstract JsonNode contentSchema(); +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/StdArraySerializers.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/StdArraySerializers.java new file mode 100644 index 0000000..52549e1 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/StdArraySerializers.java
@@ -0,0 +1,476 @@ +package org.codehaus.jackson.map.ser.std; + +import java.io.IOException; +import java.lang.reflect.Type; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.node.ObjectNode; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.JacksonStdImpl; + +/** + * Dummy container class to group standard homogenous array serializer implementations + * (primitive arrays and String array). + */ +public class StdArraySerializers +{ + protected StdArraySerializers() { } + + /* + /********************************************************** + /* Base classes + /********************************************************** + */ + + /** + * Base class for serializers that will output contents as JSON + * arrays. + */ + public abstract static class ArraySerializerBase<T> + extends ContainerSerializerBase<T> + { + /** + * Type serializer used for values, if any. + */ + protected final TypeSerializer _valueTypeSerializer; + + /** + * Array-valued property being serialized with this instance + * + * @since 1.7 + */ + protected final BeanProperty _property; + + protected ArraySerializerBase(Class<T> cls, TypeSerializer vts, BeanProperty property) + { + super(cls); + _valueTypeSerializer = vts; + _property = property; + } + + @Override + public final void serialize(T value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + jgen.writeStartArray(); + serializeContents(value, jgen, provider); + jgen.writeEndArray(); + } + + @Override + public final void serializeWithType(T value, JsonGenerator jgen, SerializerProvider provider, + TypeSerializer typeSer) + throws IOException, JsonGenerationException + { + typeSer.writeTypePrefixForArray(value, jgen); + serializeContents(value, jgen, provider); + typeSer.writeTypeSuffixForArray(value, jgen); + } + + protected abstract void serializeContents(T value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException; + } + + /* + **************************************************************** + /* Concrete serializers, arrays + **************************************************************** + */ + + /** + * Standard serializer used for <code>String[]</code> values. + */ + @JacksonStdImpl + public final static class StringArraySerializer + extends ArraySerializerBase<String[]> + implements ResolvableSerializer + { + /** + * Value serializer to use, if it's not the standard one + * (if it is we can optimize serialization a lot) + * + * @since 1.7 + */ + protected JsonSerializer<Object> _elementSerializer; + + public StringArraySerializer(BeanProperty prop) { + super(String[].class, null, prop); + } + + /** + * Strings never add type info; hence, even if type serializer is suggested, + * we'll ignore it... + */ + @Override + public ContainerSerializerBase<?> _withValueTypeSerializer(TypeSerializer vts) { + return this; + } + + @Override + public void serializeContents(String[] value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + final int len = value.length; + if (len == 0) { + return; + } + if (_elementSerializer != null) { + serializeContentsSlow(value, jgen, provider, _elementSerializer); + return; + } + /* 08-Dec-2008, tatus: If we want this to be fully overridable + * (for example, to support String cleanup during writing + * or something), we should find serializer by provider. + * But for now, that seems like an overkill: and caller can + * add custom serializer if that is needed as well. + * (ditto for null values) + */ + //JsonSerializer<String> ser = (JsonSerializer<String>)provider.findValueSerializer(String.class); + for (int i = 0; i < len; ++i) { + String str = value[i]; + if (str == null) { + jgen.writeNull(); + } else { + //ser.serialize(value[i], jgen, provider); + jgen.writeString(value[i]); + } + } + } + + private void serializeContentsSlow(String[] value, JsonGenerator jgen, SerializerProvider provider, + JsonSerializer<Object> ser) + throws IOException, JsonGenerationException + { + for (int i = 0, len = value.length; i < len; ++i) { + String str = value[i]; + if (str == null) { + provider.defaultSerializeNull(jgen); + } else { + ser.serialize(value[i], jgen, provider); + } + } + } + + /** + * Need to get callback to resolve value serializer, which may + * be overridden by custom serializer + */ + @Override + public void resolve(SerializerProvider provider) + throws JsonMappingException + { + JsonSerializer<Object> ser = provider.findValueSerializer(String.class, _property); + // Retain if not the standard implementation + if (ser != null && ser.getClass().getAnnotation(JacksonStdImpl.class) == null) { + _elementSerializer = ser; + } + } + + @Override + public JsonNode getSchema(SerializerProvider provider, Type typeHint) + { + ObjectNode o = createSchemaNode("array", true); + o.put("items", createSchemaNode("string")); + return o; + } + } + + @JacksonStdImpl + public final static class BooleanArraySerializer + extends ArraySerializerBase<boolean[]> + { + public BooleanArraySerializer() { super(boolean[].class, null, null); } + + /** + * Booleans never add type info; hence, even if type serializer is suggested, + * we'll ignore it... + */ + @Override + public ContainerSerializerBase<?> _withValueTypeSerializer(TypeSerializer vts) + { + return this; + } + + @Override + public void serializeContents(boolean[] value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + for (int i = 0, len = value.length; i < len; ++i) { + jgen.writeBoolean(value[i]); + } + } + + @Override + public JsonNode getSchema(SerializerProvider provider, Type typeHint) + { + ObjectNode o = createSchemaNode("array", true); + o.put("items", createSchemaNode("boolean")); + return o; + } + } + + /** + * Unlike other integral number array serializers, we do not just print out byte values + * as numbers. Instead, we assume that it would make more sense to output content + * as base64 encoded bytes (using default base64 encoding). + *<p> + * NOTE: since it is NOT serialized as an array, can not use AsArraySerializer as base + */ + @JacksonStdImpl + public final static class ByteArraySerializer + extends SerializerBase<byte[]> + { + public ByteArraySerializer() { + super(byte[].class); + } + + @Override + public void serialize(byte[] value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + jgen.writeBinary(value); + } + + @Override + public void serializeWithType(byte[] value, JsonGenerator jgen, SerializerProvider provider, + TypeSerializer typeSer) + throws IOException, JsonGenerationException + { + typeSer.writeTypePrefixForScalar(value, jgen); + jgen.writeBinary(value); + typeSer.writeTypeSuffixForScalar(value, jgen); + } + + @Override + public JsonNode getSchema(SerializerProvider provider, Type typeHint) + { + ObjectNode o = createSchemaNode("array", true); + ObjectNode itemSchema = createSchemaNode("string"); //binary values written as strings? + o.put("items", itemSchema); + return o; + } + } + + @JacksonStdImpl + public final static class ShortArraySerializer + extends ArraySerializerBase<short[]> + { + public ShortArraySerializer() { this(null); } + public ShortArraySerializer(TypeSerializer vts) { super(short[].class, vts, null); } + + @Override + public ContainerSerializerBase<?> _withValueTypeSerializer(TypeSerializer vts) { + return new ShortArraySerializer(vts); + } + + @SuppressWarnings("cast") + @Override + public void serializeContents(short[] value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + for (int i = 0, len = value.length; i < len; ++i) { + jgen.writeNumber((int)value[i]); + } + } + + @Override + public JsonNode getSchema(SerializerProvider provider, Type typeHint) + { + //no "short" type defined by json + ObjectNode o = createSchemaNode("array", true); + o.put("items", createSchemaNode("integer")); + return o; + } + } + + /** + * Character arrays are different from other integral number arrays in that + * they are most likely to be textual data, and should be written as + * Strings, not arrays of entries. + *<p> + * NOTE: since it is NOT serialized as an array, can not use AsArraySerializer as base + */ + @JacksonStdImpl + public final static class CharArraySerializer + extends SerializerBase<char[]> + { + public CharArraySerializer() { super(char[].class); } + + @Override + public void serialize(char[] value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + // [JACKSON-289] allows serializing as 'sparse' char array too: + if (provider.isEnabled(SerializationConfig.Feature.WRITE_CHAR_ARRAYS_AS_JSON_ARRAYS)) { + jgen.writeStartArray(); + _writeArrayContents(jgen, value); + jgen.writeEndArray(); + } else { + jgen.writeString(value, 0, value.length); + } + } + + @Override + public void serializeWithType(char[] value, JsonGenerator jgen, SerializerProvider provider, + TypeSerializer typeSer) + throws IOException, JsonGenerationException + { + // [JACKSON-289] allows serializing as 'sparse' char array too: + if (provider.isEnabled(SerializationConfig.Feature.WRITE_CHAR_ARRAYS_AS_JSON_ARRAYS)) { + typeSer.writeTypePrefixForArray(value, jgen); + _writeArrayContents(jgen, value); + typeSer.writeTypeSuffixForArray(value, jgen); + } else { // default is to write as simple String + typeSer.writeTypePrefixForScalar(value, jgen); + jgen.writeString(value, 0, value.length); + typeSer.writeTypeSuffixForScalar(value, jgen); + } + } + + private final void _writeArrayContents(JsonGenerator jgen, char[] value) + throws IOException, JsonGenerationException + { + for (int i = 0, len = value.length; i < len; ++i) { + jgen.writeString(value, i, 1); + } + } + + @Override + public JsonNode getSchema(SerializerProvider provider, Type typeHint) + { + ObjectNode o = createSchemaNode("array", true); + ObjectNode itemSchema = createSchemaNode("string"); + itemSchema.put("type", "string"); + o.put("items", itemSchema); + return o; + } + } + + @JacksonStdImpl + public final static class IntArraySerializer + extends ArraySerializerBase<int[]> + { + public IntArraySerializer() { super(int[].class, null, null); } + + /** + * Ints never add type info; hence, even if type serializer is suggested, + * we'll ignore it... + */ + @Override + public ContainerSerializerBase<?> _withValueTypeSerializer(TypeSerializer vts) + { + return this; + } + + @Override + public void serializeContents(int[] value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + for (int i = 0, len = value.length; i < len; ++i) { + jgen.writeNumber(value[i]); + } + } + + @Override + public JsonNode getSchema(SerializerProvider provider, Type typeHint) + { + ObjectNode o = createSchemaNode("array", true); + o.put("items", createSchemaNode("integer")); + return o; + } + } + + @JacksonStdImpl + public final static class LongArraySerializer + extends ArraySerializerBase<long[]> + { + public LongArraySerializer() { this(null); } + public LongArraySerializer(TypeSerializer vts) { super(long[].class, vts, null); } + + @Override + public ContainerSerializerBase<?> _withValueTypeSerializer(TypeSerializer vts) { + return new LongArraySerializer(vts); + } + + @Override + public void serializeContents(long[] value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + for (int i = 0, len = value.length; i < len; ++i) { + jgen.writeNumber(value[i]); + } + } + + @Override + public JsonNode getSchema(SerializerProvider provider, Type typeHint) + { + ObjectNode o = createSchemaNode("array", true); + o.put("items", createSchemaNode("number", true)); + return o; + } + } + + @JacksonStdImpl + public final static class FloatArraySerializer + extends ArraySerializerBase<float[]> + { + public FloatArraySerializer() { this(null); } + public FloatArraySerializer(TypeSerializer vts) { super(float[].class, vts, null); } + + @Override + public ContainerSerializerBase<?> _withValueTypeSerializer(TypeSerializer vts) { + return new FloatArraySerializer(vts); + } + + @Override + public void serializeContents(float[] value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + for (int i = 0, len = value.length; i < len; ++i) { + jgen.writeNumber(value[i]); + } + } + + @Override + public JsonNode getSchema(SerializerProvider provider, Type typeHint) + { + ObjectNode o = createSchemaNode("array", true); + o.put("items", createSchemaNode("number")); + return o; + } + } + + @JacksonStdImpl + public final static class DoubleArraySerializer + extends ArraySerializerBase<double[]> + { + public DoubleArraySerializer() { super(double[].class, null, null); } + + /** + * Doubles never add type info; hence, even if type serializer is suggested, + * we'll ignore it... + */ + @Override + public ContainerSerializerBase<?> _withValueTypeSerializer(TypeSerializer vts) + { + return this; + } + + @Override + public void serializeContents(double[] value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + for (int i = 0, len = value.length; i < len; ++i) { + jgen.writeNumber(value[i]); + } + } + + @Override + public JsonNode getSchema(SerializerProvider provider, Type typeHint) + { + ObjectNode o = createSchemaNode("array", true); + o.put("items", createSchemaNode("number")); + return o; + } + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/StdContainerSerializers.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/StdContainerSerializers.java new file mode 100644 index 0000000..57a91e1 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/StdContainerSerializers.java
@@ -0,0 +1,243 @@ +package org.codehaus.jackson.map.ser.std; + +import java.io.IOException; +import java.util.*; + +import org.codehaus.jackson.JsonGenerationException; +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.JacksonStdImpl; +import org.codehaus.jackson.map.ser.impl.PropertySerializerMap; +import org.codehaus.jackson.map.ser.std.CollectionSerializer; +import org.codehaus.jackson.type.JavaType; + +/** + * Dummy container class to group standard container serializers: serializers + * that can serialize things like {@link java.util.List}s, + * {@link java.util.Map}s and such. + */ +public class StdContainerSerializers +{ + protected StdContainerSerializers() { } + + /* + /********************************************************** + /* Factory methods + /********************************************************** + */ + + public static ContainerSerializerBase<?> indexedListSerializer(JavaType elemType, + boolean staticTyping, TypeSerializer vts, BeanProperty property, + JsonSerializer<Object> valueSerializer) + { + return new IndexedListSerializer(elemType, staticTyping, vts, property, valueSerializer); + } + + public static ContainerSerializerBase<?> collectionSerializer(JavaType elemType, + boolean staticTyping, TypeSerializer vts, BeanProperty property, + JsonSerializer<Object> valueSerializer) + { + return new CollectionSerializer(elemType, staticTyping, vts, property, valueSerializer); + } + + public static ContainerSerializerBase<?> iteratorSerializer(JavaType elemType, + boolean staticTyping, TypeSerializer vts, BeanProperty property) + { + return new IteratorSerializer(elemType, staticTyping, vts, property); + } + + public static ContainerSerializerBase<?> iterableSerializer(JavaType elemType, + boolean staticTyping, TypeSerializer vts, BeanProperty property) + { + return new IterableSerializer(elemType, staticTyping, vts, property); + } + + public static JsonSerializer<?> enumSetSerializer(JavaType enumType, BeanProperty property) + { + return new EnumSetSerializer(enumType, property); + } + + /* + /********************************************************** + /* Concrete serializers, Lists/collections + /********************************************************** + */ + + /** + * This is an optimized serializer for Lists that can be efficiently + * traversed by index (as opposed to others, such as {@link LinkedList} + * that can not}. + */ + @JacksonStdImpl + public static class IndexedListSerializer + extends AsArraySerializerBase<List<?>> + { + public IndexedListSerializer(JavaType elemType, boolean staticTyping, TypeSerializer vts, + BeanProperty property, JsonSerializer<Object> valueSerializer) + { + super(List.class, elemType, staticTyping, vts, property, valueSerializer); + } + + @Override + public ContainerSerializerBase<?> _withValueTypeSerializer(TypeSerializer vts) { + return new IndexedListSerializer(_elementType, _staticTyping, vts, _property, _elementSerializer); + } + + @Override + public void serializeContents(List<?> value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + if (_elementSerializer != null) { + serializeContentsUsing(value, jgen, provider, _elementSerializer); + return; + } + if (_valueTypeSerializer != null) { + serializeTypedContents(value, jgen, provider); + return; + } + final int len = value.size(); + if (len == 0) { + return; + } + int i = 0; + try { + PropertySerializerMap serializers = _dynamicSerializers; + for (; i < len; ++i) { + Object elem = value.get(i); + if (elem == null) { + provider.defaultSerializeNull(jgen); + } else { + Class<?> cc = elem.getClass(); + JsonSerializer<Object> serializer = serializers.serializerFor(cc); + if (serializer == null) { + // To fix [JACKSON-508] + if (_elementType.hasGenericTypes()) { + serializer = _findAndAddDynamic(serializers, + provider.constructSpecializedType(_elementType, cc), provider); + } else { + serializer = _findAndAddDynamic(serializers, cc, provider); + } + serializers = _dynamicSerializers; + } + serializer.serialize(elem, jgen, provider); + } + } + } catch (Exception e) { + // [JACKSON-55] Need to add reference information + wrapAndThrow(provider, e, value, i); + } + } + + public void serializeContentsUsing(List<?> value, JsonGenerator jgen, SerializerProvider provider, + JsonSerializer<Object> ser) + throws IOException, JsonGenerationException + { + final int len = value.size(); + if (len == 0) { + return; + } + final TypeSerializer typeSer = _valueTypeSerializer; + for (int i = 0; i < len; ++i) { + Object elem = value.get(i); + try { + if (elem == null) { + provider.defaultSerializeNull(jgen); + } else if (typeSer == null) { + ser.serialize(elem, jgen, provider); + } else { + ser.serializeWithType(elem, jgen, provider, typeSer); + } + } catch (Exception e) { + // [JACKSON-55] Need to add reference information + wrapAndThrow(provider, e, value, i); + } + } + } + + public void serializeTypedContents(List<?> value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + final int len = value.size(); + if (len == 0) { + return; + } + int i = 0; + try { + final TypeSerializer typeSer = _valueTypeSerializer; + PropertySerializerMap serializers = _dynamicSerializers; + for (; i < len; ++i) { + Object elem = value.get(i); + if (elem == null) { + provider.defaultSerializeNull(jgen); + } else { + Class<?> cc = elem.getClass(); + JsonSerializer<Object> serializer = serializers.serializerFor(cc); + if (serializer == null) { + // To fix [JACKSON-508] + if (_elementType.hasGenericTypes()) { + serializer = _findAndAddDynamic(serializers, + provider.constructSpecializedType(_elementType, cc), provider); + } else { + serializer = _findAndAddDynamic(serializers, cc, provider); + } + serializers = _dynamicSerializers; + } + serializer.serializeWithType(elem, jgen, provider, typeSer); + } + } + } catch (Exception e) { + // [JACKSON-55] Need to add reference information + wrapAndThrow(provider, e, value, i); + } + } + } + + @JacksonStdImpl + public static class IteratorSerializer + extends AsArraySerializerBase<Iterator<?>> + { + public IteratorSerializer(JavaType elemType, boolean staticTyping, TypeSerializer vts, + BeanProperty property) + { + super(Iterator.class, elemType, staticTyping, vts, property, null); + } + + @Override + public ContainerSerializerBase<?> _withValueTypeSerializer(TypeSerializer vts) { + return new IteratorSerializer(_elementType, _staticTyping, vts, _property); + } + + @Override + public void serializeContents(Iterator<?> value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + if (value.hasNext()) { + final TypeSerializer typeSer = _valueTypeSerializer; + JsonSerializer<Object> prevSerializer = null; + Class<?> prevClass = null; + do { + Object elem = value.next(); + if (elem == null) { + provider.defaultSerializeNull(jgen); + } else { + // Minor optimization to avoid most lookups: + Class<?> cc = elem.getClass(); + JsonSerializer<Object> currSerializer; + if (cc == prevClass) { + currSerializer = prevSerializer; + } else { + currSerializer = provider.findValueSerializer(cc, _property); + prevSerializer = currSerializer; + prevClass = cc; + } + if (typeSer == null) { + currSerializer.serialize(elem, jgen, provider); + } else { + currSerializer.serializeWithType(elem, jgen, provider, typeSer); + } + } + } while (value.hasNext()); + } + } + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/StdJdkSerializers.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/StdJdkSerializers.java new file mode 100644 index 0000000..e2cb319 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/StdJdkSerializers.java
@@ -0,0 +1,195 @@ +package org.codehaus.jackson.map.ser.std; + +import java.io.*; +import java.lang.reflect.Type; +import java.util.*; +import java.util.concurrent.atomic.*; + +import org.codehaus.jackson.JsonGenerationException; +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.ser.BasicSerializerFactory; +import org.codehaus.jackson.map.util.Provider; + +/** + * Class that providers access to serializers user for non-structured JDK types that + * are serializer as scalars; some using basic {@link ToStringSerializer}, + * others explicit serializers. + */ +public class StdJdkSerializers + implements Provider<Map.Entry<Class<?>,Object>> +{ + /** + * Method called by {@link BasicSerializerFactory} to access + * all serializers this class provides. + */ + @Override + public Collection<Map.Entry<Class<?>, Object>> provide() + { + HashMap<Class<?>,Object> sers = new HashMap<Class<?>,Object>(); + + // First things that 'toString()' can handle + final ToStringSerializer sls = ToStringSerializer.instance; + + sers.put(java.net.URL.class, sls); + sers.put(java.net.URI.class, sls); + + sers.put(Currency.class, sls); + sers.put(UUID.class, sls); + sers.put(java.util.regex.Pattern.class, sls); + sers.put(Locale.class, sls); + + // starting with 1.7, use compact String for Locale + sers.put(Locale.class, sls); + + // then atomic types + sers.put(AtomicReference.class, AtomicReferenceSerializer.class); + sers.put(AtomicBoolean.class, AtomicBooleanSerializer.class); + sers.put(AtomicInteger.class, AtomicIntegerSerializer.class); + sers.put(AtomicLong.class, AtomicLongSerializer.class); + + // then types that need specialized serializers + sers.put(File.class, FileSerializer.class); + sers.put(Class.class, ClassSerializer.class); + + // And then some stranger types... not 100% they are needed but: + sers.put(Void.TYPE, NullSerializer.class); + + return sers.entrySet(); + } + + /* + ******************************************************** + * Serializers for atomic types + ******************************************************** + */ + + public final static class AtomicBooleanSerializer + extends ScalarSerializerBase<AtomicBoolean> + { + public AtomicBooleanSerializer() { super(AtomicBoolean.class, false); } + + @Override + public void serialize(AtomicBoolean value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + jgen.writeBoolean(value.get()); + } + + @Override + public JsonNode getSchema(SerializerProvider provider, Type typeHint) + { + return createSchemaNode("boolean", true); + } + } + + public final static class AtomicIntegerSerializer + extends ScalarSerializerBase<AtomicInteger> + { + public AtomicIntegerSerializer() { super(AtomicInteger.class, false); } + + @Override + public void serialize(AtomicInteger value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + jgen.writeNumber(value.get()); + } + + @Override + public JsonNode getSchema(SerializerProvider provider, Type typeHint) + { + return createSchemaNode("integer", true); + } + } + + public final static class AtomicLongSerializer + extends ScalarSerializerBase<AtomicLong> + { + public AtomicLongSerializer() { super(AtomicLong.class, false); } + + @Override + public void serialize(AtomicLong value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + jgen.writeNumber(value.get()); + } + + @Override + public JsonNode getSchema(SerializerProvider provider, Type typeHint) + { + return createSchemaNode("integer", true); + } + } + + public final static class AtomicReferenceSerializer + extends SerializerBase<AtomicReference<?>> + { + public AtomicReferenceSerializer() { super(AtomicReference.class, false); } + + @Override + public void serialize(AtomicReference<?> value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + provider.defaultSerializeValue(value.get(), jgen); + } + + @Override + public JsonNode getSchema(SerializerProvider provider, Type typeHint) + { + return createSchemaNode("any", true); + } + } + + /* + /********************************************************** + /* Specialized serializers, referential types + /********************************************************** + */ + + /** + * For now, File objects get serialized by just outputting + * absolute (but not canonical) name as String value + */ + public final static class FileSerializer + extends ScalarSerializerBase<File> + { + public FileSerializer() { super(File.class); } + + @Override + public void serialize(File value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + jgen.writeString(value.getAbsolutePath()); + } + + @Override + public JsonNode getSchema(SerializerProvider provider, Type typeHint) + { + return createSchemaNode("string", true); + } + } + + /** + * Also: default bean access will not do much good with Class.class. But + * we can just serialize the class name and that should be enough. + */ + public final static class ClassSerializer + extends ScalarSerializerBase<Class<?>> + { + public ClassSerializer() { super(Class.class, false); } + + @Override + public void serialize(Class<?> value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + jgen.writeString(value.getName()); + } + + @Override + public JsonNode getSchema(SerializerProvider provider, Type typeHint) + { + return createSchemaNode("string", true); + } + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/StdKeySerializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/StdKeySerializer.java new file mode 100644 index 0000000..d52d9fc --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/StdKeySerializer.java
@@ -0,0 +1,43 @@ +package org.codehaus.jackson.map.ser.std; + +import java.io.IOException; +import java.lang.reflect.Type; +import java.util.Date; + +import org.codehaus.jackson.JsonGenerationException; +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.map.SerializerProvider; +import org.codehaus.jackson.map.JsonMappingException; +import org.codehaus.jackson.map.ser.std.SerializerBase; + +/** + * Specialized serializer that can be used as the generic key + * serializer, when serializing {@link java.util.Map}s to JSON + * Objects. + */ +public class StdKeySerializer + extends SerializerBase<Object> +{ + final static StdKeySerializer instace = new StdKeySerializer(); + + public StdKeySerializer() { super(Object.class); } + + @Override + public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + if (value instanceof Date) { + provider.defaultSerializeDateKey((Date) value, jgen); + } else { + jgen.writeFieldName(value.toString()); + } + } + + @Override + public JsonNode getSchema(SerializerProvider provider, Type typeHint) + throws JsonMappingException + { + return createSchemaNode("string"); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/StdKeySerializers.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/StdKeySerializers.java new file mode 100644 index 0000000..a6fdbf1 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/StdKeySerializers.java
@@ -0,0 +1,95 @@ +package org.codehaus.jackson.map.ser.std; + +import java.io.IOException; +import java.util.Calendar; +import java.util.Date; + +import org.codehaus.jackson.JsonGenerationException; +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.map.JsonSerializer; +import org.codehaus.jackson.map.SerializerProvider; +import org.codehaus.jackson.type.JavaType; + +public class StdKeySerializers +{ + protected final static JsonSerializer<Object> DEFAULT_KEY_SERIALIZER = new StdKeySerializer(); + + @SuppressWarnings("unchecked") + protected final static JsonSerializer<Object> DEFAULT_STRING_SERIALIZER + = (JsonSerializer<Object>)(JsonSerializer<?>) new StringKeySerializer(); + + private StdKeySerializers() { } + + @SuppressWarnings("unchecked") + public static JsonSerializer<Object> getStdKeySerializer(JavaType keyType) + { + if (keyType == null) { + return DEFAULT_KEY_SERIALIZER; + } + Class<?> cls = keyType.getRawClass(); + if (cls == String.class) { + return DEFAULT_STRING_SERIALIZER; + } + if (cls == Object.class) { + return DEFAULT_KEY_SERIALIZER; + } + // [JACKSON-606] special handling for dates... + if (Date.class.isAssignableFrom(cls)) { + return (JsonSerializer<Object>) DateKeySerializer.instance; + } + if (Calendar.class.isAssignableFrom(cls)) { + return (JsonSerializer<Object>) CalendarKeySerializer.instance; + } + // If no match, just use default one: + return DEFAULT_KEY_SERIALIZER; + } + + /* + /********************************************************** + /* Standard implementations + /********************************************************** + */ + + public static class StringKeySerializer + extends SerializerBase<String> + { + public StringKeySerializer() { super(String.class); } + + @Override + public void serialize(String value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + jgen.writeFieldName(value); + } + } + + public static class DateKeySerializer + extends SerializerBase<Date> + { + protected final static JsonSerializer<?> instance = new DateKeySerializer(); + + public DateKeySerializer() { super(Date.class); } + + @Override + public void serialize(Date value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + provider.defaultSerializeDateKey(value, jgen); + } + } + + public static class CalendarKeySerializer + extends SerializerBase<Calendar> + { + protected final static JsonSerializer<?> instance = new CalendarKeySerializer(); + + public CalendarKeySerializer() { super(Calendar.class); } + + @Override + public void serialize(Calendar value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + provider.defaultSerializeDateKey(value.getTimeInMillis(), jgen); + } + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/StringCollectionSerializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/StringCollectionSerializer.java new file mode 100644 index 0000000..7a32fca --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/StringCollectionSerializer.java
@@ -0,0 +1,125 @@ +package org.codehaus.jackson.map.ser.std; + +import java.io.IOException; +import java.util.*; + +import org.codehaus.jackson.JsonGenerationException; +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.map.BeanProperty; +import org.codehaus.jackson.map.JsonMappingException; +import org.codehaus.jackson.map.JsonSerializer; +import org.codehaus.jackson.map.ResolvableSerializer; +import org.codehaus.jackson.map.SerializerProvider; +import org.codehaus.jackson.map.TypeSerializer; +import org.codehaus.jackson.map.annotate.JacksonStdImpl; + +/** + * Efficient implement for serializing {@link Collection}s that contain Strings. + * The only complexity is due to possibility that serializer for {@link String} + * may be overridde; because of this, logic is needed to ensure that the default + * serializer is in use to use fastest mode, or if not, to defer to custom + * String serializer. + */ +@JacksonStdImpl +public class StringCollectionSerializer + extends StaticListSerializerBase<Collection<String>> + implements ResolvableSerializer +{ + protected JsonSerializer<String> _serializer; + + @Deprecated + public StringCollectionSerializer(BeanProperty property) { + this(property, null); + } + + @SuppressWarnings("unchecked") + public StringCollectionSerializer(BeanProperty property, JsonSerializer<?> ser) { + super(Collection.class, property); + _serializer = (JsonSerializer<String>) ser; + } + + @Override protected JsonNode contentSchema() { + return createSchemaNode("string", true); + } + + @SuppressWarnings("unchecked") + @Override + public void resolve(SerializerProvider provider) throws JsonMappingException + { + if (_serializer == null) { + JsonSerializer<?> ser = provider.findValueSerializer(String.class, _property); + if (!isDefaultSerializer(ser)) { + _serializer = (JsonSerializer<String>) ser; + } + } + } + + @Override + public void serialize(Collection<String> value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + jgen.writeStartArray(); + if (_serializer == null) { + serializeContents(value, jgen, provider); + } else { + serializeUsingCustom(value, jgen, provider); + } + jgen.writeEndArray(); + } + + @Override + public void serializeWithType(Collection<String> value, JsonGenerator jgen, SerializerProvider provider, + TypeSerializer typeSer) + throws IOException, JsonGenerationException + { + typeSer.writeTypePrefixForArray(value, jgen); + if (_serializer == null) { + serializeContents(value, jgen, provider); + } else { + serializeUsingCustom(value, jgen, provider); + } + typeSer.writeTypeSuffixForArray(value, jgen); + } + + private final void serializeContents(Collection<String> value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + if (_serializer != null) { + serializeUsingCustom(value, jgen, provider); + return; + } + int i = 0; + for (String str : value) { + try { + if (str == null) { + provider.defaultSerializeNull(jgen); + } else { + jgen.writeString(str); + } + ++i; + } catch (Exception e) { + wrapAndThrow(provider, e, value, i); + } + } + } + + private void serializeUsingCustom(Collection<String> value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + final JsonSerializer<String> ser = _serializer; + int i = 0; + for (String str : value) { + try { + if (str == null) { + provider.defaultSerializeNull(jgen); + } else { + ser.serialize(str, jgen, provider); + } + } catch (Exception e) { + wrapAndThrow(provider, e, value, i); + } + } + } + +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/StringSerializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/StringSerializer.java new file mode 100644 index 0000000..0eeeb9c --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/StringSerializer.java
@@ -0,0 +1,36 @@ +package org.codehaus.jackson.map.ser.std; + +import java.io.IOException; +import java.lang.reflect.Type; + +import org.codehaus.jackson.JsonGenerationException; +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.map.SerializerProvider; +import org.codehaus.jackson.map.annotate.JacksonStdImpl; + +/** + * This is the special serializer for regular {@link java.lang.String}s. + *<p> + * Since this is one of "native" types, no type information is ever + * included on serialization (unlike for most scalar types as of 1.5) + */ +@JacksonStdImpl +public final class StringSerializer + extends NonTypedScalarSerializerBase<String> +{ + public StringSerializer() { super(String.class); } + + @Override + public void serialize(String value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + jgen.writeString(value); + } + + @Override + public JsonNode getSchema(SerializerProvider provider, Type typeHint) + { + return createSchemaNode("string", true); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/TimeZoneSerializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/TimeZoneSerializer.java new file mode 100644 index 0000000..585b47e --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/TimeZoneSerializer.java
@@ -0,0 +1,38 @@ +package org.codehaus.jackson.map.ser.std; + +import java.io.IOException; +import java.util.TimeZone; + +import org.codehaus.jackson.JsonGenerationException; +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.map.SerializerProvider; +import org.codehaus.jackson.map.TypeSerializer; + +/** + * @since 1.8 + */ +public class TimeZoneSerializer + extends ScalarSerializerBase<TimeZone> +{ + public final static TimeZoneSerializer instance = new TimeZoneSerializer(); + + public TimeZoneSerializer() { super(TimeZone.class); } + + @Override + public void serialize(TimeZone value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + jgen.writeString(value.getID()); + } + + @Override + public void serializeWithType(TimeZone value, JsonGenerator jgen, SerializerProvider provider, + TypeSerializer typeSer) + throws IOException, JsonGenerationException + { + // Better ensure we don't use specific sub-classes: + typeSer.writeTypePrefixForScalar(value, jgen, TimeZone.class); + serialize(value, jgen, provider); + typeSer.writeTypeSuffixForScalar(value, jgen); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/ToStringSerializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/ToStringSerializer.java new file mode 100644 index 0000000..569d59f --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/ToStringSerializer.java
@@ -0,0 +1,73 @@ +package org.codehaus.jackson.map.ser.std; + +import java.io.IOException; +import java.lang.reflect.Type; + +import org.codehaus.jackson.JsonGenerationException; +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.map.SerializerProvider; +import org.codehaus.jackson.map.JsonMappingException; +import org.codehaus.jackson.map.TypeSerializer; +import org.codehaus.jackson.map.annotate.JacksonStdImpl; + +/** + * Simple general purpose serializer, useful for any + * type for which {@link Object#toString} returns the desired JSON + * value. + */ +@JacksonStdImpl +public class ToStringSerializer + extends SerializerBase<Object> +{ + /** + * Singleton instance to use. + */ + public final static ToStringSerializer instance = new ToStringSerializer(); + + /** + *<p> + * Note: usually you should NOT create new instances, but instead use + * {@link #instance} which is stateless and fully thread-safe. However, + * there are cases where constructor is needed; for example, + * when using explicit serializer annotations like + * {@link org.codehaus.jackson.map.annotate.JsonSerialize#using}. + */ + public ToStringSerializer() { super(Object.class); } + + @Override + public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + jgen.writeString(value.toString()); + } + + /* 01-Mar-2011, tatu: We were serializing as "raw" String; but generally that + * is not what we want, since lack of type information would imply real + * String type. + */ + /** + * Default implementation will write type prefix, call regular serialization + * method (since assumption is that value itself does not need JSON + * Array or Object start/end markers), and then write type suffix. + * This should work for most cases; some sub-classes may want to + * change this behavior. + */ + @Override + public void serializeWithType(Object value, JsonGenerator jgen, SerializerProvider provider, + TypeSerializer typeSer) + throws IOException, JsonGenerationException + { + typeSer.writeTypePrefixForScalar(value, jgen); + serialize(value, jgen, provider); + typeSer.writeTypeSuffixForScalar(value, jgen); + } + + @Override + public JsonNode getSchema(SerializerProvider provider, Type typeHint) + throws JsonMappingException + { + return createSchemaNode("string", true); + } + +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/TokenBufferSerializer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/TokenBufferSerializer.java new file mode 100644 index 0000000..b974109 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/ser/std/TokenBufferSerializer.java
@@ -0,0 +1,66 @@ +package org.codehaus.jackson.map.ser.std; + +import java.io.IOException; +import java.lang.reflect.Type; + +import org.codehaus.jackson.JsonGenerationException; +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.map.SerializerProvider; +import org.codehaus.jackson.map.TypeSerializer; +import org.codehaus.jackson.map.annotate.JacksonStdImpl; +import org.codehaus.jackson.util.TokenBuffer; + +/** + * We also want to directly support serialization of {@link TokenBuffer}; + * and since it is part of core package, it can not implement + * {@link org.codehaus.jackson.map.JsonSerializable} + * (which is only included in the mapper package) + * + * @since 1.5 + */ +@JacksonStdImpl +public class TokenBufferSerializer + extends SerializerBase<TokenBuffer> +{ + public TokenBufferSerializer() { super(TokenBuffer.class); } + + @Override + public void serialize(TokenBuffer value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + value.serialize(jgen); + } + + /** + * Implementing typed output for contents of a TokenBuffer is very tricky, + * since we do not know for sure what its contents might look like (or, rather, + * we do know when serializing, but not necessarily when deserializing!) + * One possibility would be to check the current token, and use that to + * determine if we would output JSON Array, Object or scalar value. + * Jackson 1.5 did NOT include any type information; but this seems wrong, + * and so 1.6 WILL include type information. + *<p> + * Note that we just claim it is scalar; this should work ok and is simpler + * than doing introspection on both serialization and deserialization. + */ + @Override + public final void serializeWithType(TokenBuffer value, JsonGenerator jgen, SerializerProvider provider, + TypeSerializer typeSer) + throws IOException, JsonGenerationException + { + typeSer.writeTypePrefixForScalar(value, jgen); + serialize(value, jgen, provider); + typeSer.writeTypeSuffixForScalar(value, jgen); + } + + @Override + public JsonNode getSchema(SerializerProvider provider, Type typeHint) + { + /* 01-Jan-2010, tatu: Not 100% sure what we should say here: + * type is basically not known. This seems closest + * approximation + */ + return createSchemaNode("any", true); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/type/ArrayType.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/type/ArrayType.java new file mode 100644 index 0000000..6316012 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/type/ArrayType.java
@@ -0,0 +1,260 @@ +package org.codehaus.jackson.map.type; + +import java.lang.reflect.Array; + +import org.codehaus.jackson.type.JavaType; + +/** + * Array types represent Java arrays, both primitive and object valued. + * Further, Object-valued arrays can have element type of any other + * legal {@link JavaType}. + */ +public final class ArrayType + extends TypeBase +{ + /** + * Type of elements in the array. + */ + protected final JavaType _componentType; + + /** + * We will also keep track of shareable instance of empty array, + * since it usually needs to be constructed any way; and because + * it is essentially immutable and thus can be shared. + */ + protected final Object _emptyArray; + + private ArrayType(JavaType componentType, Object emptyInstance, + Object valueHandler, Object typeHandler) + { + super(emptyInstance.getClass(), componentType.hashCode(), + valueHandler, typeHandler); + _componentType = componentType; + _emptyArray = emptyInstance; + } + + /** + * @deprecated Since 1.9, if you must directly instantiate, + * call method that takes handlers + */ + @Deprecated + public static ArrayType construct(JavaType componentType) + { + return construct(componentType, null, null); + } + + public static ArrayType construct(JavaType componentType, + Object valueHandler, Object typeHandler) + { + /* This is bit messy: there is apparently no other way to + * reconstruct actual concrete/raw array class from component + * type, than to construct an instance, get class (same is + * true for GenericArracyType as well; hence we won't bother + * passing that in). + */ + Object emptyInstance = Array.newInstance(componentType.getRawClass(), 0); + return new ArrayType(componentType, emptyInstance, null, null); + } + + // Since 1.7: + @Override + public ArrayType withTypeHandler(Object h) + { + if (h == _typeHandler) { + return this; + } + return new ArrayType(_componentType, _emptyArray, _valueHandler, h); + } + + // Since 1.7: + @Override + public ArrayType withContentTypeHandler(Object h) + { + if (h == _componentType.getTypeHandler()) { + return this; + } + return new ArrayType(_componentType.withTypeHandler(h), _emptyArray, + _valueHandler, _typeHandler); + } + + // Since 1.9: + @Override + public ArrayType withValueHandler(Object h) { + if (h == _valueHandler) { + return this; + } + return new ArrayType(_componentType, _emptyArray, h, _typeHandler); + } + + // Since 1.9: + @Override + public ArrayType withContentValueHandler(Object h) { + if (h == _componentType.getValueHandler()) { + return this; + } + return new ArrayType(_componentType.withValueHandler(h), _emptyArray, + _valueHandler, _typeHandler); + } + + @Override + protected String buildCanonicalName() { + return _class.getName(); + } + + /* + /********************************************************** + /* Methods for narrowing conversions + /********************************************************** + */ + + /** + * Handling of narrowing conversions for arrays is trickier: for now, + * it is not even allowed. + */ + @Override + protected JavaType _narrow(Class<?> subclass) + { + /* Ok: need a bit of indirection here. First, must replace component + * type (and check that it is compatible), then re-construct. + */ + if (!subclass.isArray()) { // sanity check, should never occur + throw new IllegalArgumentException("Incompatible narrowing operation: trying to narrow "+toString()+" to class "+subclass.getName()); + } + /* Hmmh. This is an awkward back reference... but seems like the + * only simple way to do it. + */ + Class<?> newCompClass = subclass.getComponentType(); + /* 14-Mar-2011, tatu: it gets even worse, as we do not have access to + * currently configured TypeFactory. This could theoretically cause + * problems (when narrowing from array of Objects, to array of non-standard + * Maps, for example); but for now need to defer solving this until + * it actually becomes a real problem, not just potential one. + * (famous last words?) + */ + JavaType newCompType = TypeFactory.defaultInstance().constructType(newCompClass); + return construct(newCompType, _valueHandler, _typeHandler); + } + + /** + * For array types, both main type and content type can be modified; + * but ultimately they are interchangeable. + */ + @Override + public JavaType narrowContentsBy(Class<?> contentClass) + { + // Can do a quick check first: + if (contentClass == _componentType.getRawClass()) { + return this; + } + return construct(_componentType.narrowBy(contentClass), + _valueHandler, _typeHandler); + } + + @Override + public JavaType widenContentsBy(Class<?> contentClass) + { + // Can do a quick check first: + if (contentClass == _componentType.getRawClass()) { + return this; + } + return construct(_componentType.widenBy(contentClass), + _valueHandler, _typeHandler); + } + + /* + /********************************************************** + /* Overridden methods + /********************************************************** + */ + + @Override + public boolean isArrayType() { return true; } + + /** + * For some odd reason, modifiers for array classes would + * claim they are abstract types. Not so, at least for our + * purposes. + */ + @Override + public boolean isAbstract() { return false; } + + /** + * For some odd reason, modifiers for array classes would + * claim they are abstract types. Not so, at least for our + * purposes. + */ + @Override + public boolean isConcrete() { return true; } + + @Override + public boolean hasGenericTypes() { + // arrays are not parameterized, but element type may be: + return _componentType.hasGenericTypes(); + } + + /** + * Not sure what symbolic name is used internally, if any; + * let's follow naming of Collection types here. + * Should not really matter since array types have no + * super types. + */ + @Override + public String containedTypeName(int index) { + if (index == 0) return "E"; + return null; + } + + /* + /********************************************************** + /* Public API + /********************************************************** + */ + + @Override + public boolean isContainerType() { return true; } + + @Override + public JavaType getContentType() { return _componentType; } + + @Override + public int containedTypeCount() { return 1; } + @Override + public JavaType containedType(int index) { + return (index == 0) ? _componentType : null; + } + + @Override + public StringBuilder getGenericSignature(StringBuilder sb) { + sb.append('['); + return _componentType.getGenericSignature(sb); + } + + @Override + public StringBuilder getErasedSignature(StringBuilder sb) { + sb.append('['); + return _componentType.getErasedSignature(sb); + } + + /* + /********************************************************** + /* Standard methods + /********************************************************** + */ + + @Override + public String toString() + { + return "[array type, component type: "+_componentType+"]"; + } + + @Override + public boolean equals(Object o) + { + if (o == this) return true; + if (o == null) return false; + if (o.getClass() != getClass()) return false; + + ArrayType other = (ArrayType) o; + return _componentType.equals(other._componentType); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/type/ClassKey.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/type/ClassKey.java new file mode 100644 index 0000000..7817dc4 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/type/ClassKey.java
@@ -0,0 +1,94 @@ +package org.codehaus.jackson.map.type; + +/** + * Key class, used as an efficient and accurate key + * for locating per-class values, such as + * {@link org.codehaus.jackson.map.JsonSerializer}s. + *<p> + * The reason for having a separate key class instead of + * directly using {@link Class} as key is mostly + * to allow for redefining <code>hashCode</code> method -- + * for some strange reason, {@link Class} does not + * redefine {@link Object#hashCode} and thus uses identity + * hash, which is pretty slow. This makes key access using + * {@link Class} unnecessarily slow. + *<p> + * Note: since class is not strictly immutable, caller must + * know what it is doing, if changing field values. + */ +public final class ClassKey + implements Comparable<ClassKey> +{ + private String _className; + + private Class<?> _class; + + /** + * Let's cache hash code straight away, since we are + * almost certain to need it. + */ + private int _hashCode; + + public ClassKey() + { + _class = null; + _className = null; + _hashCode = 0; + } + + public ClassKey(Class<?> clz) + { + _class = clz; + _className = clz.getName(); + _hashCode = _className.hashCode(); + } + + public void reset(Class<?> clz) + { + _class = clz; + _className = clz.getName(); + _hashCode = _className.hashCode(); + } + + /* + /********************************************************** + /* Comparable + /********************************************************** + */ + + @Override + public int compareTo(ClassKey other) + { + // Just need to sort by name, ok to collide (unless used in TreeMap/Set!) + return _className.compareTo(other._className); + } + + /* + /********************************************************** + /* Standard methods + /********************************************************** + */ + + @Override + public boolean equals(Object o) + { + if (o == this) return true; + if (o == null) return false; + if (o.getClass() != getClass()) return false; + ClassKey other = (ClassKey) o; + + /* Is it possible to have different Class object for same name + class loader combo? + * Let's assume answer is no: if this is wrong, will need to uncomment following functionality + */ + /* + return (other._className.equals(_className)) + && (other._class.getClassLoader() == _class.getClassLoader()); + */ + return other._class == _class; + } + + @Override public int hashCode() { return _hashCode; } + + @Override public String toString() { return _className; } + +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/type/CollectionLikeType.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/type/CollectionLikeType.java new file mode 100644 index 0000000..dca2a55 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/type/CollectionLikeType.java
@@ -0,0 +1,204 @@ +package org.codehaus.jackson.map.type; + +import java.util.Collection; + +import org.codehaus.jackson.type.JavaType; + +/** + * Type that represents things that act similar to {@link java.util.Collection}; + * but may or may not be instances of that interface. + * This specifically allows framework to check for configuration and annotation + * settings used for Map types, and pass these to custom handlers that may be more + * familiar with actual type. + * + * @since 1.8 + */ +public class CollectionLikeType extends TypeBase +{ + /** + * Type of elements in collection + */ + protected final JavaType _elementType; + + /* + /********************************************************** + /* Life-cycle + /********************************************************** + */ + + @Deprecated // since 1.9 + protected CollectionLikeType(Class<?> collT, JavaType elemT) + { + super(collT, elemT.hashCode(), null, null); + _elementType = elemT; + } + + protected CollectionLikeType(Class<?> collT, JavaType elemT, + Object valueHandler, Object typeHandler) + { + super(collT, elemT.hashCode(), valueHandler, typeHandler); + _elementType = elemT; + } + + @Override + protected JavaType _narrow(Class<?> subclass) { + return new CollectionLikeType(subclass, _elementType, + _valueHandler, _typeHandler); + } + + @Override + public JavaType narrowContentsBy(Class<?> contentClass) + { + // Can do a quick check first: + if (contentClass == _elementType.getRawClass()) { + return this; + } + return new CollectionLikeType(_class, _elementType.narrowBy(contentClass), + _valueHandler, _typeHandler); } + + @Override + public JavaType widenContentsBy(Class<?> contentClass) + { + // Can do a quick check first: + if (contentClass == _elementType.getRawClass()) { + return this; + } + return new CollectionLikeType(_class, _elementType.widenBy(contentClass), + _valueHandler, _typeHandler); + } + + public static CollectionLikeType construct(Class<?> rawType, JavaType elemT) + { + // nominally component types will be just Object.class + return new CollectionLikeType(rawType, elemT, null, null); + } + + // Since 1.7: + @Override + public CollectionLikeType withTypeHandler(Object h) + { + return new CollectionLikeType(_class, _elementType, _valueHandler, h); + } + + // Since 1.7: + @Override + public CollectionLikeType withContentTypeHandler(Object h) + { + return new CollectionLikeType(_class, _elementType.withTypeHandler(h), + _valueHandler, _typeHandler); + } + + // Since 1.9: + @Override + public CollectionLikeType withValueHandler(Object h) { + return new CollectionLikeType(_class, _elementType, h, _typeHandler); + } + + // Since 1.9: + @Override + public CollectionLikeType withContentValueHandler(Object h) { + return new CollectionLikeType(_class, _elementType.withValueHandler(h), + _valueHandler, _typeHandler); + } + + /* + /********************************************************** + /* Public API + /********************************************************** + */ + + @Override + public boolean isContainerType() { return true; } + + @Override + public boolean isCollectionLikeType() { return true; } + + @Override + public JavaType getContentType() { return _elementType; } + + @Override + public int containedTypeCount() { return 1; } + + @Override + public JavaType containedType(int index) { + return (index == 0) ? _elementType : null; + } + + /** + * Not sure if we should count on this, but type names + * for core interfaces use "E" for element type + */ + @Override + public String containedTypeName(int index) { + if (index == 0) return "E"; + return null; + } + + @Override + public StringBuilder getErasedSignature(StringBuilder sb) { + return _classSignature(_class, sb, true); + } + + @Override + public StringBuilder getGenericSignature(StringBuilder sb) { + _classSignature(_class, sb, false); + sb.append('<'); + _elementType.getGenericSignature(sb); + sb.append(">;"); + return sb; + } + + @Override + protected String buildCanonicalName() { + StringBuilder sb = new StringBuilder(); + sb.append(_class.getName()); + if (_elementType != null) { + sb.append('<'); + sb.append(_elementType.toCanonical()); + sb.append('>'); + } + return sb.toString(); + } + + /* + /********************************************************** + /* Extended API + /********************************************************** + */ + + /** + * Method that can be used for checking whether this type is a + * "real" Collection type; meaning whether it represents a parameterized + * subtype of {@link java.util.Collection} or just something that acts + * like one. + * + * @since 1.8 + */ + public boolean isTrueCollectionType() { + return Collection.class.isAssignableFrom(_class); + } + + /* + /********************************************************** + /* Standard methods + /********************************************************** + */ + + @Override + public boolean equals(Object o) + { + if (o == this) return true; + if (o == null) return false; + if (o.getClass() != getClass()) return false; + + CollectionLikeType other = (CollectionLikeType) o; + return (_class == other._class) && _elementType.equals(other._elementType); + } + + @Override + public String toString() + { + return "[collection-like type; class "+_class.getName()+", contains "+_elementType+"]"; + } + +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/type/CollectionType.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/type/CollectionType.java new file mode 100644 index 0000000..a36cfd6 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/type/CollectionType.java
@@ -0,0 +1,94 @@ +package org.codehaus.jackson.map.type; + +import org.codehaus.jackson.type.JavaType; + +/** + * Type that represents Java Collection types (Lists, Sets). + */ +public final class CollectionType + extends CollectionLikeType +{ + /* + /********************************************************** + /* Life-cycle + /********************************************************** + */ + + private CollectionType(Class<?> collT, JavaType elemT, + Object valueHandler, Object typeHandler) + { + super(collT, elemT, valueHandler, typeHandler); + } + + @Override + protected JavaType _narrow(Class<?> subclass) { + return new CollectionType(subclass, _elementType, null, null); + } + + @Override + public JavaType narrowContentsBy(Class<?> contentClass) + { + // Can do a quick check first: + if (contentClass == _elementType.getRawClass()) { + return this; + } + return new CollectionType(_class, _elementType.narrowBy(contentClass), + _valueHandler, _typeHandler); + } + + @Override + public JavaType widenContentsBy(Class<?> contentClass) + { + // Can do a quick check first: + if (contentClass == _elementType.getRawClass()) { + return this; + } + return new CollectionType(_class, _elementType.widenBy(contentClass), + _valueHandler, _typeHandler); + } + + public static CollectionType construct(Class<?> rawType, JavaType elemT) + { + // nominally component types will be just Object.class + return new CollectionType(rawType, elemT, null, null); + } + + // Since 1.7: + @Override + public CollectionType withTypeHandler(Object h) { + return new CollectionType(_class, _elementType, _valueHandler, h); + } + + // Since 1.7: + @Override + public CollectionType withContentTypeHandler(Object h) + { + return new CollectionType(_class, _elementType.withTypeHandler(h), + _valueHandler, _typeHandler); + } + + // Since 1.9: + @Override + public CollectionType withValueHandler(Object h) { + return new CollectionType(_class, _elementType, h, _typeHandler); + } + + // Since 1.9: + @Override + public CollectionType withContentValueHandler(Object h) { + return new CollectionType(_class, _elementType.withValueHandler(h), + _valueHandler, _typeHandler); + } + + /* + /********************************************************** + /* Standard methods + /********************************************************** + */ + + @Override + public String toString() + { + return "[collection type; class "+_class.getName()+", contains "+_elementType+"]"; + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/type/HierarchicType.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/type/HierarchicType.java new file mode 100644 index 0000000..236986e --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/type/HierarchicType.java
@@ -0,0 +1,88 @@ +package org.codehaus.jackson.map.type; + +import java.lang.reflect.*; + +/** + * Simple replacement for {@link java.lang.Class} (and/or various Type subtypes) + * that is used as part of single-path extends/implements chain to express + * specific relationship between one subtype and one supertype. This is needed + * for resolving type parameters. Instances are doubly-linked so that chain + * can be traversed in both directions + * + * @since 1.6 + */ +public class HierarchicType +{ + /** + * Type which will be either plain {@link java.lang.Class} or + * {@link java.lang.reflect.ParameterizedType}. + */ + protected final Type _actualType; + + protected final Class<?> _rawClass; + + protected final ParameterizedType _genericType; + + protected HierarchicType _superType; + + protected HierarchicType _subType; + + public HierarchicType(Type type) + { + this._actualType = type; + if (type instanceof Class<?>) { + _rawClass = (Class<?>) type; + _genericType = null; + } else if (type instanceof ParameterizedType) { + _genericType = (ParameterizedType) type; + _rawClass = (Class<?>) _genericType.getRawType(); + } else { // should never happen... can't extend GenericArrayType? + throw new IllegalArgumentException("Type "+type.getClass().getName()+" can not be used to construct HierarchicType"); + } + } + + private HierarchicType(Type actualType, Class<?> rawClass, ParameterizedType genericType, + HierarchicType superType, HierarchicType subType) + { + _actualType = actualType; + _rawClass = rawClass; + _genericType = genericType; + _superType = superType; + _subType = subType; + } + + /** + * Method that can be used to create a deep clone of this hierarchic type, including + * super types (but not subtypes) + * + * @since 1.9 + */ + public HierarchicType deepCloneWithoutSubtype() + { + HierarchicType sup = (_superType == null) ? null : _superType.deepCloneWithoutSubtype(); + HierarchicType result = new HierarchicType(_actualType, _rawClass, _genericType, sup, null); + if (sup != null) { + sup.setSubType(result); + } + return result; + } + + public void setSuperType(HierarchicType sup) { _superType = sup; } + public final HierarchicType getSuperType() { return _superType; } + public void setSubType(HierarchicType sub) { _subType = sub; } + public final HierarchicType getSubType() { return _subType; } + + public final boolean isGeneric() { return _genericType != null; } + public final ParameterizedType asGeneric() { return _genericType; } + + public final Class<?> getRawClass() { return _rawClass; } + + @Override + public String toString() { + if (_genericType != null) { + return _genericType.toString(); + } + return _rawClass.getName(); + } + +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/type/MapLikeType.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/type/MapLikeType.java new file mode 100644 index 0000000..0f5f32b --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/type/MapLikeType.java
@@ -0,0 +1,265 @@ +package org.codehaus.jackson.map.type; + +import java.util.*; + +import org.codehaus.jackson.type.JavaType; + +/** + * Type that represents Map-like types; things that consist of key/value pairs but that + * do not necessarily implement {@link java.util.Map}, but that do not have enough + * introspection functionality to allow for some level of generic handling. + * This specifically allows framework to check for configuration and annotation + * settings used for Map types, and pass these to custom handlers that may be more + * familiar with actual type. + * + * @since 1.8 + */ +public class MapLikeType extends TypeBase +{ + /** + * Type of keys of Map. + */ + protected final JavaType _keyType; + + /** + * Type of values of Map. + */ + protected final JavaType _valueType; + + /* + /********************************************************** + /* Life-cycle + /********************************************************** + */ + + @Deprecated // since 1.9 + protected MapLikeType(Class<?> mapType, JavaType keyT, JavaType valueT) + { + super(mapType, keyT.hashCode() ^ valueT.hashCode(), null, null); + _keyType = keyT; + _valueType = valueT; + } + + protected MapLikeType(Class<?> mapType, JavaType keyT, JavaType valueT, + Object valueHandler, Object typeHandler) + { + super(mapType, keyT.hashCode() ^ valueT.hashCode(), valueHandler, typeHandler); + _keyType = keyT; + _valueType = valueT; + } + + public static MapLikeType construct(Class<?> rawType, JavaType keyT, JavaType valueT) + { + // nominally component types will be just Object.class + return new MapLikeType(rawType, keyT, valueT, null, null); + } + + @Override + protected JavaType _narrow(Class<?> subclass) + { + return new MapLikeType(subclass, _keyType, _valueType, _valueHandler, _typeHandler); + } + + @Override + public JavaType narrowContentsBy(Class<?> contentClass) + { + // Can do a quick check first: + if (contentClass == _valueType.getRawClass()) { + return this; + } + return new MapLikeType(_class, _keyType, _valueType.narrowBy(contentClass), + _valueHandler, _typeHandler); + } + + @Override + public JavaType widenContentsBy(Class<?> contentClass) + { + if (contentClass == _valueType.getRawClass()) { + return this; + } + return new MapLikeType(_class, _keyType, _valueType.widenBy(contentClass), + _valueHandler, _typeHandler); + } + + public JavaType narrowKey(Class<?> keySubclass) + { + // Can do a quick check first: + if (keySubclass == _keyType.getRawClass()) { + return this; + } + return new MapLikeType(_class, _keyType.narrowBy(keySubclass), _valueType, + _valueHandler, _typeHandler); + } + + /** + * @since 1.8 + */ + public JavaType widenKey(Class<?> keySubclass) + { + // Can do a quick check first: + if (keySubclass == _keyType.getRawClass()) { + return this; + } + return new MapLikeType(_class, _keyType.widenBy(keySubclass), _valueType, + _valueHandler, _typeHandler); + } + + // Since 1.7: + @Override + public MapLikeType withTypeHandler(Object h) + { + return new MapLikeType(_class, _keyType, _valueType, _valueHandler, h); + } + + // Since 1.7: + @Override + public MapLikeType withContentTypeHandler(Object h) + { + return new MapLikeType(_class, _keyType, _valueType.withTypeHandler(h), + _valueHandler, _typeHandler); + } + + // Since 1.9: + @Override + public MapLikeType withValueHandler(Object h) { + return new MapLikeType(_class, _keyType, _valueType, h, _typeHandler); + } + + // Since 1.9: + @Override + public MapLikeType withContentValueHandler(Object h) { + return new MapLikeType(_class, _keyType, _valueType.withValueHandler(h), + _valueHandler, _typeHandler); + } + + @Override + protected String buildCanonicalName() { + StringBuilder sb = new StringBuilder(); + sb.append(_class.getName()); + if (_keyType != null) { + sb.append('<'); + sb.append(_keyType.toCanonical()); + sb.append(','); + sb.append(_valueType.toCanonical()); + sb.append('>'); + } + return sb.toString(); + } + + /* + /********************************************************** + /* Public API + /********************************************************** + */ + + @Override + public boolean isContainerType() { return true; } + + @Override + public boolean isMapLikeType() { return true; } + + @Override + public JavaType getKeyType() { return _keyType; } + + @Override + public JavaType getContentType() { return _valueType; } + + @Override + public int containedTypeCount() { return 2; } + + @Override + public JavaType containedType(int index) { + if (index == 0) return _keyType; + if (index == 1) return _valueType; + return null; + } + + /** + * Not sure if we should count on this, but type names + * for core interfaces are "K" and "V" respectively. + * For now let's assume this should work. + */ + @Override + public String containedTypeName(int index) { + if (index == 0) return "K"; + if (index == 1) return "V"; + return null; + } + + @Override + public StringBuilder getErasedSignature(StringBuilder sb) { + return _classSignature(_class, sb, true); + } + + @Override + public StringBuilder getGenericSignature(StringBuilder sb) + { + _classSignature(_class, sb, false); + sb.append('<'); + _keyType.getGenericSignature(sb); + _valueType.getGenericSignature(sb); + sb.append(">;"); + return sb; + } + + /* + /********************************************************** + /* Extended API + /********************************************************** + */ + + /** + * @since 1.9 + */ + public MapLikeType withKeyTypeHandler(Object h) + { + return new MapLikeType(_class, _keyType.withTypeHandler(h), _valueType, + _valueHandler, _typeHandler); + } + + /** + * @since 1.9 + */ + public MapLikeType withKeyValueHandler(Object h) { + return new MapLikeType(_class, _keyType.withValueHandler(h), _valueType, + _valueHandler, _typeHandler); + } + + /** + * Method that can be used for checking whether this type is a + * "real" Collection type; meaning whether it represents a parameterized + * subtype of {@link java.util.Collection} or just something that acts + * like one. + * + * @since 1.8 + */ + public boolean isTrueMapType() { + return Map.class.isAssignableFrom(_class); + } + + /* + /********************************************************** + /* Standard methods + /********************************************************** + */ + + @Override + public String toString() + { + return "[map-like type; class "+_class.getName()+", "+_keyType+" -> "+_valueType+"]"; + } + + @Override + public boolean equals(Object o) + { + if (o == this) return true; + if (o == null) return false; + if (o.getClass() != getClass()) return false; + + MapLikeType other = (MapLikeType) o; + return (_class == other._class) + && _keyType.equals(other._keyType) + && _valueType.equals(other._valueType); + } + +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/type/MapType.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/type/MapType.java new file mode 100644 index 0000000..2e3a249 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/type/MapType.java
@@ -0,0 +1,146 @@ +package org.codehaus.jackson.map.type; + +import org.codehaus.jackson.type.JavaType; + +/** + * Type that represents "true" Java Map types. + */ +public final class MapType extends MapLikeType +{ + /* + /********************************************************** + /* Life-cycle + /********************************************************** + */ + + @Deprecated + private MapType(Class<?> mapType, JavaType keyT, JavaType valueT) { + this(mapType, keyT, valueT, null, null); + } + + private MapType(Class<?> mapType, JavaType keyT, JavaType valueT, + Object valueHandler, Object typeHandler) { + super(mapType, keyT, valueT, valueHandler, typeHandler); + } + + public static MapType construct(Class<?> rawType, JavaType keyT, JavaType valueT) { + // nominally component types will be just Object.class + return new MapType(rawType, keyT, valueT, null, null); + } + + @Override + protected JavaType _narrow(Class<?> subclass) { + return new MapType(subclass, _keyType, _valueType, + _valueHandler, _typeHandler); + } + + @Override + public JavaType narrowContentsBy(Class<?> contentClass) + { + // Can do a quick check first: + if (contentClass == _valueType.getRawClass()) { + return this; + } + return new MapType(_class, _keyType, _valueType.narrowBy(contentClass), + _valueHandler, _typeHandler); + } + + @Override + public JavaType widenContentsBy(Class<?> contentClass) + { + if (contentClass == _valueType.getRawClass()) { + return this; + } + return new MapType(_class, _keyType, _valueType.widenBy(contentClass), + _valueHandler, _typeHandler); + } + + @Override + public JavaType narrowKey(Class<?> keySubclass) + { + // Can do a quick check first: + if (keySubclass == _keyType.getRawClass()) { + return this; + } + return new MapType(_class, _keyType.narrowBy(keySubclass), _valueType, + _valueHandler, _typeHandler); + } + + /** + * @since 1.8 + */ + @Override + public JavaType widenKey(Class<?> keySubclass) + { + // Can do a quick check first: + if (keySubclass == _keyType.getRawClass()) { + return this; + } + return new MapType(_class, _keyType.widenBy(keySubclass), _valueType, + _valueHandler, _typeHandler); + } + + // Since 1.7: + @Override + public MapType withTypeHandler(Object h) { + return new MapType(_class, _keyType, _valueType, _valueHandler, h); + } + + // Since 1.7: + @Override + public MapType withContentTypeHandler(Object h) + { + return new MapType(_class, _keyType, _valueType.withTypeHandler(h), + _valueHandler, _typeHandler); + } + + // Since 1.9: + @Override + public MapType withValueHandler(Object h) { + return new MapType(_class, _keyType, _valueType, h, _typeHandler); + } + + // Since 1.9: + @Override + public MapType withContentValueHandler(Object h) { + return new MapType(_class, _keyType, _valueType.withValueHandler(h), + _valueHandler, _typeHandler); + } + + /* + /********************************************************** + /* Extended API + /********************************************************** + */ + + /** + * @since 1.9 + */ + @Override + public MapType withKeyTypeHandler(Object h) + { + return new MapType(_class, _keyType.withTypeHandler(h), _valueType, + _valueHandler, _typeHandler); + } + + /** + * @since 1.9 + */ + @Override + public MapType withKeyValueHandler(Object h) { + return new MapType(_class, _keyType.withValueHandler(h), _valueType, + _valueHandler, _typeHandler); + } + + /* + /********************************************************** + /* Standard methods + /********************************************************** + */ + + @Override + public String toString() + { + return "[map type; class "+_class.getName()+", "+_keyType+" -> "+_valueType+"]"; + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/type/SimpleType.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/type/SimpleType.java new file mode 100644 index 0000000..dfc3dee --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/type/SimpleType.java
@@ -0,0 +1,250 @@ +package org.codehaus.jackson.map.type; + +import java.util.*; + +import org.codehaus.jackson.type.JavaType; + +/** + * Simple types are defined as anything other than one of recognized + * container types (arrays, Collections, Maps). For our needs we + * need not know anything further, since we have no way of dealing + * with generic types other than Collections and Maps. + */ +public final class SimpleType + extends TypeBase +{ + /** + * Generic type arguments for this type. + */ + protected final JavaType[] _typeParameters; + + /** + * Names of generic type arguments for this type; will + * match values in {@link #_typeParameters} + */ + protected final String[] _typeNames; + + /* + /********************************************************** + /* Life-cycle + /********************************************************** + */ + + protected SimpleType(Class<?> cls) { + this(cls, null, null, null, null); + } + + @Deprecated // since 1.9 + protected SimpleType(Class<?> cls, String[] typeNames, JavaType[] typeParams) + { + this(cls, typeNames, typeParams, null, null); + } + + protected SimpleType(Class<?> cls, String[] typeNames, JavaType[] typeParams, + Object valueHandler, Object typeHandler) + { + super(cls, 0, valueHandler, typeHandler); + if (typeNames == null || typeNames.length == 0) { + _typeNames = null; + _typeParameters = null; + } else { + _typeNames = typeNames; + _typeParameters = typeParams; + } + } + + /** + * Method used by core Jackson classes: NOT to be used by application code. + *<p> + * NOTE: public only because it is called by <code>ObjectMapper</code> which is + * not in same package + */ + public static SimpleType constructUnsafe(Class<?> raw) { + return new SimpleType(raw, null, null, null, null); + } + + @Override + protected JavaType _narrow(Class<?> subclass) + { + // Should we check that there is a sub-class relationship? + return new SimpleType(subclass, _typeNames, _typeParameters, _valueHandler, _typeHandler); + } + + @Override + public JavaType narrowContentsBy(Class<?> subclass) + { + // should never get called + throw new IllegalArgumentException("Internal error: SimpleType.narrowContentsBy() should never be called"); + } + + @Override + public JavaType widenContentsBy(Class<?> subclass) + { + // should never get called + throw new IllegalArgumentException("Internal error: SimpleType.widenContentsBy() should never be called"); + } + + public static SimpleType construct(Class<?> cls) + { + /* Let's add sanity checks, just to ensure no + * Map/Collection entries are constructed + */ + if (Map.class.isAssignableFrom(cls)) { + throw new IllegalArgumentException("Can not construct SimpleType for a Map (class: "+cls.getName()+")"); + } + if (Collection.class.isAssignableFrom(cls)) { + throw new IllegalArgumentException("Can not construct SimpleType for a Collection (class: "+cls.getName()+")"); + } + // ... and while we are at it, not array types either + if (cls.isArray()) { + throw new IllegalArgumentException("Can not construct SimpleType for an array (class: "+cls.getName()+")"); + } + return new SimpleType(cls); + } + + // Since 1.7: + @Override + public SimpleType withTypeHandler(Object h) + { + return new SimpleType(_class, _typeNames, _typeParameters, _valueHandler, h); + } + + // Since 1.7: + @Override + public JavaType withContentTypeHandler(Object h) { + // no content type, so: + throw new IllegalArgumentException("Simple types have no content types; can not call withContenTypeHandler()"); + } + + // Since 1.9: + @Override + public SimpleType withValueHandler(Object h) { + if (h == _valueHandler) { + return this; + } + return new SimpleType(_class, _typeNames, _typeParameters, h, _typeHandler); + } + + // Since 1.9: + @Override + public SimpleType withContentValueHandler(Object h) { + // no content type, so: + throw new IllegalArgumentException("Simple types have no content types; can not call withContenValueHandler()"); + } + + @Override + protected String buildCanonicalName() + { + StringBuilder sb = new StringBuilder(); + sb.append(_class.getName()); + if (_typeParameters != null && _typeParameters.length > 0) { + sb.append('<'); + boolean first = true; + for (JavaType t : _typeParameters) { + if (first) { + first = false; + } else { + sb.append(','); + } + sb.append(t.toCanonical()); + } + sb.append('>'); + } + return sb.toString(); + } + + /* + /********************************************************** + /* Public API + /********************************************************** + */ + + @Override + public boolean isContainerType() { return false; } + + @Override + public int containedTypeCount() { + return (_typeParameters == null) ? 0 : _typeParameters.length; + } + + @Override + public JavaType containedType(int index) + { + if (index < 0 || _typeParameters == null || index >= _typeParameters.length) { + return null; + } + return _typeParameters[index]; + } + + @Override + public String containedTypeName(int index) + { + if (index < 0 || _typeNames == null || index >= _typeNames.length) { + return null; + } + return _typeNames[index]; + } + + @Override + public StringBuilder getErasedSignature(StringBuilder sb) { + return _classSignature(_class, sb, true); + } + + @Override + public StringBuilder getGenericSignature(StringBuilder sb) + { + _classSignature(_class, sb, false); + if (_typeParameters != null) { + sb.append('<'); + for (JavaType param : _typeParameters) { + sb = param.getGenericSignature(sb); + } + sb.append('>'); + } + sb.append(';'); + return sb; + } + + /* + /********************************************************** + /* Standard methods + /********************************************************** + */ + + @Override + public String toString() + { + StringBuilder sb = new StringBuilder(40); + sb.append("[simple type, class ").append(buildCanonicalName()).append(']'); + return sb.toString(); + } + + @Override + public boolean equals(Object o) + { + if (o == this) return true; + if (o == null) return false; + if (o.getClass() != getClass()) return false; + + SimpleType other = (SimpleType) o; + + // Classes must be identical... + if (other._class != this._class) return false; + + // And finally, generic bindings, if any + JavaType[] p1 = _typeParameters; + JavaType[] p2 = other._typeParameters; + if (p1 == null) { + return (p2 == null) || p2.length == 0; + } + if (p2 == null) return false; + + if (p1.length != p2.length) return false; + for (int i = 0, len = p1.length; i < len; ++i) { + if (!p1[i].equals(p2[i])) { + return false; + } + } + return true; + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/type/TypeBase.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/type/TypeBase.java new file mode 100644 index 0000000..1c192ad --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/type/TypeBase.java
@@ -0,0 +1,148 @@ +package org.codehaus.jackson.map.type; + +import java.io.IOException; + +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.map.JsonSerializableWithType; +import org.codehaus.jackson.map.SerializerProvider; +import org.codehaus.jackson.map.TypeSerializer; +import org.codehaus.jackson.type.JavaType; + +public abstract class TypeBase + extends JavaType + implements JsonSerializableWithType +{ + /** + * Lazily initialized external representation of the type + */ + volatile String _canonicalName; + + @Deprecated // since 1.9; to remove from 2.0 + protected TypeBase(Class<?> raw, int hash) { + super(raw, hash); + } + + /** + * Main constructor to use by extending classes. + * + * @since 1.9 + */ + protected TypeBase(Class<?> raw, int hash, + Object valueHandler, Object typeHandler) + { + super(raw, hash); + // @TODO: !!! 16-Aug-2011, tatu: With 2.0, we will move value and type + // handles higher in type hierarchy, make final + + // and then comment out these: + _valueHandler = valueHandler; + _typeHandler = typeHandler; + } + + @Override + public String toCanonical() + { + String str = _canonicalName; + if (str == null) { + str = buildCanonicalName(); + } + return str; + } + + protected abstract String buildCanonicalName(); + + @Override + public abstract StringBuilder getGenericSignature(StringBuilder sb); + + @Override + public abstract StringBuilder getErasedSignature(StringBuilder sb); + + @Override + @SuppressWarnings("unchecked") + public <T> T getValueHandler() { return (T) _valueHandler; } + + @Override + @SuppressWarnings("unchecked") + public <T> T getTypeHandler() { return (T) _typeHandler; } + + /* + /********************************************************** + /* JsonSerializableWithType base implementation + /********************************************************** + */ + + @Override + public void serializeWithType(JsonGenerator jgen, SerializerProvider provider, + TypeSerializer typeSer) + throws IOException, JsonProcessingException + { + typeSer.writeTypePrefixForScalar(this, jgen); + this.serialize(jgen, provider); + typeSer.writeTypeSuffixForScalar(this, jgen); + } + + @Override + public void serialize(JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonProcessingException + { + jgen.writeString(toCanonical()); + } + + /* + /********************************************************** + /* Methods for sub-classes to use + /********************************************************** + */ + + /** + * @param trailingSemicolon Whether to add trailing semicolon for non-primitive + * (reference) types or not + */ + protected static StringBuilder _classSignature(Class<?> cls, StringBuilder sb, + boolean trailingSemicolon) + { + if (cls.isPrimitive()) { + if (cls == Boolean.TYPE) { + sb.append('Z'); + } else if (cls == Byte.TYPE) { + sb.append('B'); + } + else if (cls == Short.TYPE) { + sb.append('S'); + } + else if (cls == Character.TYPE) { + sb.append('C'); + } + else if (cls == Integer.TYPE) { + sb.append('I'); + } + else if (cls == Long.TYPE) { + sb.append('J'); + } + else if (cls == Float.TYPE) { + sb.append('F'); + } + else if (cls == Double.TYPE) { + sb.append('D'); + } + else if (cls == Void.TYPE) { + sb.append('V'); + } else { + throw new IllegalStateException("Unrecognized primitive type: "+cls.getName()); + } + } else { + sb.append('L'); + String name = cls.getName(); + for (int i = 0, len = name.length(); i < len; ++i) { + char c = name.charAt(i); + if (c == '.') c = '/'; + sb.append(c); + } + if (trailingSemicolon) { + sb.append(';'); + } + } + return sb; + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/type/TypeBindings.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/type/TypeBindings.java new file mode 100644 index 0000000..2145897 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/type/TypeBindings.java
@@ -0,0 +1,351 @@ +package org.codehaus.jackson.map.type; + +import java.lang.reflect.*; +import java.util.*; + +import org.codehaus.jackson.type.JavaType; + +/** + * Helper class used for resolving type parameters for given class + * + * @since 1.5 + */ +public class TypeBindings +{ + private final static JavaType[] NO_TYPES = new JavaType[0]; + + /** + * Marker to use for (temporarily) unbound references. + */ + public final static JavaType UNBOUND = new SimpleType(Object.class); + + /** + * Factory to use for constructing resolved related types. + */ + protected final TypeFactory _typeFactory; + + /** + * Context type used for resolving all types, if specified. May be null, + * in which case {@link #_contextClass} is used instead. + */ + protected final JavaType _contextType; + + /** + * Specific class to use for resolving all types, for methods and fields + * class and its superclasses and -interfaces contain. + */ + protected final Class<?> _contextClass; + + /** + * Lazily-instantiated bindings of resolved type parameters + */ + protected Map<String,JavaType> _bindings; + + /** + * Also: we may temporarily want to mark certain named types + * as resolved (but without exact type); if so, we'll just store + * names here. + */ + protected HashSet<String> _placeholders; + + /** + * Sometimes it is necessary to allow hierarchic resolution of types: specifically + * in cases where there are local bindings (for methods, constructors). If so, + * we'll just use simple delegation model. + * + * @since 1.7 + */ + private final TypeBindings _parentBindings; + + /* + /********************************************************** + /* Construction + /********************************************************** + */ + + public TypeBindings(TypeFactory typeFactory, Class<?> cc) + { + this(typeFactory, null, cc, null); + } + + public TypeBindings(TypeFactory typeFactory, JavaType type) + { + this(typeFactory, null, type.getRawClass(), type); + } + + /** + * Constructor used to create "child" instances; mostly to + * allow delegation from explicitly defined local overrides + * (local type variables for methods, constructors) to + * contextual (class-defined) ones. + * + * @since 1.7 + */ + public TypeBindings childInstance() { + return new TypeBindings(_typeFactory, this, _contextClass, _contextType); + } + + /** + * @since 1.7 + */ + private TypeBindings(TypeFactory tf, TypeBindings parent, Class<?> cc, JavaType type) + { + _typeFactory = tf; + _parentBindings = parent; + _contextClass = cc; + _contextType = type; + } + + /* + /********************************************************** + /* Pass-through type resolution methods + /********************************************************** + */ + + public JavaType resolveType(Class<?> cls) { + return _typeFactory._constructType(cls, this); + } + + public JavaType resolveType(Type type) { + return _typeFactory._constructType(type, this); + } + + /* + /********************************************************** + /* Accesors + /********************************************************** + */ + + /** + * @since 1.8 + */ + /* + public TypeFactory getTypeFactory() { + return _typeFactory; + } + */ + + public int getBindingCount() { + if (_bindings == null) { + _resolve(); + } + return _bindings.size(); + } + + public JavaType findType(String name) + { + if (_bindings == null) { + _resolve(); + } + JavaType t = _bindings.get(name); + if (t != null) { + return t; + } + if (_placeholders != null && _placeholders.contains(name)) { + return UNBOUND; + } + // New with 1.7: check parent context + if (_parentBindings != null) { + return _parentBindings.findType(name); + } + // nothing found, so... + // Should we throw an exception or just return null? + + /* [JACKSON-499] 18-Feb-2011, tatu: There are some tricky type bindings within + * java.util, such as HashMap$KeySet; so let's punt the problem + * (honestly not sure what to do -- they are unbound for good, I think) + */ + if (_contextClass != null) { + Class<?> enclosing = _contextClass.getEnclosingClass(); + if (enclosing != null) { + // [JACKSON-572]: Actually, let's skip this for all non-static inner classes + // (which will also cover 'java.util' type cases... + if (!Modifier.isStatic(_contextClass.getModifiers())) { + return UNBOUND; + } + + // ... so this piece of code should not be needed any more + /* + Package pkg = enclosing.getPackage(); + if (pkg != null) { + // as per [JACKSON-533], also include "java.util.concurrent": + if (pkg.getName().startsWith("java.util")) { + return UNBOUND; + } + } + */ + } + } + + String className; + if (_contextClass != null) { + className = _contextClass.getName(); + } else if (_contextType != null) { + className = _contextType.toString(); + } else { + className = "UNKNOWN"; + } + throw new IllegalArgumentException("Type variable '"+name + +"' can not be resolved (with context of class "+className+")"); + //t = UNBOUND; + } + + public void addBinding(String name, JavaType type) + { + // note: emptyMap() is unmodifiable, hence second check is needed: + if (_bindings == null || _bindings.size() == 0) { + _bindings = new LinkedHashMap<String,JavaType>(); + } + _bindings.put(name, type); + } + + public JavaType[] typesAsArray() + { + if (_bindings == null) { + _resolve(); + } + if (_bindings.size() == 0) { + return NO_TYPES; + } + return _bindings.values().toArray(new JavaType[_bindings.size()]); + } + + /* + /********************************************************** + /* Internal methods + /********************************************************** + */ + + protected void _resolve() + { + _resolveBindings(_contextClass); + + // finally: may have root level type info too + if (_contextType != null) { + int count = _contextType.containedTypeCount(); + if (count > 0) { + if (_bindings == null) { + _bindings = new LinkedHashMap<String,JavaType>(); + } + for (int i = 0; i < count; ++i) { + String name = _contextType.containedTypeName(i); + JavaType type = _contextType.containedType(i); + _bindings.put(name, type); + } + } + } + + // nothing bound? mark with empty map to prevent further calls + if (_bindings == null) { + _bindings = Collections.emptyMap(); + } + } + + public void _addPlaceholder(String name) { + if (_placeholders == null) { + _placeholders = new HashSet<String>(); + } + _placeholders.add(name); + } + + protected void _resolveBindings(Type t) + { + if (t == null) return; + + Class<?> raw; + if (t instanceof ParameterizedType) { + ParameterizedType pt = (ParameterizedType) t; + Type[] args = pt.getActualTypeArguments(); + if (args != null && args.length > 0) { + Class<?> rawType = (Class<?>) pt.getRawType(); + TypeVariable<?>[] vars = rawType.getTypeParameters(); + if (vars.length != args.length) { + throw new IllegalArgumentException("Strange parametrized type (in class "+rawType.getName()+"): number of type arguments != number of type parameters ("+args.length+" vs "+vars.length+")"); + } + for (int i = 0, len = args.length; i < len; ++i) { + TypeVariable<?> var = vars[i]; + String name = var.getName(); + if (_bindings == null) { + _bindings = new LinkedHashMap<String,JavaType>(); + } else { + /* 24-Mar-2010, tatu: Better ensure that we do not overwrite something + * collected earlier (since we descend towards super-classes): + */ + if (_bindings.containsKey(name)) continue; + } + // first: add a placeholder to prevent infinite loops + _addPlaceholder(name); + // then resolve type + _bindings.put(name, _typeFactory._constructType(args[i], this)); + } + } + raw = (Class<?>)pt.getRawType(); + } else if (t instanceof Class<?>) { + raw = (Class<?>) t; + /* [JACKSON-677]: If this is an inner class then the generics are defined on the + * enclosing class so we have to check there as well. We don't + * need to call getEnclosingClass since anonymous classes declare + * generics + */ + _resolveBindings(raw.getDeclaringClass()); + /* 24-Mar-2010, tatu: Can not have true generics definitions, but can + * have lower bounds ("<T extends BeanBase>") in declaration itself + */ + TypeVariable<?>[] vars = raw.getTypeParameters(); + if (vars != null && vars.length > 0) { + JavaType[] typeParams = null; + + if (_contextType != null && raw.isAssignableFrom(_contextType.getRawClass())) { + typeParams = _typeFactory.findTypeParameters(_contextType, raw); + } + + for (int i = 0; i < vars.length; i++) { + TypeVariable<?> var = vars[i]; + + String name = var.getName(); + Type varType = var.getBounds()[0]; + if (varType != null) { + if (_bindings == null) { + _bindings = new LinkedHashMap<String,JavaType>(); + } else { // and no overwriting... + if (_bindings.containsKey(name)) continue; + } + _addPlaceholder(name); // to prevent infinite loops + + if (typeParams != null) { + _bindings.put(name, typeParams[i]); + } else { + _bindings.put(name, _typeFactory._constructType(varType, this)); + } + } + } + } + } else { // probably can't be any of these... so let's skip for now + //if (type instanceof GenericArrayType) { + //if (type instanceof TypeVariable<?>) { + // if (type instanceof WildcardType) { + return; + } + // but even if it's not a parameterized type, its super types may be: + _resolveBindings(raw.getGenericSuperclass()); + for (Type intType : raw.getGenericInterfaces()) { + _resolveBindings(intType); + } + } + + @Override + public String toString() + { + if (_bindings == null) { + _resolve(); + } + StringBuilder sb = new StringBuilder("[TypeBindings for "); + if (_contextType != null) { + sb.append(_contextType.toString()); + } else { + sb.append(_contextClass.getName()); + } + sb.append(": ").append(_bindings).append("]"); + return sb.toString(); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/type/TypeFactory.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/type/TypeFactory.java new file mode 100644 index 0000000..dfed4e2 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/type/TypeFactory.java
@@ -0,0 +1,1165 @@ +package org.codehaus.jackson.map.type; + +import java.util.*; +import java.lang.reflect.*; + +import org.codehaus.jackson.map.util.ArrayBuilders; +import org.codehaus.jackson.type.JavaType; +import org.codehaus.jackson.type.TypeReference; + +/** + * Class used for creating concrete {@link JavaType} instances, + * given various inputs. + *<p> + * As of Jackson 1.8, usage should be done using instance configured + * via {@link org.codehaus.jackson.map.ObjectMapper} (and exposed through + * {@link org.codehaus.jackson.map.DeserializationConfig} and + * {@link org.codehaus.jackson.map.SerializationConfig}). + * However, old static-singleton access methods are supported as well; however, + * using those may cause issues with extension modules that register + * "type enchancers". + *<p> + * Typical usage pattern before Jackson 1.8 was to statically import factory methods + * of this class, to allow convenient instantiation of structured + * types, especially {@link Collection} and {@link Map} types + * to represent generic types. For example + *<pre> + * mapType(String.class, Integer.class) + *</pre> + * to represent + *<pre> + * Map<String,Integer> + *</pre> + * This is an alternative to using {@link TypeReference} that would + * be something like + *<pre> + * new TypeReference<Map<String,Integer>>() { } + *</pre> + */ +@SuppressWarnings({"rawtypes", "unchecked"}) +public final class TypeFactory +{ + /** + * Globally shared singleton. Should never be accessed directly; non-core + * code should use per-ObjectMapper instance (via configuration objects). + * Core Jackson code uses {@link #defaultInstance} for accessing it. + * + * @deprecated As of 1.8, should use a per-ObjectMapper instance instead + * of global singleton + */ + @Deprecated + public final static TypeFactory instance = new TypeFactory(); + + private final static JavaType[] NO_TYPES = new JavaType[0]; + + /** + * Registered {@link TypeModifier}s: objects that can change details + * of {@link JavaType} instances factory constructs. + * + * @since 1.8 + */ + protected final TypeModifier[] _modifiers; + + protected final TypeParser _parser; + + /* + * Looks like construction of {@link JavaType} instances can be + * a bottleneck, esp. for root-level Maps, so we better do bit + * of low-level component caching here... + */ + + /** + * Lazily constructed copy of type hierarchy from {@link java.util.HashMap} + * to its supertypes. + * + * @since 1.9 + */ + protected HierarchicType _cachedHashMapType; + + /** + * Lazily constructed copy of type hierarchy from {@link java.util.ArrayList} + * to its supertypes. + * + * @since 1.9 + */ + protected HierarchicType _cachedArrayListType; + + /* + /********************************************************** + /* Life-cycle + /********************************************************** + */ + + private TypeFactory() { + _parser = new TypeParser(this); + _modifiers = null; + } + + protected TypeFactory(TypeParser p, TypeModifier[] mods) { + _parser = p; + _modifiers = mods; + } + + public TypeFactory withModifier(TypeModifier mod) + { + if (_modifiers == null) { + return new TypeFactory(_parser, new TypeModifier[] { mod }); + } + return new TypeFactory(_parser, ArrayBuilders.insertInListNoDup(_modifiers, mod)); + } + + /** + * Method used to access the globally shared instance, which has + * no custom configuration. Used by <code>ObjectMapper</code> to + * get the default factory when constructed. + * + * @since 1.8 + */ + public static TypeFactory defaultInstance() { return instance; } + + /* + /********************************************************** + /* Static methods for non-instance-specific functionality + /********************************************************** + */ + + /** + * Method for constructing a marker type that indicates missing generic + * type information, which is handled same as simple type for + * <code>java.lang.Object</code>. + * + * @since 1.8 + */ + public static JavaType unknownType() { + return defaultInstance()._unknownType(); + } + + public static Class<?> rawClass(Type t) { + if (t instanceof Class<?>) { + return (Class<?>) t; + } + // Can optimize bit more in future... + return defaultInstance().constructType(t).getRawClass(); + } + + /* + /********************************************************** + /* Legacy factory methods (pre-1.8) + /********************************************************** + */ + + @Deprecated + public static JavaType type(Type t) { + return instance._constructType(t, null); + } + + @Deprecated + public static JavaType type(Type type, Class<?> context) { + return instance.constructType(type, context); + } + + @Deprecated + public static JavaType type(Type type, JavaType context) { + return instance.constructType(type, context); + } + + @Deprecated + public static JavaType type(Type type, TypeBindings bindings) { + return instance._constructType(type, bindings); + } + + @Deprecated + public static JavaType type(TypeReference<?> ref) { + return instance.constructType(ref.getType()); + } + + @Deprecated + public static JavaType arrayType(Class<?> elementType) { + return instance.constructArrayType(instance.constructType(elementType)); + } + + @Deprecated + public static JavaType arrayType(JavaType elementType) { + return instance.constructArrayType(elementType); + } + + @Deprecated + public static JavaType collectionType(Class<? extends Collection> collectionType, Class<?> elementType) { + return instance.constructCollectionType(collectionType, instance.constructType(elementType)); + } + + @Deprecated + public static JavaType collectionType(Class<? extends Collection> collectionType, JavaType elementType) { + return instance.constructCollectionType(collectionType, elementType); + } + + @Deprecated + public static JavaType mapType(Class<? extends Map> mapClass, Class<?> keyType, Class<?> valueType) + { + return instance.constructMapType(mapClass, type(keyType), instance.constructType(valueType)); + } + + @Deprecated + public static JavaType mapType(Class<? extends Map> mapType, JavaType keyType, JavaType valueType) { + return instance.constructMapType(mapType, keyType, valueType); + } + + @Deprecated + public static JavaType parametricType(Class<?> parametrized, Class<?>... parameterClasses) { + return instance.constructParametricType(parametrized, parameterClasses); + } + + @Deprecated + public static JavaType parametricType(Class<?> parametrized, JavaType... parameterTypes) { + return instance.constructParametricType(parametrized, parameterTypes); + } + + public static JavaType fromCanonical(String canonical) throws IllegalArgumentException { + return instance.constructFromCanonical(canonical); + } + + @Deprecated + public static JavaType specialize(JavaType baseType, Class<?> subclass) { + return instance.constructSpecializedType(baseType, subclass); + } + + @Deprecated + public static JavaType fastSimpleType(Class<?> cls) { + return instance.uncheckedSimpleType(cls); + } + + @Deprecated + public static JavaType[] findParameterTypes(Class<?> clz, Class<?> expType) { + return instance.findTypeParameters(clz, expType); + } + + @Deprecated + public static JavaType[] findParameterTypes(Class<?> clz, Class<?> expType, TypeBindings bindings) { + return instance.findTypeParameters(clz, expType, bindings); + } + + @Deprecated + public static JavaType[] findParameterTypes(JavaType type, Class<?> expType) { + return instance.findTypeParameters(type, expType); + } + + /* + /********************************************************** + /* Legacy methods + /********************************************************** + */ + + /** + * Factory method that can be used if only type information + * available is of type {@link Class}. This means that there + * will not be generic type information due to type erasure, + * but at least it will be possible to recognize array + * types and non-typed container types. + * And for other types (primitives/wrappers, beans), this + * is all that is needed. + * + * @deprecated Use {@link #type(Type)} instead + */ + @Deprecated + public static JavaType fromClass(Class<?> clz) + { + return instance._fromClass(clz, null); + } + + /** + * Factory method that can be used if the full generic type has + * been passed using {@link TypeReference}. This only needs to be + * done if the root type to bind to is generic; but if so, + * it must be done to get proper typing. + * + * @deprecated Use {@link #type(Type)} instead + */ + @Deprecated + public static JavaType fromTypeReference(TypeReference<?> ref) + { + return type(ref.getType()); + } + + /** + * Factory method that can be used if type information is passed + * as Java typing returned from <code>getGenericXxx</code> methods + * (usually for a return or argument type). + * + * @deprecated Use {@link #type(Type)} instead + */ + @Deprecated + public static JavaType fromType(Type type) + { + return instance._constructType(type, null); + } + + /* + /********************************************************** + /* Type conversion, parameterization resolution methods + /********************************************************** + */ + + /** + * Factory method for creating a subtype of given base type, as defined + * by specified subclass; but retaining generic type information if any. + * Can be used, for example, to get equivalent of "HashMap<String,Integer>" + * from "Map<String,Integer>" by giving <code>HashMap.class</code> + * as subclass. + */ + public JavaType constructSpecializedType(JavaType baseType, Class<?> subclass) + { + // Currently only SimpleType instances can become something else + if (baseType instanceof SimpleType) { + // and only if subclass is an array, Collection or Map + if (subclass.isArray() + || Map.class.isAssignableFrom(subclass) + || Collection.class.isAssignableFrom(subclass)) { + // need to assert type compatibility... + if (!baseType.getRawClass().isAssignableFrom(subclass)) { + throw new IllegalArgumentException("Class "+subclass.getClass().getName()+" not subtype of "+baseType); + } + // this _should_ work, right? + JavaType subtype = _fromClass(subclass, new TypeBindings(this, baseType.getRawClass())); + // one more thing: handlers to copy? + Object h = baseType.getValueHandler(); + if (h != null) { +// subtype.setValueHandler(h); + subtype = subtype.withValueHandler(h); + } + h = baseType.getTypeHandler(); + if (h != null) { + subtype = subtype.withTypeHandler(h); + } + return subtype; + } + } + // otherwise regular narrowing should work just fine + return baseType.narrowBy(subclass); + } + + /** + * Factory method for constructing a {@link JavaType} out of its canonical + * representation (see {@link JavaType#toCanonical()}). + * + * @param canonical Canonical string representation of a type + * + * @throws IllegalArgumentException If canonical representation is malformed, + * or class that type represents (including its generic parameters) is + * not found + * + * @since 1.8 + */ + public JavaType constructFromCanonical(String canonical) throws IllegalArgumentException + { + return _parser.parse(canonical); + } + + /** + * Method that is to figure out actual type parameters that given + * class binds to generic types defined by given (generic) + * interface or class. + * This could mean, for example, trying to figure out + * key and value types for Map implementations. + * + * @param type Sub-type (leaf type) that implements <code>expType</code> + * + * @since 1.6 + */ + public JavaType[] findTypeParameters(JavaType type, Class<?> expType) + { + /* Tricky part here is that some JavaType instances have been constructed + * from generic type (usually via TypeReference); and in those case + * types have been resolved. Alternative is that the leaf type is type-erased + * class, in which case this has not been done. + * For now simplest way to handle this is to split processing in two: latter + * case actually fully works; and former mostly works. In future may need to + * rewrite former part, which requires changes to JavaType as well. + */ + Class<?> raw = type.getRawClass(); + if (raw == expType) { + // Direct type info; good since we can return it as is + int count = type.containedTypeCount(); + if (count == 0) return null; + JavaType[] result = new JavaType[count]; + for (int i = 0; i < count; ++i) { + result[i] = type.containedType(i); + } + return result; + } + /* Otherwise need to go through type-erased class. This may miss cases where + * we get generic type; ideally JavaType/SimpleType would retain information + * about generic declaration at main level... but let's worry about that + * if/when there are problems; current handling is an improvement over earlier + * code. + */ + return findTypeParameters(raw, expType, new TypeBindings(this, type)); + } + + public JavaType[] findTypeParameters(Class<?> clz, Class<?> expType) { + return findTypeParameters(clz, expType, new TypeBindings(this, clz)); + } + + public JavaType[] findTypeParameters(Class<?> clz, Class<?> expType, TypeBindings bindings) + { + // First: find full inheritance chain + HierarchicType subType = _findSuperTypeChain(clz, expType); + // Caller is supposed to ensure this never happens, so: + if (subType == null) { + throw new IllegalArgumentException("Class "+clz.getName()+" is not a subtype of "+expType.getName()); + } + // Ok and then go to the ultimate super-type: + HierarchicType superType = subType; + while (superType.getSuperType() != null) { + superType = superType.getSuperType(); + Class<?> raw = superType.getRawClass(); + TypeBindings newBindings = new TypeBindings(this, raw); + if (superType.isGeneric()) { // got bindings, need to resolve + ParameterizedType pt = superType.asGeneric(); + Type[] actualTypes = pt.getActualTypeArguments(); + TypeVariable<?>[] vars = raw.getTypeParameters(); + int len = actualTypes.length; + for (int i = 0; i < len; ++i) { + String name = vars[i].getName(); + JavaType type = instance._constructType(actualTypes[i], bindings); + newBindings.addBinding(name, type); + } + } + bindings = newBindings; + } + + // which ought to be generic (if not, it's raw type) + if (!superType.isGeneric()) { + return null; + } + return bindings.typesAsArray(); + } + + /* + /********************************************************** + /* Public factory methods + /********************************************************** + */ + + public JavaType constructType(Type type) { + return _constructType(type, null); + } + + public JavaType constructType(Type type, TypeBindings bindings) { + return _constructType(type, bindings); + } + + public JavaType constructType(TypeReference<?> typeRef) { + return _constructType(typeRef.getType(), null); + } + + public JavaType constructType(Type type, Class<?> context) { + TypeBindings b = (context == null) ? null : new TypeBindings(this, context); + return _constructType(type, b); + } + + public JavaType constructType(Type type, JavaType context) { + TypeBindings b = (context == null) ? null : new TypeBindings(this, context); + return _constructType(type, b); + } + + /** + * Factory method that can be used if type information is passed + * as Java typing returned from <code>getGenericXxx</code> methods + * (usually for a return or argument type). + */ + public JavaType _constructType(Type type, TypeBindings context) + { + JavaType resultType; + + // simple class? + if (type instanceof Class<?>) { + Class<?> cls = (Class<?>) type; + /* 24-Mar-2010, tatu: Better create context if one was not passed; + * mostly matters for root serialization types + */ + if (context == null) { + context = new TypeBindings(this, cls); + } + resultType = _fromClass(cls, context); + } + // But if not, need to start resolving. + else if (type instanceof ParameterizedType) { + resultType = _fromParamType((ParameterizedType) type, context); + } + else if (type instanceof GenericArrayType) { + resultType = _fromArrayType((GenericArrayType) type, context); + } + else if (type instanceof TypeVariable<?>) { + resultType = _fromVariable((TypeVariable<?>) type, context); + } + else if (type instanceof WildcardType) { + resultType = _fromWildcard((WildcardType) type, context); + } else { + // sanity check + throw new IllegalArgumentException("Unrecognized Type: "+type.toString()); + } + /* [JACKSON-521]: Need to allow TypeModifiers to alter actual type; however, + * for now only call for simple types (i.e. not for arrays, map or collections). + * Can be changed in future it necessary + */ + if (_modifiers != null && !resultType.isContainerType()) { + for (TypeModifier mod : _modifiers) { + resultType = mod.modifyType(resultType, type, context, this); + } + } + return resultType; + } + + /* + /********************************************************** + /* Direct factory methods + /********************************************************** + */ + + /** + * Method for constructing an {@link ArrayType}. + *<p> + * NOTE: type modifiers are NOT called on array type itself; but are called + * for element type (and other contained types) + */ + public ArrayType constructArrayType(Class<?> elementType) { + return ArrayType.construct(_constructType(elementType, null), null, null); + } + + /** + * Method for constructing an {@link ArrayType}. + *<p> + * NOTE: type modifiers are NOT called on array type itself; but are called + * for contained types. + */ + public ArrayType constructArrayType(JavaType elementType) { + return ArrayType.construct(elementType, null, null); + } + + /** + * Method for constructing a {@link CollectionType}. + *<p> + * NOTE: type modifiers are NOT called on Collection type itself; but are called + * for contained types. + */ + public CollectionType constructCollectionType(Class<? extends Collection> collectionClass, Class<?> elementClass) { + return CollectionType.construct(collectionClass, constructType(elementClass)); + } + + /** + * Method for constructing a {@link CollectionType}. + *<p> + * NOTE: type modifiers are NOT called on Collection type itself; but are called + * for contained types. + */ + public CollectionType constructCollectionType(Class<? extends Collection> collectionClass, JavaType elementType) { + return CollectionType.construct(collectionClass, elementType); + } + + /** + * Method for constructing a {@link CollectionLikeType}. + *<p> + * NOTE: type modifiers are NOT called on constructed type itself; but are called + * for contained types. + * + * @since 1.8 + */ + public CollectionLikeType constructCollectionLikeType(Class<?> collectionClass, Class<?> elementClass) { + return CollectionLikeType.construct(collectionClass, constructType(elementClass)); + } + + /** + * Method for constructing a {@link CollectionLikeType}. + *<p> + * NOTE: type modifiers are NOT called on constructed type itself; but are called + * for contained types. + * + * @since 1.8 + */ + public CollectionLikeType constructCollectionLikeType(Class<?> collectionClass, JavaType elementType) { + return CollectionLikeType.construct(collectionClass, elementType); + } + + /** + * Method for constructing a {@link MapType} instance + *<p> + * NOTE: type modifiers are NOT called on constructed type itself; but are called + * for contained types. + * + * @since 1.8 + */ + public MapType constructMapType(Class<? extends Map> mapClass, JavaType keyType, JavaType valueType) { + return MapType.construct(mapClass, keyType, valueType); + } + + /** + * Method for constructing a {@link MapType} instance + *<p> + * NOTE: type modifiers are NOT called on constructed type itself; but are called + * for contained types. + * + * @since 1.8 + */ + public MapType constructMapType(Class<? extends Map> mapClass, Class<?> keyClass, Class<?> valueClass) { + return MapType.construct(mapClass, constructType(keyClass), constructType(valueClass)); + } + + /** + * Method for constructing a {@link MapLikeType} instance + *<p> + * NOTE: type modifiers are NOT called on constructed type itself; but are called + * for contained types. + * + * @since 1.8 + */ + public MapLikeType constructMapLikeType(Class<?> mapClass, JavaType keyType, JavaType valueType) { + return MapLikeType.construct(mapClass, keyType, valueType); + } + + /** + * Method for constructing a {@link MapLikeType} instance + *<p> + * NOTE: type modifiers are NOT called on constructed type itself; but are called + * for contained types. + * + * @since 1.8 + */ + public MapLikeType constructMapLikeType(Class<?> mapClass, Class<?> keyClass, Class<?> valueClass) { + return MapType.construct(mapClass, constructType(keyClass), constructType(valueClass)); + } + + /** + * Method for constructing a type instance with specified parameterization. + * + * @since 1.8 + */ + public JavaType constructSimpleType(Class<?> rawType, JavaType[] parameterTypes) + { + // Quick sanity check: must match numbers of types with expected... + TypeVariable<?>[] typeVars = rawType.getTypeParameters(); + if (typeVars.length != parameterTypes.length) { + throw new IllegalArgumentException("Parameter type mismatch for "+rawType.getName() + +": expected "+typeVars.length+" parameters, was given "+parameterTypes.length); + } + String[] names = new String[typeVars.length]; + for (int i = 0, len = typeVars.length; i < len; ++i) { + names[i] = typeVars[i].getName(); + } + JavaType resultType = new SimpleType(rawType, names, parameterTypes, null, null); + return resultType; + } + + /** + * Method that will force construction of a simple type, without trying to + * check for more specialized types. + *<p> + * NOTE: no type modifiers are called on type either, so calling this method + * should only be used if caller really knows what it's doing... + * + * @since 1.8 + */ + public JavaType uncheckedSimpleType(Class<?> cls) { + return new SimpleType(cls); + } + + /** + * Factory method for constructing {@link JavaType} that + * represents a parameterized type. For example, to represent + * type <code>List<Set<Integer>></code>, you could + * call + *<pre> + * TypeFactory.parametricType(List.class, Integer.class); + *</pre> + *<p> + * NOTE: type modifiers are NOT called on constructed type itself; but are called + * for contained types. + * + * @since 1.5 + */ + public JavaType constructParametricType(Class<?> parametrized, Class<?>... parameterClasses) + { + int len = parameterClasses.length; + JavaType[] pt = new JavaType[len]; + for (int i = 0; i < len; ++i) { + pt[i] = _fromClass(parameterClasses[i], null); + } + return constructParametricType(parametrized, pt); + } + + /** + * Factory method for constructing {@link JavaType} that + * represents a parameterized type. For example, to represent + * type <code>List<Set<Integer>></code>, you could + * call + *<pre> + * JavaType inner = TypeFactory.parametricType(Set.class, Integer.class); + * TypeFactory.parametricType(List.class, inner); + *</pre> + *<p> + * NOTE: type modifiers are NOT called on constructed type itself; but are called + * for contained types. + * + * @since 1.5 + */ + public JavaType constructParametricType(Class<?> parametrized, JavaType... parameterTypes) + { + JavaType resultType; + + // Need to check kind of class we are dealing with... + if (parametrized.isArray()) { + // 19-Jan-2010, tatus: should we support multi-dimensional arrays directly? + if (parameterTypes.length != 1) { + throw new IllegalArgumentException("Need exactly 1 parameter type for arrays ("+parametrized.getName()+")"); + } + resultType = constructArrayType(parameterTypes[0]); + } + else if (Map.class.isAssignableFrom(parametrized)) { + if (parameterTypes.length != 2) { + throw new IllegalArgumentException("Need exactly 2 parameter types for Map types ("+parametrized.getName()+")"); + } + resultType = constructMapType((Class<Map<?,?>>)parametrized, parameterTypes[0], parameterTypes[1]); + } + else if (Collection.class.isAssignableFrom(parametrized)) { + if (parameterTypes.length != 1) { + throw new IllegalArgumentException("Need exactly 1 parameter type for Collection types ("+parametrized.getName()+")"); + } + resultType = constructCollectionType((Class<Collection<?>>)parametrized, parameterTypes[0]); + } else { + resultType = constructSimpleType(parametrized, parameterTypes); + } + return resultType; + } + + /* + /********************************************************** + /* Direct factory methods for "raw" variants, used when + /* parameterization is unknown + /********************************************************** + */ + + /** + * Method that can be used to construct "raw" Collection type; meaning that its + * parameterization is unknown. + * This is similar to using <code>Object.class</code> parameterization, + * and is equivalent to calling: + *<pre> + * typeFactory.constructCollectionType(collectionClass, typeFactory.unknownType()); + *<pre> + *<p> + * This method should only be used if parameterization is completely unavailable. + * + * @since 1.9 + */ + public CollectionType constructRawCollectionType(Class<? extends Collection> collectionClass) { + return CollectionType.construct(collectionClass, unknownType()); + } + + /** + * Method that can be used to construct "raw" Collection-like type; meaning that its + * parameterization is unknown. + * This is similar to using <code>Object.class</code> parameterization, + * and is equivalent to calling: + *<pre> + * typeFactory.constructCollectionLikeType(collectionClass, typeFactory.unknownType()); + *<pre> + *<p> + * This method should only be used if parameterization is completely unavailable. + * + * @since 1.9 + */ + public CollectionLikeType constructRawCollectionLikeType(Class<?> collectionClass) { + return CollectionLikeType.construct(collectionClass, unknownType()); + } + + /** + * Method that can be used to construct "raw" Map type; meaning that its + * parameterization is unknown. + * This is similar to using <code>Object.class</code> parameterization, + * and is equivalent to calling: + *<pre> + * typeFactory.constructMapType(collectionClass, typeFactory.unknownType(), typeFactory.unknownType()); + *<pre> + *<p> + * This method should only be used if parameterization is completely unavailable. + * + * @since 1.9 + */ + public MapType constructRawMapType(Class<? extends Map> mapClass) { + return MapType.construct(mapClass, unknownType(), unknownType()); + } + + /** + * Method that can be used to construct "raw" Map-like type; meaning that its + * parameterization is unknown. + * This is similar to using <code>Object.class</code> parameterization, + * and is equivalent to calling: + *<pre> + * typeFactory.constructMapLikeType(collectionClass, typeFactory.unknownType(), typeFactory.unknownType()); + *<pre> + *<p> + * This method should only be used if parameterization is completely unavailable. + * + * @since 1.9 + */ + public MapLikeType constructRawMapLikeType(Class<?> mapClass) { + return MapLikeType.construct(mapClass, unknownType(), unknownType()); + } + + /* + /********************************************************** + /* Actual factory methods + /********************************************************** + */ + + /** + * @param context Mapping of formal parameter declarations (for generic + * types) into actual types + */ + protected JavaType _fromClass(Class<?> clz, TypeBindings context) + { + // First: do we have an array type? + if (clz.isArray()) { + return ArrayType.construct(_constructType(clz.getComponentType(), null), null, null); + } + /* Also: although enums can also be fully resolved, there's little + * point in doing so (T extends Enum<T>) etc. + */ + if (clz.isEnum()) { + return new SimpleType(clz); + } + /* Maps and Collections aren't quite as hot; problem is, due + * to type erasure we often do not know typing and can only assume + * base Object. + */ + if (Map.class.isAssignableFrom(clz)) { + return _mapType(clz); + } + if (Collection.class.isAssignableFrom(clz)) { + return _collectionType(clz); + } + return new SimpleType(clz); + } + + /** + * Method used by {@link TypeParser} when generics-aware version + * is constructed. + */ + protected JavaType _fromParameterizedClass(Class<?> clz, List<JavaType> paramTypes) + { + if (clz.isArray()) { // ignore generics (should never have any) + return ArrayType.construct(_constructType(clz.getComponentType(), null), null, null); + } + if (clz.isEnum()) { // ditto for enums + return new SimpleType(clz); + } + if (Map.class.isAssignableFrom(clz)) { + // First: if we do have param types, use them + JavaType keyType, contentType; + if (paramTypes.size() > 0) { + keyType = paramTypes.get(0); + contentType = (paramTypes.size() >= 2) ? + paramTypes.get(1) : _unknownType(); + return MapType.construct(clz, keyType, contentType); + } + return _mapType(clz); + } + if (Collection.class.isAssignableFrom(clz)) { + if (paramTypes.size() >= 1) { + return CollectionType.construct(clz, paramTypes.get(0)); + } + return _collectionType(clz); + } + if (paramTypes.size() == 0) { + return new SimpleType(clz); + } + JavaType[] pt = paramTypes.toArray(new JavaType[paramTypes.size()]); + return constructSimpleType(clz, pt); + } + + /** + * This method deals with parameterized types, that is, + * first class generic classes. + *<p> + * Since version 1.2, this resolves all parameterized types, not just + * Maps or Collections. + */ + protected JavaType _fromParamType(ParameterizedType type, TypeBindings context) + { + /* First: what is the actual base type? One odd thing + * is that 'getRawType' returns Type, not Class<?> as + * one might expect. But let's assume it is always of + * type Class: if not, need to add more code to resolve + * it to Class. + */ + Class<?> rawType = (Class<?>) type.getRawType(); + Type[] args = type.getActualTypeArguments(); + int paramCount = (args == null) ? 0 : args.length; + + JavaType[] pt; + + if (paramCount == 0) { + pt = NO_TYPES; + } else { + pt = new JavaType[paramCount]; + for (int i = 0; i < paramCount; ++i) { + pt[i] = _constructType(args[i], context); + } + } + + // Ok: Map or Collection? + if (Map.class.isAssignableFrom(rawType)) { + JavaType subtype = constructSimpleType(rawType, pt); + JavaType[] mapParams = findTypeParameters(subtype, Map.class); + if (mapParams.length != 2) { + throw new IllegalArgumentException("Could not find 2 type parameters for Map class "+rawType.getName()+" (found "+mapParams.length+")"); + } + return MapType.construct(rawType, mapParams[0], mapParams[1]); + } + if (Collection.class.isAssignableFrom(rawType)) { + JavaType subtype = constructSimpleType(rawType, pt); + JavaType[] collectionParams = findTypeParameters(subtype, Collection.class); + if (collectionParams.length != 1) { + throw new IllegalArgumentException("Could not find 1 type parameter for Collection class "+rawType.getName()+" (found "+collectionParams.length+")"); + } + return CollectionType.construct(rawType, collectionParams[0]); + } + if (paramCount == 0) { // no generics + return new SimpleType(rawType); + } + return constructSimpleType(rawType, pt); + } + + + protected JavaType _fromArrayType(GenericArrayType type, TypeBindings context) + { + JavaType compType = _constructType(type.getGenericComponentType(), context); + return ArrayType.construct(compType, null, null); + } + + protected JavaType _fromVariable(TypeVariable<?> type, TypeBindings context) + { + /* 26-Sep-2009, tatus: It should be possible to try "partial" + * resolution; meaning that it is ok not to find bindings. + * For now this is indicated by passing null context. + */ + if (context == null) { + return _unknownType(); + } + + // Ok: here's where context might come in handy! + String name = type.getName(); + JavaType actualType = context.findType(name); + if (actualType != null) { + return actualType; + } + + /* 29-Jan-2010, tatu: We used to throw exception here, if type was + * bound: but the problem is that this can occur for generic "base" + * method, overridden by sub-class. If so, we will want to ignore + * current type (for method) since it will be masked. + */ + Type[] bounds = type.getBounds(); + + // With type variables we must use bound information. + // Theoretically this gets tricky, as there may be multiple + // bounds ("... extends A & B"); and optimally we might + // want to choose the best match. Also, bounds are optional; + // but here we are lucky in that implicit "Object" is + // added as bounds if so. + // Either way let's just use the first bound, for now, and + // worry about better match later on if there is need. + + /* 29-Jan-2010, tatu: One more problem are recursive types + * (T extends Comparable<T>). Need to add "placeholder" + * for resolution to catch those. + */ + context._addPlaceholder(name); + return _constructType(bounds[0], context); + } + + protected JavaType _fromWildcard(WildcardType type, TypeBindings context) + { + /* Similar to challenges with TypeVariable, we may have + * multiple upper bounds. But it is also possible that if + * upper bound defaults to Object, we might want to consider + * lower bounds instead. + * + * For now, we won't try anything more advanced; above is + * just for future reference. + */ + return _constructType(type.getUpperBounds()[0], context); + } + + private JavaType _mapType(Class<?> rawClass) + { + JavaType[] typeParams = findTypeParameters(rawClass, Map.class); + // ok to have no types ("raw") + if (typeParams == null) { + return MapType.construct(rawClass, _unknownType(), _unknownType()); + } + // but exactly 2 types if any found + if (typeParams.length != 2) { + throw new IllegalArgumentException("Strange Map type "+rawClass.getName()+": can not determine type parameters"); + } + return MapType.construct(rawClass, typeParams[0], typeParams[1]); + } + + private JavaType _collectionType(Class<?> rawClass) + { + JavaType[] typeParams = findTypeParameters(rawClass, Collection.class); + // ok to have no types ("raw") + if (typeParams == null) { + return CollectionType.construct(rawClass, _unknownType()); + } + // but exactly 2 types if any found + if (typeParams.length != 1) { + throw new IllegalArgumentException("Strange Collection type "+rawClass.getName()+": can not determine type parameters"); + } + return CollectionType.construct(rawClass, typeParams[0]); + } + + protected JavaType _resolveVariableViaSubTypes(HierarchicType leafType, String variableName, TypeBindings bindings) + { + // can't resolve raw types; possible to have as-of-yet-unbound types too: + if (leafType != null && leafType.isGeneric()) { + TypeVariable<?>[] typeVariables = leafType.getRawClass().getTypeParameters(); + for (int i = 0, len = typeVariables.length; i < len; ++i) { + TypeVariable<?> tv = typeVariables[i]; + if (variableName.equals(tv.getName())) { + // further resolution needed? + Type type = leafType.asGeneric().getActualTypeArguments()[i]; + if (type instanceof TypeVariable<?>) { + return _resolveVariableViaSubTypes(leafType.getSubType(), ((TypeVariable<?>) type).getName(), bindings); + } + // no we're good for the variable (but it may have parameterization of its own) + return _constructType(type, bindings); + } + } + } + return _unknownType(); + } + + protected JavaType _unknownType() { + return new SimpleType(Object.class); + } + + /* + /********************************************************** + /* Helper methods + /********************************************************** + */ + + /** + * Helper method used to find inheritance (implements, extends) path + * between given types, if one exists (caller generally checks before + * calling this method). Returned type represents given <b>subtype</b>, + * with supertype linkage extending to <b>supertype</b>. + */ + protected HierarchicType _findSuperTypeChain(Class<?> subtype, Class<?> supertype) + { + // If super-type is a class (not interface), bit simpler + if (supertype.isInterface()) { + return _findSuperInterfaceChain(subtype, supertype); + } + return _findSuperClassChain(subtype, supertype); + } + + protected HierarchicType _findSuperClassChain(Type currentType, Class<?> target) + { + HierarchicType current = new HierarchicType(currentType); + Class<?> raw = current.getRawClass(); + if (raw == target) { + return current; + } + // Otherwise, keep on going down the rat hole... + Type parent = raw.getGenericSuperclass(); + if (parent != null) { + HierarchicType sup = _findSuperClassChain(parent, target); + if (sup != null) { + sup.setSubType(current); + current.setSuperType(sup); + return current; + } + } + return null; + } + + protected HierarchicType _findSuperInterfaceChain(Type currentType, Class<?> target) + { + HierarchicType current = new HierarchicType(currentType); + Class<?> raw = current.getRawClass(); + if (raw == target) { + return new HierarchicType(currentType); + } + // Otherwise, keep on going down the rat hole; first implemented interfaces + /* 16-Aug-2011, tatu: Minor optimization based on profiled hot spot; let's + * try caching certain commonly needed cases + */ + if (raw == HashMap.class) { + if (target == Map.class) { + return _hashMapSuperInterfaceChain(current); + } + } + if (raw == ArrayList.class) { + if (target == List.class) { + return _arrayListSuperInterfaceChain(current); + } + } + return _doFindSuperInterfaceChain(current, target); + } + + protected HierarchicType _doFindSuperInterfaceChain(HierarchicType current, Class<?> target) + { + Class<?> raw = current.getRawClass(); + Type[] parents = raw.getGenericInterfaces(); + // as long as there are superclasses + // and unless we have already seen the type (<T extends X<T>>) + if (parents != null) { + for (Type parent : parents) { + HierarchicType sup = _findSuperInterfaceChain(parent, target); + if (sup != null) { + sup.setSubType(current); + current.setSuperType(sup); + return current; + } + } + } + // and then super-class if any + Type parent = raw.getGenericSuperclass(); + if (parent != null) { + HierarchicType sup = _findSuperInterfaceChain(parent, target); + if (sup != null) { + sup.setSubType(current); + current.setSuperType(sup); + return current; + } + } + return null; + } + + protected synchronized HierarchicType _hashMapSuperInterfaceChain(HierarchicType current) + { + if (_cachedHashMapType == null) { + HierarchicType base = current.deepCloneWithoutSubtype(); + _doFindSuperInterfaceChain(base, Map.class); + _cachedHashMapType = base.getSuperType(); + } + HierarchicType t = _cachedHashMapType.deepCloneWithoutSubtype(); + current.setSuperType(t); + t.setSubType(current); + return current; + } + + protected synchronized HierarchicType _arrayListSuperInterfaceChain(HierarchicType current) + { + if (_cachedArrayListType == null) { + HierarchicType base = current.deepCloneWithoutSubtype(); + _doFindSuperInterfaceChain(base, List.class); + _cachedArrayListType = base.getSuperType(); + } + HierarchicType t = _cachedArrayListType.deepCloneWithoutSubtype(); + current.setSuperType(t); + t.setSubType(current); + return current; + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/type/TypeModifier.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/type/TypeModifier.java new file mode 100644 index 0000000..92734e8 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/type/TypeModifier.java
@@ -0,0 +1,38 @@ +package org.codehaus.jackson.map.type; + +import java.lang.reflect.Type; + +import org.codehaus.jackson.type.JavaType; + +/** + * Class that defines API that can be used to modify details of + * {@link JavaType} instances constructed using {@link TypeFactory}. + * Registered modifiers are called in order, to let them modify (or + * replace) basic type instance factory constructs. + * This is typically needed to support creation of + * {@link MapLikeType} and {@link CollectionLikeType} instances, + * as those can not be constructed in generic fashion. + * + * @since 1.8 + */ +public abstract class TypeModifier +{ + /** + * Method called to let modifier change constructed type definition. + * Note that as of version 1.8 this is only guaranteed to be called for + * non-container types ("simple" types not recognized as arrays, + * <code>java.util.Collection</code> or <code>java.util.Map</code>). + * + * @param type Instance to modify + * @param jdkType JDK type that was used to construct instance to modify + * @param context Type resolution context used for the type + * @param typeFactory Type factory that can be used to construct parameter type; note, + * however, that care must be taken to avoid infinite loops -- specifically, do not + * construct instance of primary type itself + * + * @return Actual type instance to use; usually either <code>type</code> (as is or with + * modifications), or a newly constructed type instance based on it. Can not be null. + */ + public abstract JavaType modifyType(JavaType type, Type jdkType, TypeBindings context, + TypeFactory typeFactory); +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/type/TypeParser.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/type/TypeParser.java new file mode 100644 index 0000000..f53ccb2 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/type/TypeParser.java
@@ -0,0 +1,130 @@ +package org.codehaus.jackson.map.type; + +import java.util.*; + +import org.codehaus.jackson.type.JavaType; +import org.codehaus.jackson.map.util.ClassUtil; + +/** + * Simple recursive-descent parser for parsing canonical {@link JavaType} + * representations and constructing type instances. + * + * @author tatu + * @since 1.5 + */ +public class TypeParser +{ + final TypeFactory _factory; + + public TypeParser(TypeFactory f) { + _factory = f; + } + + public JavaType parse(String canonical) + throws IllegalArgumentException + { + canonical = canonical.trim(); + MyTokenizer tokens = new MyTokenizer(canonical); + JavaType type = parseType(tokens); + // must be end, now + if (tokens.hasMoreTokens()) { + throw _problem(tokens, "Unexpected tokens after complete type"); + } + return type; + } + + protected JavaType parseType(MyTokenizer tokens) + throws IllegalArgumentException + { + if (!tokens.hasMoreTokens()) { + throw _problem(tokens, "Unexpected end-of-string"); + } + Class<?> base = findClass(tokens.nextToken(), tokens); + // either end (ok, non generic type), or generics + if (tokens.hasMoreTokens()) { + String token = tokens.nextToken(); + if ("<".equals(token)) { + return _factory._fromParameterizedClass(base, parseTypes(tokens)); + } + // can be comma that separates types, or closing '>' + tokens.pushBack(token); + } + return _factory._fromClass(base, null); + } + + protected List<JavaType> parseTypes(MyTokenizer tokens) + throws IllegalArgumentException + { + ArrayList<JavaType> types = new ArrayList<JavaType>(); + while (tokens.hasMoreTokens()) { + types.add(parseType(tokens)); + if (!tokens.hasMoreTokens()) break; + String token = tokens.nextToken(); + if (">".equals(token)) return types; + if (!",".equals(token)) { + throw _problem(tokens, "Unexpected token '"+token+"', expected ',' or '>')"); + } + } + throw _problem(tokens, "Unexpected end-of-string"); + } + + protected Class<?> findClass(String className, MyTokenizer tokens) + { + try { + return ClassUtil.findClass(className); + } catch (Exception e) { + if (e instanceof RuntimeException) { + throw (RuntimeException) e; + } + throw _problem(tokens, "Can not locate class '"+className+"', problem: "+e.getMessage()); + } + } + + protected IllegalArgumentException _problem(MyTokenizer tokens, String msg) + { + return new IllegalArgumentException("Failed to parse type '"+tokens.getAllInput() + +"' (remaining: '"+tokens.getRemainingInput()+"'): "+msg); + } + + final static class MyTokenizer + extends StringTokenizer + { + protected final String _input; + + protected int _index; + + protected String _pushbackToken; + + public MyTokenizer(String str) { + super(str, "<,>", true); + _input = str; + } + + @Override + public boolean hasMoreTokens() { + return (_pushbackToken != null) || super.hasMoreTokens(); + } + + @Override + public String nextToken() { + String token; + if (_pushbackToken != null) { + token = _pushbackToken; + _pushbackToken = null; + } else { + token = super.nextToken(); + } + _index += token.length(); + return token; + } + + public void pushBack(String token) { + _pushbackToken = token; + _index -= token.length(); + } + + public String getAllInput() { return _input; } + public String getUsedInput() { return _input.substring(0, _index); } + public String getRemainingInput() { return _input.substring(_index); } + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/type/package-info.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/type/package-info.java new file mode 100644 index 0000000..b13de0d --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/type/package-info.java
@@ -0,0 +1,10 @@ +/** + * Package that contains concrete implementations of + * {@link org.codehaus.jackson.type.JavaType}, as + * well as the factory ({@link org.codehaus.jackson.map.type.TypeFactory}) for + * constructing instances from various input data types + * (like {@link java.lang.Class}, {@link java.lang.reflect.Type}) + * and programmatically (for structured types, arrays, + * {@link java.util.List}s and {@link java.util.Map}s). + */ +package org.codehaus.jackson.map.type;
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/util/Annotations.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/util/Annotations.java new file mode 100644 index 0000000..6e781e8 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/util/Annotations.java
@@ -0,0 +1,23 @@ +package org.codehaus.jackson.map.util; + +import java.lang.annotation.Annotation; + +/** + * Interface that defines interface for collection of annotations. + *<p> + * Standard mutable implementation is {@link org.codehaus.jackson.map.introspect.AnnotationMap} + * + * @since 1.7 + */ +public interface Annotations +{ + /** + * Main access method used to find value for given annotation. + */ + public <A extends Annotation> A get(Class<A> cls); + + /** + * Returns number of annotation entries in this collection. + */ + public int size(); +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/util/ArrayBuilders.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/util/ArrayBuilders.java new file mode 100644 index 0000000..fd236a3 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/util/ArrayBuilders.java
@@ -0,0 +1,293 @@ +package org.codehaus.jackson.map.util; + +import java.lang.reflect.Array; +import java.util.*; + +/** + * Helper class that contains set of distinct builders for different + * arrays of primitive values. It also provides trivially simple + * reuse scheme, which assumes that caller knows not to use instances + * concurrently (which works ok with primitive arrays since they can + * not contain other non-primitive types). + */ +public final class ArrayBuilders +{ + BooleanBuilder _booleanBuilder = null; + + // note: no need for char[] builder, assume they are Strings + + ByteBuilder _byteBuilder = null; + ShortBuilder _shortBuilder = null; + IntBuilder _intBuilder = null; + LongBuilder _longBuilder = null; + + FloatBuilder _floatBuilder = null; + DoubleBuilder _doubleBuilder = null; + + public ArrayBuilders() { } + + public BooleanBuilder getBooleanBuilder() + { + if (_booleanBuilder == null) { + _booleanBuilder = new BooleanBuilder(); + } + return _booleanBuilder; + } + + public ByteBuilder getByteBuilder() + { + if (_byteBuilder == null) { + _byteBuilder = new ByteBuilder(); + } + return _byteBuilder; + } + public ShortBuilder getShortBuilder() + { + if (_shortBuilder == null) { + _shortBuilder = new ShortBuilder(); + } + return _shortBuilder; + } + public IntBuilder getIntBuilder() + { + if (_intBuilder == null) { + _intBuilder = new IntBuilder(); + } + return _intBuilder; + } + public LongBuilder getLongBuilder() + { + if (_longBuilder == null) { + _longBuilder = new LongBuilder(); + } + return _longBuilder; + } + + public FloatBuilder getFloatBuilder() + { + if (_floatBuilder == null) { + _floatBuilder = new FloatBuilder(); + } + return _floatBuilder; + } + public DoubleBuilder getDoubleBuilder() + { + if (_doubleBuilder == null) { + _doubleBuilder = new DoubleBuilder(); + } + return _doubleBuilder; + } + + /* + /********************************************************** + /* Impl classes + /********************************************************** + */ + + public final static class BooleanBuilder + extends PrimitiveArrayBuilder<boolean[]> + { + public BooleanBuilder() { } + @Override + public final boolean[] _constructArray(int len) { return new boolean[len]; } + } + + public final static class ByteBuilder + extends PrimitiveArrayBuilder<byte[]> + { + public ByteBuilder() { } + @Override + public final byte[] _constructArray(int len) { return new byte[len]; } + } + public final static class ShortBuilder + extends PrimitiveArrayBuilder<short[]> + { + public ShortBuilder() { } + @Override + public final short[] _constructArray(int len) { return new short[len]; } + } + public final static class IntBuilder + extends PrimitiveArrayBuilder<int[]> + { + public IntBuilder() { } + @Override + public final int[] _constructArray(int len) { return new int[len]; } + } + public final static class LongBuilder + extends PrimitiveArrayBuilder<long[]> + { + public LongBuilder() { } + @Override + public final long[] _constructArray(int len) { return new long[len]; } + } + + public final static class FloatBuilder + extends PrimitiveArrayBuilder<float[]> + { + public FloatBuilder() { } + @Override + public final float[] _constructArray(int len) { return new float[len]; } + } + public final static class DoubleBuilder + extends PrimitiveArrayBuilder<double[]> + { + public DoubleBuilder() { } + @Override + public final double[] _constructArray(int len) { return new double[len]; } + } + + /* + /********************************************************** + /* Static helper methods + /********************************************************** + */ + + public static <T> HashSet<T> arrayToSet(T[] elements) + { + HashSet<T> result = new HashSet<T>(); + if (elements != null) { + for (T elem : elements) { + result.add(elem); + } + } + return result; + } + + /** + * Helper method for adding specified element to a List, but also + * considering case where the List may not have been yet constructed + * (that is, null is passed instead). + * + * @param list List to add to; may be null to indicate that a new + * List is to be constructed + * @param element Element to add to list + * + * @return List in which element was added; either <code>list</code> + * (if it was not null), or a newly constructed List. + */ + public static <T> List<T> addToList(List<T> list, T element) + { + if (list == null) { + list = new ArrayList<T>(); + } + list.add(element); + return list; + } + + /** + * Helper method for constructing a new array that contains specified + * element followed by contents of the given array. No checking is done + * to see if element being inserted is duplicate. + */ + public static <T> T[] insertInList(T[] array, T element) + { + int len = array.length; + @SuppressWarnings("unchecked") + T[] result = (T[]) Array.newInstance(array.getClass().getComponentType(), len+1); + if (len > 0) { + System.arraycopy(array, 0, result, 1, len); + } + result[0] = element; + return result; + } + + /** + * Helper method for constructing a new array that contains specified + * element followed by contents of the given array but never contains + * duplicates. + * If element already existed, one of two things happens: if the element + * was already the first one in array, array is returned as is; but + * if not, a new copy is created in which element has moved as the head. + */ + @SuppressWarnings("unchecked") + public static <T> T[] insertInListNoDup(T[] array, T element) + { + final int len = array.length; + + // First: see if the element already exists + for (int ix = 0; ix < len; ++ix) { + if (array[ix] == element) { + // if at head already, return as is + if (ix == 0) { + return array; + } + // otherwise move things around + T[] result = (T[]) Array.newInstance(array.getClass().getComponentType(), len); + System.arraycopy(array, 0, result, 1, ix); + array[0] = element; + return result; + } + } + + // but if not, allocate new array, move + T[] result = (T[]) Array.newInstance(array.getClass().getComponentType(), len+1); + if (len > 0) { + System.arraycopy(array, 0, result, 1, len); + } + result[0] = element; + return result; + } + + /** + * Helper method for exposing contents of arrays using a read-only + * iterator + * + * @since 1.7 + */ + public static <T> Iterator<T> arrayAsIterator(T[] array) + { + return new ArrayIterator<T>(array); + } + + public static <T> Iterable<T> arrayAsIterable(T[] array) + { + return new ArrayIterator<T>(array); + } + + /* + /********************************************************** + /* Helper classes + /********************************************************** + */ + + /** + * Iterator implementation used to efficiently expose contents of an + * Array as read-only iterator. + * + * @since 1.7 + */ + private final static class ArrayIterator<T> + implements Iterator<T>, Iterable<T> + { + private final T[] _array; + + private int _index; + + public ArrayIterator(T[] array) { + _array = array; + _index = 0; + } + + @Override public boolean hasNext() { + return _index < _array.length; + } + + @Override + public T next() + { + if (_index >= _array.length) { + throw new NoSuchElementException(); + } + return _array[_index++]; + } + + @Override public void remove() { + throw new UnsupportedOperationException(); + } + + @Override + public Iterator<T> iterator() { + return this; + } + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/util/BeanUtil.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/util/BeanUtil.java new file mode 100644 index 0000000..44fadfa --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/util/BeanUtil.java
@@ -0,0 +1,260 @@ +package org.codehaus.jackson.map.util; + +import org.codehaus.jackson.map.introspect.AnnotatedMethod; + +/** + * Helper class that contains functionality needed by both serialization + * and deserialization side. + * + * @since 1.9 + */ +public class BeanUtil +{ + /* + * Helper method to use for sorting bean properties, based on + * ordering rules indicated by annotations, config features. + * + * @param config Serialization/Deserialization configuration in effect + * @param beanDesc Bean description + * @param props Properties to sort if/as necessary + * @param defaultSortByAlpha Whether properties should be (re)sorted alphabetically + * by default (unless overridden by type) + */ + /* + public static <T extends Named> List<T> sortProperties(MapperConfig<?> config, + BasicBeanDescription beanDesc, List<T> props, + boolean defaultSortByAlpha) + { + // First, order by [JACKSON-90] (explicit ordering and/or alphabetic) + // and then for [JACKSON-170] (implicitly order creator properties before others) + List<String> creatorProps = beanDesc.findCreatorPropertyNames(); + // Then how about explicit ordering? + AnnotationIntrospector intr = config.getAnnotationIntrospector(); + AnnotatedClass ac = beanDesc.getClassInfo(); + String[] propertyOrder = intr.findSerializationPropertyOrder(ac); + Boolean alpha = intr.findSerializationSortAlphabetically(ac); + boolean sort; + + if (alpha == null) { + sort = defaultSortByAlpha; + } else { + sort = alpha.booleanValue(); + } + // no sorting? no need to shuffle, then + if (!sort && creatorProps.isEmpty() && propertyOrder == null) { + return props; + } + int size = props.size(); + Map<String,T> all; + // Need to (re)sort alphabetically? + if (sort) { + all = new TreeMap<String,T>(); + } else { + all = new LinkedHashMap<String,T>(size+size); + } + + for (T w : props) { + all.put(w.getName(), w); + } + Map<String,T> ordered = new LinkedHashMap<String,T>(size+size); + // Ok: primarily by explicit order + if (propertyOrder != null) { + for (String name : propertyOrder) { + T w = all.get(name); + if (w != null) { + ordered.put(name, w); + } + } + } + // And secondly by sorting Creator properties before other unordered properties + for (String name : creatorProps) { + T w = all.get(name); + if (w != null) { + ordered.put(name, w); + } + } + // And finally whatever is left (trying to put again will not change ordering) + ordered.putAll(all); + return new ArrayList<T>(ordered.values()); + } + */ + + /* + /********************************************************** + /* Handling "getter" names + /********************************************************** + */ + + public static String okNameForGetter(AnnotatedMethod am) + { + String name = am.getName(); + String str = okNameForIsGetter(am, name); + if (str == null) { + str = okNameForRegularGetter(am, name); + } + return str; + } + + public static String okNameForRegularGetter(AnnotatedMethod am, String name) + { + if (name.startsWith("get")) { + /* 16-Feb-2009, tatu: To handle [JACKSON-53], need to block + * CGLib-provided method "getCallbacks". Not sure of exact + * safe criteria to get decent coverage without false matches; + * but for now let's assume there's no reason to use any + * such getter from CGLib. + * But let's try this approach... + */ + if ("getCallbacks".equals(name)) { + if (isCglibGetCallbacks(am)) { + return null; + } + } else if ("getMetaClass".equals(name)) { + /* 30-Apr-2009, tatu: [JACKSON-103], need to suppress + * serialization of a cyclic (and useless) reference + */ + if (isGroovyMetaClassGetter(am)) { + return null; + } + } + return manglePropertyName(name.substring(3)); + } + return null; + } + + public static String okNameForIsGetter(AnnotatedMethod am, String name) + { + if (name.startsWith("is")) { + // plus, must return boolean... + Class<?> rt = am.getRawType(); + if (rt != Boolean.class && rt != Boolean.TYPE) { + return null; + } + return manglePropertyName(name.substring(2)); + } + // no, not a match by name + return null; + } + + public static String okNameForSetter(AnnotatedMethod am) + { + String name = am.getName(); + if (name.startsWith("set")) { + name = manglePropertyName(name.substring(3)); + if (name == null) { // plain old "set" is no good... + return null; + } + if ("metaClass".equals(name)) { + // 26-Nov-2009 [JACSON-103], need to suppress this internal groovy method + if (isGroovyMetaClassSetter(am)) { + return null; + } + } + return name; + } + return null; + } + + /* + /********************************************************** + /* Helper methods for bean property name handling + /********************************************************** + */ + + /** + * This method was added to address [JACKSON-53]: need to weed out + * CGLib-injected "getCallbacks". + * At this point caller has detected a potential getter method + * with name "getCallbacks" and we need to determine if it is + * indeed injectect by Cglib. We do this by verifying that the + * result type is "net.sf.cglib.proxy.Callback[]" + *<p> + * Also, see [JACKSON-177]; Hibernate may repackage cglib + * it uses, so we better catch that too + */ + protected static boolean isCglibGetCallbacks(AnnotatedMethod am) + { + Class<?> rt = am.getRawType(); + // Ok, first: must return an array type + if (rt == null || !rt.isArray()) { + return false; + } + /* And that type needs to be "net.sf.cglib.proxy.Callback". + * Theoretically could just be a type that implements it, but + * for now let's keep things simple, fix if need be. + */ + Class<?> compType = rt.getComponentType(); + // Actually, let's just verify it's a "net.sf.cglib.*" class/interface + Package pkg = compType.getPackage(); + if (pkg != null) { + String pname = pkg.getName(); + if (pname.startsWith("net.sf.cglib") + // also, as per [JACKSON-177] + || pname.startsWith("org.hibernate.repackage.cglib")) { + return true; + } + } + return false; + } + + /** + * Similar to {@link #isCglibGetCallbacks}, need to suppress + * a cyclic reference to resolve [JACKSON-103] + */ + protected static boolean isGroovyMetaClassSetter(AnnotatedMethod am) + { + Class<?> argType = am.getParameterClass(0); + Package pkg = argType.getPackage(); + if (pkg != null && pkg.getName().startsWith("groovy.lang")) { + return true; + } + return false; + } + + /** + * Another helper method to deal with rest of [JACKSON-103] + */ + protected static boolean isGroovyMetaClassGetter(AnnotatedMethod am) + { + Class<?> rt = am.getRawType(); + if (rt == null || rt.isArray()) { + return false; + } + Package pkg = rt.getPackage(); + if (pkg != null && pkg.getName().startsWith("groovy.lang")) { + return true; + } + return false; + } + + /** + * Method called to figure out name of the property, given + * corresponding suggested name based on a method or field name. + * + * @param basename Name of accessor/mutator method, not including prefix + * ("get"/"is"/"set") + */ + protected static String manglePropertyName(String basename) + { + int len = basename.length(); + + // First things first: empty basename is no good + if (len == 0) { + return null; + } + // otherwise, lower case initial chars + StringBuilder sb = null; + for (int i = 0; i < len; ++i) { + char upper = basename.charAt(i); + char lower = Character.toLowerCase(upper); + if (upper == lower) { + break; + } + if (sb == null) { + sb = new StringBuilder(basename); + } + sb.setCharAt(i, lower); + } + return (sb == null) ? basename : sb.toString(); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/util/ClassUtil.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/util/ClassUtil.java new file mode 100644 index 0000000..b2ac0ab --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/util/ClassUtil.java
@@ -0,0 +1,691 @@ +package org.codehaus.jackson.map.util; + +import java.lang.reflect.*; +import java.util.*; + +public final class ClassUtil +{ + /* + /********************************************************** + /* Methods that deal with inheritance + /********************************************************** + */ + + /** + * Method that will find all sub-classes and implemented interfaces + * of a given class or interface. Classes are listed in order of + * precedence, starting with the immediate super-class, followed by + * interfaces class directly declares to implemented, and then recursively + * followed by parent of super-class and so forth. + * Note that <code>Object.class</code> is not included in the list + * regardless of whether <code>endBefore</code> argument is defined or not. + * + * @param endBefore Super-type to NOT include in results, if any; when + * encountered, will be ignored (and no super types are checked). + */ + public static List<Class<?>> findSuperTypes(Class<?> cls, Class<?> endBefore) + { + return findSuperTypes(cls, endBefore, new ArrayList<Class<?>>(8)); + } + + public static List<Class<?>> findSuperTypes(Class<?> cls, Class<?> endBefore, List<Class<?>> result) + { + _addSuperTypes(cls, endBefore, result, false); + return result; + } + + private static void _addSuperTypes(Class<?> cls, Class<?> endBefore, Collection<Class<?>> result, boolean addClassItself) + { + if (cls == endBefore || cls == null || cls == Object.class) { + return; + } + if (addClassItself) { + if (result.contains(cls)) { // already added, no need to check supers + return; + } + result.add(cls); + } + for (Class<?> intCls : cls.getInterfaces()) { + _addSuperTypes(intCls, endBefore, result, true); + } + _addSuperTypes(cls.getSuperclass(), endBefore, result, true); + } + + /* + /********************************************************** + /* Class type detection methods + /********************************************************** + */ + + /** + * @return Null if class might be a bean; type String (that identifies + * why it's not a bean) if not + */ + public static String canBeABeanType(Class<?> type) + { + // First: language constructs that ain't beans: + if (type.isAnnotation()) { + return "annotation"; + } + if (type.isArray()) { + return "array"; + } + if (type.isEnum()) { + return "enum"; + } + if (type.isPrimitive()) { + return "primitive"; + } + + // Anything else? Seems valid, then + return null; + } + + /** + * @deprecated since 1.9, use variant that takes second argument + */ + @Deprecated + public static String isLocalType(Class<?> type) { + return isLocalType(type, false); + } + + /** + * @since 1.9 + */ + public static String isLocalType(Class<?> type, boolean allowNonStatic) + { + /* As per [JACKSON-187], GAE seems to throw SecurityExceptions + * here and there... and GAE itself has a bug, too + * (see []). Bah. So we need to catch some wayward exceptions on GAE + */ + try { + // one more: method locals, anonymous, are not good: + if (type.getEnclosingMethod() != null) { + return "local/anonymous"; + } + + /* But how about non-static inner classes? Can't construct + * easily (theoretically, we could try to check if parent + * happens to be enclosing... but that gets convoluted) + */ + if (!allowNonStatic) { + if (type.getEnclosingClass() != null) { + if (!Modifier.isStatic(type.getModifiers())) { + return "non-static member class"; + } + } + } + } + catch (SecurityException e) { } + catch (NullPointerException e) { } + return null; + } + + /** + * Method for finding enclosing class for non-static inner classes + * + * @since 1.9 + */ + public static Class<?> getOuterClass(Class<?> type) + { + // as above, GAE has some issues... + try { + // one more: method locals, anonymous, are not good: + if (type.getEnclosingMethod() != null) { + return null; + } + if (!Modifier.isStatic(type.getModifiers())) { + return type.getEnclosingClass(); + } + } catch (SecurityException e) { } + catch (NullPointerException e) { } + return null; + } + + + /** + * Helper method used to weed out dynamic Proxy types; types that do + * not expose concrete method API that we could use to figure out + * automatic Bean (property) based serialization. + */ + public static boolean isProxyType(Class<?> type) + { + // As per [Issue#57], should NOT disqualify JDK proxy: + /* + if (Proxy.isProxyClass(type)) { + return true; + } + */ + String name = type.getName(); + // Hibernate uses proxies heavily as well: + if (name.startsWith("net.sf.cglib.proxy.") + || name.startsWith("org.hibernate.proxy.")) { + return true; + } + // Not one of known proxies, nope: + return false; + } + + /** + * Helper method that checks if given class is a concrete one; + * that is, not an interface or abstract class. + */ + public static boolean isConcrete(Class<?> type) + { + int mod = type.getModifiers(); + return (mod & (Modifier.INTERFACE | Modifier.ABSTRACT)) == 0; + } + + /** + * @since 1.6 + */ + public static boolean isConcrete(Member member) + { + int mod = member.getModifiers(); + return (mod & (Modifier.INTERFACE | Modifier.ABSTRACT)) == 0; + } + + public static boolean isCollectionMapOrArray(Class<?> type) + { + if (type.isArray()) return true; + if (Collection.class.isAssignableFrom(type)) return true; + if (Map.class.isAssignableFrom(type)) return true; + return false; + } + + /* + /********************************************************** + /* Type name handling methods + /********************************************************** + */ + + /** + * Helper method used to construct appropriate description + * when passed either type (Class) or an instance; in latter + * case, class of instance is to be used. + */ + public static String getClassDescription(Object classOrInstance) + { + if (classOrInstance == null) { + return "unknown"; + } + Class<?> cls = (classOrInstance instanceof Class<?>) ? + (Class<?>) classOrInstance : classOrInstance.getClass(); + return cls.getName(); + } + + /* + /********************************************************** + /* Class loading + /********************************************************** + */ + + public static Class<?> findClass(String className) throws ClassNotFoundException + { + // [JACKSON-597]: support primitive types (and void) + if (className.indexOf('.') < 0) { + if ("int".equals(className)) return Integer.TYPE; + if ("long".equals(className)) return Long.TYPE; + if ("float".equals(className)) return Float.TYPE; + if ("double".equals(className)) return Double.TYPE; + if ("boolean".equals(className)) return Boolean.TYPE; + if ("byte".equals(className)) return Byte.TYPE; + if ("char".equals(className)) return Character.TYPE; + if ("short".equals(className)) return Short.TYPE; + if ("void".equals(className)) return Void.TYPE; + } + // Two-phase lookup: first using context ClassLoader; then default + Throwable prob = null; + ClassLoader loader = Thread.currentThread().getContextClassLoader(); + + if (loader != null) { + try { + return Class.forName(className, true, loader); + } catch (Exception e) { + prob = getRootCause(e); + } + } + try { + return Class.forName(className); + } catch (Exception e) { + if (prob == null) { + prob = getRootCause(e); + } + } + if (prob instanceof RuntimeException) { + throw (RuntimeException) prob; + } + throw new ClassNotFoundException(prob.getMessage(), prob); + } + + /* + /********************************************************** + /* Method type detection methods + /********************************************************** + */ + + public static boolean hasGetterSignature(Method m) + { + // First: static methods can't be getters + if (Modifier.isStatic(m.getModifiers())) { + return false; + } + // Must take no args + Class<?>[] pts = m.getParameterTypes(); + if (pts != null && pts.length != 0) { + return false; + } + // Can't be a void method + if (Void.TYPE == m.getReturnType()) { + return false; + } + // Otherwise looks ok: + return true; + } + + /* + /********************************************************** + /* Exception handling + /********************************************************** + */ + + /** + * Method that can be used to find the "root cause", innermost + * of chained (wrapped) exceptions. + */ + public static Throwable getRootCause(Throwable t) + { + while (t.getCause() != null) { + t = t.getCause(); + } + return t; + } + + /** + * Method that will unwrap root causes of given Throwable, and throw + * the innermost {@link Exception} or {@link Error} as is. + * This is useful in cases where mandatory wrapping is added, which + * is often done by Reflection API. + * + * @since 1.7 + */ + public static void throwRootCause(Throwable t) throws Exception + { + t = getRootCause(t); + if (t instanceof Exception) { + throw (Exception) t; + } + throw (Error) t; + } + + /** + * Method that will wrap 't' as an {@link IllegalArgumentException} if it + * is a checked exception; otherwise (runtime exception or error) throw as is + */ + public static void throwAsIAE(Throwable t) + { + throwAsIAE(t, t.getMessage()); + } + + /** + * Method that will wrap 't' as an {@link IllegalArgumentException} (and with + * specified message) if it + * is a checked exception; otherwise (runtime exception or error) throw as is + */ + public static void throwAsIAE(Throwable t, String msg) + { + if (t instanceof RuntimeException) { + throw (RuntimeException) t; + } + if (t instanceof Error) { + throw (Error) t; + } + throw new IllegalArgumentException(msg, t); + } + + /** + * Method that will locate the innermost exception for given Throwable; + * and then wrap it as an {@link IllegalArgumentException} if it + * is a checked exception; otherwise (runtime exception or error) throw as is + */ + public static void unwrapAndThrowAsIAE(Throwable t) + { + throwAsIAE(getRootCause(t)); + } + + /** + * Method that will locate the innermost exception for given Throwable; + * and then wrap it as an {@link IllegalArgumentException} if it + * is a checked exception; otherwise (runtime exception or error) throw as is + */ + public static void unwrapAndThrowAsIAE(Throwable t, String msg) + { + throwAsIAE(getRootCause(t), msg); + } + + /* + /********************************************************** + /* Instantiation + /********************************************************** + */ + + /** + * Method that can be called to try to create an instantiate of + * specified type. Instantiation is done using default no-argument + * constructor. + * + * @param canFixAccess Whether it is possible to try to change access + * rights of the default constructor (in case it is not publicly + * accessible) or not. + * + * @throws IllegalArgumentException If instantiation fails for any reason; + * except for cases where constructor throws an unchecked exception + * (which will be passed as is) + */ + public static <T> T createInstance(Class<T> cls, boolean canFixAccess) + throws IllegalArgumentException + { + Constructor<T> ctor = findConstructor(cls, canFixAccess); + if (ctor == null) { + throw new IllegalArgumentException("Class "+cls.getName()+" has no default (no arg) constructor"); + } + try { + return ctor.newInstance(); + } catch (Exception e) { + ClassUtil.unwrapAndThrowAsIAE(e, "Failed to instantiate class "+cls.getName()+", problem: "+e.getMessage()); + return null; + } + } + + public static <T> Constructor<T> findConstructor(Class<T> cls, boolean canFixAccess) + throws IllegalArgumentException + { + try { + Constructor<T> ctor = cls.getDeclaredConstructor(); + if (canFixAccess) { + checkAndFixAccess(ctor); + } else { + // Has to be public... + if (!Modifier.isPublic(ctor.getModifiers())) { + throw new IllegalArgumentException("Default constructor for "+cls.getName()+" is not accessible (non-public?): not allowed to try modify access via Reflection: can not instantiate type"); + } + } + return ctor; + } catch (NoSuchMethodException e) { + ; + } catch (Exception e) { + ClassUtil.unwrapAndThrowAsIAE(e, "Failed to find default constructor of class "+cls.getName()+", problem: "+e.getMessage()); + } + return null; + } + + /* + /********************************************************** + /* Primitive type support + /********************************************************** + */ + + /** + * Helper method used to get default value for wrappers used for primitive types + * (0 for Integer etc) + * + * @since 1.6.1 + */ + public static Object defaultValue(Class<?> cls) + { + if (cls == Integer.TYPE) { + return Integer.valueOf(0); + } + if (cls == Long.TYPE) { + return Long.valueOf(0L); + } + if (cls == Boolean.TYPE) { + return Boolean.FALSE; + } + if (cls == Double.TYPE) { + return Double.valueOf(0.0); + } + if (cls == Float.TYPE) { + return Float.valueOf(0.0f); + } + if (cls == Byte.TYPE) { + return Byte.valueOf((byte) 0); + } + if (cls == Short.TYPE) { + return Short.valueOf((short) 0); + } + if (cls == Character.TYPE) { + return '\0'; + } + throw new IllegalArgumentException("Class "+cls.getName()+" is not a primitive type"); + } + + /** + * Helper method for finding wrapper type for given primitive type (why isn't + * there one in JDK?) + * + * @since 1.7.1 + */ + public static Class<?> wrapperType(Class<?> primitiveType) + { + if (primitiveType == Integer.TYPE) { + return Integer.class; + } + if (primitiveType == Long.TYPE) { + return Long.class; + } + if (primitiveType == Boolean.TYPE) { + return Boolean.class; + } + if (primitiveType == Double.TYPE) { + return Double.class; + } + if (primitiveType == Float.TYPE) { + return Float.class; + } + if (primitiveType == Byte.TYPE) { + return Byte.class; + } + if (primitiveType == Short.TYPE) { + return Short.class; + } + if (primitiveType == Character.TYPE) { + return Character.class; + } + throw new IllegalArgumentException("Class "+primitiveType.getName()+" is not a primitive type"); + } + + /* + /********************************************************** + /* Access checking/handling methods + /********************************************************** + */ + + /** + * Method called to check if we can use the passed method or constructor + * (wrt access restriction -- public methods can be called, others + * usually not); and if not, if there is a work-around for + * the problem. + */ + public static void checkAndFixAccess(Member member) + { + // We know all members are also accessible objects... + AccessibleObject ao = (AccessibleObject) member; + + /* 14-Jan-2009, tatu: It seems safe and potentially beneficial to + * always to make it accessible (latter because it will force + * skipping checks we have no use for...), so let's always call it. + */ + //if (!ao.isAccessible()) { + try { + ao.setAccessible(true); + } catch (SecurityException se) { + /* 17-Apr-2009, tatu: Related to [JACKSON-101]: this can fail on + * platforms like EJB and Google App Engine); so let's + * only fail if we really needed it... + */ + if (!ao.isAccessible()) { + Class<?> declClass = member.getDeclaringClass(); + throw new IllegalArgumentException("Can not access "+member+" (from class "+declClass.getName()+"; failed to set access: "+se.getMessage()); + } + } + //} + } + + /* + /********************************************************** + /* Enum type detection + /********************************************************** + */ + + /** + * Helper method that can be used to dynamically figure out + * enumeration type of given {@link EnumSet}, without having + * access to its declaration. + * Code is needed to work around design flaw in JDK. + * + * @since 1.5 + */ + public static Class<? extends Enum<?>> findEnumType(EnumSet<?> s) + { + // First things first: if not empty, easy to determine + if (!s.isEmpty()) { + return findEnumType(s.iterator().next()); + } + // Otherwise need to locate using an internal field + return EnumTypeLocator.instance.enumTypeFor(s); + } + + /** + * Helper method that can be used to dynamically figure out + * enumeration type of given {@link EnumSet}, without having + * access to its declaration. + * Code is needed to work around design flaw in JDK. + * + * @since 1.5 + */ + public static Class<? extends Enum<?>> findEnumType(EnumMap<?,?> m) + { + if (!m.isEmpty()) { + return findEnumType(m.keySet().iterator().next()); + } + // Otherwise need to locate using an internal field + return EnumTypeLocator.instance.enumTypeFor(m); + } + + /** + * Helper method that can be used to dynamically figure out formal + * enumeration type (class) for given enumeration. This is either + * class of enum instance (for "simple" enumerations), or its + * superclass (for enums with instance fields or methods) + */ + @SuppressWarnings("unchecked") + public static Class<? extends Enum<?>> findEnumType(Enum<?> en) + { + // enums with "body" are sub-classes of the formal type + Class<?> ec = en.getClass(); + if (ec.getSuperclass() != Enum.class) { + ec = ec.getSuperclass(); + } + return (Class<? extends Enum<?>>) ec; + } + + /** + * Helper method that can be used to dynamically figure out formal + * enumeration type (class) for given class of an enumeration value. + * This is either class of enum instance (for "simple" enumerations), + * or its superclass (for enums with instance fields or methods) + */ + @SuppressWarnings("unchecked") + public static Class<? extends Enum<?>> findEnumType(Class<?> cls) + { + // enums with "body" are sub-classes of the formal type + if (cls.getSuperclass() != Enum.class) { + cls = cls.getSuperclass(); + } + return (Class<? extends Enum<?>>) cls; + } + + /* + /********************************************************** + /* Helper classes + /********************************************************** + */ + + /** + * Inner class used to contain gory details of how we can determine + * details of instances of common JDK types like {@link EnumMap}s. + */ + private static class EnumTypeLocator + { + final static EnumTypeLocator instance = new EnumTypeLocator(); + + private final Field enumSetTypeField; + private final Field enumMapTypeField; + + private EnumTypeLocator() { + /* JDK uses following fields to store information about actual Enumeration + * type for EnumSets, EnumMaps... + */ + enumSetTypeField = locateField(EnumSet.class, "elementType", Class.class); + enumMapTypeField = locateField(EnumMap.class, "elementType", Class.class); + } + + @SuppressWarnings("unchecked") + public Class<? extends Enum<?>> enumTypeFor(EnumSet<?> set) + { + if (enumSetTypeField != null) { + return (Class<? extends Enum<?>>) get(set, enumSetTypeField); + } + throw new IllegalStateException("Can not figure out type for EnumSet (odd JDK platform?)"); + } + + @SuppressWarnings("unchecked") + public Class<? extends Enum<?>> enumTypeFor(EnumMap<?,?> set) + { + if (enumMapTypeField != null) { + return (Class<? extends Enum<?>>) get(set, enumMapTypeField); + } + throw new IllegalStateException("Can not figure out type for EnumMap (odd JDK platform?)"); + + } + + private Object get(Object bean, Field field) + { + try { + return field.get(bean); + } catch (Exception e) { + throw new IllegalArgumentException(e); + } + } + + private static Field locateField(Class<?> fromClass, String expectedName, Class<?> type) + { + Field found = null; + // First: let's see if we can find exact match: + Field[] fields = fromClass.getDeclaredFields(); + for (Field f : fields) { + if (expectedName.equals(f.getName()) && f.getType() == type) { + found = f; + break; + } + } + // And if not, if there is just one field with the type, that field + if (found == null) { + for (Field f : fields) { + if (f.getType() == type) { + // If more than one, can't choose + if (found != null) return null; + found = f; + } + } + } + if (found != null) { // it's non-public, need to force accessible + try { + found.setAccessible(true); + } catch (Throwable t) { } + } + return found; + } + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/util/Comparators.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/util/Comparators.java new file mode 100644 index 0000000..b9dd38e --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/util/Comparators.java
@@ -0,0 +1,48 @@ +package org.codehaus.jackson.map.util; + +import java.lang.reflect.Array; + +/** + * Helper class for constructing objects for comparing content values + * + * @since 1.9.0 + */ +public class Comparators +{ + /** + * Helper method used for constructing simple value comparator used for + * comparing arrays for content equality. + *<p> + * Note: current implementation is not optimized for speed; if performance + * ever becomes an issue, it is possible to construct much more efficient + * typed instances (one for Object[] and sub-types; one per primitive type) + * + * @since 1.9 + */ + public static Object getArrayComparator(final Object defaultValue) + { + final int length = Array.getLength(defaultValue); + return new Object() { + @Override + public boolean equals(Object other) { + if (other == this) return true; + if (other == null || other.getClass() != defaultValue.getClass()) { + return false; + } + if (Array.getLength(other) != length) return false; + // so far so good: compare actual equality; but only shallow one + for (int i = 0; i < length; ++i) { + Object value1 = Array.get(defaultValue, i); + Object value2 = Array.get(other, i); + if (value1 == value2) continue; + if (value1 != null) { + if (!value1.equals(value2)) { + return false; + } + } + } + return true; + } + }; + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/util/EnumResolver.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/util/EnumResolver.java new file mode 100644 index 0000000..8be2bb4 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/util/EnumResolver.java
@@ -0,0 +1,108 @@ +package org.codehaus.jackson.map.util; + +import org.codehaus.jackson.map.AnnotationIntrospector; + +import java.util.*; + +/** + * Helper class used to resolve String values (either JSON Object field + * names or regular String values) into Java Enum instances. + * + * @since 1.9 renamed from 'org.codehaus.jackson.map.deser.EnumResolver' + */ +public class EnumResolver<T extends Enum<T>> +{ + protected final Class<T> _enumClass; + + protected final T[] _enums; + + protected final HashMap<String, T> _enumsById; + + protected EnumResolver(Class<T> enumClass, T[] enums, HashMap<String, T> map) + { + _enumClass = enumClass; + _enums = enums; + _enumsById = map; + } + + /** + * Factory method for constructing resolver that maps from Enum.name() into + * Enum value + */ + public static <ET extends Enum<ET>> EnumResolver<ET> constructFor(Class<ET> enumCls, AnnotationIntrospector ai) + { + ET[] enumValues = enumCls.getEnumConstants(); + if (enumValues == null) { + throw new IllegalArgumentException("No enum constants for class "+enumCls.getName()); + } + HashMap<String, ET> map = new HashMap<String, ET>(); + for (ET e : enumValues) { + map.put(ai.findEnumValue(e), e); + } + return new EnumResolver<ET>(enumCls, enumValues, map); + } + + /** + * Factory method for constructing resolver that maps from Enum.toString() into + * Enum value + * + * @since 1.6 + */ + public static <ET extends Enum<ET>> EnumResolver<ET> constructUsingToString(Class<ET> enumCls) + { + ET[] enumValues = enumCls.getEnumConstants(); + HashMap<String, ET> map = new HashMap<String, ET>(); + // from last to first, so that in case of duplicate values, first wins + for (int i = enumValues.length; --i >= 0; ) { + ET e = enumValues[i]; + map.put(e.toString(), e); + } + return new EnumResolver<ET>(enumCls, enumValues, map); + } + + /** + * This method is needed because of the dynamic nature of constructing Enum + * resolvers. + */ + @SuppressWarnings({ "unchecked", "rawtypes" }) + public static EnumResolver<?> constructUnsafe(Class<?> rawEnumCls, AnnotationIntrospector ai) + { + /* This is oh so wrong... but at least ugliness is mostly hidden in just + * this one place. + */ + Class<Enum> enumCls = (Class<Enum>) rawEnumCls; + return constructFor(enumCls, ai); + } + + /** + * Method that needs to be used instead of {@link #constructUsingToString} + * if static type of enum is not known. + * + * @since 1.6 + */ + @SuppressWarnings({ "unchecked", "rawtypes" }) + public static EnumResolver<?> constructUnsafeUsingToString(Class<?> rawEnumCls) + { + // oh so wrong... not much that can be done tho + Class<Enum> enumCls = (Class<Enum>) rawEnumCls; + return constructUsingToString(enumCls); + } + + public T findEnum(String key) + { + return _enumsById.get(key); + } + + public T getEnum(int index) + { + if (index < 0 || index >= _enums.length) { + return null; + } + return _enums[index]; + } + + public Class<T> getEnumClass() { return _enumClass; } + + public int lastValidIndex() { return _enums.length-1; } +} +
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/util/EnumValues.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/util/EnumValues.java new file mode 100644 index 0000000..9d21c8c --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/util/EnumValues.java
@@ -0,0 +1,82 @@ +package org.codehaus.jackson.map.util; + +import java.util.*; + +import org.codehaus.jackson.io.SerializedString; +import org.codehaus.jackson.map.*; + +/** + * Helper class used for storing String serializations of + * enumerations. + */ +public final class EnumValues +{ + /** + * Since 1.7, we are storing values as SerializedStrings, to further + * speed up serialization. + */ + private final EnumMap<?,SerializedString> _values; + + @SuppressWarnings({ "unchecked", "rawtypes" }) + private EnumValues(Map<Enum<?>,SerializedString> v) { + _values = new EnumMap(v); + } + + public static EnumValues construct(Class<Enum<?>> enumClass, AnnotationIntrospector intr) + { + return constructFromName(enumClass, intr); + } + + public static EnumValues constructFromName(Class<Enum<?>> enumClass, AnnotationIntrospector intr) + { + /* [JACKSON-214]: Enum types with per-instance sub-classes + * need special handling + */ + Class<? extends Enum<?>> cls = ClassUtil.findEnumType(enumClass); + Enum<?>[] values = cls.getEnumConstants(); + if (values != null) { + // Type juggling... unfortunate + Map<Enum<?>,SerializedString> map = new HashMap<Enum<?>,SerializedString>(); + for (Enum<?> en : values) { + String value = intr.findEnumValue(en); + map.put(en, new SerializedString(value)); + } + return new EnumValues(map); + } + throw new IllegalArgumentException("Can not determine enum constants for Class "+enumClass.getName()); + } + + public static EnumValues constructFromToString(Class<Enum<?>> enumClass, AnnotationIntrospector intr) + { + Class<? extends Enum<?>> cls = ClassUtil.findEnumType(enumClass); + Enum<?>[] values = cls.getEnumConstants(); + if (values != null) { + // Type juggling... unfortunate + Map<Enum<?>,SerializedString> map = new HashMap<Enum<?>,SerializedString>(); + for (Enum<?> en : values) { + map.put(en, new SerializedString(en.toString())); + } + return new EnumValues(map); + } + throw new IllegalArgumentException("Can not determine enum constants for Class "+enumClass.getName()); + } + + /** + * @deprecated since 1.7, use {@link #serializedValueFor} instead + */ + @Deprecated + public String valueFor(Enum<?> key) + { + SerializedString sstr = _values.get(key); + return (sstr == null) ? null : sstr.getValue(); + } + + public SerializedString serializedValueFor(Enum<?> key) + { + return _values.get(key); + } + + public Collection<SerializedString> values() { + return _values.values(); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/util/ISO8601DateFormat.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/util/ISO8601DateFormat.java new file mode 100644 index 0000000..bc12ddf --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/util/ISO8601DateFormat.java
@@ -0,0 +1,52 @@ +package org.codehaus.jackson.map.util; + +import java.text.*; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; + +/** + * Provide a fast thread-safe formatter/parser DateFormat for ISO8601 dates ONLY. + * It was mainly done to be used with Jackson JSON Processor. + * <p/> + * Watch out for clone implementation that returns itself. + * <p/> + * All other methods but parse and format and clone are undefined behavior. + * + * @see ISO8601Utils + */ +public class ISO8601DateFormat extends DateFormat +{ + private static final long serialVersionUID = 1L; + + // those classes are to try to allow a consistent behavior for hascode/equals and other methods + private static Calendar CALENDAR = new GregorianCalendar(); + private static NumberFormat NUMBER_FORMAT = new DecimalFormat(); + + public ISO8601DateFormat() { + this.numberFormat = NUMBER_FORMAT; + this.calendar = CALENDAR; + } + + @Override + public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) + { + String value = ISO8601Utils.format(date); + toAppendTo.append(value); + return toAppendTo; + } + + @Override + public Date parse(String source, ParsePosition pos) + { + // index must be set to other than 0, I would swear this requirement is not there in + // some version of jdk 6. + pos.setIndex(source.length()); + return ISO8601Utils.parse(source); + } + + @Override + public Object clone() { + return this; // jackson calls clone everytime. We are threadsafe so just returns the instance + } +} \ No newline at end of file
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/util/ISO8601Utils.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/util/ISO8601Utils.java new file mode 100644 index 0000000..f750a50 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/util/ISO8601Utils.java
@@ -0,0 +1,230 @@ +package org.codehaus.jackson.map.util; + +import java.util.*; + +/** + * Utilities methods for manipulating dates in iso8601 format. This is much much faster and GC friendly than + * using SimpleDateFormat so highly suitable if you (un)serialize lots of date objects. + */ +public class ISO8601Utils { + + /** + * ID to represent the 'GMT' string + */ + private static final String GMT_ID = "GMT"; + + /** + * The GMT timezone + */ + private static final TimeZone TIMEZONE_GMT = TimeZone.getTimeZone(GMT_ID); + + /** + * Format a date into 'yyyy-MM-ddThh:mm:ssZ' (GMT timezone, no milliseconds precision) + * + * @param date the date to format + * @return the date formatted as 'yyyy-MM-ddThh:mm:ssZ' + */ + public static String format(Date date) { + return format(date, false, TIMEZONE_GMT); + } + + /** + * Format a date into 'yyyy-MM-ddThh:mm:ss[.sss]Z' (GMT timezone) + * + * @param date the date to format + * @param millis true to include millis precision otherwise false + * @return the date formatted as 'yyyy-MM-ddThh:mm:ss[.sss]Z' + */ + public static String format(Date date, boolean millis) { + return format(date, millis, TIMEZONE_GMT); + } + + /** + * Format date into yyyy-MM-ddThh:mm:ss[.sss][Z|[+-]hh:mm] + * + * @param date the date to format + * @param millis true to include millis precision otherwise false + * @param tz timezone to use for the formatting (GMT will produce 'Z') + * @return the date formatted as yyyy-MM-ddThh:mm:ss[.sss][Z|[+-]hh:mm] + */ + public static String format(Date date, boolean millis, TimeZone tz) { + Calendar calendar = new GregorianCalendar(tz, Locale.US); + calendar.setTime(date); + + // estimate capacity of buffer as close as we can (yeah, that's pedantic ;) + int capacity = "yyyy-MM-ddThh:mm:ss".length(); + capacity += millis ? ".sss".length() : 0; + capacity += tz.getRawOffset() == 0 ? "Z".length() : "+hh:mm".length(); + StringBuilder formatted = new StringBuilder(capacity); + + padInt(formatted, calendar.get(Calendar.YEAR), "yyyy".length()); + formatted.append('-'); + padInt(formatted, calendar.get(Calendar.MONTH) + 1, "MM".length()); + formatted.append('-'); + padInt(formatted, calendar.get(Calendar.DAY_OF_MONTH), "dd".length()); + formatted.append('T'); + padInt(formatted, calendar.get(Calendar.HOUR_OF_DAY), "hh".length()); + formatted.append(':'); + padInt(formatted, calendar.get(Calendar.MINUTE), "mm".length()); + formatted.append(':'); + padInt(formatted, calendar.get(Calendar.SECOND), "ss".length()); + if (millis) { + formatted.append('.'); + padInt(formatted, calendar.get(Calendar.MILLISECOND), "sss".length()); + } + + int offset = tz.getOffset(calendar.getTimeInMillis()); + if (offset != 0) { + int hours = Math.abs((offset / (60 * 1000)) / 60); + int minutes = Math.abs((offset / (60 * 1000)) % 60); + formatted.append(offset < 0 ? '-' : '+'); + padInt(formatted, hours, "hh".length()); + formatted.append(':'); + padInt(formatted, minutes, "mm".length()); + } else { + formatted.append('Z'); + } + + return formatted.toString(); + } + + + /** + * Parse a date from ISO-8601 formatted string. It expects a format yyyy-MM-ddThh:mm:ss[.sss][Z|[+-]hh:mm] + * + * @param date ISO string to parse in the appropriate format. + * @return the parsed date + * @throws IllegalArgumentException if the date is not in the appropriate format + */ + public static Date parse(String date) { + try { + int offset = 0; + + // extract year + int year = parseInt(date, offset, offset += 4); + checkOffset(date, offset, '-'); + + // extract month + int month = parseInt(date, offset += 1, offset += 2); + checkOffset(date, offset, '-'); + + // extract day + int day = parseInt(date, offset += 1, offset += 2); + checkOffset(date, offset, 'T'); + + // extract hours, minutes, seconds and milliseconds + int hour = parseInt(date, offset += 1, offset += 2); + checkOffset(date, offset, ':'); + + int minutes = parseInt(date, offset += 1, offset += 2); + checkOffset(date, offset, ':'); + + int seconds = parseInt(date, offset += 1, offset += 2); + // milliseconds can be optional in the format + int milliseconds = 0; // always use 0 otherwise returned date will include millis of current time + if (date.charAt(offset) == '.') { + checkOffset(date, offset, '.'); + milliseconds = parseInt(date, offset += 1, offset += 3); + } + + // extract timezone + String timezoneId; + char timezoneIndicator = date.charAt(offset); + if (timezoneIndicator == '+' || timezoneIndicator == '-') { + timezoneId = GMT_ID + date.substring(offset); + } else if (timezoneIndicator == 'Z') { + timezoneId = GMT_ID; + } else { + throw new IndexOutOfBoundsException("Invalid time zone indicator " + timezoneIndicator); + } + TimeZone timezone = TimeZone.getTimeZone(timezoneId); + if (!timezone.getID().equals(timezoneId)) { + throw new IndexOutOfBoundsException(); + } + + Calendar calendar = new GregorianCalendar(timezone); + calendar.setLenient(false); + calendar.set(Calendar.YEAR, year); + calendar.set(Calendar.MONTH, month - 1); + calendar.set(Calendar.DAY_OF_MONTH, day); + calendar.set(Calendar.HOUR_OF_DAY, hour); + calendar.set(Calendar.MINUTE, minutes); + calendar.set(Calendar.SECOND, seconds); + calendar.set(Calendar.MILLISECOND, milliseconds); + + return calendar.getTime(); + } catch (IndexOutOfBoundsException e) { + throw new IllegalArgumentException("Failed to parse date " + date, e); + } catch (NumberFormatException e) { + throw new IllegalArgumentException("Failed to parse date " + date, e); + } catch (IllegalArgumentException e) { + throw new IllegalArgumentException("Failed to parse date " + date, e); + } + } + + /** + * Check if the expected character exist at the given offset of the + * + * @param value the string to check at the specified offset + * @param offset the offset to look for the expected character + * @param expected the expected character + * @throws IndexOutOfBoundsException if the expected character is not found + */ + private static void checkOffset(String value, int offset, char expected) throws IndexOutOfBoundsException { + char found = value.charAt(offset); + if (found != expected) { + throw new IndexOutOfBoundsException("Expected '" + expected + "' character but found '" + found + "'"); + } + } + + /** + * Parse an integer located between 2 given offsets in a string + * + * @param value the string to parse + * @param beginIndex the start index for the integer in the string + * @param endIndex the end index for the integer in the string + * @return the int + * @throws NumberFormatException if the value is not a number + */ + private static int parseInt(String value, int beginIndex, int endIndex) throws NumberFormatException { + if (beginIndex < 0 || endIndex > value.length() || beginIndex > endIndex) { + throw new NumberFormatException(value); + } + // use same logic as in Integer.parseInt() but less generic we're not supporting negative values + int i = beginIndex; + int result = 0; + int digit; + if (i < endIndex) { + digit = Character.digit(value.charAt(i++), 10); + if (digit < 0) { + throw new NumberFormatException("Invalid number: " + value); + } + result = -digit; + } + while (i < endIndex) { + digit = Character.digit(value.charAt(i++), 10); + if (digit < 0) { + throw new NumberFormatException("Invalid number: " + value); + } + result *= 10; + result -= digit; + } + return -result; + } + + /** + * Zero pad a number to a specified length + * + * @param buffer buffer to use for padding + * @param value the integer value to pad if necessary. + * @param length the length of the string we should zero pad + */ + private static void padInt(StringBuilder buffer, int value, int length) { + String strValue = Integer.toString(value); + for (int i = length - strValue.length(); i > 0; i--) { + buffer.append('0'); + } + buffer.append(strValue); + } +} +
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/util/JSONPObject.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/util/JSONPObject.java new file mode 100644 index 0000000..ae65469 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/util/JSONPObject.java
@@ -0,0 +1,105 @@ +package org.codehaus.jackson.map.util; + +import java.io.IOException; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.type.TypeFactory; +import org.codehaus.jackson.type.JavaType; + +/** + * Container class that can be used to wrap any Object instances (including + * nulls), and will serialize embedded in + * <a href="http://en.wikipedia.org/wiki/JSONP">JSONP</a> wrapping. + * + * @see org.codehaus.jackson.map.util.JSONWrappedObject + * + * @author tatu + * @since 1.5 + */ +public class JSONPObject + implements JsonSerializableWithType +{ + /** + * JSONP function name to use for serialization + */ + protected final String _function; + + /** + * Value to be serialized as JSONP padded; can be null. + */ + protected final Object _value; + + /** + * Optional static type to use for serialization; if null, runtime + * type is used. Can be used to specify declared type which defines + * serializer to use, as well as aspects of extra type information + * to include (if any). + */ + protected final JavaType _serializationType; + + public JSONPObject(String function, Object value) { + this(function, value, (JavaType) null); + } + + public JSONPObject(String function, Object value, JavaType asType) + { + _function = function; + _value = value; + _serializationType = asType; + } + + /** + * @deprecated Since 1.8; instead use variant that takes JavaType: this ensures + * that type information is properly resolved + */ + @Deprecated + public JSONPObject(String function, Object value, Class<?> rawType) { + _function = function; + _value = value; + _serializationType = (rawType == null) ? null : TypeFactory.defaultInstance().constructType(rawType); + } + + /* + /********************************************************** + /* JsonSerializable(WithType) implementation + /********************************************************** + */ + + @Override + public void serializeWithType(JsonGenerator jgen, SerializerProvider provider, TypeSerializer typeSer) + throws IOException, JsonProcessingException + { + // No type for JSONP wrapping: value serializer will handle typing for value: + serialize(jgen, provider); + } + + @Override + @SuppressWarnings("deprecation") + public void serialize(JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonProcessingException + { + // First, wrapping: + jgen.writeRaw(_function); + jgen.writeRaw('('); + if (_value == null) { + provider.defaultSerializeNull(jgen); + } else if (_serializationType != null) { + provider.findTypedValueSerializer(_serializationType, true, null).serialize(_value, jgen, provider); + } else { + Class<?> cls = _value.getClass(); + provider.findTypedValueSerializer(cls, true, null).serialize(_value, jgen, provider); + } + jgen.writeRaw(')'); + } + + /* + /************************************************************** + /* Accessors + /************************************************************** + */ + + public String getFunction() { return _function; } + public Object getValue() { return _value; } + public JavaType getSerializationType() { return _serializationType; } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/util/JSONWrappedObject.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/util/JSONWrappedObject.java new file mode 100644 index 0000000..85d0496 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/util/JSONWrappedObject.java
@@ -0,0 +1,117 @@ +package org.codehaus.jackson.map.util; + +import java.io.IOException; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.type.TypeFactory; +import org.codehaus.jackson.type.JavaType; + + +/** + * General-purpose wrapper class that can be used to decorate serialized + * value with arbitrary literal prefix and suffix. This can be used for + * example to construct arbitrary Javascript values (similar to how basic + * function name and parenthesis are used with JSONP). + * + * @see org.codehaus.jackson.map.util.JSONPObject + * + * @author tatu + * @since 1.5 + */ +public class JSONWrappedObject + implements JsonSerializableWithType +{ + /** + * Literal String to output before serialized value. + * Will not be quoted when serializing value. + */ + protected final String _prefix; + + /** + * Literal String to output after serialized value. + * Will not be quoted when serializing value. + */ + protected final String _suffix; + + /** + * Value to be serialized as JSONP padded; can be null. + */ + protected final Object _value; + + /** + * Optional static type to use for serialization; if null, runtime + * type is used. Can be used to specify declared type which defines + * serializer to use, as well as aspects of extra type information + * to include (if any). + */ + protected final JavaType _serializationType; + + public JSONWrappedObject(String prefix, String suffix, Object value) { + this(prefix, suffix, value, (JavaType) null); + } + + public JSONWrappedObject(String prefix, String suffix, Object value, JavaType asType) + { + _prefix = prefix; + _suffix = suffix; + _value = value; + _serializationType = asType; + } + + /** + * @deprecated Since 1.8; should construct with resolved <code>JavaType</code>, + * to ensure type has been properly resolved + */ + @Deprecated + public JSONWrappedObject(String prefix, String suffix, Object value, Class<?> rawType) { + _prefix = prefix; + _suffix = suffix; + _value = value; + _serializationType = (rawType == null) ? null : TypeFactory.defaultInstance().constructType(rawType); + } + + /* + /************************************************************** + /* JsonSerializable(WithType) implementation + /************************************************************** + */ + + @Override + public void serializeWithType(JsonGenerator jgen, SerializerProvider provider, TypeSerializer typeSer) + throws IOException, JsonProcessingException + { + // No type for JSONP wrapping: value serializer will handle typing for value: + serialize(jgen, provider); + } + + @Override + @SuppressWarnings("deprecation") + public void serialize(JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonProcessingException + { + // First, wrapping: + if (_prefix != null) jgen.writeRaw(_prefix); + if (_value == null) { + provider.defaultSerializeNull(jgen); + } else if (_serializationType != null) { + provider.findTypedValueSerializer(_serializationType, true, null).serialize(_value, jgen, provider); + } else { + Class<?> cls = _value.getClass(); + provider.findTypedValueSerializer(cls, true, null).serialize(_value, jgen, provider); + } + if (_suffix != null) jgen.writeRaw(_suffix); + } + + /* + /************************************************************** + /* Accessors + /************************************************************** + */ + + public String getPrefix() { return _prefix; } + public String getSuffix() { return _suffix; } + public Object getValue() { return _value; } + public JavaType getSerializationType() { return _serializationType; } + +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/util/LRUMap.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/util/LRUMap.java new file mode 100644 index 0000000..1375e15 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/util/LRUMap.java
@@ -0,0 +1,28 @@ +package org.codehaus.jackson.map.util; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * Helper for simple bounded LRU maps used for reusing lookup values. + * + * @since 1.7 + */ +@SuppressWarnings("serial") +public class LRUMap<K,V> extends LinkedHashMap<K,V> +{ + protected final int _maxEntries; + + public LRUMap(int initialEntries, int maxEntries) + { + super(initialEntries, 0.8f, true); + _maxEntries = maxEntries; + } + + @Override + protected boolean removeEldestEntry(Map.Entry<K,V> eldest) + { + return size() > _maxEntries; + } + +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/util/LinkedNode.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/util/LinkedNode.java new file mode 100644 index 0000000..a0f2ace --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/util/LinkedNode.java
@@ -0,0 +1,45 @@ +package org.codehaus.jackson.map.util; + +/** + * Node of a forward-only linked list. + * + * @author tatu + * + * @param <T> Type of contained object + */ +public final class LinkedNode<T> +{ + final T _value; + final LinkedNode<T> _next; + + public LinkedNode(T value, LinkedNode<T> next) + { + _value = value; + _next = next; + } + + public LinkedNode<T> next() { return _next; } + + public T value() { return _value; } + + /** + * Convenience method that can be used to check if a linked list + * with given head node (which may be null to indicate empty list) + * contains given value + * + * @param <ST> Type argument that defines contents of the linked list parameter + * @param node Head node of the linked list + * @param value Value to look for + * @return True if linked list contains the value, false otherwise + */ + public static <ST> boolean contains(LinkedNode<ST> node, ST value) + { + while (node != null) { + if (node.value() == value) { + return true; + } + node = node.next(); + } + return false; + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/util/Named.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/util/Named.java new file mode 100644 index 0000000..8d59d76 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/util/Named.java
@@ -0,0 +1,10 @@ +package org.codehaus.jackson.map.util; + +/** + * Simple tag interface mostly to allow sorting by name + * + * @since 1.9 + */ +public interface Named { + public String getName(); +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/util/ObjectBuffer.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/util/ObjectBuffer.java new file mode 100644 index 0000000..2ebccad --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/util/ObjectBuffer.java
@@ -0,0 +1,257 @@ +package org.codehaus.jackson.map.util; + +import java.lang.reflect.Array; +import java.util.List; + +/** + * Helper class to use for constructing Object arrays by appending entries + * to create arrays of various lengths (length that is not known a priori). + */ +public final class ObjectBuffer +{ + // // // Config constants + + /** + * Let's start with small chunks; typical usage is for small arrays anyway. + */ + final static int INITIAL_CHUNK_SIZE = 12; + + /** + * Also: let's expand by doubling up until 64k chunks (which is 16k entries for + * 32-bit machines) + */ + final static int SMALL_CHUNK_SIZE = (1 << 14); + + /** + * Let's limit maximum size of chunks we use; helps avoid excessive allocation + * overhead for huge data sets. + * For now, let's limit to quarter million entries, 1 meg chunks for 32-bit + * machines. + */ + final static int MAX_CHUNK_SIZE = (1 << 18); + + // // // Data storage + + private Node _bufferHead; + + private Node _bufferTail; + + /** + * Number of total buffered entries in this buffer, counting all instances + * within linked list formed by following {@link #_bufferHead}. + */ + private int _bufferedEntryCount; + + // // // Simple reuse + + /** + * Reusable Object array, stored here after buffer has been released having + * been used previously. + */ + private Object[] _freeBuffer; + + /* + /********************************************************** + /* Construction + /********************************************************** + */ + + public ObjectBuffer() { } + + /* + /********************************************************** + /* Public API + /********************************************************** + */ + + /** + * Method called to start buffering process. Will ensure that the buffer + * is empty, and then return an object array to start chunking content on + */ + public Object[] resetAndStart() + { + _reset(); + if (_freeBuffer == null) { + return new Object[INITIAL_CHUNK_SIZE]; + } + return _freeBuffer; + } + + /** + * Method called to add a full Object array as a chunk buffered within + * this buffer, and to obtain a new array to fill. Caller is not to use + * the array it gives; but to use the returned array for continued + * buffering. + * + * @param fullChunk Completed chunk that the caller is requesting + * to append to this buffer. It is generally chunk that was + * returned by an earlier call to {@link #resetAndStart} or + * {@link #appendCompletedChunk} (although this is not required or + * enforced) + * + * @return New chunk buffer for caller to fill + */ + public Object[] appendCompletedChunk(Object[] fullChunk) + { + Node next = new Node(fullChunk); + if (_bufferHead == null) { // first chunk + _bufferHead = _bufferTail = next; + } else { // have something already + _bufferTail.linkNext(next); + _bufferTail = next; + } + int len = fullChunk.length; + _bufferedEntryCount += len; + // double the size for small chunks + if (len < SMALL_CHUNK_SIZE) { + len += len; + } else { // but by +25% for larger (to limit overhead) + len += (len >> 2); + } + return new Object[len]; + } + + /** + * Method called to indicate that the buffering process is now + * complete; and to construct a combined exactly-sized result + * array. Additionally the buffer itself will be reset to + * reduce memory retention. + *<p> + * Resulting array will be of generic <code>Object[]</code> type: + * if a typed array is needed, use the method with additional + * type argument. + */ + public Object[] completeAndClearBuffer(Object[] lastChunk, int lastChunkEntries) + { + int totalSize = lastChunkEntries + _bufferedEntryCount; + Object[] result = new Object[totalSize]; + _copyTo(result, totalSize, lastChunk, lastChunkEntries); + return result; + } + + /** + * Type-safe alternative to + * {@link #completeAndClearBuffer(Object[], int)}, to allow + * for constructing explicitly typed result array. + * + * @param componentType Type of elements included in the buffer. Will be + * used for constructing the result array. + */ + public <T> T[] completeAndClearBuffer(Object[] lastChunk, int lastChunkEntries, Class<T> componentType) + { + int totalSize = lastChunkEntries + _bufferedEntryCount; + @SuppressWarnings("unchecked") + T[] result = (T[]) Array.newInstance(componentType, totalSize); + _copyTo(result, totalSize, lastChunk, lastChunkEntries); + _reset(); + return result; + } + + /** + * Another + * + * @since 1.6 + */ + public void completeAndClearBuffer(Object[] lastChunk, int lastChunkEntries, List<Object> resultList) + { + for (Node n = _bufferHead; n != null; n = n.next()) { + Object[] curr = n.getData(); + for (int i = 0, len = curr.length; i < len; ++i) { + resultList.add(curr[i]); + } + } + // and then the last one + for (int i = 0; i < lastChunkEntries; ++i) { + resultList.add(lastChunk[i]); + } + } + + /** + * Helper method that can be used to check how much free capacity + * will this instance start with. Can be used to choose the best + * instance to reuse, based on size of reusable object chunk + * buffer holds reference to. + */ + public int initialCapacity() + { + return (_freeBuffer == null) ? 0 : _freeBuffer.length; + } + + /** + * Method that can be used to check how many Objects have been buffered + * within this buffer. + */ + public int bufferedSize() { return _bufferedEntryCount; } + + /* + /********************************************************** + /* Internal methods + /********************************************************** + */ + + protected void _reset() + { + // can we reuse the last (and thereby biggest) array for next time? + if (_bufferTail != null) { + _freeBuffer = _bufferTail.getData(); + } + // either way, must discard current contents + _bufferHead = _bufferTail = null; + _bufferedEntryCount = 0; + } + + protected final void _copyTo(Object resultArray, int totalSize, + Object[] lastChunk, int lastChunkEntries) + { + int ptr = 0; + + for (Node n = _bufferHead; n != null; n = n.next()) { + Object[] curr = n.getData(); + int len = curr.length; + System.arraycopy(curr, 0, resultArray, ptr, len); + ptr += len; + } + System.arraycopy(lastChunk, 0, resultArray, ptr, lastChunkEntries); + ptr += lastChunkEntries; + + // sanity check (could have failed earlier due to out-of-bounds, too) + if (ptr != totalSize) { + throw new IllegalStateException("Should have gotten "+totalSize+" entries, got "+ptr); + } + } + + /* + /********************************************************** + /* Helper classes + /********************************************************** + */ + + /** + * Helper class used to store actual data, in a linked list. + */ + final static class Node + { + /** + * Data stored in this node. Array is considered to be full. + */ + final Object[] _data; + + Node _next; + + public Node(Object[] data) { + _data = data; + } + + public Object[] getData() { return _data; } + + public Node next() { return _next; } + + public void linkNext(Node next) + { + if (_next != null) { // sanity check + throw new IllegalStateException(); + } + _next = next; + } + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/util/PrimitiveArrayBuilder.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/util/PrimitiveArrayBuilder.java new file mode 100644 index 0000000..6b015b0 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/util/PrimitiveArrayBuilder.java
@@ -0,0 +1,180 @@ +package org.codehaus.jackson.map.util; + +/** + * Base class for specialized primitive array builders. + */ +public abstract class PrimitiveArrayBuilder<T> +{ + /** + * Let's start with small chunks; typical usage is for small arrays anyway. + */ + final static int INITIAL_CHUNK_SIZE = 12; + + /** + * Also: let's expand by doubling up until 64k chunks (which is 16k entries for + * 32-bit machines) + */ + final static int SMALL_CHUNK_SIZE = (1 << 14); + + /** + * Let's limit maximum size of chunks we use; helps avoid excessive allocation + * overhead for huge data sets. + * For now, let's limit to quarter million entries, 1 meg chunks for 32-bit + * machines. + */ + final static int MAX_CHUNK_SIZE = (1 << 18); + + // // // Data storage + + T _freeBuffer; + + Node<T> _bufferHead; + + Node<T> _bufferTail; + + /** + * Number of total buffered entries in this buffer, counting all instances + * within linked list formed by following {@link #_bufferHead}. + */ + int _bufferedEntryCount; + + // // // Recycled instances of sub-classes + + // // // Life-cycle + + protected PrimitiveArrayBuilder() { } + + /* + //////////////////////////////////////////////////////////////////////// + // Public API + //////////////////////////////////////////////////////////////////////// + */ + + public T resetAndStart() + { + _reset(); + return (_freeBuffer == null) ? + _constructArray(INITIAL_CHUNK_SIZE) : _freeBuffer; + } + + /** + * @return Length of the next chunk to allocate + */ + public final T appendCompletedChunk(T fullChunk, int fullChunkLength) + { + Node<T> next = new Node<T>(fullChunk, fullChunkLength); + if (_bufferHead == null) { // first chunk + _bufferHead = _bufferTail = next; + } else { // have something already + _bufferTail.linkNext(next); + _bufferTail = next; + } + _bufferedEntryCount += fullChunkLength; + int nextLen = fullChunkLength; // start with last chunk size + // double the size for small chunks + if (nextLen < SMALL_CHUNK_SIZE) { + nextLen += nextLen; + } else { // but by +25% for larger (to limit overhead) + nextLen += (nextLen >> 2); + } + return _constructArray(nextLen); + } + + public T completeAndClearBuffer(T lastChunk, int lastChunkEntries) + { + int totalSize = lastChunkEntries + _bufferedEntryCount; + T resultArray = _constructArray(totalSize); + + int ptr = 0; + + for (Node<T> n = _bufferHead; n != null; n = n.next()) { + ptr = n.copyData(resultArray, ptr); + } + System.arraycopy(lastChunk, 0, resultArray, ptr, lastChunkEntries); + ptr += lastChunkEntries; + + // sanity check (could have failed earlier due to out-of-bounds, too) + if (ptr != totalSize) { + throw new IllegalStateException("Should have gotten "+totalSize+" entries, got "+ptr); + } + return resultArray; + } + + /* + //////////////////////////////////////////////////////////////////////// + // Abstract methods for sub-classes to implement + //////////////////////////////////////////////////////////////////////// + */ + + protected abstract T _constructArray(int len); + + /* + //////////////////////////////////////////////////////////////////////// + // Internal methods + //////////////////////////////////////////////////////////////////////// + */ + + protected void _reset() + { + // can we reuse the last (and thereby biggest) array for next time? + if (_bufferTail != null) { + _freeBuffer = _bufferTail.getData(); + } + // either way, must discard current contents + _bufferHead = _bufferTail = null; + _bufferedEntryCount = 0; + } + + /* + //////////////////////////////////////////////////////////////////////// + // Helper classes + //////////////////////////////////////////////////////////////////////// + */ + + /** + * For actual buffering beyond the current buffer, we can actually + * use shared class which only deals with opaque "untyped" chunks. + * This works because {@link java.lang.System#arraycopy} does not + * take type; hence we can implement some aspects of primitive data + * handling in generic fashion. + */ + final static class Node<T> + { + /** + * Data stored in this node. + */ + final T _data; + + /** + * Number entries in the (untyped) array. Offset is assumed to be 0. + */ + final int _dataLength; + + Node<T> _next; + + public Node(T data, int dataLen) + { + _data = data; + _dataLength = dataLen; + } + + public T getData() { return _data; } + + public int copyData(T dst, int ptr) + { + System.arraycopy(_data, 0, dst, ptr, _dataLength); + ptr += _dataLength; + return ptr; + } + + public Node<T> next() { return _next; } + + public void linkNext(Node<T> next) + { + if (_next != null) { // sanity check + throw new IllegalStateException(); + } + _next = next; + } + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/util/Provider.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/util/Provider.java new file mode 100644 index 0000000..5b66c35 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/util/Provider.java
@@ -0,0 +1,21 @@ +package org.codehaus.jackson.map.util; + +import java.util.*; + +/** +* Simple helper class used for decoupling instantiation of +* optionally loaded handlers, like deserializers and deserializers +* for libraries that are only present on some platforms. + * + * @author tatu + * + * @param <T> Type of objects provided + */ +public interface Provider<T> +{ + /** + * Method used to request provider to provide entries it has + */ + public Collection<T> provide(); +} +
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/util/RootNameLookup.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/util/RootNameLookup.java new file mode 100644 index 0000000..89b6020 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/util/RootNameLookup.java
@@ -0,0 +1,54 @@ +package org.codehaus.jackson.map.util; + +import org.codehaus.jackson.io.SerializedString; +import org.codehaus.jackson.map.AnnotationIntrospector; +import org.codehaus.jackson.map.MapperConfig; +import org.codehaus.jackson.map.introspect.AnnotatedClass; +import org.codehaus.jackson.map.introspect.BasicBeanDescription; +import org.codehaus.jackson.map.type.ClassKey; +import org.codehaus.jackson.type.JavaType; + +/** + * Helper class for caching resolved root names. + */ +public class RootNameLookup +{ + /** + * For efficient operation, let's try to minimize number of times we + * need to introspect root element name to use. + */ + protected LRUMap<ClassKey,SerializedString> _rootNames; + + public RootNameLookup() { } + + public SerializedString findRootName(JavaType rootType, MapperConfig<?> config) + { + return findRootName(rootType.getRawClass(), config); + } + + public synchronized SerializedString findRootName(Class<?> rootType, MapperConfig<?> config) + { + ClassKey key = new ClassKey(rootType); + + if (_rootNames == null) { + _rootNames = new LRUMap<ClassKey,SerializedString>(20, 200); + } else { + SerializedString name = _rootNames.get(key); + if (name != null) { + return name; + } + } + BasicBeanDescription beanDesc = (BasicBeanDescription) config.introspectClassAnnotations(rootType); + AnnotationIntrospector intr = config.getAnnotationIntrospector(); + AnnotatedClass ac = beanDesc.getClassInfo(); + String nameStr = intr.findRootName(ac); + // No answer so far? Let's just default to using simple class name + if (nameStr == null) { + // Should we strip out enclosing class tho? For now, nope: + nameStr = rootType.getSimpleName(); + } + SerializedString name = new SerializedString(nameStr); + _rootNames.put(key, name); + return name; + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/util/StdDateFormat.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/util/StdDateFormat.java new file mode 100644 index 0000000..2a684d3 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/util/StdDateFormat.java
@@ -0,0 +1,348 @@ +package org.codehaus.jackson.map.util; + +import java.text.DateFormat; +import java.text.FieldPosition; +import java.text.ParseException; +import java.text.ParsePosition; +import java.text.SimpleDateFormat; +import java.util.*; + +import org.codehaus.jackson.io.NumberInput; + +/** + * Default {@link DateFormat} implementation used by standard Date + * serializers and deserializers. For serialization defaults to using + * an ISO-8601 compliant format (format String "yyyy-MM-dd'T'HH:mm:ss.SSSZ") + * and for deserialization, both ISO-8601 and RFC-1123. + */ +@SuppressWarnings("serial") +public class StdDateFormat + extends DateFormat +{ + /* TODO !!! 24-Nov-2009, tatu: Need to rewrite this class soon: + * JDK date parsing is awfully brittle, and ISO-8601 is quite + * permissive. The two don't mix, need to write a better one. + */ + + /** + * Defines a commonly used date format that conforms + * to ISO-8601 date formatting standard, when it includes basic undecorated + * timezone definition + */ + protected final static String DATE_FORMAT_STR_ISO8601 = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"; + + /** + * Same as 'regular' 8601, but handles 'Z' as an alias for "+0000" + * (or "GMT") + */ + protected final static String DATE_FORMAT_STR_ISO8601_Z = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"; + + /** + * ISO-8601 with just the Date part, no time + * + * @since 1.3.1 + */ + protected final static String DATE_FORMAT_STR_PLAIN = "yyyy-MM-dd"; + + /** + * This constant defines the date format specified by + * RFC 1123. + */ + protected final static String DATE_FORMAT_STR_RFC1123 = "EEE, dd MMM yyyy HH:mm:ss zzz"; + + /** + * For error messages we'll also need a list of all formats. + */ + protected final static String[] ALL_FORMATS = new String[] { + DATE_FORMAT_STR_ISO8601, + DATE_FORMAT_STR_ISO8601_Z, + DATE_FORMAT_STR_RFC1123, + DATE_FORMAT_STR_PLAIN + }; + + protected final static DateFormat DATE_FORMAT_RFC1123; + + protected final static DateFormat DATE_FORMAT_ISO8601; + protected final static DateFormat DATE_FORMAT_ISO8601_Z; + + protected final static DateFormat DATE_FORMAT_PLAIN; + + /* Let's construct "blueprint" date format instances: can not be used + * as is, due to thread-safety issues, but can be used for constructing + * actual instances more cheaply (avoids re-parsing). + */ + static { + /* Another important thing: let's force use of GMT for + * baseline DataFormat objects + */ + TimeZone gmt = TimeZone.getTimeZone("GMT"); + DATE_FORMAT_RFC1123 = new SimpleDateFormat(DATE_FORMAT_STR_RFC1123); + DATE_FORMAT_RFC1123.setTimeZone(gmt); + DATE_FORMAT_ISO8601 = new SimpleDateFormat(DATE_FORMAT_STR_ISO8601); + DATE_FORMAT_ISO8601.setTimeZone(gmt); + DATE_FORMAT_ISO8601_Z = new SimpleDateFormat(DATE_FORMAT_STR_ISO8601_Z); + DATE_FORMAT_ISO8601_Z.setTimeZone(gmt); + DATE_FORMAT_PLAIN = new SimpleDateFormat(DATE_FORMAT_STR_PLAIN); + DATE_FORMAT_PLAIN.setTimeZone(gmt); + } + + /** + * A singleton instance can be used for cloning purposes. + */ + public final static StdDateFormat instance = new StdDateFormat(); + + protected transient DateFormat _formatRFC1123; + protected transient DateFormat _formatISO8601; + protected transient DateFormat _formatISO8601_z; + protected transient DateFormat _formatPlain; + + /* + /********************************************************** + /* Life cycle, accessing singleton "standard" formats + /********************************************************** + */ + + public StdDateFormat() { } + + @Override + public StdDateFormat clone() { + /* Since we always delegate all work to child DateFormat instances, + * let's NOT call super.clone(); this is bit unusual, but makes + * sense here to avoid unnecessary work. + */ + return new StdDateFormat(); + } + + /** + * Method for getting the globally shared DateFormat instance + * that uses GMT timezone and can handle simple ISO-8601 + * compliant date format. + */ + public static DateFormat getBlueprintISO8601Format() { + return DATE_FORMAT_ISO8601; + } + + /** + * Method for getting a non-shared DateFormat instance + * that uses specified timezone and can handle simple ISO-8601 + * compliant date format. + */ + public static DateFormat getISO8601Format(TimeZone tz) { + DateFormat df = (DateFormat) DATE_FORMAT_ISO8601.clone(); + df.setTimeZone(tz); + return df; + } + + /** + * Method for getting the globally shared DateFormat instance + * that uses GMT timezone and can handle RFC-1123 + * compliant date format. + */ + public static DateFormat getBlueprintRFC1123Format() { + return DATE_FORMAT_RFC1123; + } + + + /** + * Method for getting a non-shared DateFormat instance + * that uses specific timezone and can handle RFC-1123 + * compliant date format. + */ + public static DateFormat getRFC1123Format(TimeZone tz) + { + DateFormat df = (DateFormat) DATE_FORMAT_RFC1123.clone(); + df.setTimeZone(tz); + return df; + } + + /* + /********************************************************** + /* Public API + /********************************************************** + */ + + @Override + public Date parse(String dateStr) throws ParseException + { + dateStr = dateStr.trim(); + ParsePosition pos = new ParsePosition(0); + Date result = parse(dateStr, pos); + if (result != null) { + return result; + } + + StringBuilder sb = new StringBuilder(); + for (String f : ALL_FORMATS) { + if (sb.length() > 0) { + sb.append("\", \""); + } else { + sb.append('"'); + } + sb.append(f); + } + sb.append('"'); + throw new ParseException + (String.format("Can not parse date \"%s\": not compatible with any of standard forms (%s)", + dateStr, sb.toString()), pos.getErrorIndex()); + } + + @Override + public Date parse(String dateStr, ParsePosition pos) + { + if (looksLikeISO8601(dateStr)) { // also includes "plain" + return parseAsISO8601(dateStr, pos); + } + /* 14-Feb-2010, tatu: As per [JACKSON-236], better also + * consider "stringified" simple time stamp + */ + int i = dateStr.length(); + while (--i >= 0) { + char ch = dateStr.charAt(i); + if (ch < '0' || ch > '9') break; + } + if (i < 0) { // all digits + if (NumberInput.inLongRange(dateStr, false)) { + return new Date(Long.parseLong(dateStr)); + } + } + // Otherwise, fall back to using RFC 1123 + return parseAsRFC1123(dateStr, pos); + } + + @Override + public StringBuffer format(Date date, StringBuffer toAppendTo, + FieldPosition fieldPosition) + { + if (_formatISO8601 == null) { + _formatISO8601 = (DateFormat) DATE_FORMAT_ISO8601.clone(); + } + return _formatISO8601.format(date, toAppendTo, fieldPosition); + } + + /* + /********************************************************** + /* Helper methods + /********************************************************** + */ + + /** + * Overridable helper method used to figure out which of supported + * formats is the likeliest match. + */ + protected boolean looksLikeISO8601(String dateStr) + { + if (dateStr.length() >= 5 + && Character.isDigit(dateStr.charAt(0)) + && Character.isDigit(dateStr.charAt(3)) + && dateStr.charAt(4) == '-' + ) { + return true; + } + return false; + } + + protected Date parseAsISO8601(String dateStr, ParsePosition pos) + { + /* 21-May-2009, tatu: DateFormat has very strict handling of + * timezone modifiers for ISO-8601. So we need to do some scrubbing. + */ + + /* First: do we have "zulu" format ('Z' == "GMT")? If yes, that's + * quite simple because we already set date format timezone to be + * GMT, and hence can just strip out 'Z' altogether + */ + int len = dateStr.length(); + char c = dateStr.charAt(len-1); + DateFormat df; + + // [JACKSON-200]: need to support "plain" date... + if (len <= 10 && Character.isDigit(c)) { + df = _formatPlain; + if (df == null) { + df = _formatPlain = (DateFormat) DATE_FORMAT_PLAIN.clone(); + } + } else if (c == 'Z') { + df = _formatISO8601_z; + if (df == null) { + df = _formatISO8601_z = (DateFormat) DATE_FORMAT_ISO8601_Z.clone(); + } + // [JACKSON-334]: may be missing milliseconds... if so, add + if (dateStr.charAt(len-4) == ':') { + StringBuilder sb = new StringBuilder(dateStr); + sb.insert(len-1, ".000"); + dateStr = sb.toString(); + } + } else { + // Let's see if we have timezone indicator or not... + if (hasTimeZone(dateStr)) { + c = dateStr.charAt(len-3); + if (c == ':') { // remove optional colon + // remove colon + StringBuilder sb = new StringBuilder(dateStr); + sb.delete(len-3, len-2); + dateStr = sb.toString(); + } else if (c == '+' || c == '-') { // missing minutes + // let's just append '00' + dateStr += "00"; + } + // [JACKSON-334]: may be missing milliseconds... if so, add + len = dateStr.length(); + // '+0000' (5 chars); should come after '.000' (4 chars) of milliseconds, so: + c = dateStr.charAt(len-9); + if (Character.isDigit(c)) { + StringBuilder sb = new StringBuilder(dateStr); + sb.insert(len-5, ".000"); + dateStr = sb.toString(); + } + + df = _formatISO8601; + if (_formatISO8601 == null) { + df = _formatISO8601 = (DateFormat) DATE_FORMAT_ISO8601.clone(); + } + } else { + /* 24-Nov-2009, tatu: Ugh. This is getting pretty + * ugly. Need to rewrite soon! + */ + + // If not, plain date. Easiest to just patch 'Z' in the end? + StringBuilder sb = new StringBuilder(dateStr); + // And possible also millisecond part if missing + int timeLen = len - dateStr.lastIndexOf('T') - 1; + if (timeLen <= 8) { + sb.append(".000"); + } + sb.append('Z'); + dateStr = sb.toString(); + df = _formatISO8601_z; + if (df == null) { + df = _formatISO8601_z = (DateFormat) DATE_FORMAT_ISO8601_Z.clone(); + } + } + } + return df.parse(dateStr, pos); + } + + protected Date parseAsRFC1123(String dateStr, ParsePosition pos) + { + if (_formatRFC1123 == null) { + _formatRFC1123 = (DateFormat) DATE_FORMAT_RFC1123.clone(); + } + return _formatRFC1123.parse(dateStr, pos); + } + + private final static boolean hasTimeZone(String str) + { + // Only accept "+hh", "+hhmm" and "+hh:mm" (and with minus), so + int len = str.length(); + if (len >= 6) { + char c = str.charAt(len-6); + if (c == '+' || c == '-') return true; + c = str.charAt(len-5); + if (c == '+' || c == '-') return true; + c = str.charAt(len-3); + if (c == '+' || c == '-') return true; + } + return false; + } +} +
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/map/util/package-info.java b/1.9.10/src/mapper/java/org/codehaus/jackson/map/util/package-info.java new file mode 100644 index 0000000..c39e41c --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/map/util/package-info.java
@@ -0,0 +1,4 @@ +/** + * Utility classes for Mapper package. + */ +package org.codehaus.jackson.map.util;
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/node/ArrayNode.java b/1.9.10/src/mapper/java/org/codehaus/jackson/node/ArrayNode.java new file mode 100644 index 0000000..443371b --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/node/ArrayNode.java
@@ -0,0 +1,758 @@ +package org.codehaus.jackson.node; + +import java.io.IOException; +import java.math.BigDecimal; +import java.util.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.SerializerProvider; +import org.codehaus.jackson.map.TypeSerializer; + +/** + * Node class that represents Arrays mapped from Json content. + */ +public final class ArrayNode + extends ContainerNode +{ + protected ArrayList<JsonNode> _children; + + public ArrayNode(JsonNodeFactory nc) { super(nc); } + + /* + /********************************************************** + /* Implementation of core JsonNode API + /********************************************************** + */ + + @Override public JsonToken asToken() { return JsonToken.START_ARRAY; } + + @Override + public boolean isArray() { return true; } + + @Override + public int size() + { + return (_children == null) ? 0 : _children.size(); + } + + @Override + public Iterator<JsonNode> getElements() + { + return (_children == null) ? NoNodesIterator.instance() : _children.iterator(); + } + + @Override + public JsonNode get(int index) + { + if (index >= 0 && (_children != null) && index < _children.size()) { + return _children.get(index); + } + return null; + } + + @Override + public JsonNode get(String fieldName) { return null; } + + @Override + public JsonNode path(String fieldName) { return MissingNode.getInstance(); } + + @Override + public JsonNode path(int index) + { + if (index >= 0 && (_children != null) && index < _children.size()) { + return _children.get(index); + } + return MissingNode.getInstance(); + } + + /* + /********************************************************** + /* Public API, serialization + /********************************************************** + */ + + @Override + public final void serialize(JsonGenerator jg, SerializerProvider provider) + throws IOException, JsonProcessingException + { + jg.writeStartArray(); + if (_children != null) { + for (JsonNode n : _children) { + /* 17-Feb-2009, tatu: Can we trust that all nodes will always + * extend BaseJsonNode? Or if not, at least implement + * JsonSerializable? Let's start with former, change if + * we must. + */ + ((BaseJsonNode)n).serialize(jg, provider); + } + } + jg.writeEndArray(); + } + + @Override + public void serializeWithType(JsonGenerator jg, SerializerProvider provider, + TypeSerializer typeSer) + throws IOException, JsonProcessingException + { + typeSer.writeTypePrefixForArray(this, jg); + if (_children != null) { + for (JsonNode n : _children) { + ((BaseJsonNode)n).serialize(jg, provider); + } + } + typeSer.writeTypeSuffixForArray(this, jg); + } + + /* + /********************************************************** + /* Public API, finding value nodes + /********************************************************** + */ + + @Override + public JsonNode findValue(String fieldName) + { + if (_children != null) { + for (JsonNode node : _children) { + JsonNode value = node.findValue(fieldName); + if (value != null) { + return value; + } + } + } + return null; + } + + @Override + public List<JsonNode> findValues(String fieldName, List<JsonNode> foundSoFar) + { + if (_children != null) { + for (JsonNode node : _children) { + foundSoFar = node.findValues(fieldName, foundSoFar); + } + } + return foundSoFar; + } + + @Override + public List<String> findValuesAsText(String fieldName, List<String> foundSoFar) + { + if (_children != null) { + for (JsonNode node : _children) { + foundSoFar = node.findValuesAsText(fieldName, foundSoFar); + } + } + return foundSoFar; + } + + @Override + public ObjectNode findParent(String fieldName) + { + if (_children != null) { + for (JsonNode node : _children) { + JsonNode parent = node.findParent(fieldName); + if (parent != null) { + return (ObjectNode) parent; + } + } + } + return null; + } + + @Override + public List<JsonNode> findParents(String fieldName, List<JsonNode> foundSoFar) + { + if (_children != null) { + for (JsonNode node : _children) { + foundSoFar = node.findParents(fieldName, foundSoFar); + } + } + return foundSoFar; + } + + /* + /********************************************************** + /* Extended ObjectNode API, accessors + /********************************************************** + */ + + /** + * Method that will set specified field, replacing old value, + * if any. + * + * @param value to set field to; if null, will be converted + * to a {@link NullNode} first (to remove field entry, call + * {@link #remove} instead) + * + * @return Old value of the field, if any; null if there was no + * old value. + */ + public JsonNode set(int index, JsonNode value) + { + if (value == null) { // let's not store 'raw' nulls but nodes + value = nullNode(); + } + return _set(index, value); + } + + public void add(JsonNode value) + { + if (value == null) { // let's not store 'raw' nulls but nodes + value = nullNode(); + } + _add(value); + } + + /** + * Method for adding all child nodes of given Array, appending to + * child nodes this array contains + * + * @param other Array to add contents from + * + * @return This node (to allow chaining) + * + * @since 1.3 + */ + public JsonNode addAll(ArrayNode other) + { + int len = other.size(); + if (len > 0) { + if (_children == null) { + _children = new ArrayList<JsonNode>(len+2); + } + other.addContentsTo(_children); + } + return this; + } + + /** + * Method for adding given nodes as child nodes of this array node. + * + * @param nodes Nodes to add + * + * @return This node (to allow chaining) + * + * @since 1.3 + */ + public JsonNode addAll(Collection<JsonNode> nodes) + { + int len = nodes.size(); + if (len > 0) { + if (_children == null) { + _children = new ArrayList<JsonNode>(nodes); + } else { + _children.addAll(nodes); + } + } + return this; + } + + /** + * Method for inserting specified child node as an element + * of this Array. If index is 0 or less, it will be inserted as + * the first element; if >= size(), appended at the end, and otherwise + * inserted before existing element in specified index. + * No exceptions are thrown for any index. + */ + public void insert(int index, JsonNode value) + { + if (value == null) { + value = nullNode(); + } + _insert(index, value); + } + + /** + * Method for removing an entry from this ArrayNode. + * Will return value of the entry at specified index, if entry existed; + * null if not. + */ + public JsonNode remove(int index) + { + if (index >= 0 && (_children != null) && index < _children.size()) { + return _children.remove(index); + } + return null; + } + + @Override + public ArrayNode removeAll() + { + _children = null; + return this; + } + + /* + /********************************************************** + /* Extended ObjectNode API, mutators, generic; addXxx()/insertXxx() + /********************************************************** + */ + + /** + * Method that will construct an ArrayNode and add it as a + * field of this ObjectNode, replacing old value, if any. + * + * @return Newly constructed ArrayNode + */ + public ArrayNode addArray() + { + ArrayNode n = arrayNode(); + _add(n); + return n; + } + + /** + * Method that will construct an ObjectNode and add it at the end + * of this array node. + * + * @return Newly constructed ObjectNode + */ + public ObjectNode addObject() + { + ObjectNode n = objectNode(); + _add(n); + return n; + } + + /** + * Method that will construct a POJONode and add it at the end + * of this array node. + */ + public void addPOJO(Object value) + { + if (value == null) { + addNull(); + } else { + _add(POJONode(value)); + } + } + + public void addNull() + { + _add(nullNode()); + } + + /** + * Method for setting value of a field to specified numeric value. + */ + public void add(int v) { _add(numberNode(v)); } + + /** + * Alternative method that we need to avoid bumping into NPE issues + * with auto-unboxing. + * + * @since 1.9 + */ + public void add(Integer value) { + if (value == null) { + addNull(); + } else { + _add(numberNode(value.intValue())); + } + } + + /** + * Method for setting value of a field to specified numeric value. + */ + public void add(long v) { _add(numberNode(v)); } + + /** + * Alternative method that we need to avoid bumping into NPE issues + * with auto-unboxing. + * + * @since 1.9 + */ + public void add(Long value) { + if (value == null) { + addNull(); + } else { + _add(numberNode(value.longValue())); + } + } + + /** + * Method for setting value of a field to specified numeric value. + */ + public void add(float v) { _add(numberNode(v)); } + + /** + * Alternative method that we need to avoid bumping into NPE issues + * with auto-unboxing. + * + * @since 1.9 + */ + public void add(Float value) { + if (value == null) { + addNull(); + } else { + _add(numberNode(value.floatValue())); + } + } + + /** + * Method for setting value of a field to specified numeric value. + */ + public void add(double v) { _add(numberNode(v)); } + + /** + * Alternative method that we need to avoid bumping into NPE issues + * with auto-unboxing. + * + * @since 1.9 + */ + public void add(Double value) { + if (value == null) { + addNull(); + } else { + _add(numberNode(value.doubleValue())); + } + } + + /** + * Method for setting value of a field to specified numeric value. + */ + public void add(BigDecimal v) { + if (v == null) { + addNull(); + } else { + _add(numberNode(v)); + } + } + + /** + * Method for setting value of a field to specified String value. + */ + public void add(String v) { + if (v == null) { + addNull(); + } else { + _add(textNode(v)); + } + } + + /** + * Method for setting value of a field to specified String value. + */ + public void add(boolean v) { _add(booleanNode(v)); } + + /** + * Alternative method that we need to avoid bumping into NPE issues + * with auto-unboxing. + * + * @since 1.9 + */ + public void add(Boolean value) { + if (value == null) { + addNull(); + } else { + _add(booleanNode(value.booleanValue())); + } + } + + /** + * Method for setting value of a field to specified binary value + */ + public void add(byte[] v) { + if (v == null) { + addNull(); + } else { + _add(binaryNode(v)); + } + } + + public ArrayNode insertArray(int index) + { + ArrayNode n = arrayNode(); + _insert(index, n); + return n; + } + + /** + * Method that will construct an ObjectNode and add it at the end + * of this array node. + * + * @return Newly constructed ObjectNode + */ + public ObjectNode insertObject(int index) + { + ObjectNode n = objectNode(); + _insert(index, n); + return n; + } + + /** + * Method that will construct a POJONode and add it at the end + * of this array node. + */ + public void insertPOJO(int index, Object value) + { + if (value == null) { + insertNull(index); + } else { + _insert(index, POJONode(value)); + } + } + + public void insertNull(int index) + { + _insert(index, nullNode()); + } + + /** + * Method for setting value of a field to specified numeric value. + */ + public void insert(int index, int v) { _insert(index, numberNode(v)); } + + /** + * Alternative method that we need to avoid bumping into NPE issues + * with auto-unboxing. + * + * @since 1.9 + */ + public void insert(int index, Integer value) { + if (value == null) { + insertNull(index); + } else { + _insert(index, numberNode(value.intValue())); + } + } + + /** + * Method for setting value of a field to specified numeric value. + */ + public void insert(int index, long v) { _insert(index, numberNode(v)); } + + /** + * Alternative method that we need to avoid bumping into NPE issues + * with auto-unboxing. + * + * @since 1.9 + */ + public void insert(int index, Long value) { + if (value == null) { + insertNull(index); + } else { + _insert(index, numberNode(value.longValue())); + } + } + + /** + * Method for setting value of a field to specified numeric value. + */ + public void insert(int index, float v) { _insert(index, numberNode(v)); } + + /** + * Alternative method that we need to avoid bumping into NPE issues + * with auto-unboxing. + * + * @since 1.9 + */ + public void insert(int index, Float value) { + if (value == null) { + insertNull(index); + } else { + _insert(index, numberNode(value.floatValue())); + } + } + + /** + * Method for setting value of a field to specified numeric value. + */ + public void insert(int index, double v) { _insert(index, numberNode(v)); } + + /** + * Alternative method that we need to avoid bumping into NPE issues + * with auto-unboxing. + * + * @since 1.9 + */ + public void insert(int index, Double value) { + if (value == null) { + insertNull(index); + } else { + _insert(index, numberNode(value.doubleValue())); + } + } + + /** + * Method for setting value of a field to specified numeric value. + */ + public void insert(int index, BigDecimal v) { + if (v == null) { + insertNull(index); + } else { + _insert(index, numberNode(v)); + } + } + + /** + * Method for setting value of a field to specified String value. + */ + public void insert(int index, String v) { + if (v == null) { + insertNull(index); + } else { + _insert(index, textNode(v)); + } + } + + /** + * Method for setting value of a field to specified String value. + */ + public void insert(int index, boolean v) { _insert(index, booleanNode(v)); } + + /** + * Alternative method that we need to avoid bumping into NPE issues + * with auto-unboxing. + * + * @since 1.9 + */ + public void insert(int index, Boolean value) { + if (value == null) { + insertNull(index); + } else { + _insert(index, booleanNode(value.booleanValue())); + } + } + + /** + * Method for setting value of a field to specified binary value + */ + public void insert(int index, byte[] v) { + if (v == null) { + insertNull(index); + } else { + _insert(index, binaryNode(v)); + } + } + + /* + /********************************************************** + /* Package methods (for other node classes to use) + /********************************************************** + */ + + /** + * @since 1.6 + */ + protected void addContentsTo(List<JsonNode> dst) + { + if (_children != null) { + for (JsonNode n : _children) { + dst.add(n); + } + } + } + + /* + /********************************************************** + /* Standard methods + /********************************************************** + */ + + @Override + public boolean equals(Object o) + { + if (o == this) return true; + if (o == null) return false; + if (o.getClass() != getClass()) { // final class, can do this + return false; + } + ArrayNode other = (ArrayNode) o; + if (_children == null || _children.size() == 0) { + return other.size() == 0; + } + return other._sameChildren(_children); + } + + @Override + public int hashCode() + { + int hash; + if (_children == null) { + hash = 1; + } else { + hash = _children.size(); + for (JsonNode n : _children) { + if (n != null) { + hash ^= n.hashCode(); + } + } + } + return hash; + } + + + @Override + public String toString() + { + StringBuilder sb = new StringBuilder(16 + (size() << 4)); + sb.append('['); + if (_children != null) { + for (int i = 0, len = _children.size(); i < len; ++i) { + if (i > 0) { + sb.append(','); + } + sb.append(_children.get(i).toString()); + } + } + sb.append(']'); + return sb.toString(); + } + + /* + /********************************************************** + /* Internal methods + /********************************************************** + */ + + public JsonNode _set(int index, JsonNode value) + { + if (_children == null || index < 0 || index >= _children.size()) { + throw new IndexOutOfBoundsException("Illegal index "+index+", array size "+size()); + } + return _children.set(index, value); + } + + private void _add(JsonNode node) + { + if (_children == null) { + _children = new ArrayList<JsonNode>(); + } + _children.add(node); + } + + private void _insert(int index, JsonNode node) + { + if (_children == null) { + _children = new ArrayList<JsonNode>(); + _children.add(node); + return; + } + if (index < 0) { + _children.add(0, node); + } else if (index >= _children.size()) { + _children.add(node); + } else { + _children.add(index, node); + } + } + + /** + * Note: this method gets called iff <code>otherChildren</code> + * is non-empty + */ + private boolean _sameChildren(ArrayList<JsonNode> otherChildren) + { + int len = otherChildren.size(); + if (this.size() != len) { // important: call size() to handle case of null list... + return false; + } + for (int i = 0; i < len; ++i) { + if (!_children.get(i).equals(otherChildren.get(i))) { + return false; + } + } + return true; + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/node/BaseJsonNode.java b/1.9.10/src/mapper/java/org/codehaus/jackson/node/BaseJsonNode.java new file mode 100644 index 0000000..4ecad83 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/node/BaseJsonNode.java
@@ -0,0 +1,122 @@ +package org.codehaus.jackson.node; + +import java.io.IOException; +import java.util.List; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.JsonSerializableWithType; +import org.codehaus.jackson.map.SerializerProvider; +import org.codehaus.jackson.map.TypeSerializer; + +/** + * Abstract base class common to all standard {@link JsonNode} + * implementations. + * The main addition here is that we declare that sub-classes must + * implement {@link JsonSerializableWithType}. + * This simplifies object mapping + * aspects a bit, as no external serializers are needed. + */ +public abstract class BaseJsonNode + extends JsonNode + implements JsonSerializableWithType +{ + protected BaseJsonNode() { } + + /* + /********************************************************** + /* Basic definitions for non-container types + /********************************************************** + */ + + @Override + public JsonNode findValue(String fieldName) { + return null; + } + + @Override + public final JsonNode findPath(String fieldName) + { + JsonNode value = findValue(fieldName); + if (value == null) { + return MissingNode.getInstance(); + } + return value; + } + + // note: co-variant return type + @Override + public ObjectNode findParent(String fieldName) { + return null; + } + + @Override + public List<JsonNode> findValues(String fieldName, List<JsonNode> foundSoFar) { + return foundSoFar; + } + + @Override + public List<String> findValuesAsText(String fieldName, List<String> foundSoFar) { + return foundSoFar; + } + + @Override + public List<JsonNode> findParents(String fieldName, List<JsonNode> foundSoFar) { + return foundSoFar; + } + + /* + /********************************************************** + /* Support for traversal-as-stream + /********************************************************** + */ + + @Override + public JsonParser traverse() { + return new TreeTraversingParser(this); + } + + /** + * Method that can be used for efficient type detection + * when using stream abstraction for traversing nodes. + * Will return the first {@link JsonToken} that equivalent + * stream event would produce (for most nodes there is just + * one token but for structured/container types multiple) + * + * @since 1.3 + */ + @Override + public abstract JsonToken asToken(); + + /** + * @since 1.3 + */ + @Override + public JsonParser.NumberType getNumberType() { + // most types non-numeric, so: + return null; + } + + /* + /********************************************************** + /* JsonSerializable + /********************************************************** + */ + + /** + * Method called to serialize node instances using given generator. + */ + @SuppressWarnings("deprecation") + @Override + public abstract void serialize(JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonProcessingException; + + /** + * Type information is needed, even if JsonNode instances are "plain" JSON, + * since they may be mixed with other types. + */ + @Override + public abstract void serializeWithType(JsonGenerator jgen, SerializerProvider provider, + TypeSerializer typeSer) + throws IOException, JsonProcessingException; +} +
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/node/BigIntegerNode.java b/1.9.10/src/mapper/java/org/codehaus/jackson/node/BigIntegerNode.java new file mode 100644 index 0000000..ecbbecd --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/node/BigIntegerNode.java
@@ -0,0 +1,104 @@ +package org.codehaus.jackson.node; + +import java.io.IOException; +import java.math.BigDecimal; +import java.math.BigInteger; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.SerializerProvider; + +/** + * Numeric node that contains simple 64-bit integer values. + */ +public final class BigIntegerNode + extends NumericNode +{ + final protected BigInteger _value; + + /* + /********************************************************** + /* Construction + /********************************************************** + */ + + public BigIntegerNode(BigInteger v) { _value = v; } + + public static BigIntegerNode valueOf(BigInteger v) { return new BigIntegerNode(v); } + + /* + /********************************************************** + /* Overrridden JsonNode methods + /********************************************************** + */ + + @Override + public JsonToken asToken() { return JsonToken.VALUE_NUMBER_INT; } + + @Override + public JsonParser.NumberType getNumberType() { return JsonParser.NumberType.BIG_INTEGER; } + + @Override + public boolean isIntegralNumber() { return true; } + + @Override + public boolean isBigInteger() { return true; } + + @Override + public Number getNumberValue() { + return _value; + } + + @Override + public int getIntValue() { return _value.intValue(); } + + @Override + public long getLongValue() { return _value.longValue(); } + + @Override + public BigInteger getBigIntegerValue() { return _value; } + + @Override + public double getDoubleValue() { return _value.doubleValue(); } + + @Override + public BigDecimal getDecimalValue() { return new BigDecimal(_value); } + + /* + /********************************************************** + /* General type coercions + /********************************************************** + */ + + @Override + public String asText() { + return _value.toString(); + } + + @Override + public boolean asBoolean(boolean defaultValue) { + return !BigInteger.ZERO.equals(_value); + } + + @Override + public final void serialize(JsonGenerator jg, SerializerProvider provider) + throws IOException, JsonProcessingException + { + jg.writeNumber(_value); + } + + @Override + public boolean equals(Object o) + { + if (o == this) return true; + if (o == null) return false; + if (o.getClass() != getClass()) { // final class, can do this + return false; + } + return ((BigIntegerNode) o)._value.equals(_value); + } + + @Override + public int hashCode() { + return _value.hashCode(); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/node/BinaryNode.java b/1.9.10/src/mapper/java/org/codehaus/jackson/node/BinaryNode.java new file mode 100644 index 0000000..198f0b4 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/node/BinaryNode.java
@@ -0,0 +1,136 @@ +package org.codehaus.jackson.node; + +import java.io.IOException; +import java.util.Arrays; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.SerializerProvider; + +/** + * Value node that contains Base64 encoded binary value, which will be + * output and stored as Json String value. + */ +public final class BinaryNode + extends ValueNode +{ + final static BinaryNode EMPTY_BINARY_NODE = new BinaryNode(new byte[0]); + + final byte[] _data; + + /* + /********************************************************** + /* Construction + /********************************************************** + */ + + public BinaryNode(byte[] data) + { + _data = data; + } + + public BinaryNode(byte[] data, int offset, int length) + { + if (offset == 0 && length == data.length) { + _data = data; + } else { + _data = new byte[length]; + System.arraycopy(data, offset, _data, 0, length); + } + } + + public static BinaryNode valueOf(byte[] data) + { + if (data == null) { + return null; + } + if (data.length == 0) { + return EMPTY_BINARY_NODE; + } + return new BinaryNode(data); + } + + public static BinaryNode valueOf(byte[] data, int offset, int length) + { + if (data == null) { + return null; + } + if (length == 0) { + return EMPTY_BINARY_NODE; + } + return new BinaryNode(data, offset, length); + } + + /* + /********************************************************** + /* General type coercions + /********************************************************** + */ + + @Override + public JsonToken asToken() { + /* No distinct type; could use one for textual values, + * but given that it's not in text form at this point, + * embedded-object is closest + */ + return JsonToken.VALUE_EMBEDDED_OBJECT; + } + + @Override + public boolean isBinary() { return true; } + + /** + *<p> + * Note: caller is not to modify returned array in any way, since + * it is not a copy but reference to the underlying byte array. + */ + @Override + public byte[] getBinaryValue() { return _data; } + + /** + * Hmmh. This is not quite as efficient as using {@link #serialize}, + * but will work correctly. + */ + @Override + public String asText() { + return Base64Variants.getDefaultVariant().encode(_data, false); + } + + /* + /********************************************************** + /* Public API, serialization + /********************************************************** + */ + + @Override + public final void serialize(JsonGenerator jg, SerializerProvider provider) + throws IOException, JsonProcessingException + { + jg.writeBinary(_data); + } + + @Override + public boolean equals(Object o) + { + if (o == this) return true; + if (o == null) return false; + if (o.getClass() != getClass()) { // final class, can do this + return false; + } + return Arrays.equals(((BinaryNode) o)._data, _data); + } + + @Override + public int hashCode() { + return (_data == null) ? -1 : _data.length; + } + + /** + * Different from other values, since contents need to be surrounded + * by (double) quotes. + */ + @Override + public String toString() + { + return Base64Variants.getDefaultVariant().encode(_data, true); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/node/BooleanNode.java b/1.9.10/src/mapper/java/org/codehaus/jackson/node/BooleanNode.java new file mode 100644 index 0000000..8485bc7 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/node/BooleanNode.java
@@ -0,0 +1,84 @@ +package org.codehaus.jackson.node; + +import java.io.IOException; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.SerializerProvider; + +/** + * This concrete value class is used to contain boolean (true / false) + * values. Only two instances are ever created, to minimize memory + * usage + */ +public final class BooleanNode + extends ValueNode +{ + // // Just need two instances... + + public final static BooleanNode TRUE = new BooleanNode(); + public final static BooleanNode FALSE = new BooleanNode(); + + private BooleanNode() { } + + public static BooleanNode getTrue() { return TRUE; } + public static BooleanNode getFalse() { return FALSE; } + + public static BooleanNode valueOf(boolean b) { return b ? TRUE : FALSE; } + + // Interesting... two choices... + @Override public JsonToken asToken() { + return (this == TRUE) ? JsonToken.VALUE_TRUE : JsonToken.VALUE_FALSE; + } + + @Override + public boolean isBoolean() { return true; } + + @Override + public boolean getBooleanValue() { + return (this == TRUE); + } + + @Override + public String asText() { + return (this == TRUE) ? "true" : "false"; + } + + @Override + public boolean asBoolean() { + return (this == TRUE); + } + + @Override + public boolean asBoolean(boolean defaultValue) { + return (this == TRUE); + } + + @Override + public int asInt(int defaultValue) { + return (this == TRUE) ? 1 : 0; + } + @Override + public long asLong(long defaultValue) { + return (this == TRUE) ? 1L : 0L; + } + @Override + public double asDouble(double defaultValue) { + return (this == TRUE) ? 1.0 : 0.0; + } + + @Override + public final void serialize(JsonGenerator jg, SerializerProvider provider) + throws IOException, JsonProcessingException + { + jg.writeBoolean(this == TRUE); + } + + @Override + public boolean equals(Object o) + { + /* Since there are only ever two instances in existence + * can do identity comparison + */ + return (o == this); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/node/ContainerNode.java b/1.9.10/src/mapper/java/org/codehaus/jackson/node/ContainerNode.java new file mode 100644 index 0000000..f09c723 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/node/ContainerNode.java
@@ -0,0 +1,185 @@ +package org.codehaus.jackson.node; + +import java.math.BigDecimal; +import java.util.Iterator; +import java.util.List; +import java.util.NoSuchElementException; + +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.JsonToken; + +/** + * This intermediate base class is used for all container nodes, + * specifically, array and object nodes. + */ +public abstract class ContainerNode + extends BaseJsonNode +{ + /** + * We will keep a reference to the Object (usually TreeMapper) + * that can construct instances of nodes to add to this container + * node. + */ + JsonNodeFactory _nodeFactory; + + protected ContainerNode(JsonNodeFactory nc) + { + _nodeFactory = nc; + } + + @Override + public boolean isContainerNode() { return true; } + + @Override + public abstract JsonToken asToken(); + + /* NOTE: must have separate implementations since semantics have + * slight difference; deprecated method must return null, + * new method empty string. + */ + + @SuppressWarnings("deprecation") + @Override + public String getValueAsText() { return null; } + + + @Override + public String asText() { return ""; } + + /* + /********************************************************** + /* Find methods; made abstract again to ensure implementation + /********************************************************** + */ + + @Override + public abstract JsonNode findValue(String fieldName); + + @Override + public abstract ObjectNode findParent(String fieldName); + + @Override + public abstract List<JsonNode> findValues(String fieldName, List<JsonNode> foundSoFar); + + @Override + public abstract List<JsonNode> findParents(String fieldName, List<JsonNode> foundSoFar); + + @Override + public abstract List<String> findValuesAsText(String fieldName, List<String> foundSoFar); + + /* + /********************************************************** + /* Methods reset as abstract to force real implementation + /********************************************************** + */ + + @Override + public abstract int size(); + + @Override + public abstract JsonNode get(int index); + + @Override + public abstract JsonNode get(String fieldName); + + /* + /********************************************************** + /* NodeCreator implementation, just dispatch to + /* the real creator + /********************************************************** + */ + + /** + * Factory method that constructs and returns an empty {@link ArrayNode} + * Construction is done using registered {@link JsonNodeFactory}. + */ + public final ArrayNode arrayNode() { return _nodeFactory.arrayNode(); } + + /** + * Factory method that constructs and returns an empty {@link ObjectNode} + * Construction is done using registered {@link JsonNodeFactory}. + */ + public final ObjectNode objectNode() { return _nodeFactory.objectNode(); } + + public final NullNode nullNode() { return _nodeFactory.nullNode(); } + + public final BooleanNode booleanNode(boolean v) { return _nodeFactory.booleanNode(v); } + + public final NumericNode numberNode(byte v) { return _nodeFactory.numberNode(v); } + public final NumericNode numberNode(short v) { return _nodeFactory.numberNode(v); } + public final NumericNode numberNode(int v) { return _nodeFactory.numberNode(v); } + public final NumericNode numberNode(long v) { return _nodeFactory.numberNode(v); } + public final NumericNode numberNode(float v) { return _nodeFactory.numberNode(v); } + public final NumericNode numberNode(double v) { return _nodeFactory.numberNode(v); } + public final NumericNode numberNode(BigDecimal v) { return (_nodeFactory.numberNode(v)); } + + public final TextNode textNode(String text) { return _nodeFactory.textNode(text); } + + public final BinaryNode binaryNode(byte[] data) { return _nodeFactory.binaryNode(data); } + public final BinaryNode binaryNode(byte[] data, int offset, int length) { return _nodeFactory.binaryNode(data, offset, length); } + + public final POJONode POJONode(Object pojo) { return _nodeFactory.POJONode(pojo); } + + /* + /********************************************************** + /* Common mutators + /********************************************************** + */ + + /** + * Method for removing all children container has (if any) + * + * @return Container node itself (to allow method call chaining) + * + * @since 1.3 + */ + public abstract ContainerNode removeAll(); + + /* + /********************************************************** + /* Helper classes + /********************************************************** + */ + + protected static class NoNodesIterator + implements Iterator<JsonNode> + { + final static NoNodesIterator instance = new NoNodesIterator(); + + private NoNodesIterator() { } + + public static NoNodesIterator instance() { return instance; } + + @Override + public boolean hasNext() { return false; } + @Override + public JsonNode next() { throw new NoSuchElementException(); } + + @Override + public void remove() { + // could as well throw IllegalOperationException? + throw new IllegalStateException(); + } + } + + protected static class NoStringsIterator + implements Iterator<String> + { + final static NoStringsIterator instance = new NoStringsIterator(); + + private NoStringsIterator() { } + + public static NoStringsIterator instance() { return instance; } + + @Override + public boolean hasNext() { return false; } + @Override + public String next() { throw new NoSuchElementException(); } + + @Override + public void remove() { + // could as well throw IllegalOperationException? + throw new IllegalStateException(); + } + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/node/DecimalNode.java b/1.9.10/src/mapper/java/org/codehaus/jackson/node/DecimalNode.java new file mode 100644 index 0000000..a56c4d1 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/node/DecimalNode.java
@@ -0,0 +1,96 @@ +package org.codehaus.jackson.node; + +import java.io.IOException; +import java.math.BigDecimal; +import java.math.BigInteger; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.SerializerProvider; + +/** + * Numeric node that contains values that do not fit in simple + * integer (int, long) or floating point (double) values. + */ +public final class DecimalNode + extends NumericNode +{ + final protected BigDecimal _value; + + /* + /********************************************************** + /* Construction + /********************************************************** + */ + + public DecimalNode(BigDecimal v) { _value = v; } + + public static DecimalNode valueOf(BigDecimal d) { return new DecimalNode(d); } + + /* + /********************************************************** + /* BaseJsonNode extended API + /********************************************************** + */ + + @Override public JsonToken asToken() { return JsonToken.VALUE_NUMBER_FLOAT; } + + @Override + public JsonParser.NumberType getNumberType() { return JsonParser.NumberType.BIG_DECIMAL; } + + /* + /********************************************************** + /* Overrridden JsonNode methods + /********************************************************** + */ + + @Override + public boolean isFloatingPointNumber() { return true; } + + @Override + public boolean isBigDecimal() { return true; } + + @Override + public Number getNumberValue() { return _value; } + + @Override + public int getIntValue() { return _value.intValue(); } + + @Override + public long getLongValue() { return _value.longValue(); } + + + @Override + public BigInteger getBigIntegerValue() { return _value.toBigInteger(); } + + @Override + public double getDoubleValue() { return _value.doubleValue(); } + + @Override + public BigDecimal getDecimalValue() { return _value; } + + @Override + public String asText() { + return _value.toString(); + } + + @Override + public final void serialize(JsonGenerator jg, SerializerProvider provider) + throws IOException, JsonProcessingException + { + jg.writeNumber(_value); + } + + @Override + public boolean equals(Object o) + { + if (o == this) return true; + if (o == null) return false; + if (o.getClass() != getClass()) { // final class, can do this + return false; + } + return ((DecimalNode) o)._value.equals(_value); + } + + @Override + public int hashCode() { return _value.hashCode(); } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/node/DoubleNode.java b/1.9.10/src/mapper/java/org/codehaus/jackson/node/DoubleNode.java new file mode 100644 index 0000000..bf4dc20 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/node/DoubleNode.java
@@ -0,0 +1,106 @@ +package org.codehaus.jackson.node; + +import java.io.IOException; +import java.math.BigDecimal; +import java.math.BigInteger; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.io.NumberOutput; +import org.codehaus.jackson.map.SerializerProvider; + +/** + * Numeric node that contains 64-bit ("double precision") + * floating point values simple 32-bit integer values. + */ +public final class DoubleNode + extends NumericNode +{ + protected final double _value; + + /* + /********************************************************** + /* Construction + /********************************************************** + */ + + public DoubleNode(double v) { _value = v; } + + public static DoubleNode valueOf(double v) { return new DoubleNode(v); } + + /* + /********************************************************** + /* BaseJsonNode extended API + /********************************************************** + */ + + @Override public JsonToken asToken() { return JsonToken.VALUE_NUMBER_FLOAT; } + + @Override + public JsonParser.NumberType getNumberType() { return JsonParser.NumberType.DOUBLE; } + + /* + /********************************************************** + /* Overrridden JsonNode methods + /********************************************************** + */ + + @Override + public boolean isFloatingPointNumber() { return true; } + + @Override + public boolean isDouble() { return true; } + + @Override + public Number getNumberValue() { + return Double.valueOf(_value); + } + + @Override + public int getIntValue() { return (int) _value; } + + @Override + public long getLongValue() { return (long) _value; } + + @Override + public double getDoubleValue() { return _value; } + + @Override + public BigDecimal getDecimalValue() { return BigDecimal.valueOf(_value); } + + @Override + public BigInteger getBigIntegerValue() { + return getDecimalValue().toBigInteger(); + } + + @Override + public String asText() { + return NumberOutput.toString(_value); + } + + @Override + public final void serialize(JsonGenerator jg, SerializerProvider provider) + throws IOException, JsonProcessingException + { + jg.writeNumber(_value); + } + + @Override + public boolean equals(Object o) + { + if (o == this) return true; + if (o == null) return false; + if (o.getClass() != getClass()) { // final class, can do this + return false; + } + return ((DoubleNode) o)._value == _value; + } + + @Override + public int hashCode() + { + // same as hashCode Double.class uses + long l = Double.doubleToLongBits(_value); + return ((int) l) ^ (int) (l >> 32); + + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/node/IntNode.java b/1.9.10/src/mapper/java/org/codehaus/jackson/node/IntNode.java new file mode 100644 index 0000000..fed4cc9 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/node/IntNode.java
@@ -0,0 +1,122 @@ +package org.codehaus.jackson.node; + +import java.io.IOException; +import java.math.BigDecimal; +import java.math.BigInteger; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.io.NumberOutput; +import org.codehaus.jackson.map.SerializerProvider; + +/** + * Numeric node that contains simple 32-bit integer values. + */ +public final class IntNode + extends NumericNode +{ + // // // Let's cache small set of common value + + final static int MIN_CANONICAL = -1; + final static int MAX_CANONICAL = 10; + + private final static IntNode[] CANONICALS; + static { + int count = MAX_CANONICAL - MIN_CANONICAL + 1; + CANONICALS = new IntNode[count]; + for (int i = 0; i < count; ++i) { + CANONICALS[i] = new IntNode(MIN_CANONICAL + i); + } + } + + /** + * Integer value this node contains + */ + final int _value; + + /* + ************************************************ + * Construction + ************************************************ + */ + + public IntNode(int v) { _value = v; } + + public static IntNode valueOf(int i) { + if (i > MAX_CANONICAL || i < MIN_CANONICAL) return new IntNode(i); + return CANONICALS[i - MIN_CANONICAL]; + } + + /* + /********************************************************** + /* BaseJsonNode extended API + /********************************************************** + */ + + @Override public JsonToken asToken() { return JsonToken.VALUE_NUMBER_INT; } + + @Override + public JsonParser.NumberType getNumberType() { return JsonParser.NumberType.INT; } + + /* + /********************************************************** + /* Overrridden JsonNode methods + /********************************************************** + */ + + @Override + public boolean isIntegralNumber() { return true; } + + @Override + public boolean isInt() { return true; } + + @Override + public Number getNumberValue() { + return Integer.valueOf(_value); + } + + @Override + public int getIntValue() { return _value; } + + @Override + public long getLongValue() { return (long) _value; } + + @Override + public double getDoubleValue() { return (double) _value; } + + @Override + public BigDecimal getDecimalValue() { return BigDecimal.valueOf(_value); } + + @Override + public BigInteger getBigIntegerValue() { return BigInteger.valueOf(_value); } + + @Override + public String asText() { + return NumberOutput.toString(_value); + } + + @Override + public boolean asBoolean(boolean defaultValue) { + return _value != 0; + } + + @Override + public final void serialize(JsonGenerator jg, SerializerProvider provider) + throws IOException, JsonProcessingException + { + jg.writeNumber(_value); + } + + @Override + public boolean equals(Object o) + { + if (o == this) return true; + if (o == null) return false; + if (o.getClass() != getClass()) { // final class, can do this + return false; + } + return ((IntNode) o)._value == _value; + } + + @Override + public int hashCode() { return _value; } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/node/JsonNodeFactory.java b/1.9.10/src/mapper/java/org/codehaus/jackson/node/JsonNodeFactory.java new file mode 100644 index 0000000..e196c4e --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/node/JsonNodeFactory.java
@@ -0,0 +1,222 @@ +package org.codehaus.jackson.node; + +import java.math.BigDecimal; +import java.math.BigInteger; + +/** + * Base class that specifies methods for getting access to + * Node instances (newly constructed, or shared, depending + * on type), as well as basic implementation of the methods. + * Designed to be sub-classed if extended functionality (additions + * to behavior of node types, mostly) is needed. + */ +public class JsonNodeFactory +{ + /** + * Default singleton instance that construct "standard" node instances: + * given that this class is stateless, a globally shared singleton + * can be used. + */ + public final static JsonNodeFactory instance = new JsonNodeFactory(); + + protected JsonNodeFactory() { } + + /* + /********************************************************** + /* Factory methods for literal values + /********************************************************** + */ + + /** + * Factory method for getting an instance of JSON boolean value + * (either literal 'true' or 'false') + */ + public BooleanNode booleanNode(boolean v) { + return v ? BooleanNode.getTrue() : BooleanNode.getFalse(); + } + + /** + * Factory method for getting an instance of JSON null node (which + * represents literal null value) + */ + public NullNode nullNode() { return NullNode.getInstance(); } + + /* + /********************************************************** + /* Factory methods for numeric values + /********************************************************** + */ + + /** + * Factory method for getting an instance of JSON numeric value + * that expresses given 8-bit value + */ + public NumericNode numberNode(byte v) { return IntNode.valueOf(v); } + + /** + * Alternate factory method that will handle wrapper value, which may + * be null. + * Due to possibility of null, returning type is not guaranteed to be + * {@link NumericNode}, but just {@link ValueNode}. + * + * @since 1.9 + */ + public ValueNode numberNode(Byte value) { + return (value == null) ? nullNode() : IntNode.valueOf(value.intValue()); + } + + /** + * Factory method for getting an instance of JSON numeric value + * that expresses given 16-bit integer value + */ + public NumericNode numberNode(short v) { return IntNode.valueOf(v); } + + /** + * Alternate factory method that will handle wrapper value, which may + * be null. + * Due to possibility of null, returning type is not guaranteed to be + * {@link NumericNode}, but just {@link ValueNode}. + * + * @since 1.9 + */ + public ValueNode numberNode(Short value) { + return (value == null) ? nullNode() : IntNode.valueOf(value.shortValue()); + } + + /** + * Factory method for getting an instance of JSON numeric value + * that expresses given 32-bit integer value + */ + public NumericNode numberNode(int v) { return IntNode.valueOf(v); } + + /** + * Alternate factory method that will handle wrapper value, which may + * be null. + * Due to possibility of null, returning type is not guaranteed to be + * {@link NumericNode}, but just {@link ValueNode}. + * + * @since 1.9 + */ + public ValueNode numberNode(Integer value) { + return (value == null) ? nullNode() : IntNode.valueOf(value.intValue()); + } + + /** + * Factory method for getting an instance of JSON numeric value + * that expresses given 64-bit integer value + */ + public NumericNode numberNode(long v) { return LongNode.valueOf(v); } + + /** + * Alternate factory method that will handle wrapper value, which may + * be null. + * Due to possibility of null, returning type is not guaranteed to be + * {@link NumericNode}, but just {@link ValueNode}. + * + * @since 1.9 + */ + public ValueNode numberNode(Long value) { + return (value == null) ? nullNode() : LongNode.valueOf(value.longValue()); + } + + /** + * Factory method for getting an instance of JSON numeric value + * that expresses given unlimited range integer value + */ + public NumericNode numberNode(BigInteger v) { return BigIntegerNode.valueOf(v); } + + /** + * Factory method for getting an instance of JSON numeric value + * that expresses given 32-bit floating point value + */ + public NumericNode numberNode(float v) { return DoubleNode.valueOf((double) v); } + + /** + * Alternate factory method that will handle wrapper value, which may + * be null. + * Due to possibility of null, returning type is not guaranteed to be + * {@link NumericNode}, but just {@link ValueNode}. + * + * @since 1.9 + */ + public ValueNode numberNode(Float value) { + return (value == null) ? nullNode() : DoubleNode.valueOf(value.doubleValue()); + } + + /** + * Factory method for getting an instance of JSON numeric value + * that expresses given 64-bit floating point value + */ + public NumericNode numberNode(double v) { return DoubleNode.valueOf(v); } + + /** + * Alternate factory method that will handle wrapper value, which may + * be null. + * Due to possibility of null, returning type is not guaranteed to be + * {@link NumericNode}, but just {@link ValueNode}. + * + * @since 1.9 + */ + public ValueNode numberNode(Double value) { + return (value == null) ? nullNode() : DoubleNode.valueOf(value.doubleValue()); + } + + /** + * Factory method for getting an instance of JSON numeric value + * that expresses given unlimited precision floating point value + */ + public NumericNode numberNode(BigDecimal v) { return DecimalNode.valueOf(v); } + + /* + /********************************************************** + /* Factory methods for textual values + /********************************************************** + */ + + /** + * Factory method for constructing a node that represents JSON + * String value + */ + public TextNode textNode(String text) { return TextNode.valueOf(text); } + + /** + * Factory method for constructing a node that represents given + * binary data, and will get serialized as equivalent base64-encoded + * String value + */ + public BinaryNode binaryNode(byte[] data) { return BinaryNode.valueOf(data); } + + /** + * Factory method for constructing a node that represents given + * binary data, and will get serialized as equivalent base64-encoded + * String value + */ + public BinaryNode binaryNode(byte[] data, int offset, int length) { + return BinaryNode.valueOf(data, offset, length); + } + + /* + /********************************************************** + /* Factory method for structured values + /********************************************************** + */ + + /** + * Factory method for constructing an empty JSON Array node + */ + public ArrayNode arrayNode() { return new ArrayNode(this); } + + /** + * Factory method for constructing an empty JSON Object ("struct") node + */ + public ObjectNode objectNode() { return new ObjectNode(this); } + + /** + * Factory method for constructing a wrapper for POJO + * ("Plain Old Java Object") objects; these will get serialized + * using data binding, usually as JSON Objects, but in some + * cases as JSON Strings or other node types. + */ + public POJONode POJONode(Object pojo) { return new POJONode(pojo); } +} +
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/node/LongNode.java b/1.9.10/src/mapper/java/org/codehaus/jackson/node/LongNode.java new file mode 100644 index 0000000..d4c6d5b --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/node/LongNode.java
@@ -0,0 +1,99 @@ +package org.codehaus.jackson.node; + +import java.io.IOException; +import java.math.BigDecimal; +import java.math.BigInteger; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.io.NumberOutput; +import org.codehaus.jackson.map.SerializerProvider; + +/** + * Numeric node that contains simple 64-bit integer values. + */ +public final class LongNode + extends NumericNode +{ + final long _value; + + /* + ************************************************ + * Construction + ************************************************ + */ + + public LongNode(long v) { _value = v; } + + public static LongNode valueOf(long l) { return new LongNode(l); } + + /* + ************************************************ + * Overrridden JsonNode methods + ************************************************ + */ + + @Override public JsonToken asToken() { return JsonToken.VALUE_NUMBER_INT; } + + @Override + public JsonParser.NumberType getNumberType() { return JsonParser.NumberType.LONG; } + + + @Override + public boolean isIntegralNumber() { return true; } + + @Override + public boolean isLong() { return true; } + + @Override + public Number getNumberValue() { + return Long.valueOf(_value); + } + + @Override + public int getIntValue() { return (int) _value; } + + @Override + public long getLongValue() { return _value; } + + @Override + public double getDoubleValue() { return (double) _value; } + + @Override + public BigDecimal getDecimalValue() { return BigDecimal.valueOf(_value); } + + @Override + public BigInteger getBigIntegerValue() { return BigInteger.valueOf(_value); } + + @Override + public String asText() { + return NumberOutput.toString(_value); + } + + @Override + public boolean asBoolean(boolean defaultValue) { + return _value != 0; + } + + @Override + public final void serialize(JsonGenerator jg, SerializerProvider provider) + throws IOException, JsonProcessingException + { + jg.writeNumber(_value); + } + + @Override + public boolean equals(Object o) + { + if (o == this) return true; + if (o == null) return false; + if (o.getClass() != getClass()) { // final class, can do this + return false; + } + return ((LongNode) o)._value == _value; + } + + @Override + public int hashCode() { + return ((int) _value) ^ (int) (_value >> 32); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/node/MissingNode.java b/1.9.10/src/mapper/java/org/codehaus/jackson/node/MissingNode.java new file mode 100644 index 0000000..05f066d --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/node/MissingNode.java
@@ -0,0 +1,102 @@ +package org.codehaus.jackson.node; + +import java.io.IOException; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.SerializerProvider; +import org.codehaus.jackson.map.TypeSerializer; + +/** + * This singleton node class is generated to denote "missing nodes" + * along paths that do not exist. For example, if a path via + * element of an array is requested for an element outside range + * of elements in the array; or for a non-array value, result + * will be reference to this node. + *<p> + * In most respects this placeholder node will act as {@link NullNode}; + * for example, for purposes of value conversions, value is considered + * to be null and represented as value zero when used for numeric + * conversions. + */ +public final class MissingNode + extends BaseJsonNode +{ + private final static MissingNode instance = new MissingNode(); + + private MissingNode() { } + + public static MissingNode getInstance() { return instance; } + + @Override public JsonToken asToken() { return JsonToken.NOT_AVAILABLE; } + + @Override + public boolean isMissingNode() { return true; } + + // as per [JACKSON-775] + @Override + public String asText() { return ""; } + + @Override + public boolean asBoolean(boolean defaultValue) { + return defaultValue; + } + + @Override + public int asInt(int defaultValue) { + return defaultValue; + } + @Override + public long asLong(long defaultValue) { + return defaultValue; + } + @Override + public double asDouble(double defaultValue) { + return defaultValue; + } + + @Override + public JsonNode path(String fieldName) { return this; } + + @Override + public JsonNode path(int index) { return this; } + + @Override + public final void serialize(JsonGenerator jg, SerializerProvider provider) + throws IOException, JsonProcessingException + { + /* Nothing to output... should we signal an error tho? + * Chances are, this is an erroneous call. For now, let's + * not do that. + */ + jg.writeNull(); + } + + @Override + public void serializeWithType(JsonGenerator jg, SerializerProvider provider, + TypeSerializer typeSer) + throws IOException, JsonProcessingException + { + jg.writeNull(); + } + + @Override + public boolean equals(Object o) + { + /* Hmmh. Since there's just a singleton instance, this + * fails in all cases but with identity comparison. + * However: if this placeholder value was to be considered + * similar to Sql NULL, it shouldn't even equal itself? + * That might cause problems when dealing with collections + * like Sets... so for now, let's let identity comparison + * return true. + */ + return (o == this); + } + + @Override + public String toString() + { + // toString() should never return null + return ""; + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/node/NodeCursor.java b/1.9.10/src/mapper/java/org/codehaus/jackson/node/NodeCursor.java new file mode 100644 index 0000000..876028e --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/node/NodeCursor.java
@@ -0,0 +1,222 @@ +package org.codehaus.jackson.node; + +import java.util.*; + +import org.codehaus.jackson.*; + +/** + * Helper class used by {@link TreeTraversingParser} to keep track + * of current location within traversed JSON tree. + */ +abstract class NodeCursor + extends JsonStreamContext +{ + /** + * Parent cursor of this cursor, if any; null for root + * cursors. + */ + final NodeCursor _parent; + + public NodeCursor(int contextType, NodeCursor p) + { + super(); + _type = contextType; + _index = -1; + _parent = p; + } + + /* + /********************************************************** + /* JsonStreamContext impl + /********************************************************** + */ + + // note: co-variant return type + @Override + public final NodeCursor getParent() { return _parent; } + + @Override + public abstract String getCurrentName(); + + /* + /********************************************************** + /* Extended API + /********************************************************** + */ + + public abstract JsonToken nextToken(); + public abstract JsonToken nextValue(); + public abstract JsonToken endToken(); + + public abstract JsonNode currentNode(); + public abstract boolean currentHasChildren(); + + /** + * Method called to create a new context for iterating all + * contents of the current structured value (JSON array or object) + */ + public final NodeCursor iterateChildren() { + JsonNode n = currentNode(); + if (n == null) throw new IllegalStateException("No current node"); + if (n.isArray()) { // false since we have already returned START_ARRAY + return new Array(n, this); + } + if (n.isObject()) { + return new Object(n, this); + } + throw new IllegalStateException("Current node of type "+n.getClass().getName()); + } + + /* + /********************************************************** + /* Concrete implementations + /********************************************************** + */ + + /** + * Context matching root-level value nodes (i.e. anything other + * than JSON Object and Array). + * Note that context is NOT created for leaf values. + */ + protected final static class RootValue + extends NodeCursor + { + JsonNode _node; + + protected boolean _done = false; + + public RootValue(JsonNode n, NodeCursor p) { + super(JsonStreamContext.TYPE_ROOT, p); + _node = n; + } + + @Override + public String getCurrentName() { return null; } + + @Override + public JsonToken nextToken() { + if (!_done) { + _done = true; + return _node.asToken(); + } + _node = null; + return null; + } + + @Override + public JsonToken nextValue() { return nextToken(); } + @Override + public JsonToken endToken() { return null; } + @Override + public JsonNode currentNode() { return _node; } + @Override + public boolean currentHasChildren() { return false; } + } + + /** + * Cursor used for traversing non-empty JSON Array nodes + */ + protected final static class Array + extends NodeCursor + { + Iterator<JsonNode> _contents; + + JsonNode _currentNode; + + public Array(JsonNode n, NodeCursor p) { + super(JsonStreamContext.TYPE_ARRAY, p); + _contents = n.getElements(); + } + + @Override + public String getCurrentName() { return null; } + + @Override + public JsonToken nextToken() + { + if (!_contents.hasNext()) { + _currentNode = null; + return null; + } + _currentNode = _contents.next(); + return _currentNode.asToken(); + } + + @Override + public JsonToken nextValue() { return nextToken(); } + @Override + public JsonToken endToken() { return JsonToken.END_ARRAY; } + + @Override + public JsonNode currentNode() { return _currentNode; } + @Override + public boolean currentHasChildren() { + // note: ONLY to be called for container nodes + return ((ContainerNode) currentNode()).size() > 0; + } + } + + /** + * Cursor used for traversing non-empty JSON Object nodes + */ + protected final static class Object + extends NodeCursor + { + Iterator<Map.Entry<String, JsonNode>> _contents; + Map.Entry<String, JsonNode> _current; + + boolean _needEntry; + + public Object(JsonNode n, NodeCursor p) + { + super(JsonStreamContext.TYPE_OBJECT, p); + _contents = ((ObjectNode) n).getFields(); + _needEntry = true; + } + + @Override + public String getCurrentName() { + return (_current == null) ? null : _current.getKey(); + } + + @Override + public JsonToken nextToken() + { + // Need a new entry? + if (_needEntry) { + if (!_contents.hasNext()) { + _current = null; + return null; + } + _needEntry = false; + _current = _contents.next(); + return JsonToken.FIELD_NAME; + } + _needEntry = true; + return _current.getValue().asToken(); + } + + @Override + public JsonToken nextValue() + { + JsonToken t = nextToken(); + if (t == JsonToken.FIELD_NAME) { + t = nextToken(); + } + return t; + } + + @Override + public JsonToken endToken() { return JsonToken.END_OBJECT; } + + @Override + public JsonNode currentNode() { + return (_current == null) ? null : _current.getValue(); + } + @Override + public boolean currentHasChildren() { + // note: ONLY to be called for container nodes + return ((ContainerNode) currentNode()).size() > 0; + } + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/node/NullNode.java b/1.9.10/src/mapper/java/org/codehaus/jackson/node/NullNode.java new file mode 100644 index 0000000..7e652bb --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/node/NullNode.java
@@ -0,0 +1,58 @@ +package org.codehaus.jackson.node; + +import java.io.IOException; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.SerializerProvider; + +/** + * This singleton value class is used to contain explicit JSON null + * value. + */ +public final class NullNode + extends ValueNode +{ + // // Just need a fly-weight singleton + + public final static NullNode instance = new NullNode(); + + private NullNode() { } + + public static NullNode getInstance() { return instance; } + + @Override public JsonToken asToken() { return JsonToken.VALUE_NULL; } + + @Override + public boolean isNull() { return true; } + + @Override + public String asText() { + return "null"; + } + + @Override + public int asInt(int defaultValue) { + return 0; + } + @Override + public long asLong(long defaultValue) { + return 0L; + } + @Override + public double asDouble(double defaultValue) { + return 0.0; + } + + @Override + public final void serialize(JsonGenerator jg, SerializerProvider provider) + throws IOException, JsonProcessingException + { + jg.writeNull(); + } + + @Override + public boolean equals(Object o) + { + return (o == this); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/node/NumericNode.java b/1.9.10/src/mapper/java/org/codehaus/jackson/node/NumericNode.java new file mode 100644 index 0000000..68faad5 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/node/NumericNode.java
@@ -0,0 +1,72 @@ +package org.codehaus.jackson.node; + +import java.math.BigDecimal; +import java.math.BigInteger; + +import org.codehaus.jackson.JsonParser; + +/** + * Intermediate value node used for numeric nodes. + */ +public abstract class NumericNode + extends ValueNode +{ + protected NumericNode() { } + + @Override + public final boolean isNumber() { return true; } + + // // // Let's re-abstract so sub-classes handle them + + @Override + public abstract JsonParser.NumberType getNumberType(); + + @Override + public abstract Number getNumberValue(); + @Override + public abstract int getIntValue(); + @Override + public abstract long getLongValue(); + @Override + public abstract double getDoubleValue(); + @Override + public abstract BigDecimal getDecimalValue(); + @Override + public abstract BigInteger getBigIntegerValue(); + + /* + /********************************************************** + /* General type coercions + /********************************************************** + */ + + @Override + public abstract String asText(); + + @Override + public int asInt() { + return getIntValue(); + } + @Override + public int asInt(int defaultValue) { + return getIntValue(); + } + + @Override + public long asLong() { + return getLongValue(); + } + @Override + public long asLong(long defaultValue) { + return getLongValue(); + } + + @Override + public double asDouble() { + return getDoubleValue(); + } + @Override + public double asDouble(double defaultValue) { + return getDoubleValue(); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/node/ObjectNode.java b/1.9.10/src/mapper/java/org/codehaus/jackson/node/ObjectNode.java new file mode 100644 index 0000000..9f0587b --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/node/ObjectNode.java
@@ -0,0 +1,696 @@ +package org.codehaus.jackson.node; + +import java.io.IOException; +import java.math.BigDecimal; +import java.util.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.SerializerProvider; +import org.codehaus.jackson.map.TypeSerializer; + +/** + * Node that maps to JSON Object structures in JSON content. + */ +public class ObjectNode + extends ContainerNode +{ + protected LinkedHashMap<String, JsonNode> _children = null; + + public ObjectNode(JsonNodeFactory nc) { super(nc); } + + /* + /********************************************************** + /* Implementation of core JsonNode API + /********************************************************** + */ + + @Override public JsonToken asToken() { return JsonToken.START_OBJECT; } + + @Override + public boolean isObject() { return true; } + + @Override + public int size() { + return (_children == null) ? 0 : _children.size(); + } + + @Override + public Iterator<JsonNode> getElements() + { + return (_children == null) ? NoNodesIterator.instance() : _children.values().iterator(); + } + + @Override + public JsonNode get(int index) { return null; } + + @Override + public JsonNode get(String fieldName) + { + if (_children != null) { + return _children.get(fieldName); + } + return null; + } + + @Override + public Iterator<String> getFieldNames() + { + return (_children == null) ? NoStringsIterator.instance() : _children.keySet().iterator(); + } + + @Override + public JsonNode path(int index) + { + return MissingNode.getInstance(); + } + + @Override + public JsonNode path(String fieldName) + { + if (_children != null) { + JsonNode n = _children.get(fieldName); + if (n != null) { + return n; + } + } + return MissingNode.getInstance(); + } + + /** + * Method to use for accessing all fields (with both names + * and values) of this JSON Object. + */ + @Override + public Iterator<Map.Entry<String, JsonNode>> getFields() + { + if (_children == null) { + return NoFieldsIterator.instance; + } + return _children.entrySet().iterator(); + } + + @Override + public ObjectNode with(String propertyName) + { + if (_children == null) { + _children = new LinkedHashMap<String, JsonNode>(); + } else { + JsonNode n = _children.get(propertyName); + if (n != null) { + if (n instanceof ObjectNode) { + return (ObjectNode) n; + } + throw new UnsupportedOperationException("Property '"+propertyName + +"' has value that is not of type ObjectNode (but " + +n.getClass().getName()+")"); + } + } + ObjectNode result = objectNode(); + _children.put(propertyName, result); + return result; + } + + /* + /********************************************************** + /* Public API, finding value nodes + /********************************************************** + */ + + @Override + public JsonNode findValue(String fieldName) + { + if (_children != null) { + for (Map.Entry<String, JsonNode> entry : _children.entrySet()) { + if (fieldName.equals(entry.getKey())) { + return entry.getValue(); + } + JsonNode value = entry.getValue().findValue(fieldName); + if (value != null) { + return value; + } + } + } + return null; + } + + @Override + public List<JsonNode> findValues(String fieldName, List<JsonNode> foundSoFar) + { + if (_children != null) { + for (Map.Entry<String, JsonNode> entry : _children.entrySet()) { + if (fieldName.equals(entry.getKey())) { + if (foundSoFar == null) { + foundSoFar = new ArrayList<JsonNode>(); + } + foundSoFar.add(entry.getValue()); + } else { // only add children if parent not added + foundSoFar = entry.getValue().findValues(fieldName, foundSoFar); + } + } + } + return foundSoFar; + } + + @Override + public List<String> findValuesAsText(String fieldName, List<String> foundSoFar) + { + if (_children != null) { + for (Map.Entry<String, JsonNode> entry : _children.entrySet()) { + if (fieldName.equals(entry.getKey())) { + if (foundSoFar == null) { + foundSoFar = new ArrayList<String>(); + } + foundSoFar.add(entry.getValue().asText()); + } else { // only add children if parent not added + foundSoFar = entry.getValue().findValuesAsText(fieldName, foundSoFar); + } + } + } + return foundSoFar; + } + + @Override + public ObjectNode findParent(String fieldName) + { + if (_children != null) { + for (Map.Entry<String, JsonNode> entry : _children.entrySet()) { + if (fieldName.equals(entry.getKey())) { + return this; + } + JsonNode value = entry.getValue().findParent(fieldName); + if (value != null) { + return (ObjectNode) value; + } + } + } + return null; + } + + @Override + public List<JsonNode> findParents(String fieldName, List<JsonNode> foundSoFar) + { + if (_children != null) { + for (Map.Entry<String, JsonNode> entry : _children.entrySet()) { + if (fieldName.equals(entry.getKey())) { + if (foundSoFar == null) { + foundSoFar = new ArrayList<JsonNode>(); + } + foundSoFar.add(this); + } else { // only add children if parent not added + foundSoFar = entry.getValue().findParents(fieldName, foundSoFar); + } + } + } + return foundSoFar; + } + + /* + /********************************************************** + /* Public API, serialization + /********************************************************** + */ + + /** + * Method that can be called to serialize this node and + * all of its descendants using specified JSON generator. + */ + @Override + public final void serialize(JsonGenerator jg, SerializerProvider provider) + throws IOException, JsonProcessingException + { + jg.writeStartObject(); + if (_children != null) { + for (Map.Entry<String, JsonNode> en : _children.entrySet()) { + jg.writeFieldName(en.getKey()); + /* 17-Feb-2009, tatu: Can we trust that all nodes will always + * extend BaseJsonNode? Or if not, at least implement + * JsonSerializable? Let's start with former, change if + * we must. + */ + ((BaseJsonNode) en.getValue()).serialize(jg, provider); + } + } + jg.writeEndObject(); + } + + @Override + public void serializeWithType(JsonGenerator jg, SerializerProvider provider, + TypeSerializer typeSer) + throws IOException, JsonProcessingException + { + typeSer.writeTypePrefixForObject(this, jg); + if (_children != null) { + for (Map.Entry<String, JsonNode> en : _children.entrySet()) { + jg.writeFieldName(en.getKey()); + ((BaseJsonNode) en.getValue()).serialize(jg, provider); + } + } + typeSer.writeTypeSuffixForObject(this, jg); + } + + /* + /********************************************************** + /* Extended ObjectNode API, mutators, generic + /********************************************************** + */ + + /** + * Method that will set specified field, replacing old value, + * if any. + * + * @param value to set field to; if null, will be converted + * to a {@link NullNode} first (to remove field entry, call + * {@link #remove} instead) + * + * @return Old value of the field, if any; null if there was no + * old value. + */ + public JsonNode put(String fieldName, JsonNode value) + { + if (value == null) { // let's not store 'raw' nulls but nodes + value = nullNode(); + } + return _put(fieldName, value); + } + + /** + * Method for removing field entry from this ObjectNode. + * Will return value of the field, if such field existed; + * null if not. + */ + public JsonNode remove(String fieldName) + { + if (_children != null) { + return _children.remove(fieldName); + } + return null; + } + + /** + * Method for removing specified field properties out of + * this ObjectNode. + * + * @param fieldNames Names of fields to remove + * + * @return This ObjectNode after removing entries + * + * @since 1.6 + */ + public ObjectNode remove(Collection<String> fieldNames) + { + if (_children != null) { + for (String fieldName : fieldNames) { + _children.remove(fieldName); + } + } + return this; + } + + /** + * Method for removing all field properties, such that this + * ObjectNode will contain no properties after call. + */ + @Override + public ObjectNode removeAll() + { + _children = null; + return this; + } + + /** + * Method for adding given properties to this object node, overriding + * any existing values for those properties. + * + * @param properties Properties to add + * + * @return This node (to allow chaining) + * + * @since 1.3 + */ + public JsonNode putAll(Map<String,JsonNode> properties) + { + if (_children == null) { + _children = new LinkedHashMap<String, JsonNode>(properties); + } else { + for (Map.Entry<String, JsonNode> en : properties.entrySet()) { + JsonNode n = en.getValue(); + if (n == null) { + n = nullNode(); + } + _children.put(en.getKey(), n); + } + } + return this; + } + + /** + * Method for adding all properties of the given Object, overriding + * any existing values for those properties. + * + * @param other Object of which properties to add to this object + * + * @return This node (to allow chaining) + * + * @since 1.3 + */ + public JsonNode putAll(ObjectNode other) + { + int len = other.size(); + if (len > 0) { + if (_children == null) { + _children = new LinkedHashMap<String, JsonNode>(len); + } + other.putContentsTo(_children); + } + return this; + } + + /** + * Method for removing all field properties out of this ObjectNode + * <b>except</b> for ones specified in argument. + * + * @param fieldNames Fields to <b>retain</b> in this ObjectNode + * + * @return This ObjectNode (to allow call chaining) + * + * @since 1.6 + */ + public ObjectNode retain(Collection<String> fieldNames) + { + if (_children != null) { + Iterator<Map.Entry<String,JsonNode>> entries = _children.entrySet().iterator(); + while (entries.hasNext()) { + Map.Entry<String, JsonNode> entry = entries.next(); + if (!fieldNames.contains(entry.getKey())) { + entries.remove(); + } + } + } + return this; + } + + /** + * Method for removing all field properties out of this ObjectNode + * <b>except</b> for ones specified in argument. + * + * @param fieldNames Fields to <b>retain</b> in this ObjectNode + * + * @return This ObjectNode (to allow call chaining) + * + * @since 1.6 + */ + public ObjectNode retain(String... fieldNames) { + return retain(Arrays.asList(fieldNames)); + } + + /* + /********************************************************** + /* Extended ObjectNode API, mutators, typed + /********************************************************** + */ + + /** + * Method that will construct an ArrayNode and add it as a + * field of this ObjectNode, replacing old value, if any. + * + * @return Newly constructed ArrayNode (NOT the old value, + * which could be of any type) + */ + public ArrayNode putArray(String fieldName) + { + ArrayNode n = arrayNode(); + _put(fieldName, n); + return n; + } + + /** + * Method that will construct an ObjectNode and add it as a + * field of this ObjectNode, replacing old value, if any. + * + * @return Newly constructed ObjectNode (NOT the old value, + * which could be of any type) + */ + public ObjectNode putObject(String fieldName) + { + ObjectNode n = objectNode(); + _put(fieldName, n); + return n; + } + + public void putPOJO(String fieldName, Object pojo) + { + _put(fieldName, POJONode(pojo)); + } + + public void putNull(String fieldName) + { + _put(fieldName, nullNode()); + } + + /** + * Method for setting value of a field to specified numeric value. + */ + public void put(String fieldName, int v) { _put(fieldName, numberNode(v)); } + + /** + * Alternative method that we need to avoid bumping into NPE issues + * with auto-unboxing. + * + * @since 1.9 + */ + public void put(String fieldName, Integer value) { + if (value == null) { + _put(fieldName, nullNode()); + } else { + _put(fieldName, numberNode(value.intValue())); + } + } + + /** + * Method for setting value of a field to specified numeric value. + */ + public void put(String fieldName, long v) { _put(fieldName, numberNode(v)); } + + /** + * Alternative method that we need to avoid bumping into NPE issues + * with auto-unboxing. + * + * @since 1.9 + */ + public void put(String fieldName, Long value) { + if (value == null) { + _put(fieldName, nullNode()); + } else { + _put(fieldName, numberNode(value.longValue())); + } + } + + /** + * Method for setting value of a field to specified numeric value. + */ + public void put(String fieldName, float v) { _put(fieldName, numberNode(v)); } + + /** + * Alternative method that we need to avoid bumping into NPE issues + * with auto-unboxing. + * + * @since 1.9 + */ + public void put(String fieldName, Float value) { + if (value == null) { + _put(fieldName, nullNode()); + } else { + _put(fieldName, numberNode(value.floatValue())); + } + } + + /** + * Method for setting value of a field to specified numeric value. + */ + public void put(String fieldName, double v) { _put(fieldName, numberNode(v)); } + + /** + * Alternative method that we need to avoid bumping into NPE issues + * with auto-unboxing. + * + * @since 1.9 + */ + public void put(String fieldName, Double value) { + if (value == null) { + _put(fieldName, nullNode()); + } else { + _put(fieldName, numberNode(value.doubleValue())); + } + } + + /** + * Method for setting value of a field to specified numeric value. + */ + public void put(String fieldName, BigDecimal v) { + if (v == null) { + putNull(fieldName); + } else { + _put(fieldName, numberNode(v)); + } + } + + /** + * Method for setting value of a field to specified String value. + */ + public void put(String fieldName, String v) { + if (v == null) { + putNull(fieldName); + } else { + _put(fieldName, textNode(v)); + } + } + + /** + * Method for setting value of a field to specified String value. + */ + public void put(String fieldName, boolean v) { _put(fieldName, booleanNode(v)); } + + /** + * Alternative method that we need to avoid bumping into NPE issues + * with auto-unboxing. + * + * @since 1.9 + */ + public void put(String fieldName, Boolean value) { + if (value == null) { + _put(fieldName, nullNode()); + } else { + _put(fieldName, booleanNode(value.booleanValue())); + } + } + + /** + * Method for setting value of a field to specified binary value + */ + public void put(String fieldName, byte[] v) { + if (v == null) { + _put(fieldName, nullNode()); + } else { + _put(fieldName, binaryNode(v)); + } + } + + /* + /********************************************************** + /* Package methods (for other node classes to use) + /********************************************************** + */ + + /** + * @since 1.6 + */ + protected void putContentsTo(Map<String,JsonNode> dst) + { + if (_children != null) { + for (Map.Entry<String,JsonNode> en : _children.entrySet()) { + dst.put(en.getKey(), en.getValue()); + } + } + } + + /* + /********************************************************** + /* Standard methods + /********************************************************** + */ + + @Override + public boolean equals(Object o) + { + if (o == this) return true; + if (o == null) return false; + if (o.getClass() != getClass()) { + return false; + } + ObjectNode other = (ObjectNode) o; + if (other.size() != size()) { + return false; + } + if (_children != null) { + for (Map.Entry<String, JsonNode> en : _children.entrySet()) { + String key = en.getKey(); + JsonNode value = en.getValue(); + + JsonNode otherValue = other.get(key); + + if (otherValue == null || !otherValue.equals(value)) { + return false; + } + } + } + return true; + } + + @Override + public int hashCode() + { + return (_children == null) ? -1 : _children.hashCode(); + } + + @Override + public String toString() + { + StringBuilder sb = new StringBuilder(32 + (size() << 4)); + sb.append("{"); + if (_children != null) { + int count = 0; + for (Map.Entry<String, JsonNode> en : _children.entrySet()) { + if (count > 0) { + sb.append(","); + } + ++count; + TextNode.appendQuoted(sb, en.getKey()); + sb.append(':'); + sb.append(en.getValue().toString()); + } + } + sb.append("}"); + return sb.toString(); + } + + /* + /********************************************************** + /* Internal methods + /********************************************************** + */ + + private final JsonNode _put(String fieldName, JsonNode value) + { + if (_children == null) { + _children = new LinkedHashMap<String, JsonNode>(); + } + return _children.put(fieldName, value); + } + + /* + /********************************************************** + /* Helper classes + /********************************************************** + */ + + /** + * For efficiency, let's share the "no fields" iterator... + */ + protected static class NoFieldsIterator + implements Iterator<Map.Entry<String, JsonNode>> + { + final static NoFieldsIterator instance = new NoFieldsIterator(); + + private NoFieldsIterator() { } + + @Override + public boolean hasNext() { return false; } + @Override + public Map.Entry<String,JsonNode> next() { throw new NoSuchElementException(); } + + @Override + public void remove() { // or IllegalOperationException? + throw new IllegalStateException(); + } + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/node/POJONode.java b/1.9.10/src/mapper/java/org/codehaus/jackson/node/POJONode.java new file mode 100644 index 0000000..4f45a67 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/node/POJONode.java
@@ -0,0 +1,145 @@ +package org.codehaus.jackson.node; + +import java.io.IOException; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.SerializerProvider; + +/** + * Value node that contains a wrapped POJO, to be serialized as + * a JSON constructed through data mapping (usually done by + * calling {@link org.codehaus.jackson.map.ObjectMapper}). + */ +public final class POJONode + extends ValueNode +{ + protected final Object _value; + + public POJONode(Object v) { _value = v; } + + /* + /********************************************************** + /* Base class overrides + /********************************************************** + */ + + @Override public JsonToken asToken() { return JsonToken.VALUE_EMBEDDED_OBJECT; } + + @Override + public boolean isPojo() { return true; } + + @Override + public byte[] getBinaryValue() + throws IOException + { + if (_value instanceof byte[]) { + return (byte[]) _value; + } + return super.getBinaryValue(); + } + + /* + /********************************************************** + /* General type coercions + /********************************************************** + */ + + @Override + public String asText() { + return (_value == null) ? "null" : _value.toString(); + } + + @Override + public boolean asBoolean(boolean defaultValue) + { + if (_value != null && _value instanceof Boolean) { + return ((Boolean) _value).booleanValue(); + } + return defaultValue; + } + + @Override + public int asInt(int defaultValue) + { + if (_value instanceof Number) { + return ((Number) _value).intValue(); + } + return defaultValue; + } + + @Override + public long asLong(long defaultValue) + { + if (_value instanceof Number) { + return ((Number) _value).longValue(); + } + return defaultValue; + } + + @Override + public double asDouble(double defaultValue) + { + if (_value instanceof Number) { + return ((Number) _value).doubleValue(); + } + return defaultValue; + } + + /* + /********************************************************** + /* Public API, serialization + /********************************************************** + */ + + @Override + public final void serialize(JsonGenerator jg, SerializerProvider provider) + throws IOException, JsonProcessingException + { + if (_value == null) { + jg.writeNull(); + } else { + jg.writeObject(_value); + } + } + + /* + /********************************************************** + /* Extended API + /********************************************************** + */ + + /** + * Method that can be used to access the POJO this node wraps. + */ + public Object getPojo() { return _value; } + + /* + /********************************************************** + /* Overridden standard methods + /********************************************************** + */ + + @Override + public boolean equals(Object o) + { + if (o == this) return true; + if (o == null) return false; + if (o.getClass() != getClass()) { // final class, can do this + return false; + } + POJONode other = (POJONode) o; + if (_value == null) { + return other._value == null; + } + return _value.equals(other._value); + } + + @Override + public int hashCode() { return _value.hashCode(); } + + @Override + public String toString() + { + return String.valueOf(_value); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/node/TextNode.java b/1.9.10/src/mapper/java/org/codehaus/jackson/node/TextNode.java new file mode 100644 index 0000000..320f172 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/node/TextNode.java
@@ -0,0 +1,299 @@ +package org.codehaus.jackson.node; + +import java.io.IOException; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.SerializerProvider; +import org.codehaus.jackson.io.NumberInput; +import org.codehaus.jackson.util.ByteArrayBuilder; +import org.codehaus.jackson.util.CharTypes; + +/** + * Value node that contains a text value. + */ +public final class TextNode + extends ValueNode +{ + final static int INT_SPACE = ' '; + + final static TextNode EMPTY_STRING_NODE = new TextNode(""); + + final String _value; + + public TextNode(String v) { _value = v; } + + /** + * Factory method that should be used to construct instances. + * For some common cases, can reuse canonical instances: currently + * this is the case for empty Strings, in future possible for + * others as well. If null is passed, will return null. + * + * @return Resulting {@link TextNode} object, if <b>v</b> + * is NOT null; null if it is. + */ + public static TextNode valueOf(String v) + { + if (v == null) { + return null; + } + if (v.length() == 0) { + return EMPTY_STRING_NODE; + } + return new TextNode(v); + } + + @Override public JsonToken asToken() { return JsonToken.VALUE_STRING; } + + /** + * Yes indeed it is textual + */ + @Override + public boolean isTextual() { return true; } + + @Override + public String getTextValue() { + return _value; + } + + /** + * Method for accessing textual contents assuming they were + * base64 encoded; if so, they are decoded and resulting binary + * data is returned. + */ + public byte[] getBinaryValue(Base64Variant b64variant) + throws IOException + { + ByteArrayBuilder builder = new ByteArrayBuilder(100); + final String str = _value; + int ptr = 0; + int len = str.length(); + + main_loop: + while (ptr < len) { + // first, we'll skip preceding white space, if any + char ch; + do { + ch = str.charAt(ptr++); + if (ptr >= len) { + break main_loop; + } + } while (ch <= INT_SPACE); + int bits = b64variant.decodeBase64Char(ch); + if (bits < 0) { + _reportInvalidBase64(b64variant, ch, 0); + } + int decodedData = bits; + // then second base64 char; can't get padding yet, nor ws + if (ptr >= len) { + _reportBase64EOF(); + } + ch = str.charAt(ptr++); + bits = b64variant.decodeBase64Char(ch); + if (bits < 0) { + _reportInvalidBase64(b64variant, ch, 1); + } + decodedData = (decodedData << 6) | bits; + // third base64 char; can be padding, but not ws + if (ptr >= len) { + // but as per [JACKSON-631] can be end-of-input, iff not using padding + if (!b64variant.usesPadding()) { + // Got 12 bits, only need 8, need to shift + decodedData >>= 4; + builder.append(decodedData); + break; + } + _reportBase64EOF(); + } + ch = str.charAt(ptr++); + bits = b64variant.decodeBase64Char(ch); + + // First branch: can get padding (-> 1 byte) + if (bits < 0) { + if (bits != Base64Variant.BASE64_VALUE_PADDING) { + _reportInvalidBase64(b64variant, ch, 2); + } + // Ok, must get padding + if (ptr >= len) { + _reportBase64EOF(); + } + ch = str.charAt(ptr++); + if (!b64variant.usesPaddingChar(ch)) { + _reportInvalidBase64(b64variant, ch, 3, "expected padding character '"+b64variant.getPaddingChar()+"'"); + } + // Got 12 bits, only need 8, need to shift + decodedData >>= 4; + builder.append(decodedData); + continue; + } + // Nope, 2 or 3 bytes + decodedData = (decodedData << 6) | bits; + // fourth and last base64 char; can be padding, but not ws + if (ptr >= len) { + // but as per [JACKSON-631] can be end-of-input, iff not using padding + if (!b64variant.usesPadding()) { + decodedData >>= 2; + builder.appendTwoBytes(decodedData); + break; + } + _reportBase64EOF(); + } + ch = str.charAt(ptr++); + bits = b64variant.decodeBase64Char(ch); + if (bits < 0) { + if (bits != Base64Variant.BASE64_VALUE_PADDING) { + _reportInvalidBase64(b64variant, ch, 3); + } + decodedData >>= 2; + builder.appendTwoBytes(decodedData); + } else { + // otherwise, our triple is now complete + decodedData = (decodedData << 6) | bits; + builder.appendThreeBytes(decodedData); + } + } + return builder.toByteArray(); + } + + @Override + public byte[] getBinaryValue() throws IOException + { + return getBinaryValue(Base64Variants.getDefaultVariant()); + } + + /* + /********************************************************** + /* General type coercions + /********************************************************** + */ + + @Override + public String asText() { + return _value; + } + + // note: neither fast nor elegant, but these work for now: + + @Override + public boolean asBoolean(boolean defaultValue) { + if (_value != null) { + if ("true".equals(_value.trim())) { + return true; + } + } + return defaultValue; + } + + @Override + public int asInt(int defaultValue) { + return NumberInput.parseAsInt(_value, defaultValue); + } + + @Override + public long asLong(long defaultValue) { + return NumberInput.parseAsLong(_value, defaultValue); + } + + @Override + public double asDouble(double defaultValue) { + return NumberInput.parseAsDouble(_value, defaultValue); + } + + /* + /********************************************************** + /* Serialization + /********************************************************** + */ + + @Override + public final void serialize(JsonGenerator jg, SerializerProvider provider) + throws IOException, JsonProcessingException + { + if (_value == null) { + jg.writeNull(); + } else { + jg.writeString(_value); + } + } + + /* + /********************************************************** + /* Overridden standard methods + /********************************************************** + */ + + @Override + public boolean equals(Object o) + { + if (o == this) return true; + if (o == null) return false; + if (o.getClass() != getClass()) { // final class, can do this + return false; + } + return ((TextNode) o)._value.equals(_value); + } + + @Override + public int hashCode() { return _value.hashCode(); } + + /** + * Different from other values, Strings need quoting + */ + @Override + public String toString() + { + int len = _value.length(); + len = len + 2 + (len >> 4); + StringBuilder sb = new StringBuilder(len); + appendQuoted(sb, _value); + return sb.toString(); + } + + protected static void appendQuoted(StringBuilder sb, String content) + { + sb.append('"'); + CharTypes.appendQuoted(sb, content); + sb.append('"'); + } + + /* + /********************************************************** + /* Helper methods + /********************************************************** + */ + + protected void _reportInvalidBase64(Base64Variant b64variant, char ch, int bindex) + throws JsonParseException + { + _reportInvalidBase64(b64variant, ch, bindex, null); + } + + /** + * @param bindex Relative index within base64 character unit; between 0 + * and 3 (as unit has exactly 4 characters) + */ + protected void _reportInvalidBase64(Base64Variant b64variant, char ch, int bindex, String msg) + throws JsonParseException + { + String base; + if (ch <= INT_SPACE) { + base = "Illegal white space character (code 0x"+Integer.toHexString(ch)+") as character #"+(bindex+1)+" of 4-char base64 unit: can only used between units"; + } else if (b64variant.usesPaddingChar(ch)) { + base = "Unexpected padding character ('"+b64variant.getPaddingChar()+"') as character #"+(bindex+1)+" of 4-char base64 unit: padding only legal as 3rd or 4th character"; + } else if (!Character.isDefined(ch) || Character.isISOControl(ch)) { + // Not sure if we can really get here... ? (most illegal xml chars are caught at lower level) + base = "Illegal character (code 0x"+Integer.toHexString(ch)+") in base64 content"; + } else { + base = "Illegal character '"+ch+"' (code 0x"+Integer.toHexString(ch)+") in base64 content"; + } + if (msg != null) { + base = base + ": " + msg; + } + throw new JsonParseException(base, JsonLocation.NA); + } + + protected void _reportBase64EOF() + throws JsonParseException + { + throw new JsonParseException("Unexpected end-of-String when base64 content", JsonLocation.NA); + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/node/TreeTraversingParser.java b/1.9.10/src/mapper/java/org/codehaus/jackson/node/TreeTraversingParser.java new file mode 100644 index 0000000..42586df --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/node/TreeTraversingParser.java
@@ -0,0 +1,383 @@ +package org.codehaus.jackson.node; + +import java.io.IOException; +import java.math.BigDecimal; +import java.math.BigInteger; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.impl.JsonParserMinimalBase; + +/** + * Facade over {@link JsonNode} that implements {@link JsonParser} to allow + * accessing contents of JSON tree in alternate form (stream of tokens). + * Useful when a streaming source is expected by code, such as data binding + * functionality. + * + * @author tatu + * + * @since 1.3 + */ +public class TreeTraversingParser extends JsonParserMinimalBase +{ + /* + /********************************************************** + /* Configuration + /********************************************************** + */ + + protected ObjectCodec _objectCodec; + + /** + * Traversal context within tree + */ + protected NodeCursor _nodeCursor; + + /* + /********************************************************** + /* State + /********************************************************** + */ + + /** + * Sometimes parser needs to buffer a single look-ahead token; if so, + * it'll be stored here. This is currently used for handling + */ + protected JsonToken _nextToken; + + /** + * Flag needed to handle recursion into contents of child + * Array/Object nodes. + */ + protected boolean _startContainer; + + /** + * Flag that indicates whether parser is closed or not. Gets + * set when parser is either closed by explicit call + * ({@link #close}) or when end-of-input is reached. + */ + protected boolean _closed; + + /* + /********************************************************** + /* Life-cycle + /********************************************************** + */ + + public TreeTraversingParser(JsonNode n) { this(n, null); } + + public TreeTraversingParser(JsonNode n, ObjectCodec codec) + { + super(0); + _objectCodec = codec; + if (n.isArray()) { + _nextToken = JsonToken.START_ARRAY; + _nodeCursor = new NodeCursor.Array(n, null); + } else if (n.isObject()) { + _nextToken = JsonToken.START_OBJECT; + _nodeCursor = new NodeCursor.Object(n, null); + } else { // value node + _nodeCursor = new NodeCursor.RootValue(n, null); + } + } + + @Override + public void setCodec(ObjectCodec c) { + _objectCodec = c; + } + + @Override + public ObjectCodec getCodec() { + return _objectCodec; + } + + /* + /********************************************************** + /* Closeable implementation + /********************************************************** + */ + + @Override + public void close() throws IOException + { + if (!_closed) { + _closed = true; + _nodeCursor = null; + _currToken = null; + } + } + + /* + /********************************************************** + /* Public API, traversal + /********************************************************** + */ + + @Override + public JsonToken nextToken() throws IOException, JsonParseException + { + if (_nextToken != null) { + _currToken = _nextToken; + _nextToken = null; + return _currToken; + } + // are we to descend to a container child? + if (_startContainer) { + _startContainer = false; + // minor optimization: empty containers can be skipped + if (!_nodeCursor.currentHasChildren()) { + _currToken = (_currToken == JsonToken.START_OBJECT) ? + JsonToken.END_OBJECT : JsonToken.END_ARRAY; + return _currToken; + } + _nodeCursor = _nodeCursor.iterateChildren(); + _currToken = _nodeCursor.nextToken(); + if (_currToken == JsonToken.START_OBJECT || _currToken == JsonToken.START_ARRAY) { + _startContainer = true; + } + return _currToken; + } + // No more content? + if (_nodeCursor == null) { + _closed = true; // if not already set + return null; + } + // Otherwise, next entry from current cursor + _currToken = _nodeCursor.nextToken(); + if (_currToken != null) { + if (_currToken == JsonToken.START_OBJECT || _currToken == JsonToken.START_ARRAY) { + _startContainer = true; + } + return _currToken; + } + // null means no more children; need to return end marker + _currToken = _nodeCursor.endToken(); + _nodeCursor = _nodeCursor.getParent(); + return _currToken; + } + + // default works well here: + //public JsonToken nextValue() throws IOException, JsonParseException + + @Override + public JsonParser skipChildren() throws IOException, JsonParseException + { + if (_currToken == JsonToken.START_OBJECT) { + _startContainer = false; + _currToken = JsonToken.END_OBJECT; + } else if (_currToken == JsonToken.START_ARRAY) { + _startContainer = false; + _currToken = JsonToken.END_ARRAY; + } + return this; + } + + @Override + public boolean isClosed() { + return _closed; + } + + /* + /********************************************************** + /* Public API, token accessors + /********************************************************** + */ + + @Override + public String getCurrentName() { + return (_nodeCursor == null) ? null : _nodeCursor.getCurrentName(); + } + + @Override + public JsonStreamContext getParsingContext() { + return _nodeCursor; + } + + @Override + public JsonLocation getTokenLocation() { + return JsonLocation.NA; + } + + @Override + public JsonLocation getCurrentLocation() { + return JsonLocation.NA; + } + + /* + /********************************************************** + /* Public API, access to textual content + /********************************************************** + */ + + @Override + public String getText() + { + if (_closed) { + return null; + } + // need to separate handling a bit... + switch (_currToken) { + case FIELD_NAME: + return _nodeCursor.getCurrentName(); + case VALUE_STRING: + return currentNode().getTextValue(); + case VALUE_NUMBER_INT: + case VALUE_NUMBER_FLOAT: + return String.valueOf(currentNode().getNumberValue()); + case VALUE_EMBEDDED_OBJECT: + JsonNode n = currentNode(); + if (n != null && n.isBinary()) { + // this will convert it to base64 + return n.asText(); + } + } + + return (_currToken == null) ? null : _currToken.asString(); + } + + @Override + public char[] getTextCharacters() throws IOException, JsonParseException { + return getText().toCharArray(); + } + + @Override + public int getTextLength() throws IOException, JsonParseException { + return getText().length(); + } + + @Override + public int getTextOffset() throws IOException, JsonParseException { + return 0; + } + + @Override + public boolean hasTextCharacters() { + // generally we do not have efficient access as char[], hence: + return false; + } + + /* + /********************************************************** + /* Public API, typed non-text access + /********************************************************** + */ + + //public byte getByteValue() throws IOException, JsonParseException + + @Override + public NumberType getNumberType() throws IOException, JsonParseException { + JsonNode n = currentNumericNode(); + return (n == null) ? null : n.getNumberType(); + } + + @Override + public BigInteger getBigIntegerValue() throws IOException, JsonParseException + { + return currentNumericNode().getBigIntegerValue(); + } + + @Override + public BigDecimal getDecimalValue() throws IOException, JsonParseException { + return currentNumericNode().getDecimalValue(); + } + + @Override + public double getDoubleValue() throws IOException, JsonParseException { + return currentNumericNode().getDoubleValue(); + } + + @Override + public float getFloatValue() throws IOException, JsonParseException { + return (float) currentNumericNode().getDoubleValue(); + } + + @Override + public long getLongValue() throws IOException, JsonParseException { + return currentNumericNode().getLongValue(); + } + + @Override + public int getIntValue() throws IOException, JsonParseException { + return currentNumericNode().getIntValue(); + } + + @Override + public Number getNumberValue() throws IOException, JsonParseException { + return currentNumericNode().getNumberValue(); + } + + @Override + public Object getEmbeddedObject() + { + if (!_closed) { + JsonNode n = currentNode(); + if (n != null) { + if (n.isPojo()) { + return ((POJONode) n).getPojo(); + } + if (n.isBinary()) { + return ((BinaryNode) n).getBinaryValue(); + } + } + } + return null; + } + + /* + /********************************************************** + /* Public API, typed binary (base64) access + /********************************************************** + */ + + @Override + public byte[] getBinaryValue(Base64Variant b64variant) + throws IOException, JsonParseException + { + // Multiple possibilities... + JsonNode n = currentNode(); + if (n != null) { // binary node? + byte[] data = n.getBinaryValue(); + // (or TextNode, which can also convert automatically!) + if (data != null) { + return data; + } + // Or maybe byte[] as POJO? + if (n.isPojo()) { + Object ob = ((POJONode) n).getPojo(); + if (ob instanceof byte[]) { + return (byte[]) ob; + } + } + } + // otherwise return null to mark we have no binary content + return null; + } + + /* + /********************************************************** + /* Internal methods + /********************************************************** + */ + + protected JsonNode currentNode() { + if (_closed || _nodeCursor == null) { + return null; + } + return _nodeCursor.currentNode(); + } + + protected JsonNode currentNumericNode() + throws JsonParseException + { + JsonNode n = currentNode(); + if (n == null || !n.isNumber()) { + JsonToken t = (n == null) ? null : n.asToken(); + throw _constructError("Current token ("+t+") not numeric, can not use numeric value accessors"); + } + return n; + } + + @Override + protected void _handleEOF() throws JsonParseException { + _throwInternal(); // should never get called + } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/node/ValueNode.java b/1.9.10/src/mapper/java/org/codehaus/jackson/node/ValueNode.java new file mode 100644 index 0000000..c333f5c --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/node/ValueNode.java
@@ -0,0 +1,58 @@ +package org.codehaus.jackson.node; + +import java.io.IOException; + +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.JsonToken; +import org.codehaus.jackson.map.SerializerProvider; +import org.codehaus.jackson.map.TypeSerializer; + +/** + * This intermediate base class is used for all leaf nodes, that is, + * all non-container (array or object) nodes, except for the + * "missing node". + */ +public abstract class ValueNode + extends BaseJsonNode +{ + protected ValueNode() { } + + @Override + public boolean isValueNode() { return true; } + + @Override + public abstract JsonToken asToken(); + + @Override + public void serializeWithType(JsonGenerator jg, SerializerProvider provider, + TypeSerializer typeSer) + throws IOException, JsonProcessingException + { + typeSer.writeTypePrefixForScalar(this, jg); + serialize(jg, provider); + typeSer.writeTypeSuffixForScalar(this, jg); + } + + /* + /********************************************************************** + /* Public API, path handling + /********************************************************************** + */ + + @Override + public JsonNode path(String fieldName) { return MissingNode.getInstance(); } + + @Override + public JsonNode path(int index) { return MissingNode.getInstance(); } + + /* + /********************************************************************** + /* Base impls for standard methods + /********************************************************************** + */ + + @Override + public String toString() { return asText(); } +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/node/package-info.java b/1.9.10/src/mapper/java/org/codehaus/jackson/node/package-info.java new file mode 100644 index 0000000..aa131bc --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/node/package-info.java
@@ -0,0 +1,8 @@ +/** + * Contains concrete {@link org.codehaus.jackson.JsonNode} implementations + * Jackson uses for the Tree model. + * These classes are public since concrete type will be needed + * for most operations that modify node trees. For read-only access concrete + * types are usually not needed. + */ +package org.codehaus.jackson.node;
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/schema/JsonSchema.java b/1.9.10/src/mapper/java/org/codehaus/jackson/schema/JsonSchema.java new file mode 100644 index 0000000..48e9945 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/schema/JsonSchema.java
@@ -0,0 +1,82 @@ +package org.codehaus.jackson.schema; + +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.annotate.JsonCreator; +import org.codehaus.jackson.annotate.JsonValue; +import org.codehaus.jackson.node.ObjectNode; +import org.codehaus.jackson.node.JsonNodeFactory; + +/** + * A {@link org.codehaus.jackson.JsonNode} that represents a JSON-Schema instance. + * + * @author Ryan Heaton + * @see <a href="http://json-schema.org/">JSON Schema</a> + */ +public class JsonSchema +{ + private final ObjectNode schema; + + /** + * Main constructor for schema instances. + *<p> + * This is the creator constructor used by Jackson itself when + * deserializing instances. It is so-called delegating creator, + * meaning that its argument will be bound by Jackson before + * constructor gets called. + */ + @JsonCreator + public JsonSchema(ObjectNode schema) + { + this.schema = schema; + } + + /** + * Method for accessing root JSON object of the contained schema. + *<p> + * Note: this method is specified with {@link JsonValue} annotation + * to represent serialization to use; same as if explicitly + * serializing returned object. + * + * @return Root node of the schema tree + */ + @JsonValue + public ObjectNode getSchemaNode() + { + return schema; + } + + @Override + public String toString() + { + return this.schema.toString(); + } + + @Override + public boolean equals(Object o) + { + if (o == this) return true; + if (o == null) return false; + if (!(o instanceof JsonSchema)) return false; + + JsonSchema other = (JsonSchema) o; + if (schema == null) { + return other.schema == null; + } + return schema.equals(other.schema); + } + + /** + * Get the default schema node. + * + * @return The default schema node. + */ + public static JsonNode getDefaultSchemaNode() + { + ObjectNode objectNode = JsonNodeFactory.instance.objectNode(); + objectNode.put("type", "any"); + // "required" is false by default, no need to include + //objectNode.put("required", false); + return objectNode; + } + +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/schema/JsonSerializableSchema.java b/1.9.10/src/mapper/java/org/codehaus/jackson/schema/JsonSerializableSchema.java new file mode 100644 index 0000000..1f14f6b --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/schema/JsonSerializableSchema.java
@@ -0,0 +1,46 @@ +package org.codehaus.jackson.schema; + +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Retention; +import java.lang.annotation.ElementType; +import java.lang.annotation.Target; + +import org.codehaus.jackson.annotate.JacksonAnnotation; + +/** + * Annotation that can be used to define JSON Schema definition for + * the annotated class. + *<p> + * Note that annotation is often not needed: for example, regular + * Jackson beans that Jackson can introspect can be used without + * annotations, to produce JSON schema definition. + * + * @author Ryan Heaton + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@JacksonAnnotation +public @interface JsonSerializableSchema +{ + /** + * The schema type for this JsonSerializable instance. + * Possible values: "string", "number", "boolean", "object", "array", "null", "any" + * + * @return The schema type for this JsonSerializable instance. + */ + String schemaType() default "any"; + + /** + * If the schema type is "object", the node that defines the properties of the object. + * + * @return The node representing the schema properties, or "##irrelevant" if irrelevant. + */ + String schemaObjectPropertiesDefinition() default "##irrelevant"; + + /** + * If the schema type if "array", the node that defines the schema for the items in the array. + * + * @return The schema for the items in the array, or "##irrelevant" if irrelevant. + */ + String schemaItemDefinition() default "##irrelevant"; +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/schema/SchemaAware.java b/1.9.10/src/mapper/java/org/codehaus/jackson/schema/SchemaAware.java new file mode 100644 index 0000000..79f8b8a --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/schema/SchemaAware.java
@@ -0,0 +1,25 @@ +package org.codehaus.jackson.schema; + +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.map.SerializerProvider; +import org.codehaus.jackson.map.JsonMappingException; + +import java.lang.reflect.Type; + +/** + * Marker interface for schema-aware serializers. + * + * @author Ryan Heaton + */ +public interface SchemaAware +{ + /** + * Get the representation of the schema to which this serializer will conform. + * + * @param provider The serializer provider. + * @param typeHint A hint about the type. + * @return <a href="http://json-schema.org/">Json-schema</a> for this serializer. + */ + JsonNode getSchema(SerializerProvider provider, Type typeHint) + throws JsonMappingException; +}
diff --git a/1.9.10/src/mapper/java/org/codehaus/jackson/schema/package-info.java b/1.9.10/src/mapper/java/org/codehaus/jackson/schema/package-info.java new file mode 100644 index 0000000..1ae42c0 --- /dev/null +++ b/1.9.10/src/mapper/java/org/codehaus/jackson/schema/package-info.java
@@ -0,0 +1,5 @@ +/** + * Classes needed for JSON schema support (currently just ability + * to generate schemas using serialization part of data mapping) + */ +package org.codehaus.jackson.schema;
diff --git a/1.9.10/src/maven/jackson-core-asl.pom b/1.9.10/src/maven/jackson-core-asl.pom new file mode 100644 index 0000000..7f06005 --- /dev/null +++ b/1.9.10/src/maven/jackson-core-asl.pom
@@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project> + + <!-- General information --> + + <modelVersion>4.0.0</modelVersion> + <groupId>org.codehaus.jackson</groupId> + <artifactId>jackson-core-asl</artifactId> + <packaging>jar</packaging> + <name>Jackson</name> + <version>@VERSION@</version> + <description>Jackson is a high-performance JSON processor (parser, generator) +</description> + + <!-- Contact information --> + + <url>http://jackson.codehaus.org</url> + <issueManagement> + <url>http://jira.codehaus.org/browse/JACKSON</url> + </issueManagement> + + <!-- Dependency information --> + + <dependencies> + <!-- no dependencies, for now --> + </dependencies> + + <!-- Licensing (joy!) --> + <licenses> + <license> + <name>The Apache Software License, Version 2.0</name> + <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url> + <distribution>repo</distribution> + </license> + </licenses> + + <organization> + <name>FasterXML</name> + <url>http://fasterxml.com</url> + </organization> + +</project>
diff --git a/1.9.10/src/maven/jackson-core-lgpl.pom b/1.9.10/src/maven/jackson-core-lgpl.pom new file mode 100644 index 0000000..6c608a5 --- /dev/null +++ b/1.9.10/src/maven/jackson-core-lgpl.pom
@@ -0,0 +1,40 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project> + + <!-- General information --> + + <modelVersion>4.0.0</modelVersion> + <groupId>org.codehaus.jackson</groupId> + <artifactId>jackson-core-lgpl</artifactId> + <packaging>jar</packaging> + <name>Jackson</name> + <version>@VERSION@</version> + <description>Jackson is a high-performance JSON processor (parser, generator)</description> + + <!-- Contact information --> + + <url>http://jackson.codehaus.org</url> + <issueManagement> + <url>http://jira.codehaus.org/browse/JACKSON</url> + </issueManagement> + + <!-- Dependency information --> + + <dependencies> + <!-- no dependencies, for now --> + </dependencies> + + <!-- Licensing --> + <licenses> + <license> + <name>GNU Lesser General Public License (LGPL), Version 2.1</name> + <url>http://www.fsf.org/licensing/licenses/lgpl.txt</url> + <distribution>repo</distribution> + </license> + </licenses> + + <organization> + <name>FasterXML</name> + <url>http://fasterxml.com</url> + </organization> +</project>
diff --git a/1.9.10/src/maven/jackson-jaxrs.pom b/1.9.10/src/maven/jackson-jaxrs.pom new file mode 100644 index 0000000..ff475cc --- /dev/null +++ b/1.9.10/src/maven/jackson-jaxrs.pom
@@ -0,0 +1,59 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project> + + <!-- General information --> + + <modelVersion>4.0.0</modelVersion> + <groupId>org.codehaus.jackson</groupId> + <artifactId>jackson-jaxrs</artifactId> + <packaging>jar</packaging> + <name>JAX-RS provider for JSON content type</name> + <version>@VERSION@</version> + <description>Jax-RS provider for JSON content type, based on +Jackson JSON processor's data binding functionality. +</description> + + <!-- Contact information --> + + <url>http://jackson.codehaus.org</url> + <issueManagement> + <url>http://jira.codehaus.org/browse/JACKSON</url> + </issueManagement> + + <!-- Dependency information --> + + <dependencies> + <!-- need the core Jackson core and mapper jars + --> + <dependency> + <groupId>org.codehaus.jackson</groupId> + <artifactId>jackson-core-asl</artifactId> + <version>@VERSION@</version> + </dependency> + <dependency> + <groupId>org.codehaus.jackson</groupId> + <artifactId>jackson-mapper-asl</artifactId> + <version>@VERSION@</version> + </dependency> + </dependencies> + + <!-- Licensing: ASL or GPL --> + <licenses> + <license> + <name>The Apache Software License, Version 2.0</name> + <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url> + <distribution>repo</distribution> + </license> + <license> + <name>GNU Lesser General Public License (LGPL), Version 2.1</name> + <url>http://www.fsf.org/licensing/licenses/lgpl.txt</url> + <distribution>repo</distribution> + </license> + </licenses> + + <organization> + <name>FasterXML</name> + <url>http://fasterxml.com</url> + </organization> + +</project>
diff --git a/1.9.10/src/maven/jackson-mapper-asl.pom b/1.9.10/src/maven/jackson-mapper-asl.pom new file mode 100644 index 0000000..569671d --- /dev/null +++ b/1.9.10/src/maven/jackson-mapper-asl.pom
@@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project> + + <!-- General information --> + + <modelVersion>4.0.0</modelVersion> + <groupId>org.codehaus.jackson</groupId> + <artifactId>jackson-mapper-asl</artifactId> + <packaging>jar</packaging> + <name>Data Mapper for Jackson</name> + <version>@VERSION@</version> + <description>Data Mapper package is a high-performance data binding package +built on Jackson JSON processor +</description> + + <!-- Contact information --> + + <url>http://jackson.codehaus.org</url> + <issueManagement> + <url>http://jira.codehaus.org/browse/JACKSON</url> + </issueManagement> + + <!-- Dependency information --> + + <dependencies> + <!-- need the core Jackson parser/generator jar --> + <dependency> + <groupId>org.codehaus.jackson</groupId> + <artifactId>jackson-core-asl</artifactId> + <version>@VERSION@</version> + </dependency> + </dependencies> + + <!-- Licensing (joy!) --> + <licenses> + <license> + <name>The Apache Software License, Version 2.0</name> + <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url> + <distribution>repo</distribution> + </license> + </licenses> + + <organization> + <name>FasterXML</name> + <url>http://fasterxml.com</url> + </organization> + +</project>
diff --git a/1.9.10/src/maven/jackson-mapper-lgpl.pom b/1.9.10/src/maven/jackson-mapper-lgpl.pom new file mode 100644 index 0000000..e8e459a --- /dev/null +++ b/1.9.10/src/maven/jackson-mapper-lgpl.pom
@@ -0,0 +1,48 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project> + + <!-- General information --> + + <modelVersion>4.0.0</modelVersion> + <groupId>org.codehaus.jackson</groupId> + <artifactId>jackson-mapper-lgpl</artifactId> + <packaging>jar</packaging> + <name>Data Mapper for Jackson</name> + <version>@VERSION@</version> + <description>Data Mapper package is a high-performance data binding package +built on Jackson JSON processor +</description> + + <!-- Contact information --> + + <url>http://jackson.codehaus.org</url> + <issueManagement> + <url>http://jira.codehaus.org/browse/JACKSON</url> + </issueManagement> + + <!-- Dependency information --> + + <dependencies> + <!-- need the core Jackson parser/generator jar --> + <dependency> + <groupId>org.codehaus.jackson</groupId> + <artifactId>jackson-core-lgpl</artifactId> + <version>@VERSION@</version> + </dependency> + </dependencies> + + <!-- Licensing --> + <licenses> + <license> + <name>GNU Lesser General Public License (LGPL), Version 2.1</name> + <url>http://www.fsf.org/licensing/licenses/lgpl.txt</url> + <distribution>repo</distribution> + </license> + </licenses> + + <organization> + <name>FasterXML</name> + <url>http://fasterxml.com</url> + </organization> + +</project>
diff --git a/1.9.10/src/maven/jackson-mrbean.pom b/1.9.10/src/maven/jackson-mrbean.pom new file mode 100644 index 0000000..d23b889 --- /dev/null +++ b/1.9.10/src/maven/jackson-mrbean.pom
@@ -0,0 +1,50 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project> + + <!-- General information --> + + <modelVersion>4.0.0</modelVersion> + <groupId>org.codehaus.jackson</groupId> + <artifactId>jackson-mrbean</artifactId> + <packaging>jar</packaging> + <name>Bean Materializer +</name> + <version>@VERSION@</version> + <description>Functionality for implementing interfaces and abstract types +dynamically ("bean materialization") +</description> + + <!-- Contact information --> + + <url>http://jackson.codehaus.org</url> + <issueManagement> + <url>http://jira.codehaus.org/browse/JACKSON</url> + </issueManagement> + + <!-- Dependency information --> + + <dependencies> + <!-- builds on basic Jackson mapper functionality + --> + <dependency> + <groupId>org.codehaus.jackson</groupId> + <artifactId>jackson-mapper-asl</artifactId> + <version>@VERSION@</version> + </dependency> + </dependencies> + + <!-- Licensing: BSD, due to embedded ASM code --> + <licenses> + <license> + <name>BSD</name> + <url>http://www.opensource.org/licenses/bsd-license.php</url> + <distribution>repo</distribution> + </license> + </licenses> + + <organization> + <name>FasterXML</name> + <url>http://fasterxml.com</url> + </organization> + +</project>
diff --git a/1.9.10/src/maven/jackson-smile.pom b/1.9.10/src/maven/jackson-smile.pom new file mode 100644 index 0000000..c22bad7 --- /dev/null +++ b/1.9.10/src/maven/jackson-smile.pom
@@ -0,0 +1,57 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project> + + <!-- General information --> + + <modelVersion>4.0.0</modelVersion> + <groupId>org.codehaus.jackson</groupId> + <artifactId>jackson-smile</artifactId> + <packaging>jar</packaging> + <name>Support for Smile data format ("binary infoset for JSON") +</name> + <version>@VERSION@</version> + <description>Support for efficient binary data format that can be +access same as textual JSON ("binary infoset for JSON"), using standard +Jackson abstractions: specifically, extension of JsonFactory and implementations +of JsonParser and JsonGenerator. +</description> + + <!-- Contact information --> + + <url>http://jackson.codehaus.org</url> + <issueManagement> + <url>http://jira.codehaus.org/browse/JACKSON</url> + </issueManagement> + + <!-- Dependency information --> + + <dependencies> + <!-- need the core Jackson core jar + --> + <dependency> + <groupId>org.codehaus.jackson</groupId> + <artifactId>jackson-core-asl</artifactId> + <version>@VERSION@</version> + </dependency> + </dependencies> + + <!-- Licensing: ASL or LGPL --> + <licenses> + <license> + <name>The Apache Software License, Version 2.0</name> + <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url> + <distribution>repo</distribution> + </license> + <license> + <name>GNU Lesser General Public License (LGPL), Version 2.1</name> + <url>http://www.fsf.org/licensing/licenses/lgpl.txt</url> + <distribution>repo</distribution> + </license> + </licenses> + + <organization> + <name>FasterXML</name> + <url>http://fasterxml.com</url> + </organization> + +</project>
diff --git a/1.9.10/src/maven/jackson-xc.pom b/1.9.10/src/maven/jackson-xc.pom new file mode 100644 index 0000000..6b61668 --- /dev/null +++ b/1.9.10/src/maven/jackson-xc.pom
@@ -0,0 +1,59 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project> + + <!-- General information --> + + <modelVersion>4.0.0</modelVersion> + <groupId>org.codehaus.jackson</groupId> + <artifactId>jackson-xc</artifactId> + <packaging>jar</packaging> + <name>Xml Compatibility extensions for Jackson</name> + <version>@VERSION@</version> + <description>Extensions that provide interoperability support for +Jackson JSON processor's data binding functionality. +</description> + + <!-- Contact information --> + + <url>http://jackson.codehaus.org</url> + <issueManagement> + <url>http://jira.codehaus.org/browse/JACKSON</url> + </issueManagement> + + <!-- Dependency information --> + + <dependencies> + <!-- need the core Jackson core and mapper jars + --> + <dependency> + <groupId>org.codehaus.jackson</groupId> + <artifactId>jackson-core-asl</artifactId> + <version>@VERSION@</version> + </dependency> + <dependency> + <groupId>org.codehaus.jackson</groupId> + <artifactId>jackson-mapper-asl</artifactId> + <version>@VERSION@</version> + </dependency> + </dependencies> + + <!-- Licensing: ASL or GPL --> + <licenses> + <license> + <name>The Apache Software License, Version 2.0</name> + <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url> + <distribution>repo</distribution> + </license> + <license> + <name>GNU Lesser General Public License (LGPL), Version 2.1</name> + <url>http://www.fsf.org/licensing/licenses/lgpl.txt</url> + <distribution>repo</distribution> + </license> + </licenses> + + <organization> + <name>FasterXML</name> + <url>http://fasterxml.com</url> + </organization> + +</project>
diff --git a/1.9.10/src/mrbean/java/org/codehaus/jackson/mrbean/AbstractTypeMaterializer.java b/1.9.10/src/mrbean/java/org/codehaus/jackson/mrbean/AbstractTypeMaterializer.java new file mode 100644 index 0000000..99a8868 --- /dev/null +++ b/1.9.10/src/mrbean/java/org/codehaus/jackson/mrbean/AbstractTypeMaterializer.java
@@ -0,0 +1,259 @@ +package org.codehaus.jackson.mrbean; + +import java.lang.reflect.Modifier; + +import org.codehaus.jackson.Version; +import org.codehaus.jackson.Versioned; +import org.codehaus.jackson.map.AbstractTypeResolver; +import org.codehaus.jackson.map.DeserializationConfig; +import org.codehaus.jackson.type.JavaType; +import org.codehaus.jackson.util.VersionUtil; + +/** + * Nifty class for pulling implementations of classes out of thin air. + *<p> + * ... friends call him Mister Bean... :-) + * + * @author tatu + * @author sunny + * + * @since 1.6 + */ +public class AbstractTypeMaterializer + extends AbstractTypeResolver + implements Versioned +{ + /** + * Enumeration that defines togglable features that guide + * the serialization feature. + */ + public enum Feature { + /** + * Feature that determines what happens if an "unrecognized" + * (non-getter, non-setter) abstract method is encountered: if set to + * true, will throw an exception during materialization; if false, + * will materialize method that throws exception only if called. + */ + FAIL_ON_UNMATERIALIZED_METHOD(false), + + /** + * Feature that determines what happens when attempt is made to + * generate implementation of non-public class or interface. + * If true, an exception is thrown; if false, will just quietly + * ignore attempts. + * + * @since 1.9 + */ + FAIL_ON_NON_PUBLIC_TYPES(true) + ; + + final boolean _defaultState; + + // Method that calculates bit set (flags) of all features that are enabled by default. + protected static int collectDefaults() { + int flags = 0; + for (Feature f : values()) { + if (f.enabledByDefault()) { + flags |= f.getMask(); + } + } + return flags; + } + + private Feature(boolean defaultState) { _defaultState = defaultState; } + public boolean enabledByDefault() { return _defaultState; } + public int getMask() { return (1 << ordinal()); } + } + + /** + * Bitfield (set of flags) of all Features that are enabled + * by default. + */ + protected final static int DEFAULT_FEATURE_FLAGS = Feature.collectDefaults(); + + /** + * Default package to use for generated classes. + */ + public final static String DEFAULT_PACKAGE_FOR_GENERATED = "org.codehaus.jackson.generated."; + + /** + * We will use per-materializer class loader for now; would be nice + * to find a way to reduce number of class loaders (and hence + * number of generated classes!) constructed... + */ + protected final MyClassLoader _classLoader; + + /** + * Bit set that contains all enabled features + */ + protected int _featureFlags = DEFAULT_FEATURE_FLAGS; + + /** + * Package name to use as prefix for generated classes. + */ + protected String _defaultPackage = DEFAULT_PACKAGE_FOR_GENERATED; + + /* + /********************************************************** + /* Construction, configuration + /********************************************************** + */ + + public AbstractTypeMaterializer() { + this(null); + } + + public AbstractTypeMaterializer(ClassLoader parentClassLoader) + { + if (parentClassLoader == null) { + parentClassLoader = getClass().getClassLoader(); + } + _classLoader = new MyClassLoader(parentClassLoader); + } + + /** + * Method that will return version information stored in and read from jar + * that contains this class. + * + * @since 1.6 + */ + @Override + public Version version() { + return VersionUtil.versionFor(getClass()); + } + + /** + * Method for checking whether given feature is enabled or not + */ + public final boolean isEnabled(Feature f) { + return (_featureFlags & f.getMask()) != 0; + } + + /** + * Method for enabling specified feature. + */ + public void enable(Feature f) { + _featureFlags |= f.getMask(); + } + + /** + * Method for disabling specified feature. + */ + public void disable(Feature f) { + _featureFlags &= ~f.getMask(); + } + + /** + * Method for enabling or disabling specified feature. + */ + public void set(Feature f, boolean state) + { + if (state) { + enable(f); + } else { + disable(f); + } + } + + public void setDefaultPackage(String defPkg) + { + if (!defPkg.endsWith(".")) { + defPkg = defPkg + "."; + } + _defaultPackage = defPkg; + } + + /* + /********************************************************** + /* Public API + /********************************************************** + */ + + @Override + public JavaType resolveAbstractType(DeserializationConfig config, JavaType type) + { + /* 19-Feb-2011, tatu: Future plans may include calling of this method for all kinds + * of abstract types. So as simple precaution, let's limit kinds of types we + * will try materializa implementations for. + */ + /* We won't be handling any container types (Collections, Maps and arrays), + * Throwables or enums. + */ + if (type.isContainerType() || type.isPrimitive() || type.isEnumType() || type.isThrowable()) { + return null; + } + Class<?> cls = type.getRawClass(); + /* [JACKSON-683] Fail on non-public classes, since we can't easily force + * access to such classes (unless we tried to generate impl classes in that + * package) + */ + if (!Modifier.isPublic(cls.getModifiers())) { + if (isEnabled(Feature.FAIL_ON_NON_PUBLIC_TYPES)) { + throw new IllegalArgumentException("Can not materialize implementation of "+cls+" since it is not public "); + } + return null; + } + + // might want to skip proxies, local types too... but let them be for now: + //if (intr.findTypeResolver(beanDesc.getClassInfo(), type) == null) { + return config.constructType(materializeClass(config, cls)); + } + + /* + /********************************************************** + /* Internal methods + /********************************************************** + */ + + protected Class<?> materializeClass(DeserializationConfig config, Class<?> cls) + { + // Need to have proper name mangling in future, but for now... + String newName = _defaultPackage+cls.getName(); + BeanBuilder builder = new BeanBuilder(config, cls); + byte[] bytecode = builder.implement(isEnabled(Feature.FAIL_ON_UNMATERIALIZED_METHOD)).build(newName); + Class<?> result = _classLoader.loadAndResolve(newName, bytecode, cls); + return result; + } + + /* + /********************************************************** + /* Helper classes + /********************************************************** + */ + + /** + * To support actual dynamic loading of bytecode we need a simple + * custom classloader. + */ + private static class MyClassLoader extends ClassLoader + { + public MyClassLoader(ClassLoader parent) + { + super(parent); + } + + /** + * @param targetClass Interface or abstract class that class to load should extend or + * implement + */ + public Class<?> loadAndResolve(String className, byte[] byteCode, Class<?> targetClass) + throws IllegalArgumentException + { + // First things first: just to be sure; maybe we have already loaded it? + Class<?> old = findLoadedClass(className); + if (old != null && targetClass.isAssignableFrom(old)) { + return old; + } + + Class<?> impl; + try { + impl = defineClass(className, byteCode, 0, byteCode.length); + } catch (LinkageError e) { + throw new IllegalArgumentException("Failed to load class '"+className+"': "+e.getMessage() ,e); + } + // important: must also resolve the class... + resolveClass(impl); + return impl; + } + } +}
diff --git a/1.9.10/src/mrbean/java/org/codehaus/jackson/mrbean/BeanBuilder.java b/1.9.10/src/mrbean/java/org/codehaus/jackson/mrbean/BeanBuilder.java new file mode 100644 index 0000000..b03ca0a --- /dev/null +++ b/1.9.10/src/mrbean/java/org/codehaus/jackson/mrbean/BeanBuilder.java
@@ -0,0 +1,471 @@ +package org.codehaus.jackson.mrbean; + +import java.lang.reflect.Method; +import java.util.*; + +import org.codehaus.jackson.org.objectweb.asm.*; + +import static org.codehaus.jackson.org.objectweb.asm.Opcodes.*; + +import org.codehaus.jackson.type.JavaType; +import org.codehaus.jackson.map.DeserializationConfig; +import org.codehaus.jackson.map.type.TypeFactory; + +/** + * Heavy lifter of mr Bean package: class that keeps track of logical POJO properties, + * and figures out how to create an implementation class. + * + * @since 1.6 + */ +public class BeanBuilder +{ + protected Map<String, Property> _beanProperties = new LinkedHashMap<String,Property>(); + protected LinkedHashMap<String,Method> _unsupportedMethods = new LinkedHashMap<String,Method>(); + + /** + * Abstract class or interface that the bean is created to extend or implement. + */ + protected final Class<?> _implementedType; + + protected final TypeFactory _typeFactory; + + public BeanBuilder(DeserializationConfig config, Class<?> implType) + { + _implementedType = implType; + _typeFactory = config.getTypeFactory(); + } + + /* + /********************************************************** + /* Core public API + /********************************************************** + */ + + /** + * @param failOnUnrecognized If true, and an unrecognized (non-getter, non-setter) + * method is encountered, will throw {@link IllegalArgumentException}; if false, + * will implement bogus method that will throw {@link UnsupportedOperationException} + * if called. + */ + public BeanBuilder implement(boolean failOnUnrecognized) + { + ArrayList<Class<?>> implTypes = new ArrayList<Class<?>>(); + // First: find all supertypes: + implTypes.add(_implementedType); + BeanUtil.findSuperTypes(_implementedType, Object.class, implTypes); + + for (Class<?> impl : implTypes) { + // and then find all getters, setters, and other non-concrete methods therein: + for (Method m : impl.getDeclaredMethods()) { + String methodName = m.getName(); + int argCount = m.getParameterTypes().length; + + if (argCount == 0) { // getter? + if (methodName.startsWith("get") || methodName.startsWith("is") && returnsBoolean(m)) { + addGetter(m); + continue; + } + } else if (argCount == 1 && methodName.startsWith("set")) { + addSetter(m); + continue; + } + // Otherwise, if concrete, or already handled, skip: + // !!! note: won't handle overloaded methods properly + if (BeanUtil.isConcrete(m) || _unsupportedMethods.containsKey(methodName)) { + continue; + } + if (failOnUnrecognized) { + throw new IllegalArgumentException("Unrecognized abstract method '"+methodName + +"' (not a getter or setter) -- to avoid exception, disable AbstractTypeMaterializer.Feature.FAIL_ON_UNMATERIALIZED_METHOD"); + } + _unsupportedMethods.put(methodName, m); + } + } + + return this; + } + + /** + * Method that generates byte code for class that implements abstract + * types requested so far. + * + * @param className Fully-qualified name of the class to generate + * @return Byte code Class instance built by this builder + */ + public byte[] build(String className) + { + ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); + String internalClass = getInternalClassName(className); + String implName = getInternalClassName(_implementedType.getName()); + + // muchos important: level at least 1.5 to get generics!!! + // Also: abstract class vs interface... + String superName; + if (_implementedType.isInterface()) { + superName = "java/lang/Object"; + cw.visit(V1_5, ACC_PUBLIC + ACC_SUPER, internalClass, null, + superName, new String[] { implName }); + } else { + superName = implName; + cw.visit(V1_5, ACC_PUBLIC + ACC_SUPER, internalClass, null, + implName, null); + } + cw.visitSource(className + ".java", null); + BeanBuilder.generateDefaultConstructor(cw, superName); + for (Property prop : _beanProperties.values()) { + // First: determine type to use; preferably setter (usually more explicit); otherwise getter + TypeDescription type = prop.selectType(_typeFactory); + createField(cw, prop, type); + // since some getters and/or setters may be implemented, check: + if (!prop.hasConcreteGetter()) { + createGetter(cw, internalClass, prop, type); + } + if (!prop.hasConcreteSetter()) { + createSetter(cw, internalClass, prop, type); + } + } + for (Method m : _unsupportedMethods.values()) { + createUnimplementedMethod(cw, internalClass, m); + } + cw.visitEnd(); + return cw.toByteArray(); + } + + /* + /********************************************************** + /* Internal methods, property discovery + /********************************************************** + */ + + private static String getPropertyName(String methodName) + { + int prefixLen = methodName.startsWith("is") ? 2 : 3; + String body = methodName.substring(prefixLen); + StringBuilder sb = new StringBuilder(body); + sb.setCharAt(0, Character.toLowerCase(body.charAt(0))); + return sb.toString(); + } + + private static String buildGetterName(String fieldName) { + return "get" + fieldName.substring(0, 1).toUpperCase()+ fieldName.substring(1); + } + + private static String buildSetterName(String fieldName) { + return "set" + fieldName.substring(0, 1).toUpperCase()+ fieldName.substring(1); + } + + private static String getInternalClassName(String className) { + return className.replace(".", "/"); + } + + private void addGetter(Method m) + { + Property prop = findProperty(getPropertyName(m.getName())); + // only set if not yet set; we start with super class: + if (prop.getGetter() == null) { + prop.setGetter(m); + } + } + + private void addSetter(Method m) + { + Property prop = findProperty(getPropertyName(m.getName())); + if (prop.getSetter() == null) { + prop.setSetter(m); + } + } + + private Property findProperty(String propName) + { + Property prop = _beanProperties.get(propName); + if (prop == null) { + prop = new Property(propName); + _beanProperties.put(propName, prop); + } + return prop; + } + + private final static boolean returnsBoolean(Method m) + { + Class<?> rt = m.getReturnType(); + return (rt == Boolean.class || rt == Boolean.TYPE); + } + + /* + /********************************************************** + /* Internal methods, bytecode generation + /********************************************************** + */ + + private static void generateDefaultConstructor(ClassWriter cw, String superName) + { + MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKESPECIAL, superName, "<init>", "()V"); + mv.visitInsn(RETURN); + mv.visitMaxs(0, 0); // don't care (real values: 1,1) + mv.visitEnd(); + } + + private static void createField(ClassWriter cw, Property prop, TypeDescription type) + { + String sig = type.hasGenerics() ? type.genericSignature() : null; + String desc = type.erasedSignature(); + FieldVisitor fv = cw.visitField(ACC_PUBLIC, prop.getFieldName(), desc, sig, null); + fv.visitEnd(); + } + + private static void createSetter(ClassWriter cw, String internalClassName, + Property prop, TypeDescription propertyType) + { + String methodName; + String desc; + Method setter = prop.getSetter(); + if (setter != null) { // easy, copy as is + desc = Type.getMethodDescriptor(setter); + methodName = setter.getName(); + } else { // otherwise need to explicitly construct from property type (close enough) + desc = "("+ propertyType.erasedSignature() + ")V"; + methodName = buildSetterName(prop.getName()); + } + String sig = propertyType.hasGenerics() ? ("("+propertyType.genericSignature()+")V") : null; + MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, methodName, desc, sig, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); // this + mv.visitVarInsn(propertyType.getLoadOpcode(), 1); + mv.visitFieldInsn(PUTFIELD, internalClassName, prop.getFieldName(), propertyType.erasedSignature()); + + mv.visitInsn(RETURN); + mv.visitMaxs(0, 0); // don't care (real values: 2, 2) + mv.visitEnd(); + } + + private static void createGetter(ClassWriter cw, String internalClassName, + Property prop, TypeDescription propertyType) + { + String methodName; + String desc; + Method getter = prop.getGetter(); + if (getter != null) { // easy, copy as is + desc = Type.getMethodDescriptor(getter); + methodName = getter.getName(); + } else { // otherwise need to explicitly construct from property type (close enough) + desc = "()"+propertyType.erasedSignature(); + methodName = buildGetterName(prop.getName()); + } + + String sig = propertyType.hasGenerics() ? ("()"+propertyType.genericSignature()) : null; + MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, methodName, desc, sig, null); + mv.visitCode(); + mv.visitVarInsn(ALOAD, 0); // load 'this' + mv.visitFieldInsn(GETFIELD, internalClassName, prop.getFieldName(), propertyType.erasedSignature()); + mv.visitInsn(propertyType.getReturnOpcode()); + mv.visitMaxs(0, 0); // don't care (real values: 1,1) + mv.visitEnd(); + } + + /** + * Builder for methods that just throw an exception, basically "unsupported + * operation" implementation. + */ + private static void createUnimplementedMethod(ClassWriter cw, String internalClassName, + Method method) + { + String exceptionName = getInternalClassName(UnsupportedOperationException.class.getName()); + String sig = Type.getMethodDescriptor(method); + String name = method.getName(); + // should we try to pass generic information? + MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, name, sig, null, null); + mv.visitTypeInsn(NEW, exceptionName); + mv.visitInsn(DUP); + mv.visitLdcInsn("Unimplemented method '"+name+"' (not a setter/getter, could not materialize)"); + mv.visitMethodInsn(INVOKESPECIAL, exceptionName, "<init>", "(Ljava/lang/String;)V"); + mv.visitInsn(ATHROW); + mv.visitMaxs(0, 0); // don't care (real values: 3, 1 + method.getParameterTypes().length); + mv.visitEnd(); + } + + /* + /********************************************************** + /* Helper classes + /********************************************************** + */ + + /** + * Bean that contains information about a single logical + * property, which consists of a getter and/or setter, + * and is used to generate getter, setter and matching + * backing field. + */ + private static class Property + { + protected final String _name; + protected final String _fieldName; + + protected Method _getter; + protected Method _setter; + + public Property(String name) + { + _name = name; + // Let's just prefix field name with single underscore for fun... + _fieldName = "_"+name; + } + + public String getName() { return _name; } + + public void setGetter(Method m) { _getter = m; } + public void setSetter(Method m) { _setter = m; } + + public Method getGetter() { return _getter; } + public Method getSetter() { return _setter; } + + public String getFieldName() { + return _fieldName; + } + + /* + private static boolean isConcrete(Method m) + { + return m.getModifiers() + } + */ + + public boolean hasConcreteGetter() { + return (_getter != null) && BeanUtil.isConcrete(_getter); + } + + public boolean hasConcreteSetter() { + return (_setter != null) && BeanUtil.isConcrete(_setter); + } + + private TypeDescription getterType(TypeFactory tf) + { + Class<?> context = _getter.getDeclaringClass(); + return new TypeDescription(tf.constructType(_getter.getGenericReturnType(), context)); + } + + private TypeDescription setterType(TypeFactory tf) + { + Class<?> context = _setter.getDeclaringClass(); + return new TypeDescription(tf.constructType(_setter.getGenericParameterTypes()[0], context)); + } + + public TypeDescription selectType(TypeFactory tf) + { + // First: if only know setter, or getter, use that one: + if (_getter == null) { + return setterType(tf); + } + if (_setter == null) { + return getterType(tf); + } + /* Otherwise must ensure they are compatible, choose more specific + * (most often setter - type) + */ + TypeDescription st = setterType(tf); + TypeDescription gt = getterType(tf); + TypeDescription specificType = TypeDescription.moreSpecificType(st, gt); + if (specificType == null) { // incompatible... + throw new IllegalArgumentException("Invalid property '"+getName() + +"': incompatible types for getter/setter (" + +gt+" vs "+st+")"); + + } + return specificType; + } + } + + /** + * Helper bean used to encapsulate most details of type handling + */ + private static class TypeDescription + { + private final Type _asmType; + private JavaType _jacksonType; + + /* + /********************************************************** + /* Construction + /********************************************************** + */ + + public TypeDescription(JavaType type) + { + _jacksonType = type; + _asmType = Type.getType(type.getRawClass()); + } + + /* + /********************************************************** + /* Accessors + /********************************************************** + */ + + public Class<?> getRawClass() { return _jacksonType.getRawClass(); } + + public String erasedSignature() { + return _jacksonType.getErasedSignature(); + } + + public String genericSignature() { + return _jacksonType.getGenericSignature(); + } + + /** + * @return True if type has direct generic declaration (which may need + * to be copied) + */ + public boolean hasGenerics() { + return _jacksonType.hasGenericTypes(); + } + + /* + public boolean isPrimitive() { + return _signature.length() == 1; + } + */ + + /* + public int getStoreOpcode() { + return _signatureType.getOpcode(ISTORE); + } + */ + + public int getLoadOpcode() { + return _asmType.getOpcode(ILOAD); + } + + public int getReturnOpcode() { + return _asmType.getOpcode(IRETURN); + } + + @Override + public String toString() { + return _jacksonType.toString(); + } + + /* + /********************************************************** + /* Other methods + /********************************************************** + */ + + + public static TypeDescription moreSpecificType(TypeDescription desc1, TypeDescription desc2) + { + Class<?> c1 = desc1.getRawClass(); + Class<?> c2 = desc2.getRawClass(); + + if (c1.isAssignableFrom(c2)) { // c2 more specific than c1 + return desc2; + } + if (c2.isAssignableFrom(c1)) { // c1 more specific than c2 + return desc1; + } + // not compatible, so: + return null; + } + } +}
diff --git a/1.9.10/src/mrbean/java/org/codehaus/jackson/mrbean/BeanUtil.java b/1.9.10/src/mrbean/java/org/codehaus/jackson/mrbean/BeanUtil.java new file mode 100644 index 0000000..cc0e114 --- /dev/null +++ b/1.9.10/src/mrbean/java/org/codehaus/jackson/mrbean/BeanUtil.java
@@ -0,0 +1,57 @@ +package org.codehaus.jackson.mrbean; + +import java.lang.reflect.Member; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +public class BeanUtil +{ + protected static boolean isConcrete(Member member) + { + int mod = member.getModifiers(); + return (mod & (Modifier.INTERFACE | Modifier.ABSTRACT)) == 0; + } + + /** + * Method that will find all sub-classes and implemented interfaces + * of a given class or interface. Classes are listed in order of + * precedence, starting with the immediate super-class, followed by + * interfaces class directly declares to implemented, and then recursively + * followed by parent of super-class and so forth. + * Note that <code>Object.class</code> is not included in the list + * regardless of whether <code>endBefore</code> argument is defined or not. + * + * @param endBefore Super-type to NOT include in results, if any; when + * encountered, will be ignored (and no super types are checked). + */ + public static List<Class<?>> findSuperTypes(Class<?> cls, Class<?> endBefore) + { + return findSuperTypes(cls, endBefore, new ArrayList<Class<?>>()); + } + + public static List<Class<?>> findSuperTypes(Class<?> cls, Class<?> endBefore, List<Class<?>> result) + { + _addSuperTypes(cls, endBefore, result, false); + return result; + } + + private static void _addSuperTypes(Class<?> cls, Class<?> endBefore, Collection<Class<?>> result, boolean addClassItself) + { + if (cls == endBefore || cls == null || cls == Object.class) { + return; + } + if (addClassItself) { + if (result.contains(cls)) { // already added, no need to check supers + return; + } + result.add(cls); + } + for (Class<?> intCls : cls.getInterfaces()) { + _addSuperTypes(intCls, endBefore, result, true); + } + _addSuperTypes(cls.getSuperclass(), endBefore, result, true); + } + +}
diff --git a/1.9.10/src/mrbean/java/org/codehaus/jackson/mrbean/MrBeanModule.java b/1.9.10/src/mrbean/java/org/codehaus/jackson/mrbean/MrBeanModule.java new file mode 100644 index 0000000..25d7d03 --- /dev/null +++ b/1.9.10/src/mrbean/java/org/codehaus/jackson/mrbean/MrBeanModule.java
@@ -0,0 +1,48 @@ +package org.codehaus.jackson.mrbean; + +import org.codehaus.jackson.Version; +import org.codehaus.jackson.map.Module; +import org.codehaus.jackson.mrbean.AbstractTypeMaterializer; + +public class MrBeanModule extends Module +{ + private final String NAME = "MrBeanModule"; + + // TODO: externalize + private final static Version VERSION = new Version(1, 8, 0, null); + + /** + * Configured materializer instance to register with deserializer factory. + */ + protected AbstractTypeMaterializer _materializer; + + /* + /********************************************************** + /* Life-cycle + /********************************************************** + */ + + public MrBeanModule() { + this(new AbstractTypeMaterializer()); + } + + public MrBeanModule(AbstractTypeMaterializer materializer) { + _materializer = materializer; + } + + @Override public String getModuleName() { return NAME; } + @Override public Version version() { return VERSION; } + + @Override + public void setupModule(SetupContext context) + { + // All we really need to for now is to register materializer: + context.addAbstractTypeResolver(_materializer); + } + + /* + /********************************************************** + /* Extended API, configuration + /********************************************************** + */ +}
diff --git a/1.9.10/src/mrbean/java/org/codehaus/jackson/mrbean/package-info.java b/1.9.10/src/mrbean/java/org/codehaus/jackson/mrbean/package-info.java new file mode 100644 index 0000000..2975983 --- /dev/null +++ b/1.9.10/src/mrbean/java/org/codehaus/jackson/mrbean/package-info.java
@@ -0,0 +1,6 @@ +/** + * Package that implements "interface materializer" functionality, whereby + * abstract classes and interfaces can be used as-is, and framework constructs + * implementations as needed. + */ +package org.codehaus.jackson.mrbean;
diff --git a/1.9.10/src/perf/perf/BaseReader.java b/1.9.10/src/perf/perf/BaseReader.java new file mode 100644 index 0000000..456ca65 --- /dev/null +++ b/1.9.10/src/perf/perf/BaseReader.java
@@ -0,0 +1,119 @@ +package perf; +//package org.codehaus.jackson.io; + +import java.io.*; + +import org.codehaus.jackson.io.IOContext; + +/** + * Simple basic class for optimized readers in this package; implements + * "cookie-cutter" methods that are used by all actual implementations. + */ +abstract class BaseReader + extends Reader +{ + /** + * JSON actually limits available Unicode range in the high end + * to the same as xml (to basically limit UTF-8 max byte sequence + * length to 4) + */ + final protected static int LAST_VALID_UNICODE_CHAR = 0x10FFFF; + + final protected static char NULL_CHAR = (char) 0; + final protected static char NULL_BYTE = (byte) 0; + + final protected IOContext mContext; + + protected InputStream mIn; + + protected byte[] mBuffer; + + protected int mPtr; + protected int mLength; + + /* + //////////////////////////////////////// + // Life-cycle + //////////////////////////////////////// + */ + + protected BaseReader(IOContext context, + InputStream in, byte[] buf, int ptr, int len) + { + mContext = context; + mIn = in; + mBuffer = buf; + mPtr = ptr; + mLength = len; + } + + /* + //////////////////////////////////////// + // Reader API + //////////////////////////////////////// + */ + + @Override + public void close() throws IOException + { + InputStream in = mIn; + + if (in != null) { + mIn = null; + freeBuffers(); + in.close(); + } + } + + char[] mTmpBuf = null; + + /** + * Although this method is implemented by the base class, AND it should + * never be called by main code, let's still implement it bit more + * efficiently just in case + */ + @Override + public int read() + throws IOException + { + if (mTmpBuf == null) { + mTmpBuf = new char[1]; + } + if (read(mTmpBuf, 0, 1) < 1) { + return -1; + } + return mTmpBuf[0]; + } + + /* + //////////////////////////////////////// + // Internal/package methods: + //////////////////////////////////////// + */ + + /** + * This method should be called along with (or instead of) normal + * close. After calling this method, no further reads should be tried. + * Method will try to recycle read buffers (if any). + */ + public final void freeBuffers() + { + byte[] buf = mBuffer; + if (buf != null) { + mBuffer = null; + mContext.releaseReadIOBuffer(buf); + } + } + + protected void reportBounds(char[] cbuf, int start, int len) + throws IOException + { + throw new ArrayIndexOutOfBoundsException("read(buf,"+start+","+len+"), cbuf["+cbuf.length+"]"); + } + + protected void reportStrangeStream() + throws IOException + { + throw new IOException("Strange I/O stream, returned 0 bytes on read"); + } +}
diff --git a/1.9.10/src/perf/perf/MediaItem.java b/1.9.10/src/perf/perf/MediaItem.java new file mode 100644 index 0000000..a658c1a --- /dev/null +++ b/1.9.10/src/perf/perf/MediaItem.java
@@ -0,0 +1,578 @@ +package perf; + +import java.io.IOException; +import java.util.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.annotate.JsonPropertyOrder; +import org.codehaus.jackson.io.SerializedString; + +/** + * Value class for performance tests + */ +@JsonPropertyOrder({"content", "images"}) +public class MediaItem +{ + final static SerializedString NAME_IMAGES = new SerializedString("images"); + final static SerializedString NAME_CONTENT = new SerializedString("content"); + + public enum Player { JAVA, FLASH; } + public enum Size { SMALL, LARGE; } + + private List<Photo> _photos; + private Content _content; + + public MediaItem() { } + + public MediaItem(Content c) + { + _content = c; + } + + public void addPhoto(Photo p) { + if (_photos == null) { + _photos = new ArrayList<Photo>(); + } + _photos.add(p); + } + + public List<Photo> getImages() { return _photos; } + public void setImages(List<Photo> p) { _photos = p; } + + public Content getContent() { return _content; } + public void setContent(Content c) { _content = c; } + + // Custom deser + public static MediaItem deserialize(JsonParser jp) throws IOException + { + if (jp.nextToken() != JsonToken.START_OBJECT) { + throw new IOException("Need START_OBJECT for MediaItem"); + } + MediaItem item = new MediaItem(); + while (jp.nextToken() == JsonToken.FIELD_NAME) { + String name = jp.getCurrentName(); + if (name == "images") { + item._photos = deserializeImages(jp); + } else if (name == "content") { + item._content = Content.deserialize(jp); + } else throw new IOException("Unknown field"); + } + if (jp.getCurrentToken() != JsonToken.END_OBJECT) { + throw new IOException("Need END_OBJECT to complete MediaItem"); + } + return item; + } + + private final static void failName(JsonParser jp, SerializableString str) throws IOException { + throw new IOException("Expected FIELD_NAME '"+str+"'; got "+jp.getCurrentToken()+" (name '"+jp.getCurrentName()+"')"); + } + + /* Alternate deserializer that relies on ordering (just for + * test purposes -- would not work for real-world use cases) + */ + public static MediaItem deserializeFaster(JsonParser jp) throws IOException + { + if (jp.nextToken() != JsonToken.START_OBJECT) { + throw new IOException("Need START_OBJECT for MediaItem"); + } + MediaItem item = new MediaItem(); + if (!jp.nextFieldName(NAME_CONTENT)) { + failName(jp, NAME_CONTENT); + } + item._content = Content.deserializeFaster(jp); + if (!jp.nextFieldName(NAME_IMAGES)) { + failName(jp, NAME_IMAGES); + } + item._photos = deserializeImagesFaster(jp); + if (jp.nextToken() != JsonToken.END_OBJECT) { + throw new IOException("Need END_OBJECT to complete MediaItem"); + } + return item; + } + + private static List<Photo> deserializeImages(JsonParser jp) throws IOException + { + if (jp.nextToken() != JsonToken.START_ARRAY) { + throw new IOException("Need START_ARRAY for List of Photos"); + } + ArrayList<Photo> images = new ArrayList<Photo>(4); + while (jp.nextToken() == JsonToken.START_OBJECT) { + images.add(Photo.deserialize(jp)); + } + if (jp.getCurrentToken() != JsonToken.END_ARRAY) { + throw new IOException("Need END_ARRAY to complete List of Photos"); + } + return images; + } + + private static List<Photo> deserializeImagesFaster(JsonParser jp) throws IOException + { + if (jp.nextToken() != JsonToken.START_ARRAY) { + throw new IOException("Need START_ARRAY for List of Photos"); + } + ArrayList<Photo> images = new ArrayList<Photo>(4); + while (jp.nextToken() == JsonToken.START_OBJECT) { + images.add(Photo.deserializeFaster(jp)); + } + if (jp.getCurrentToken() != JsonToken.END_ARRAY) { + throw new IOException("Need END_ARRAY to complete List of Photos"); + } + return images; + } + + // Custom serializer + public void serialize(JsonGenerator jgen) throws IOException + { + jgen.writeStartObject(); + + jgen.writeFieldName("content"); + if (_content == null) { + jgen.writeNull(); + } else { + _content.serialize(jgen); + } + if (_photos == null) { + jgen.writeNullField("images"); + } else { + jgen.writeArrayFieldStart("images"); + for (Photo photo : _photos) { + photo.serialize(jgen); + } + jgen.writeEndArray(); + } + + jgen.writeEndObject(); + } + + /* + /********************************************************** + /* Helper types + /********************************************************** + */ + + @JsonPropertyOrder({"uri","title","width","height","size"}) + public static class Photo + { + public final static int F_URI = 1; + public final static int F_TITLE = 2; + public final static int F_WIDTH = 3; + public final static int F_HEIGHT = 4; + public final static int F_SIZE = 5; + + public final static HashMap<String,Integer> sFields = new HashMap<String,Integer>(); + static { + // MediaItem fields + sFields.put("uri", F_URI); + sFields.put("title", F_TITLE); + sFields.put("width", F_WIDTH); + sFields.put("height", F_HEIGHT); + sFields.put("size", F_SIZE); + } + + final static SerializedString NAME_URI = new SerializedString("uri"); + final static SerializedString NAME_TITLE = new SerializedString("title"); + final static SerializedString NAME_WIDTH = new SerializedString("width"); + final static SerializedString NAME_HEIGHT = new SerializedString("height"); + final static SerializedString NAME_SIZE = new SerializedString("size"); + + private String _uri; + private String _title; + private int _width; + private int _height; + private Size _size; + + public Photo() {} + public Photo(String uri, String title, int w, int h, Size s) + { + _uri = uri; + _title = title; + _width = w; + _height = h; + _size = s; + } + + public String getUri() { return _uri; } + public String getTitle() { return _title; } + public int getWidth() { return _width; } + public int getHeight() { return _height; } + public Size getSize() { return _size; } + + public void setUri(String u) { _uri = u; } + public void setTitle(String t) { _title = t; } + public void setWidth(int w) { _width = w; } + public void setHeight(int h) { _height = h; } + public void setSize(Size s) { _size = s; } + + private static Size findSize(String id) + { + if (id.charAt(0) == 'L') { + if ("LARGE".equals(id)) { + return Size.LARGE; + } + } else if ("SMALL".equals(id)) { + return Size.SMALL; + } + throw new IllegalArgumentException(); + } + + public static Photo deserialize(JsonParser jp) throws IOException + { + Photo photo = new Photo(); + while (jp.nextToken() == JsonToken.FIELD_NAME) { + String name = jp.getCurrentName(); + jp.nextToken(); + Integer I = sFields.get(name); + if (I != null) { + switch (I.intValue()) { + case F_URI: + photo.setUri(jp.getText()); + continue; + case F_TITLE: + photo.setTitle(jp.getText()); + continue; + case F_WIDTH: + photo.setWidth(jp.getIntValue()); + continue; + case F_HEIGHT: + photo.setHeight(jp.getIntValue()); + continue; + case F_SIZE: + photo.setSize(findSize(jp.getText())); + continue; + } + } + throw new IOException("Unknown field '"+name+"'"); + } + if (jp.getCurrentToken() != JsonToken.END_OBJECT) { + throw new IOException("Need END_OBJECT to complete Photo"); + } + return photo; + } + + public static Photo deserializeFaster(JsonParser jp) throws IOException + { + Photo photo = new Photo(); + + if (!jp.nextFieldName(NAME_URI)) { + failName(jp, NAME_URI); + } + photo.setUri(jp.nextTextValue()); + + if (!jp.nextFieldName(NAME_TITLE)) { + failName(jp, NAME_TITLE); + } + photo.setTitle(jp.nextTextValue()); + + if (!jp.nextFieldName(NAME_WIDTH)) { + failName(jp, NAME_WIDTH); + } + photo.setWidth(jp.nextIntValue(-1)); + + if (!jp.nextFieldName(NAME_HEIGHT)) { + failName(jp, NAME_HEIGHT); + } + photo.setHeight(jp.nextIntValue(-1)); + + if (!jp.nextFieldName(NAME_SIZE)) { + failName(jp, NAME_SIZE); + } + photo.setSize(findSize(jp.nextTextValue())); + + if (jp.nextToken() != JsonToken.END_OBJECT) { + throw new IOException("Need END_OBJECT to complete Photo"); + } + + return photo; + } + + public void serialize(JsonGenerator jgen) throws IOException + { + jgen.writeStartObject(); + jgen.writeStringField("uri", _uri); + jgen.writeStringField("title", _title); + jgen.writeNumberField("width", _width); + jgen.writeNumberField("height", _height); + jgen.writeStringField("size", (_size == null) ? null : _size.name()); + jgen.writeEndObject(); + } + } + + @JsonPropertyOrder({"player","uri","title","width","height","format","duration","size","bitrate","persons","copyright"}) + public static class Content + { + public final static int F_PLAYER = 0; + public final static int F_URI = 1; + public final static int F_TITLE = 2; + public final static int F_WIDTH = 3; + public final static int F_HEIGHT = 4; + public final static int F_FORMAT = 5; + public final static int F_DURATION = 6; + public final static int F_SIZE = 7; + public final static int F_BITRATE = 8; + public final static int F_PERSONS = 9; + public final static int F_COPYRIGHT = 10; + + public final static HashMap<String,Integer> sFields = new HashMap<String,Integer>(); + static { + sFields.put("player", F_PLAYER); + sFields.put("uri", F_URI); + sFields.put("title", F_TITLE); + sFields.put("width", F_WIDTH); + sFields.put("height", F_HEIGHT); + sFields.put("format", F_FORMAT); + sFields.put("duration", F_DURATION); + sFields.put("size", F_SIZE); + sFields.put("bitrate", F_BITRATE); + sFields.put("persons", F_PERSONS); + sFields.put("copyright", F_COPYRIGHT); + } + + final static SerializedString NAME_PLAYER = new SerializedString("player"); + final static SerializedString NAME_URI = new SerializedString("uri"); + final static SerializedString NAME_TITLE = new SerializedString("title"); + final static SerializedString NAME_WIDTH = new SerializedString("width"); + final static SerializedString NAME_HEIGHT = new SerializedString("height"); + final static SerializedString NAME_FORMAT = new SerializedString("format"); + final static SerializedString NAME_DURATION = new SerializedString("duration"); + final static SerializedString NAME_SIZE = new SerializedString("size"); + final static SerializedString NAME_BITRATE = new SerializedString("bitrate"); + final static SerializedString NAME_PERSONS = new SerializedString("persons"); + final static SerializedString NAME_COPYRIGHT = new SerializedString("copyright"); + + private Player _player; + private String _uri; + private String _title; + private int _width; + private int _height; + private String _format; + private long _duration; + private long _size; + private int _bitrate; + private List<String> _persons; + private String _copyright; + + public Content() { } + + public void addPerson(String p) { + if (_persons == null) { + _persons = new ArrayList<String>(); + } + _persons.add(p); + } + + public Player getPlayer() { return _player; } + public String getUri() { return _uri; } + public String getTitle() { return _title; } + public int getWidth() { return _width; } + public int getHeight() { return _height; } + public String getFormat() { return _format; } + public long getDuration() { return _duration; } + public long getSize() { return _size; } + public int getBitrate() { return _bitrate; } + public List<String> getPersons() { return _persons; } + public String getCopyright() { return _copyright; } + + public void setPlayer(Player p) { _player = p; } + public void setUri(String u) { _uri = u; } + public void setTitle(String t) { _title = t; } + public void setWidth(int w) { _width = w; } + public void setHeight(int h) { _height = h; } + public void setFormat(String f) { _format = f; } + public void setDuration(long d) { _duration = d; } + public void setSize(long s) { _size = s; } + public void setBitrate(int b) { _bitrate = b; } + public void setPersons(List<String> p) { _persons = p; } + public void setCopyright(String c) { _copyright = c; } + + private static Player findPlayer(String id) + { + if ("JAVA".equals(id)) { + return Player.JAVA; + } + if ("FLASH".equals(id)) { + return Player.FLASH; + } + throw new IllegalArgumentException("Weird Player value of '"+id+"'"); + } + + public static Content deserialize(JsonParser jp) throws IOException + { + if (jp.nextToken() != JsonToken.START_OBJECT) { + throw new IOException("Need START_OBJECT for Content"); + } + Content content = new Content(); + + while (jp.nextToken() == JsonToken.FIELD_NAME) { + String name = jp.getCurrentName(); + jp.nextToken(); + Integer I = sFields.get(name); + if (I != null) { + switch (I.intValue()) { + case F_PLAYER: + content.setPlayer(findPlayer(jp.getText())); + case F_URI: + content.setUri(jp.getText()); + continue; + case F_TITLE: + content.setTitle(jp.getText()); + continue; + case F_WIDTH: + content.setWidth(jp.getIntValue()); + continue; + case F_HEIGHT: + content.setHeight(jp.getIntValue()); + continue; + case F_FORMAT: + content.setCopyright(jp.getText()); + continue; + case F_DURATION: + content.setDuration(jp.getLongValue()); + continue; + case F_SIZE: + content.setSize(jp.getLongValue()); + continue; + case F_BITRATE: + content.setBitrate(jp.getIntValue()); + continue; + case F_PERSONS: + content.setPersons(deserializePersons(jp)); + continue; + case F_COPYRIGHT: + content.setCopyright(jp.getText()); + continue; + } + } + throw new IOException("Unknown field '"+name+"'"); + } + if (jp.getCurrentToken() != JsonToken.END_OBJECT) { + throw new IOException("Need END_OBJECT to complete Content"); + } + return content; + } + + public static Content deserializeFaster(JsonParser jp) throws IOException + { + if (jp.nextToken() != JsonToken.START_OBJECT) { + throw new IOException("Need START_OBJECT for Content"); + } + Content content = new Content(); + if (!jp.nextFieldName(NAME_PLAYER)) { + failName(jp, NAME_PLAYER); + } + content.setPlayer(findPlayer(jp.nextTextValue())); + + if (!jp.nextFieldName(NAME_URI)) { + failName(jp, NAME_URI); + } + content.setUri(jp.nextTextValue()); + + if (!jp.nextFieldName(NAME_TITLE)) { + failName(jp, NAME_TITLE); + } + content.setTitle(jp.nextTextValue()); + + if (!jp.nextFieldName(NAME_WIDTH)) { + failName(jp, NAME_WIDTH); + } + content.setWidth(jp.nextIntValue(-1)); + + if (!jp.nextFieldName(NAME_HEIGHT)) { + failName(jp, NAME_HEIGHT); + } + content.setHeight(jp.nextIntValue(-1)); + + if (!jp.nextFieldName(NAME_FORMAT)) { + failName(jp, NAME_PLAYER); + } + content.setCopyright(jp.nextTextValue()); + + if (!jp.nextFieldName(NAME_DURATION)) { + failName(jp, NAME_DURATION); + } + content.setDuration(jp.nextLongValue(-1L)); + + if (!jp.nextFieldName(NAME_SIZE)) { + failName(jp, NAME_SIZE); + } + content.setSize(jp.nextLongValue(-1L)); + + if (!jp.nextFieldName(NAME_BITRATE)) { + failName(jp, NAME_BITRATE); + } + content.setBitrate(jp.nextIntValue(-1)); + + if (!jp.nextFieldName(NAME_PERSONS)) { + failName(jp, NAME_PERSONS); + } + jp.nextToken(); + content.setPersons(deserializePersonsFaster(jp)); + + if (!jp.nextFieldName(NAME_COPYRIGHT)) { + failName(jp, NAME_COPYRIGHT); + } + content.setCopyright(jp.nextTextValue()); + + if (jp.nextToken() != JsonToken.END_OBJECT) { + throw new IOException("Need END_OBJECT to complete Content"); + } + + return content; + } + + private static List<String> deserializePersons(JsonParser jp) throws IOException + { + if (jp.getCurrentToken() != JsonToken.START_ARRAY) { + throw new IOException("Need START_ARRAY for List of Persons (got "+jp.getCurrentToken()+")"); + } + ArrayList<String> persons = new ArrayList<String>(4); + while (jp.nextToken() == JsonToken.VALUE_STRING) { + persons.add(jp.getText()); + } + if (jp.getCurrentToken() != JsonToken.END_ARRAY) { + throw new IOException("Need END_ARRAY to complete List of Persons"); + } + return persons; + } + + private static List<String> deserializePersonsFaster(JsonParser jp) throws IOException + { + if (jp.getCurrentToken() != JsonToken.START_ARRAY) { + throw new IOException("Need START_ARRAY for List of Persons (got "+jp.getCurrentToken()+")"); + } + ArrayList<String> persons = new ArrayList<String>(4); + String str; + while ((str = jp.nextTextValue()) != null) { + persons.add(str); + } + if (jp.getCurrentToken() != JsonToken.END_ARRAY) { + throw new IOException("Need END_ARRAY to complete List of Persons"); + } + return persons; + } + + public void serialize(JsonGenerator jgen) throws IOException + { + jgen.writeStartObject(); + jgen.writeStringField("player", (_player == null) ? null : _player.name()); + jgen.writeStringField("uri", _uri); + jgen.writeStringField("title", _title); + jgen.writeNumberField("width", _width); + jgen.writeNumberField("height", _height); + jgen.writeStringField("format", _format); + jgen.writeNumberField("duration", _duration); + jgen.writeNumberField("size", _size); + jgen.writeNumberField("bitrate", _bitrate); + jgen.writeStringField("copyright", _copyright); + if (_persons == null) { + jgen.writeNullField("persons"); + } else { + jgen.writeArrayFieldStart("persons"); + for (String p : _persons) { + jgen.writeString(p); + } + jgen.writeEndArray(); + } + jgen.writeEndObject(); + } + } +}
diff --git a/1.9.10/src/perf/perf/TestCopyPerf.java b/1.9.10/src/perf/perf/TestCopyPerf.java new file mode 100644 index 0000000..de48b16 --- /dev/null +++ b/1.9.10/src/perf/perf/TestCopyPerf.java
@@ -0,0 +1,99 @@ +package perf; +import java.io.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.ObjectMapper; +import org.codehaus.jackson.smile.SmileFactory; +import org.codehaus.jackson.smile.SmileGenerator; +import org.codehaus.jackson.util.TokenBuffer; + +public final class TestCopyPerf +{ + private final int REPS; + + final JsonFactory _jsonFactory; + + final SmileFactory _smileFactory; + + final TokenBuffer _tokens; + + private TestCopyPerf(File f) + throws Exception + { + _jsonFactory = new JsonFactory(); + _smileFactory = new SmileFactory(); + // whether to use back-refs for field names has measurable impact on ser/deser (but different direction): + // _smileFactory.configure(SmileGenerator.Feature.CHECK_SHARED_NAMES, false); + _smileFactory.configure(SmileGenerator.Feature.CHECK_SHARED_NAMES, true); + _smileFactory.configure(SmileGenerator.Feature.CHECK_SHARED_STRING_VALUES, true); + FileInputStream fis = new FileInputStream(f); + ObjectMapper mapper = new ObjectMapper(); + JsonParser jp = _jsonFactory.createJsonParser(fis); + _tokens = mapper.readValue(jp, TokenBuffer.class); + + // Let's try to guestimate suitable size... to get about 20 megs copied + REPS = (int) ((double) (20 * 1000 * 1000) / (double) f.length()); + + jp.close(); + } + + public void test() + throws Exception + { + ByteArrayOutputStream bos = new ByteArrayOutputStream(2000); + testCopy(1, bos, 0); + System.out.println("Output length: "+bos.size()+"; will do "+REPS+" writes per round"); + System.out.println(); + + int round = 0; + + while (true) { + try { Thread.sleep(100L); } catch (InterruptedException ie) { } + testCopy(REPS, bos, round); + ++round; + } + } + + private long testCopy(int reps, ByteArrayOutputStream bos, int round) + throws IOException + { + int mode = (round % 2); + if (mode == 0) System.out.println(); + + JsonGenerator jg = null; + final long start = System.currentTimeMillis(); + + while (--reps >= 0) { + bos.reset(); + switch (mode) { + case 0: + jg = _smileFactory.createJsonGenerator(bos); + break; + case 1: + jg = _jsonFactory.createJsonGenerator(bos, JsonEncoding.UTF8); + break; + default: + throw new Error(); + } + JsonParser jp = _tokens.asParser(); + while (jp.nextToken() != null) { + jg.copyCurrentEvent(jp); + } + jp.close(); + jg.close(); + } + long time = System.currentTimeMillis() - start; + System.out.println("Took "+time+" msecs (round "+round+"; bytes "+bos.size()+") for "+jg.getClass().getName()); + return time; + } + + public static void main(String[] args) + throws Exception + { + if (args.length != 1) { + System.err.println("Usage: java ... <file>"); + System.exit(1); + } + new TestCopyPerf(new File(args[0])).test(); + } +}
diff --git a/1.9.10/src/perf/perf/TestCreatorPerf.java b/1.9.10/src/perf/perf/TestCreatorPerf.java new file mode 100644 index 0000000..b016ed1 --- /dev/null +++ b/1.9.10/src/perf/perf/TestCreatorPerf.java
@@ -0,0 +1,152 @@ +package perf; +import java.io.*; + +import org.codehaus.jackson.annotate.*; +import org.codehaus.jackson.map.*; + +/** + * Micro-benchmark for comparing performance of bean deserialization + * using method-based method or Creator-based (constructor or + * factory method) + */ +public final class TestCreatorPerf +{ + /* + ///////////////////////////////////////////////////// + // Bean classes + ///////////////////////////////////////////////////// + */ + + final static class MethodBean + { + int x; + long y; + boolean state; + + protected MethodBean() { } + + public void setX(int v) { x = v; } + public void setY(long v) { y = v; } + public void setState(boolean v) { state = v; } + + @Override + public int hashCode() { return x ^ (int) y ^ (state ? 1 : -1); } + } + + final static class ConstructorBean + { + final int x; + final long y; + final boolean state; + + @JsonCreator public ConstructorBean(@JsonProperty("x") int a1, + @JsonProperty("y") long a2, + @JsonProperty("state") boolean a4) + { + x = a1; + y = a2; + state = a4; + } + + @Override + public int hashCode() { return x ^ (int) y ^ (state ? 1 : -1); } + } + + final static class FactoryBean + { + int x; + long y; + boolean state; + + private FactoryBean() { } + + @JsonCreator public static FactoryBean buildIt(@JsonProperty("x") int a1, + @JsonProperty("y") long a2, + @JsonProperty("state") boolean a4) + { + FactoryBean bean = new FactoryBean(); + bean.x = a1; + bean.y = a2; + bean.state = a4; + return bean; + } + + @Override + public int hashCode() { return x ^ (int) y ^ (state ? 1 : -1); } + } + + + private final int REPS; + private final ObjectMapper _mapper; + private final byte[] _data; + + public TestCreatorPerf() + throws Exception + { + // Let's try to guestimate suitable size, to spend enough (but not too much) time per round + REPS = 13000; + _mapper = new ObjectMapper(); + _data = "{ \"x\" : -15980, \"y\" : 1234567890123, \"state\" : true }".getBytes("UTF-8"); + } + + public void test() + throws Exception + { + int i = 0; + int sum = 0; + + System.out.println("START: content size "+_data.length+" bytes"); + ByteArrayInputStream in = new ByteArrayInputStream(_data); + + while (true) { + try { Thread.sleep(100L); } catch (InterruptedException ie) { } + int round = (i++ % 3); + + long curr = System.currentTimeMillis(); + String msg; + boolean lf = (round == 0); + + switch (round) { + + case 0: + msg = "Jackson, setters"; + sum += testDeser(REPS, in, MethodBean.class); + break; + case 1: + msg = "Jackson, constructor"; + sum += testDeser(REPS, in, ConstructorBean.class); + break; + case 2: + msg = "Jackson, factory"; + sum += testDeser(REPS, in, FactoryBean.class); + break; + default: + throw new Error("Internal error"); + } + + curr = System.currentTimeMillis() - curr; + if (lf) { + System.out.println(); + } + System.out.println("Test '"+msg+"' -> "+curr+" msecs (" + +(sum & 0xFF)+")."); + + } + } + + protected <T> int testDeser(int reps, ByteArrayInputStream in, Class<T> beanType) + throws Exception + { + T result = null; + for (int i = 0; i < reps; ++i) { + in.reset(); + result = _mapper.readValue(in, beanType); + } + return result.hashCode(); // just to get some non-optimizable number + } + + public static void main(String[] args) throws Exception + { + new TestCreatorPerf().test(); + } +}
diff --git a/1.9.10/src/perf/perf/TestDeserPerf.java b/1.9.10/src/perf/perf/TestDeserPerf.java new file mode 100644 index 0000000..f0bc7f5 --- /dev/null +++ b/1.9.10/src/perf/perf/TestDeserPerf.java
@@ -0,0 +1,243 @@ +package perf; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.type.TypeFactory; +import org.codehaus.jackson.smile.SmileFactory; +import org.codehaus.jackson.smile.SmileGenerator; +import org.codehaus.jackson.type.JavaType; + +/** + * Micro-benchmark for comparing performance of bean deserialization + */ +public final class TestDeserPerf +{ + /* + /********************************************************** + /* Actual test + /********************************************************** + */ + + private final int REPS; + + private TestDeserPerf() { + // Let's try to guestimate suitable size + REPS = 25000; + } + + private MediaItem buildItem() + { + MediaItem.Content content = new MediaItem.Content(); + content.setPlayer(MediaItem.Player.JAVA); + content.setUri("http://javaone.com/keynote.mpg"); + content.setTitle("Javaone Keynote"); + content.setWidth(640); + content.setHeight(480); + content.setFormat("video/mpeg4"); + content.setDuration(18000000L); + content.setSize(58982400L); + content.setBitrate(262144); + content.setCopyright("None"); + content.addPerson("Bill Gates"); + content.addPerson("Steve Jobs"); + + MediaItem item = new MediaItem(content); + + item.addPhoto(new MediaItem.Photo("http://javaone.com/keynote_large.jpg", "Javaone Keynote", 1024, 768, MediaItem.Size.LARGE)); + item.addPhoto(new MediaItem.Photo("http://javaone.com/keynote_small.jpg", "Javaone Keynote", 320, 240, MediaItem.Size.SMALL)); + + return item; + } + + public void test() + throws Exception + { + int sum = 0; + + final MediaItem item = buildItem(); + JsonFactory jsonF = +// new org.codehaus.jackson.smile.SmileFactory(); + new JsonFactory() + ; + + final ObjectMapper jsonMapper = new ObjectMapper(jsonF); +// jsonMapper.configure(SerializationConfig.Feature.USE_STATIC_TYPING, true); + final SmileFactory smileFactory = new SmileFactory(); + final ObjectMapper smileMapper = new ObjectMapper(smileFactory); + smileFactory.configure(SmileGenerator.Feature.CHECK_SHARED_NAMES, true); +// smileFactory.configure(SmileGenerator.Feature.CHECK_SHARED_STRING_VALUES, true); + smileFactory.configure(SmileGenerator.Feature.CHECK_SHARED_STRING_VALUES, false); + + // Use Jackson? + byte[] json = jsonMapper.writeValueAsBytes(item); + // or another lib? +// byte[] json = com.alibaba.fastjson.JSON.toJSONString(item, com.alibaba.fastjson.serializer.SerializerFeature.WriteEnumUsingToString).getBytes("UTF-8"); + + System.out.println("Warmed up: data size is "+json.length+" bytes; "+REPS+" reps -> " + +((REPS * json.length) >> 10)+" kB per iteration"); + System.out.println(); + byte[] smile = smileMapper.writeValueAsBytes(item); + System.out.println(" smile size: "+smile.length+" bytes"); + + /* + byte[] bson; + final ObjectMapper bsonMapper = new ObjectMapper(new de.undercouch.bson4jackson.BsonFactory()); + { + bson = bsonMapper.writeValueAsBytes(item); + System.out.println(" BSON size: "+bson.length+" bytes"); + } + */ + + { // verify equality + System.out.println("Will verify state of Smile..."); + MediaItem result = smileMapper.readValue(smile, 0, smile.length, MediaItem.class); + String jsonFromSmile = jsonMapper.writeValueAsString(result); + String jsonFromItem = jsonMapper.writeValueAsString(item); + if (!jsonFromSmile.equals(jsonFromItem)) { + int ix = 0; + + for (int max = Math.min(jsonFromSmile.length(), jsonFromItem.length()); ix < max; ++ix) { + if (jsonFromSmile.charAt(ix) != jsonFromItem.charAt(ix)) { + break; + } + } + + System.err.println("Source JSON: "); + System.err.println(jsonFromItem); + System.err.println("------------"); + System.err.println("Smile JSON: "); + System.err.println(jsonFromSmile); + System.err.println("------------"); + for (int i = 0; i < ix; ++i) { + System.err.print('='); + } + System.err.println("^"); + System.err.println("------------"); + throw new Error("No smile today -- data corruption!"); + } + System.out.println("Verification successful: Smile ok!"); + } + +// for debugging: + System.err.println("JSON = "+jsonMapper.writerWithDefaultPrettyPrinter().writeValueAsString(item)); + + int round = 0; + while (true) { +// try { Thread.sleep(100L); } catch (InterruptedException ie) { } +// int round = 2; + + long curr = System.currentTimeMillis(); + String msg; + round = (++round % 4); + +//if (true) round = 3; +if (round < 2) round += 2; + + boolean lf = (round == 0); + + switch (round) { + + case 0: + msg = "Deserialize, manual, JSON"; + sum += testDeser(jsonMapper.getJsonFactory(), json, REPS); + break; + + case 1: + msg = "Deserialize, manual/FAST, JSON"; + sum += testDeserFaster(jsonMapper.getJsonFactory(), json, REPS); + break; + + /* + case 2: + msg = "Deserialize, bind, JSON"; + sum += testDeser(jsonMapper, json, REPS); + break; + + case 2: + msg = "Deserialize, smile"; + sum += testDeser(smileMapper, smile, REPS * 2); + break; + */ + + case 2: + msg = "Deserialize, manual, Smile"; + sum += testDeser(smileMapper.getJsonFactory(), smile, REPS); + break; + + case 3: + msg = "Deserialize, manual/FAST, Smile"; + sum += testDeserFaster(smileMapper.getJsonFactory(), smile, REPS); + break; + + /* + case 2: + msg = "Deserialize, fast-json"; + sum += testFastJson(json, REPS); + break; + */ + + default: + throw new Error("Internal error"); + } + + curr = System.currentTimeMillis() - curr; + if (lf) { + System.out.println(); + } + System.out.println("Test '"+msg+"' -> "+curr+" msecs (" + +(sum & 0xFF)+")."); + } + } + + protected int testDeser(ObjectMapper mapper, byte[] input, int reps) + throws Exception + { + JavaType type = TypeFactory.defaultInstance().constructType(MediaItem.class); + MediaItem item = null; + for (int i = 0; i < reps; ++i) { + item = mapper.readValue(input, 0, input.length, type); + } + return item.hashCode(); // just to get some non-optimizable number + } + + protected int testDeser(JsonFactory jf, byte[] input, int reps) + throws Exception + { + MediaItem item = null; + for (int i = 0; i < reps; ++i) { + JsonParser jp = jf.createJsonParser(input); + item = MediaItem.deserialize(jp); + jp.close(); + } + return item.hashCode(); // just to get some non-optimizable number + } + + protected int testDeserFaster(JsonFactory jf, byte[] input, int reps) + throws Exception + { + MediaItem item = null; + for (int i = 0; i < reps; ++i) { + JsonParser jp = jf.createJsonParser(input); + item = MediaItem.deserializeFaster(jp); + jp.close(); + } + return item.hashCode(); // just to get some non-optimizable number + } + + /* + protected int testFastJson(byte[] input, int reps) + throws Exception + { + MediaItem item = null; + for (int i = 0; i < reps; ++i) { + item = com.alibaba.fastjson.JSON.parseObject(input, MediaItem.class); + } + return item.hashCode(); // just to get some non-optimizable number + } + */ + + public static void main(String[] args) throws Exception + { + new TestDeserPerf().test(); + } +}
diff --git a/1.9.10/src/perf/perf/TestIteratorPerf.java b/1.9.10/src/perf/perf/TestIteratorPerf.java new file mode 100644 index 0000000..4a70e91 --- /dev/null +++ b/1.9.10/src/perf/perf/TestIteratorPerf.java
@@ -0,0 +1,154 @@ +package perf; + +import java.io.*; +import java.util.Iterator; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.type.JavaType; + +/* Simple micro-benchmark for comparing speed of various + * methods of iterating over a sequence of beans + */ +public class TestIteratorPerf +{ + static class Bean + { + public int id; + public int b, c, d; +// public String name; + public boolean active; + public int extra; + + public Bean() { } + public Bean(int i, String n, boolean a) { + id = i; +// name = n; + active = a; + extra = 100 * i; + + b = i - 3; + c = i * 7; + d = b + c; + } + } + + private final static int REPS = 5000; + + private final ObjectMapper _mapper = new ObjectMapper(); + + private final JavaType TYPE; + + private TestIteratorPerf() { + TYPE = _mapper.constructType(Bean.class); + } + + public void test() throws Exception + { + int i = 0; + int sum = 0; + int round = 0; + + byte[] seq = generateSequence(); + + while (true) { + try { Thread.sleep(100L); } catch (InterruptedException ie) { } + + ++i; + round = i % 3; + +// if (true) round = 1; + + long curr = System.currentTimeMillis(); + String msg; + boolean lf = (round == 0); + + switch (round) { + + case 0: + msg = "Jackson, vanilla"; + sum = testJacksonStream(REPS, seq); + break; + case 1: + msg = "Jackson, iterator"; + sum = testJacksonIterator(REPS, seq); + break; + case 2: + msg = "Jackson, iterator+updating"; + sum = testJacksonUpdating(REPS, seq); + break; + default: + throw new Error("Internal error"); + } + curr = System.currentTimeMillis() - curr; + if (lf) { + System.out.println(); + } + System.out.println("Test '"+msg+"' -> "+curr+" msecs" + +"("+(sum & 0xFF)+")" + ); + } + } + + private int testJacksonStream(int reps, byte[] data) throws Exception + { + int sum = 0; + final JsonFactory factory = _mapper.getJsonFactory(); + while (--reps >= 0) { + JsonParser jp = factory.createJsonParser(data, 0, data.length); + while (jp.nextToken() != null) { + _mapper.readValue(jp, TYPE); + ++sum; + } + jp.close(); + } + return sum; + } + + private int testJacksonIterator(int reps, byte[] data) throws Exception + { + int sum = 0; + while (--reps >= 0) { + Iterator<Bean> it = _mapper.reader(TYPE).readValues(data, 0, data.length); + while (it.hasNext()) { + it.next(); + ++sum; + } + } + return sum; + } + + private int testJacksonUpdating(int reps, byte[] data) throws Exception + { + int sum = 0; + Bean updated = new Bean(); + while (--reps >= 0) { + Iterator<Bean> it = _mapper.reader(TYPE).withValueToUpdate(updated).readValues(data, 0, data.length); + while (it.hasNext()) { + it.next(); + ++sum; + } + } + return sum; + } + + private byte[] generateSequence() throws Exception + { + ByteArrayOutputStream bytes = new ByteArrayOutputStream(4000); + JsonGenerator jgen = _mapper.getJsonFactory().createJsonGenerator(bytes); + int i = 0; + do { + Bean bean = new Bean(i, "value"+i, (i & 1) != 0); + jgen.writeObject(bean); + jgen.writeRaw('\n'); + ++i; + } while (bytes.size() < 4000); + jgen.close(); + return bytes.toByteArray(); + } + + public static void main(String[] args) throws Exception + { + new TestIteratorPerf().test(); + } +}
diff --git a/1.9.10/src/perf/perf/TestJsonPerf.java b/1.9.10/src/perf/perf/TestJsonPerf.java new file mode 100644 index 0000000..99b2495 --- /dev/null +++ b/1.9.10/src/perf/perf/TestJsonPerf.java
@@ -0,0 +1,400 @@ +package perf; + +import java.io.*; +import java.nio.charset.Charset; +import java.util.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.io.IOContext; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.smile.SmileFactory; +import org.codehaus.jackson.util.BufferRecycler; + +// json.org's reference implementation +import org.json.*; + +// jackson-4-org.json +import com.fasterxml.jackson.module.jsonorg.JsonOrgModule; + +// json-smart +import net.minidev.json.JSONObject; +import net.minidev.json.JSONValue; + +@SuppressWarnings("unused") +public final class TestJsonPerf +{ + private final int REPS; + + private final static int TEST_PER_GC = 15; + + final JsonFactory _jsonFactory; + + final ObjectMapper _mapper; + + final ObjectMapper _smileMapper; + + final SmileFactory _smileFactory; + + final byte[] _jsonData; + + final String _jsonString; + + final byte[] _smileData; + + protected int _batchSize; + + public TestJsonPerf(File f) throws IOException + { + _jsonFactory = new JsonFactory(); + _mapper = new ObjectMapper(_jsonFactory); + _mapper.registerModule(new JsonOrgModule()); + + _smileFactory = new SmileFactory(); + _smileMapper = new ObjectMapper(_smileFactory); + _jsonData = readData(f); + _jsonString = new String(_jsonData, "UTF-8"); + _smileData = convertToSmile(_jsonData); + + // Let's try to guestimate suitable size... to get to 25 megs parsed + REPS = (int) ((double) (25 * 1000 * 1000) / (double) _jsonData.length); + + System.out.println("Read "+_jsonData.length+" bytes (smile: "+_smileData.length+") from '"+f+"'; will do "+REPS+" reps"); + System.out.println(); + } + + public void test() + throws Exception + { + int i = 0; + int sum = 0; + int round = 0; + + while (true) { + try { Thread.sleep(100L); } catch (InterruptedException ie) { } + + ++i; + +// round = i % 7; +// int round = 2 + (i % 2); + round = 6; + + long curr = System.currentTimeMillis(); + String msg; + boolean lf = (round == 0); + + switch (round) { + + case 0: + msg = "Jackson, stream/byte[]"; // byte + sum += testJacksonStream(REPS, _jsonFactory, _jsonData); + break; + + case 1: + msg = "Jackson, stream/String"; // String + sum += testJacksonStream(REPS, _jsonFactory, _jsonString); + break; + + case 2: + msg = "Jackson, tree/byte[]"; + sum += testJacksonTree(REPS, _mapper, _jsonData); + break; + + case 3: + msg = "Jackson, tree/String"; + sum += testJacksonTree(REPS, _mapper, _jsonString); + break; + + case 4: + msg = "Jackson, Object/byte[]"; + sum += testJacksonObject(REPS, _mapper, _jsonData); + break; + + case 5: + msg = "Jackson, Object/String"; + sum += testJacksonObject(REPS, _mapper, _jsonString); + break; + + case 6: + msg = "Json-smart/String"; + sum += testJsonSmart(REPS, _jsonData, _jsonString); + break; + + /* + case 3: + msg = "Jackson + module-org-json"; + sum += testJsonOrgViaJackson(REPS); + break; + + case 4: + msg = "Json.org"; + sum += testJsonOrg(REPS); + break; + + case 0: + msg = "Jackson/smile, stream"; + sum += testJacksonStream(REPS, _smileFactory, _smileData, true); + break; + case 0: + msg = "Smile/data-bind"; + sum += testJacksonDatabind(_smileMapper, _smileData, REPS); + break; + + case 1: + msg = "Jackson/data-bind"; + sum += testJacksonDatabind(_mapper, _jsonData, REPS); + break; + case 1: + msg = "Jackson, stream/byte"; + sum += testJacksonStream(REPS, _jsonFactory, _jsonData, true); + break; + case 2: + msg = "Jackson, stream/char"; + sum += testJacksonStream(REPS, _jsonFactory, _jsonData, false); + break; + */ + default: + throw new Error("Internal error"); + } + + curr = System.currentTimeMillis() - curr; + if (lf) { + System.out.println(); + } + System.out.println("Test '"+msg+"' -> "+curr+" msecs" +// +"("+(sum & 0xFF)+")" + ); + + + if ((i % TEST_PER_GC) == 0) { + System.out.println("[GC]"); + try { Thread.sleep(100L); } catch (InterruptedException ie) { } + System.gc(); + try { Thread.sleep(100L); } catch (InterruptedException ie) { } + } + } + } + + private final byte[] readData(File f) + throws IOException + { + int len = (int) f.length(); + byte[] data = new byte[len]; + int offset = 0; + FileInputStream fis = new FileInputStream(f); + + while (len > 0) { + int count = fis.read(data, offset, len-offset); + offset += count; + len -= count; + } + + return data; + } + + private byte[] convertToSmile(byte[] json) throws IOException + { + JsonParser jp = _jsonFactory.createJsonParser(json); + ByteArrayOutputStream out = new ByteArrayOutputStream(200); + System.out.println("Converting and verifying Smile data..."); + JsonGenerator jg = _smileFactory.createJsonGenerator(out); + while (jp.nextToken() != null) { + jg.copyCurrentEvent(jp); + } + jp.close(); + jg.close(); + byte[] smileBytes = out.toByteArray(); + System.out.println("Written as "+smileBytes.length+" Smile bytes from "+json.length+" JSON bytes; will verify correctness"); + + // One more thing: let's actually verify correctness! + JsonParser sp = _smileFactory.createJsonParser(new ByteArrayInputStream(smileBytes)); + jp = _jsonFactory.createJsonParser(json); + while (true) { + JsonToken t1 = jp.nextToken(); + JsonToken t2; + try { + t2 = sp.nextToken(); + } catch (IOException ioe) { + System.err.println("WARN: problem for token matching input token "+t1+" at "+jp.getCurrentLocation()); + throw ioe; + } + if (t1 != t2) { + throw new IllegalArgumentException("Error: tokens differ (json: "+t1+", smile "+t2+") at "+jp.getCurrentLocation()); + } + if (t1 == null) break; + if (t1.isScalarValue() || t1 == JsonToken.FIELD_NAME) { + String str1 = jp.getText(); + String str2 = jp.getText(); + if (str1 == null) { + throw new IllegalArgumentException("Error: token texts differ (json: null, smile '"+str2+"') at "+jp.getCurrentLocation()); + } else if (!str1.equals(str2)) { + throw new IllegalArgumentException("Error: token texts differ (json: '"+str1+"', smile '"+str2+"') at "+jp.getCurrentLocation()); + } + } + } + System.out.println("Verified Smile data ("+smileBytes.length+"): same as JSON ("+json.length+")"); + return smileBytes; + } + + protected int testJsonOrg(int reps) + throws Exception + { + Object ob = null; + // Json.org's code only accepts Strings: + String input = new String(_jsonData, "UTF-8"); + for (int i = 0; i < reps; ++i) { + JSONTokener tok = new JSONTokener(input); + ob = tok.nextValue(); + } + return ob.hashCode(); + } + + protected int testJsonOrgViaJackson(int reps) throws Exception + { + JSONObject ob = null; + for (int i = 0; i < reps; ++i) { + ob = _mapper.readValue(_jsonData, JSONObject.class); + } + return ob.hashCode(); + } + + private int testJacksonStream(int reps, JsonFactory factory, byte[] data) throws Exception + { + int sum = 0; + Object ob = null; + for (int i = 0; i < reps; ++i) { + JsonParser jp = factory.createJsonParser(data, 0, data.length); + ob = mapStreamToObject(jp, jp.nextToken()); + jp.close(); + } + return ob.hashCode(); + } + + private int testJacksonStream(int reps, JsonFactory factory, String data) throws Exception + { + int sum = 0; + Object ob = null; + for (int i = 0; i < reps; ++i) { + JsonParser jp = factory.createJsonParser(data); + ob = mapStreamToObject(jp, jp.nextToken()); + jp.close(); + } + return ob.hashCode(); + } + + private Object mapStreamToObject(JsonParser jp, JsonToken t) throws IOException + { + switch (t) { + case VALUE_FALSE: + return Boolean.FALSE; + case VALUE_TRUE: + return Boolean.TRUE; + case VALUE_STRING: + return jp.getText(); + case VALUE_NUMBER_INT: + case VALUE_NUMBER_FLOAT: + return jp.getNumberValue(); + case VALUE_EMBEDDED_OBJECT: + return jp.getEmbeddedObject(); + case START_ARRAY: + { + ArrayList<Object> kids = new ArrayList<Object>(4); + while ((t = jp.nextToken()) != JsonToken.END_ARRAY) { + kids.add(mapStreamToObject(jp, t)); + } + return kids; + } + case START_OBJECT: + { +// HashMap<String, Object> kids = new LinkedHashMap<String, Object>(); + HashMap<String, Object> kids = new HashMap<String, Object>(8); + while ((t = jp.nextToken()) != JsonToken.END_OBJECT) { + kids.put(jp.getCurrentName(), mapStreamToObject(jp, jp.nextToken())); + } + return kids; + } + default: + throw new RuntimeException("Unexpected token: "+t); + } + } + + private int testJacksonDatabind(int reps, ObjectMapper mapper, byte[] data) + throws Exception + { + Object ob = null; + for (int i = 0; i < reps; ++i) { + // This is "untyped"... Maps, Lists etc + ob = mapper.readValue(data, Object.class); + } + return ob.hashCode(); // just to get some non-optimizable number + } + + private int testJacksonTree(int reps, ObjectMapper mapper, byte[] data) + throws Exception + { + Object ob = null; + for (int i = 0; i < reps; ++i) { + ob = mapper.readValue(data, JsonNode.class); + /* + ByteArrayInputStream in = new ByteArrayInputStream(data); + ob = mapper.readValue(in, JsonNode.class); + */ + } + return ob.hashCode(); // just to get some non-optimizable number + } + + private int testJacksonTree(int reps, ObjectMapper mapper, String data) + throws Exception + { + JsonNode tree = null; +// Object ob = null; + for (int i = 0; i < reps; ++i) { +// ob = mapper.readValue(data, JsonNode.class); + tree = mapper.readTree(data); + } + return tree.hashCode(); // just to get some non-optimizable number + } + + private int testJacksonObject(int reps, ObjectMapper mapper, byte[] data) + throws Exception + { + Object ob = null; + for (int i = 0; i < reps; ++i) { + ob = mapper.readValue(data, Object.class); + } + return ob.hashCode(); // just to get some non-optimizable number + } + + private int testJacksonObject(int reps, ObjectMapper mapper, String data) + throws Exception + { + Object ob = null; + for (int i = 0; i < reps; ++i) { + ob = mapper.readValue(data, Object.class); + } + return ob.hashCode(); // just to get some non-optimizable number + } + + private int testJsonSmart(int reps, byte[] dataBytes, String dataString) + throws Exception + { + JSONObject root = null; + final Charset utf8 = Charset.forName("UTF-8"); + for (int i = 0; i < reps; ++i) { + // ob = mapper.readValue(data, JsonNode.class); + String str = new String(dataBytes, utf8); + root = (JSONObject) JSONValue.parse(str); + } + return root.hashCode(); + } + + public static void main(String[] args) + throws Exception + { + if (args.length != 1) { + System.err.println("Usage: java ... <file>"); + System.exit(1); + } + new TestJsonPerf(new File(args[0])).test(); + } +} +
diff --git a/1.9.10/src/perf/perf/TestMapMessageDeserPerf.java b/1.9.10/src/perf/perf/TestMapMessageDeserPerf.java new file mode 100644 index 0000000..ec0b176 --- /dev/null +++ b/1.9.10/src/perf/perf/TestMapMessageDeserPerf.java
@@ -0,0 +1,193 @@ +package perf; + +import java.io.*; +import java.util.*; + +import org.codehaus.jackson.map.ObjectMapper; +import org.codehaus.jackson.type.JavaType; + +public class TestMapMessageDeserPerf +{ + private final static String JSON = + "[{" + + " \"successful\":true," + + " \"id\":\"1\"," + + " \"clientId\":\"abcdefghijklmnopqrstuvwxyz\"," + + " \"channel\":\"/meta/connect\"," + + " \"data\":{" + + " \"peer\":\"bar\"," + + " \"chat\":\"woot\"," + + " \"user\":\"foo\"," + + " \"room\":\"abc\"" + + " }," + + " \"advice\":{" + + " \"timeout\":0" + + " }," + + " \"ext\":{" + + " \"com.acme.auth\":{" + + " \"token\":\"0123456789\"" + + " }" + + " }" + + "}]"; + + final static int REPS = 29999; + + final ObjectMapper mapper; + + final JavaType mapMessageType; + + private TestMapMessageDeserPerf() + { + mapper = new ObjectMapper(); + mapMessageType = mapper.constructType(MapMessage[].class); + } + + private void test() throws IOException + { + int i = 0; + int sum = 0; + int round = 0; + + while (true) { + try { Thread.sleep(100L); } catch (InterruptedException ie) { } + + ++i; + +// round = i % 7; +// int round = 2 + (i % 2); + round = 0; + + long curr = System.currentTimeMillis(); + String msg; + boolean lf = (round == 0); + MapMessage result; + + switch (round) { + + case 0: + msg = "Jackson, ObjectMapper"; // byte + result = testMapper(REPS); + break; + + default: + throw new Error("Internal error"); + } + + sum += result.hashCode(); + curr = System.currentTimeMillis() - curr; + if (lf) { + System.out.println(); + } + System.out.println("Test '"+msg+"' ("+i+") -> "+curr+" msecs" + +"("+(sum & 0xFF)+")" + ); + } + } + + private MapMessage testMapper(int reps) throws IOException + { + MapMessage[] msgs; + do { + msgs = mapper.readValue(JSON, MapMessage[].class); +// msgs = mapper.readValue(JSON, type); + } while (--reps > 0); + return msgs[0]; + } + + public static void main(String[] args) throws Exception { + new TestMapMessageDeserPerf().test(); + } + + /* + * Payload class(es) + */ + + static class MapMessage extends HashMap<String, Object> + { + private static final long serialVersionUID = 1L; + + public MapMessage() { } + + public String getChannel() + { + return (String)get("channel"); + } + + public String getClientId() + { + return (String)get("clientId"); + } + + public Object getData() + { + return get("data"); + } + + @SuppressWarnings("unchecked") + public Map<String, Object> getExt() + { + Object ext = get("ext"); + return (Map<String, Object>)ext; + } + + public String getId() + { + Object id = get("id"); + return id == null ? null : String.valueOf(id); + } + + public Map<String, Object> getExt(boolean create) + { + Map<String, Object> ext = getExt(); + if (create && ext == null) + { + ext = new HashMap<String, Object>(); + put("ext", ext); + } + return ext; + } + + public boolean isSuccessful() + { + Boolean value = (Boolean)get("succesful"); + return value != null && value; + } + + public void setChannel(String channel) + { + if (channel==null) + remove("channel"); + else + put("channel", channel); + } + + public void setClientId(String clientId) + { + if (clientId==null) + remove("clientId"); + else + put("clientId", clientId); + } + + public void setData(Object data) + { + if (data==null) + remove("data"); + else + put("data", data); + } + + public void setId(String id) + { + if (id==null) + remove("id"); + else + put("id", id); + } + + public void setSuccessful(boolean successful) + { + put("successful", successful); + } + } +}
diff --git a/1.9.10/src/perf/perf/TestMapSpeed.java b/1.9.10/src/perf/perf/TestMapSpeed.java new file mode 100644 index 0000000..9543c09 --- /dev/null +++ b/1.9.10/src/perf/perf/TestMapSpeed.java
@@ -0,0 +1,310 @@ +package perf; + +import java.util.*; + +public class TestMapSpeed +{ + public final static String STRING1 = "abcd"; + public final static String STRING2 = "efghij"; + public final static String STRING3 = "12345"; + public final static String STRING4 = "098765"; + public final static String STRING5 = "x"; + public final static String STRING6 = "abd1234"; + public final static String STRING7 = "ratherlong"; + public final static String STRING8 = "whatever!"; + + public final static String[] KEYS = new String[] { + STRING1, STRING2, STRING3, STRING4 + ,STRING5, STRING6 + ,STRING7, STRING8 + }; + + /* + /********************************************************** + /* Test beans + /********************************************************** + */ + + abstract static class MyMap + { + public abstract Integer find(String key); + } + + final static class SmallMyMap extends MyMap + { + final String str1; + final String str2; + final String str3; + final String str4; + final String str5; + final String str6; + final String str7; + final String str8; + + final Integer int1; + final Integer int2; + final Integer int3; + final Integer int4; + final Integer int5; + final Integer int6; + final Integer int7; + final Integer int8; + + public SmallMyMap(String str1, Integer int1, + String str2, Integer int2, + String str3, Integer int3, + String str4, Integer int4, + String str5, Integer int5, + String str6, Integer int6, + String str7, Integer int7, + String str8, Integer int8 + ) + { + this.str1 = str1; + this.int1 = int1; + this.str2 = str2; + this.int2 = int2; + this.str3 = str3; + this.int3 = int3; + this.str4 = str4; + this.int4 = int4; + this.str5 = str5; + this.int5 = int5; + this.str6 = str6; + this.int6 = int6; + this.str7 = str7; + this.int7 = int7; + this.str8 = str8; + this.int8 = int8; + } + + @Override + public Integer find(String key) + { +// int hash = key.hashCode(); + if (key == str1) return int1; + if (key == str2) return int2; + if (key == str3) return int3; + if (key == str4) return int4; + if (key == str5) return int5; + if (key == str6) return int6; + if (key == str7) return int7; + if (key == str8) return int8; + return null; + } + } + + final static class BigMyMap extends MyMap + { + private final int size; + private final String[] strings; + private final Integer[] ints; + + public BigMyMap(String[] keys) + { + size = keys.length; + strings = new String[size]; + System.arraycopy(keys, 0, strings, 0, size); + ints = new Integer[size]; + for (int i = 0; i < size; ++i) { + ints[i] = Integer.valueOf(i+1); + } + } + + @Override + public Integer find(String key) + { + final int len = size; + for (int i = 0; i < len; ++i) { + if (strings[i] == key) return ints[i]; + } + return null; + } + } + + /* Implementation similar to regular HashMap, only slightly + * more optimized + */ + final static class MyBucketMap extends MyMap + { + private final Bucket[] _buckets; + + public MyBucketMap(String[] keys) + { + Bucket[] buckets = new Bucket[16]; + final int size = keys.length; + for (int i = 0; i < size; ++i) { + int hash = keys[i].hashCode(); + int index = hash & 0xF; + buckets[index] = new Bucket(buckets[index], keys[i], Integer.valueOf(i+1)); + } + _buckets = buckets; + } + + @Override + public Integer find(String key) + { + int index = key.hashCode() & (_buckets.length-1); + Bucket bucket = _buckets[index]; + while (bucket != null) { + if (bucket.key == key) { + return bucket.value; + } + bucket = bucket.next; + } + return find2(key, index); + } + + private Integer find2(String key, int index) + { + Bucket bucket = _buckets[index]; + while (bucket != null) { + if (key.equals(bucket.key)) { + return bucket.value; + } + bucket = bucket.next; + } + return null; + } + + private final static class Bucket + { + public final Bucket next; + public final String key; + public final Integer value; + + public Bucket(Bucket next, String key, Integer value) + { + this.next = next; + this.key = key; + this.value = value; + } + } + } + + /* + /********************************************************** + /* Test methods + /********************************************************** + */ + + private final static int REPS = 299500; + + private final HashMap<String,Integer> stdMap; + + private final MyMap smallMap; + private final MyMap bigMap; + + private final MyBucketMap bucketMap; + + public TestMapSpeed() + { + stdMap = new HashMap<String,Integer>(); + for (int i = 0, len = KEYS.length; i < len; ++i) { + stdMap.put(KEYS[i], Integer.valueOf(i+1)); + } + smallMap = new SmallMyMap( + STRING1, Integer.valueOf(1), + STRING2, Integer.valueOf(2), + STRING3, Integer.valueOf(3), + STRING4, Integer.valueOf(4), + STRING5, Integer.valueOf(5), + STRING6, Integer.valueOf(6), + STRING7, Integer.valueOf(7), + STRING8, Integer.valueOf(8) + ); + bigMap = new BigMyMap(KEYS); + bucketMap = new MyBucketMap(KEYS); + } + + public void test() throws Exception + { + int i = 0; + int sum = 0; + + while (true) { + Thread.sleep(100L); + int round = (i++ % 4); + + long curr = System.currentTimeMillis(); + String msg; + boolean lf = (round == 0); + int result; + + switch (round) { + + case 0: + msg = "JDK HashMap"; + result = testWithMap(REPS, stdMap); + break; + case 1: + msg = "Custom (small)"; + result = testWithCustom(REPS, smallMap); + break; + case 2: + msg = "Custom (big)"; + result = testWithCustom(REPS, bigMap); + break; + case 3: + msg = "Custom (HashMap)"; + result = testWithBucketMap(REPS, bucketMap); + break; + + default: + throw new Error("Internal error"); + } + + curr = System.currentTimeMillis() - curr; + if (lf) { + System.out.println(); + } + sum += result; + System.out.println("Test '"+msg+"' -> "+curr+" msecs ("+(result & 0xFFFF)+" -> "+sum+")."); + Thread.sleep(100L); + } + } + + private final int testWithMap(int reps, HashMap<String,Integer> ints) + { + int sum = 0; + for (int i = 0; i < reps; ++i) { + for (int index = 0, len = KEYS.length; index < len; ++index) { + Integer I = ints.get(KEYS[index]); + sum += I.intValue(); + } + } + return sum; + } + + private final int testWithCustom(int reps, MyMap ints) + { + int sum = 0; + for (int i = 0; i < reps; ++i) { + for (int index = 0, len = KEYS.length; index < len; ++index) { + String key = KEYS[index]; + Integer I = ints.find(key); + sum += I.intValue(); + } + } + return sum; + } + + private final int testWithBucketMap(int reps, MyBucketMap buckets) + { + int sum = 0; + for (int i = 0; i < reps; ++i) { + for (int index = 0, len = KEYS.length; index < len; ++index) { + String key = KEYS[index]; + Integer I = buckets.find(key); + sum += I.intValue(); + } + } + return sum; + } + + public static void main(String[] args) throws Exception + { + new TestMapSpeed().test(); + } + +}
diff --git a/1.9.10/src/perf/perf/TestMethodDispatchSpeed.java b/1.9.10/src/perf/perf/TestMethodDispatchSpeed.java new file mode 100644 index 0000000..f3d59b9 --- /dev/null +++ b/1.9.10/src/perf/perf/TestMethodDispatchSpeed.java
@@ -0,0 +1,126 @@ +package perf; + +public class TestMethodDispatchSpeed +{ + /* + /********************************************************** + /* Test beans + /********************************************************** + */ + + public interface SerializableString { + public byte[] getUTF8(); + } + + public final class SerializableStringImpl implements SerializableString + { + private final byte[] stuff; + + public SerializableStringImpl(byte[] in) { stuff = in; } + + @Override + public byte[] getUTF8() { return stuff; } + } + + public final class SerializedString + { + private final byte[] stuff; + + public SerializedString(byte[] in) { stuff = in; } + + public byte[] getUTF8() { return stuff; } + } + + /* + /********************************************************** + /* Test methods + /********************************************************** + */ + + private final static int REPS = 1500; + + public void test() throws Exception + { + int i = 0; + int sum = 0; + + while (true) { + try { Thread.sleep(100L); } catch (InterruptedException ie) { } + int round = (i++ % 2); + + long curr = System.currentTimeMillis(); + String msg; + boolean lf = (round == 0); + + byte[] buffer = new byte[64000]; +// final String inputStr = "foobar12345"; + final String inputStr = "abc"; + final byte[] inputBytes = inputStr.getBytes("UTF-8"); + + switch (round) { + + case 0: + msg = "Final Class"; + sum += testWithClass(inputBytes, buffer, REPS); + break; + case 1: + msg = "Interface"; + sum += testWithInterface(inputBytes, buffer, REPS); + break; + + default: + throw new Error("Internal error"); + } + + curr = System.currentTimeMillis() - curr; + if (lf) { + System.out.println(); + } + System.out.println("Test '"+msg+"' -> "+curr+" msecs ("+(sum & 0xFF)+")."); + Thread.sleep(100L); + } + } + + private final int testWithInterface(byte[] input, byte[] buffer, int reps) + { + final SerializedString ss = new SerializedString(input); + int count = 0; + + for (int i = 0; i < reps; ++i) { + final int end = buffer.length - ss.getUTF8().length; + int ptr = 0; + while (ptr < end) { + byte[] curr = ss.getUTF8(); + int len = curr.length; + System.arraycopy(curr, 0, buffer, ptr, len); + ptr += len; + ++count; + } + } + return count; + } + + private final int testWithClass(byte[] input, byte[] buffer, int reps) + { + final SerializableString ss = new SerializableStringImpl(input); + int count = 0; + + for (int i = 0; i < reps; ++i) { + final int end = buffer.length - ss.getUTF8().length; + int ptr = 0; + while (ptr < end) { + byte[] curr = ss.getUTF8(); + int len = curr.length; + System.arraycopy(curr, 0, buffer, ptr, len); + ptr += len; + ++count; + } + } + return count; + } + + public static void main(String[] args) throws Exception + { + new TestMethodDispatchSpeed().test(); + } +}
diff --git a/1.9.10/src/perf/perf/TestNumberPerf.java b/1.9.10/src/perf/perf/TestNumberPerf.java new file mode 100644 index 0000000..61fcd3f --- /dev/null +++ b/1.9.10/src/perf/perf/TestNumberPerf.java
@@ -0,0 +1,120 @@ +package perf; + +public final class TestNumberPerf +{ + final static int REPS = 45000; + + final static long[] NUMBERS = new long[4000]; + static { + for (int i = 0; i < NUMBERS.length; ++i) { + NUMBERS[i] = (i % 9); + } + } + + private TestNumberPerf() { } + + public void test() + { + int i = 0; + int sum = 0; + + while (true) { + try { Thread.sleep(100L); } catch (InterruptedException ie) { } + int round = (i++ % 3); + + long curr = System.currentTimeMillis(); + String msg; + boolean lf = (round == 0); + int count; + + switch (round) { + case 0: + msg = "Compare"; + count = testCompare(REPS, NUMBERS); + break; + case 1: + msg = "ByCast"; + count = testByCast(REPS, NUMBERS); + break; + case 2: + msg = "ByShift"; + count = testByShift(REPS, NUMBERS); + break; + + default: + throw new Error("Internal error"); + } + + sum += count; + + curr = System.currentTimeMillis() - curr; + if (lf) { + System.out.println(); + } + System.out.println("Test '"+msg+"' ("+count+"/"+(sum & 0xFFF)+") -> "+curr+" msecs"); + } + } + + public int testCompare(int reps, long[] numbers) + { + int result = 0; + while (--reps >= 0) { + int count = 0; + for (int i = 0, len = numbers.length; i < len; ++i) { + long l = numbers[i]; + if (l <= Integer.MAX_VALUE && l >= Integer.MIN_VALUE) { + ++count; + } + } + if (count > result) { + result = count; + } + } + return result; + } + + public int testByCast(int reps, long[] numbers) + { + int result = 0; + while (--reps >= 0) { + int count = 0; + for (int i = 0, len = numbers.length; i < len; ++i) { + long l = numbers[i]; + int i2 = (int) l; + long l2 = (long) i2; + if (l2 == l) { + ++count; + } + } + if (count > result) { + result = count; + } + } + return result; + } + + public int testByShift(int reps, long[] numbers) + { + int result = 0; + while (--reps >= 0) { + int count = 0; + for (int i = 0, len = numbers.length; i < len; ++i) { + long l = numbers[i]; + long l2 = ((l << 32) >> 32); + if (l2 == l) { + ++count; + } + } + if (count > result) { + result = count; + } + } + return result; + } + + public static void main(String[] args) throws Exception + { + new TestNumberPerf().test(); + } + +}
diff --git a/1.9.10/src/perf/perf/TestReadPerf.java b/1.9.10/src/perf/perf/TestReadPerf.java new file mode 100644 index 0000000..2f538d1 --- /dev/null +++ b/1.9.10/src/perf/perf/TestReadPerf.java
@@ -0,0 +1,102 @@ +package perf; +import java.io.*; + +import org.codehaus.jackson.*; + +public final class TestReadPerf +{ + private final int REPS; + +// private final static int TEST_PER_GC = 5; + private final static int TEST_PER_GC = 100; + + final JsonFactory mJsonFactory; + + final byte[] mData; + + final String mDataStr; // if testing reader-backed parser + + private TestReadPerf(File f) + throws Exception + { + mJsonFactory = new JsonFactory(); + mData = readData(f); + mDataStr = new String(mData, "UTF-8"); + // Estimate about 10 megs worth of data... + REPS = 1 + (int) (10000000L / mData.length); + System.out.println("Input size: "+mData.length+" bytes ("+mDataStr.length()+" chars); use "+REPS+" reps"); + } + + public void test() + throws Exception + { + int counter = 0; + + while (true) { + try { Thread.sleep(100L); } catch (InterruptedException ie) { } + + long curr = System.currentTimeMillis(); + int result = testRead(REPS); + curr = System.currentTimeMillis() - curr; + System.out.println("Took "+curr+" msecs ("+(result & 0xFF)+")."); + if (++counter >= TEST_PER_GC) { + counter = 0; + try { Thread.sleep(100L); } catch (InterruptedException ie) { } + System.out.println("[GC]"); + System.gc(); + try { Thread.sleep(100L); } catch (InterruptedException ie) { } + } + } + } + + private int testRead(int reps) + throws IOException + { + int count = 0; + JsonParser jp = null; + while (--reps >= 0) { + // Bytes or chars? + jp = mJsonFactory.createJsonParser(mData, 0, mData.length); + //jp = mJsonFactory.createJsonParser(new StringReader(mDataStr)); + JsonToken t; + + while ((t = jp.nextToken()) != null) { + if (t == JsonToken.VALUE_NUMBER_INT) { + count += jp.getIntValue(); + } + if (t == JsonToken.VALUE_STRING) { + count += jp.getText().length(); + } + } + jp.close(); + } + return count; + } + + private final byte[] readData(File f) + throws IOException + { + int len = (int) f.length(); + byte[] data = new byte[len]; + int offset = 0; + FileInputStream fis = new FileInputStream(f); + + while (len > 0) { + int count = fis.read(data, offset, len-offset); + offset += count; + len -= count; + } + + return data; + } + + public static void main(String[] args) + throws Exception + { + if (args.length != 1) { + System.err.println("Usage: java ... <file>"); + System.exit(1); + } + new TestReadPerf(new File(args[0])).test(); + } +}
diff --git a/1.9.10/src/perf/perf/TestSerPerf.java b/1.9.10/src/perf/perf/TestSerPerf.java new file mode 100644 index 0000000..472fd50 --- /dev/null +++ b/1.9.10/src/perf/perf/TestSerPerf.java
@@ -0,0 +1,190 @@ +package perf; + +import java.io.*; + +//import de.undercouch.bson4jackson.BsonFactory; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.smile.*; + +public final class TestSerPerf +{ + /* + /********************************************************** + /* Actual test + /********************************************************** + */ + + private final int REPS; + + private TestSerPerf() throws Exception + { + // Let's try to guestimate suitable size... + REPS = 20000; + } + + private MediaItem buildItem() + { + MediaItem.Content content = new MediaItem.Content(); + content.setPlayer(MediaItem.Player.JAVA); + content.setUri("http://javaone.com/keynote.mpg"); + content.setTitle("Javaone Keynote"); + content.setWidth(640); + content.setHeight(480); + content.setFormat("video/mpeg4"); + content.setDuration(18000000L); + content.setSize(58982400L); + content.setBitrate(262144); + content.setCopyright("None"); + content.addPerson("Bill Gates"); + content.addPerson("Steve Jobs"); + + MediaItem item = new MediaItem(content); + + item.addPhoto(new MediaItem.Photo("http://javaone.com/keynote_large.jpg", "Javaone Keynote", 1024, 768, MediaItem.Size.LARGE)); + item.addPhoto(new MediaItem.Photo("http://javaone.com/keynote_small.jpg", "Javaone Keynote", 320, 240, MediaItem.Size.SMALL)); + + return item; + } + + public void test() + throws Exception + { + int i = 0; + int sum = 0; + + ByteArrayOutputStream result = new ByteArrayOutputStream(); + + final MediaItem item = buildItem(); + final JsonFactory jsonF = + new JsonFactory() +// new org.codehaus.jackson.smile.SmileFactory(); + ; +// ((SmileFactory) jsonF).configure(SmileGenerator.Feature.CHECK_SHARED_NAMES, false); + + final ObjectMapper jsonMapper = new ObjectMapper(jsonF); + +// jsonMapper.configure(SerializationConfig.Feature.USE_STATIC_TYPING, true); + + final SmileFactory smileFactory = new SmileFactory(); + smileFactory.configure(SmileGenerator.Feature.CHECK_SHARED_NAMES, true); + smileFactory.configure(SmileGenerator.Feature.CHECK_SHARED_STRING_VALUES, false); + final ObjectMapper smileMapper = new ObjectMapper(smileFactory); + + // Verify that we can round trip + { + byte[] stuff = jsonMapper.writeValueAsBytes(item); + @SuppressWarnings("unused") + MediaItem back = jsonMapper.readValue(stuff, 0, stuff.length, MediaItem.class); + System.out.println("Warmed up: data size is "+stuff.length+" bytes; "+REPS+" reps -> " + +((REPS * stuff.length) >> 10)+" kB per iteration"); + System.out.println(); + stuff = smileMapper.writeValueAsBytes(item); + System.out.println(" Smile size: "+stuff.length+" bytes"); + } + + JsonNode root = jsonMapper.valueToTree(item); + + while (true) { +// Thread.sleep(150L); + ++i; + int round = (i % 3); + + // override? +// round = 4; + + long curr = System.currentTimeMillis(); + String msg; + + switch (round) { + + case 0: + msg = "Serialize, JSON"; + sum += testObjectSer(jsonMapper, item, REPS+REPS, result); + break; + + case 1: + msg = "Serialize, JSON/manual"; + sum += testObjectSer(jsonMapper.getJsonFactory(), item, REPS+REPS, result); + break; + + case 2: + msg = "Serialize, JsonNode"; + sum += testNodeSer(jsonMapper, root, REPS+REPS, result); +// sum += testNodeSer(smileMapper, root, REPS+REPS, result); + break; + + /* + case 3: + msg = "Serialize, Smile"; + sum += testObjectSer(smileMapper, item, REPS, result); + break; + + case 4: + msg = "Serialize, Smile/manual"; + sum += testObjectSer(smileFactory, item, REPS+REPS, result); + break; +*/ + + + /* + case 4: + msg = "Serialize, BSON"; + sum += testObjectSer(new ObjectMapper(new BsonFactory()), item, REPS, result); + break; + */ + + default: + throw new Error("Internal error"); + } + + curr = System.currentTimeMillis() - curr; + if (round == 0) { System.out.println(); } + System.out.println("Test '"+msg+"' -> "+curr+" msecs ("+(sum & 0xFF)+")."); + if ((i & 0x1F) == 0) { // GC every 64 rounds + System.out.println("[GC]"); + Thread.sleep(20L); + System.gc(); + Thread.sleep(20L); + } + } + } + + protected int testObjectSer(ObjectMapper mapper, Object value, int reps, ByteArrayOutputStream result) + throws Exception + { + for (int i = 0; i < reps; ++i) { + result.reset(); + mapper.writeValue(result, value); + } + return result.size(); // just to get some non-optimizable number + } + + protected int testNodeSer(ObjectMapper mapper, JsonNode value, int reps, ByteArrayOutputStream result) + throws Exception + { + for (int i = 0; i < reps; ++i) { + result.reset(); + mapper.writeValue(result, value); + } + return result.size(); // just to get some non-optimizable number + } + + protected int testObjectSer(JsonFactory jf, MediaItem value, int reps, ByteArrayOutputStream result) + throws Exception + { + for (int i = 0; i < reps; ++i) { + result.reset(); + JsonGenerator jgen = jf.createJsonGenerator(result, JsonEncoding.UTF8); + value.serialize(jgen); + jgen.close(); + } + return result.size(); // just to get some non-optimizable number + } + + public static void main(String[] args) throws Exception + { + new TestSerPerf().test(); + } +}
diff --git a/1.9.10/src/perf/perf/TestStringDeserPerf.java b/1.9.10/src/perf/perf/TestStringDeserPerf.java new file mode 100644 index 0000000..687cd9f --- /dev/null +++ b/1.9.10/src/perf/perf/TestStringDeserPerf.java
@@ -0,0 +1,171 @@ +package perf; + +public class TestStringDeserPerf +{ + private final static int REPS = 250000; + + final static int LEN = 111; + + static final byte[] BYTES = new byte[LEN]; + static { + for (int i = 0; i < LEN; ++i) { + BYTES[i] = (byte) (32 + i & 15); + } + } + + private void test() throws Exception + { + int i = 0; + int sum = 0; + + while (true) { + try { Thread.sleep(100L); } catch (InterruptedException ie) { } + int round = (i++ % 2); + + long curr = System.currentTimeMillis(); + String msg; + boolean lf = (round == 0); + + sum = 0; + + switch (round) { + + case 0: + msg = "Char[]"; + sum += testCharArray(); + break; + case 1: + msg = "StringBuilder"; + sum += testStringBuilder(); + break; + case 2: + msg = "Char[] x 4"; + sum += testCharArray2(); + break; + default: + throw new Error("Internal error"); + } + + curr = System.currentTimeMillis() - curr; + if (lf) { + System.out.println(); + } + System.out.println("Test '"+msg+"' -> "+curr+" msecs ("+(sum & 0xFF)+")."); + } + } + + private final int testCharArray() + { + String result = null; + int reps = REPS; + char[] buffer = new char[1000]; + final byte[] INPUT = BYTES; + while (--reps >= 0) { + int i = 0; + for (int len = INPUT.length; i < len; ++i) { + buffer[i] = (char) INPUT[i]; + } + result = new String(buffer, 0, i); + } + if (result.length() != INPUT.length) { + throw new Error(); + } + return result.hashCode(); + } + + private final int testCharArray2() + { + String result = null; + int reps = REPS; + char[] buffer = new char[1000]; + final byte[] INPUT = BYTES; + while (--reps >= 0) { + int i = 0; + int end = INPUT.length - 4; + while (i <= end) { + buffer[i] = (char) INPUT[i]; + ++i; + buffer[i] = (char) INPUT[i]; + ++i; + buffer[i] = (char) INPUT[i]; + ++i; + buffer[i] = (char) INPUT[i]; + ++i; + } + end += 4; + if (i < end) { + buffer[i] = (char) INPUT[i]; + if (++i < end) { + buffer[i] = (char) INPUT[i]; + if (++i < end) { + buffer[i] = (char) INPUT[i]; + } + } + } + result = new String(buffer, 0, i); + } + if (result.length() != INPUT.length) { + throw new Error(); + } + return result.hashCode(); + } + +/* + private final int testStringBuilder() + { + String result = null; + int reps = REPS; + final byte[] INPUT = BYTES; + final StringBuilder sb = new StringBuilder(INPUT.length); + while (--reps >= 0) { + sb.setLength(0); + final int len = INPUT.length; + for (int i = 0; i < len; ++i) { + sb.append((char) INPUT[i]); + } + result = sb.toString(); + } + return result.hashCode(); + } + */ + + // Version that does not reuse instances + private final int testStringBuilder() + { + String result = null; + int reps = REPS; + final byte[] INPUT = BYTES; + while (--reps >= 0) { + final int len = INPUT.length; + StringBuilder sb = new StringBuilder(len); + for (int i = 0; i < len; ++i) { + sb.append((char) INPUT[i]); + } + result = sb.toString(); + } + return result.hashCode(); + } + + /* + private final int testStringBuffer() + { + String result = null; + int reps = REPS; + final byte[] INPUT = BYTES; + while (--reps >= 0) { + final int len = INPUT.length; + StringBuffer sb = new StringBuffer(len); + for (int i = 0; i < len; ++i) { + sb.append((char) INPUT[i]); + } + result = sb.toString(); + } + return result.hashCode(); + } + */ + + public static void main(String[] args) throws Exception + { + new TestStringDeserPerf().test(); + } +}
diff --git a/1.9.10/src/perf/perf/TestStringSerPerf.java b/1.9.10/src/perf/perf/TestStringSerPerf.java new file mode 100644 index 0000000..bab4dc7 --- /dev/null +++ b/1.9.10/src/perf/perf/TestStringSerPerf.java
@@ -0,0 +1,119 @@ +package perf; +import java.io.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.*; + +/** + * Micro benchmark for testing whether specialized String serialization + * functionality is faster than generic one + */ +public final class TestStringSerPerf +{ + private final int REPS; + private final ObjectMapper _mapper; + + final JsonNode _tree; + + final int _byteSize; + + public TestStringSerPerf(File f) + throws Exception + { + _mapper = new ObjectMapper(); + int length = (int) f.length(); + _tree = _mapper.readValue(f, JsonNode.class); + // Let's try to guestimate suitable size... ~2 megs + REPS = 5 + ((2 * 1000 * 1000) / length); + + // Also: figure out byte size + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + _mapper.writeValue(bos, _tree); + _byteSize = bos.size(); + + System.out.println("DEBUG: byte size: "+_byteSize+"; "+REPS+" reps"); + } + + public void test() + throws Exception + { + int i = 0; + int sum = 0; + + while (true) { + try { Thread.sleep(100L); } catch (InterruptedException ie) { } + int round = (i++ % 3); + + long curr = System.currentTimeMillis(); + String msg; + boolean lf = (round == 0); + + switch (round) { + + case 0: + msg = "Byte[]"; + sum += testToBytes(); + break; + case 1: + msg = "StringWriter"; + sum += testUsingStringWriter(); + break; + case 2: + msg = "String, specialized"; + sum += testUsingSpecial(); + break; + + default: + throw new Error("Internal error"); + } + + curr = System.currentTimeMillis() - curr; + if (lf) { + System.out.println(); + } + System.out.println("Test '"+msg+"' -> "+curr+" msecs (" + +(sum & 0xFF)+")."); + } + } + + protected int testToBytes() throws Exception + { + int total = 0; + for (int i = 0; i < REPS; ++i) { + ByteArrayOutputStream out = new ByteArrayOutputStream(_byteSize); + _mapper.writeValue(out, _tree); + total += out.size(); + } + return total; + } + + protected int testUsingStringWriter() throws Exception + { + int total = 0; + for (int i = 0; i < REPS; ++i) { + StringWriter sw = new StringWriter(16); + _mapper.writeValue(sw, _tree); + total += sw.toString().length(); + } + return total; + } + + protected int testUsingSpecial() throws Exception + { + int total = 0; + for (int i = 0; i < REPS; ++i) { + String str = _mapper.writeValueAsString(_tree); + total += str.length(); + } + return total; + } + + public static void main(String[] args) throws Exception + { + if (args.length != 1) { + System.err.println("Usage: java ... <file>"); + System.exit(1); + } + new TestStringSerPerf(new File(args[0])).test(); + } +}
diff --git a/1.9.10/src/perf/perf/TestViewPerf.java b/1.9.10/src/perf/perf/TestViewPerf.java new file mode 100644 index 0000000..c89588f --- /dev/null +++ b/1.9.10/src/perf/perf/TestViewPerf.java
@@ -0,0 +1,144 @@ +package perf; +import java.io.*; + +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.JsonView; + +public final class TestViewPerf +{ + /* + ///////////////////////////////////////////////////// + // Bean classes + ///////////////////////////////////////////////////// + */ + + static class ViewA { } + static class ViewB { } + + static class ViewBean + { + final Bean2 _bean = new Bean2(); + + @JsonView({ViewA.class, ViewB.class}) + public Bean2 getBean() { return _bean; } + + @JsonView({ViewB.class, ViewA.class}) + public String getBean2() { return "abc-def"; } + + @JsonView({ViewB.class, ViewA.class}) + public int getBean3() { return 218985; } + + @JsonView({ViewA.class, ViewB.class}) + public Bean2 getBean4() { return _bean; } + + @JsonView({ViewA.class}) + public String getText2() { return "foobar"; } + + @JsonView({ViewA.class}) + public String getText3() { return ".......\n"; } + } + + static class NonViewBean + { + final Bean2 _bean = new Bean2(); + + public Bean2 getBean() { return _bean; } + public String getBean2() { return "abc-def"; } + public int getBean3() { return 218985; } + public Bean2 getBean4() { return _bean; } + public String getText2() { return "foobar"; } + public String getText3() { return ".......\n"; } + } + + static class Bean2 { + public int getX() { return 3; } + public String getName() { return "foobar"; } + } + + private final int REPS; + private final ObjectMapper _mapper; + + private TestViewPerf() + throws Exception + { + _mapper = new ObjectMapper(); + REPS = 2400; + } + + public void test() + throws Exception + { + int i = 0; + + ByteArrayOutputStream out = new ByteArrayOutputStream(); + + final ViewBean viewBean = new ViewBean(); + final NonViewBean nonViewBean = new NonViewBean(); + + while (true) { + try { Thread.sleep(100L); } catch (InterruptedException ie) { } + int round = (i++ % 3); + + long curr = System.currentTimeMillis(); + String msg; + boolean lf = (round == 0); + int result; + + switch (round) { + + case 0: + msg = "With view"; + result = testViewSer(viewBean, REPS, out, ViewA.class); + break; + case 1: + msg = "WithOUT view"; + result = testViewSer(viewBean, REPS, out, null); + break; + case 2: + msg = "NO view"; + result = testSer(nonViewBean, REPS, out, null); + break; + + default: + throw new Error("Internal error"); + } + + curr = System.currentTimeMillis() - curr; + if (lf) { + System.out.println(); + } + System.out.println("Test '"+msg+"' -> "+curr+" msecs (" + +result+")."); + } + } + + protected int testViewSer(Object value, int reps, ByteArrayOutputStream result, Class<?> view) + throws Exception + { + ObjectWriter w = _mapper.writerWithView(view); + for (int i = 0; i < reps; ++i) { + result.reset(); + w.writeValue(result, value); + w.writeValue(result, value); + w.writeValue(result, value); + } + return result.size(); + } + + protected int testSer(Object value, int reps, ByteArrayOutputStream result, Class<?> dummyView) + throws Exception + { + for (int i = 0; i < reps; ++i) { + result.reset(); + _mapper.writeValue(result, value); + _mapper.writeValue(result, value); + _mapper.writeValue(result, value); + } + return result.size(); + } + + public static void main(String[] args) throws Exception + { + new TestViewPerf().test(); + } +}
diff --git a/1.9.10/src/perf/perf/TestWritePerf.java b/1.9.10/src/perf/perf/TestWritePerf.java new file mode 100644 index 0000000..b5b526c --- /dev/null +++ b/1.9.10/src/perf/perf/TestWritePerf.java
@@ -0,0 +1,212 @@ +package perf; +import java.io.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.io.SerializedString; +import org.codehaus.jackson.smile.SmileFactory; +import org.codehaus.jackson.smile.SmileGenerator; + +public class TestWritePerf +{ + private final int REPS = 250000; + + private final static String NAME1 = "name"; + private final static String NAME2 = "value"; + private final static String NAME3 = "longerName"; + private final static String NAME4 = "something"; + private final static String NAME5 = "x"; + private final static String NAME6 = "width"; + + private final static SerializedString TOKEN1 = new SerializedString(NAME1); + private final static SerializedString TOKEN2 = new SerializedString(NAME2); + private final static SerializedString TOKEN3 = new SerializedString(NAME3); + private final static SerializedString TOKEN4 = new SerializedString(NAME4); + private final static SerializedString TOKEN5 = new SerializedString(NAME5); + private final static SerializedString TOKEN6 = new SerializedString(NAME6); + + final JsonFactory _jsonFactory; + + final SmileFactory _smileFactory; + + private TestWritePerf() throws Exception + { + _jsonFactory = new JsonFactory(); + _smileFactory = new SmileFactory(); + // whether to use back-refs for field names has measurable impact on ser/deser (but different direction): + _smileFactory.configure(SmileGenerator.Feature.CHECK_SHARED_NAMES, false); + } + + public void test() throws Exception + { + int round = 0; + + while (true) { + try { Thread.sleep(100L); } catch (InterruptedException ie) { } + testCopy(REPS, round); + ++round; + } + } + + private long testCopy(int reps, int round) + throws IOException + { + int mode = (round % 1); + if (mode == 0) System.out.println(); + + final JsonFactory factory; + final boolean useSymbols; + boolean useBytes = true; + String desc; + final DummyOutputStream out = new DummyOutputStream(); + final DummyWriter outw = new DummyWriter(); + + switch (mode) { + case 0: + factory = _jsonFactory; + desc = "JsonGenerator"; + useSymbols = true; + break; + case 1: + factory = _jsonFactory; + desc = "JsonGenerator"; + useSymbols = false; + break; + case 2: + factory = _smileFactory; + desc = "SmileGenerator"; + useSymbols = true; + break; + case 3: + factory = _smileFactory; + desc = "SmileGenerator"; + useSymbols = false; + break; + case 4: + factory = _jsonFactory; + desc = "JsonGenerator/Writer"; + useSymbols = true; + useBytes = false; + break; + case 5: + factory = _jsonFactory; + desc = "JsonGenerator/Writer"; + useSymbols = false; + useBytes = false; + break; + default: + throw new Error(); + } + final long start = System.currentTimeMillis(); + JsonGenerator jg = null; + if (useSymbols) { + while (--reps >= 0) { + jg = useBytes ? factory.createJsonGenerator(out, JsonEncoding.UTF8) + : factory.createJsonGenerator(outw); + writeUsingTokens(jg); + jg.close(); + } + } else { + while (--reps >= 0) { + jg = useBytes ? factory.createJsonGenerator(out, JsonEncoding.UTF8) + : factory.createJsonGenerator(outw); + writeUsingNames(jg); + jg.close(); + } + } + jg.close(); + + long time = System.currentTimeMillis() - start; + if (useSymbols) { + desc += "/TOKEN"; + } else { + desc += "/name"; + } + int count = useBytes ? out.getCount() : outw.getCount(); + System.out.println("Took "+time+" msecs (round "+round+") for: "+desc +" / "+count); + return time; + } + + private final void writeUsingNames(JsonGenerator jgen) + throws IOException + { + jgen.writeStartObject(); + jgen.writeFieldName(NAME1); + jgen.writeNumber(10); + jgen.writeFieldName(NAME2); + jgen.writeBoolean(true); + jgen.writeFieldName(NAME3); + jgen.writeNull(); + jgen.writeFieldName(NAME4); + jgen.writeBoolean(false); + jgen.writeFieldName(NAME5); + jgen.writeNumber(3); + jgen.writeFieldName(NAME6); + jgen.writeNull(); + jgen.writeEndObject(); + } + + private final void writeUsingTokens(JsonGenerator jgen) throws IOException + { + jgen.writeStartObject(); + jgen.writeFieldName(TOKEN1); + jgen.writeNumber(10); + jgen.writeFieldName(TOKEN2); + jgen.writeBoolean(true); + jgen.writeFieldName(TOKEN3); + jgen.writeNull(); + jgen.writeFieldName(TOKEN4); + jgen.writeBoolean(false); + jgen.writeFieldName(TOKEN5); + jgen.writeNumber(3); + jgen.writeFieldName(TOKEN6); + jgen.writeNull(); + jgen.writeEndObject(); + } + + public static void main(String[] args) + throws Exception + { + if (args.length != 0) { + System.err.println("Usage: java ..."); + System.exit(1); + } + new TestWritePerf().test(); + } + + private final static class DummyOutputStream + extends OutputStream + { + public int count = 0; + + @Override public void write(byte[] b) { count += b.length; } + @Override public void write(byte[] b, int offset, int len) { count += len; } + + @Override + public void write(int b) throws IOException { + ++count; + } + + public int getCount() { return count; } + } + + private final static class DummyWriter + extends Writer + { + public int count = 0; + + @Override + public void close() throws IOException { + } + + @Override + public void flush() throws IOException { + } + + @Override + public void write(char[] cbuf, int off, int len) throws IOException { + count += len; + } + + public int getCount() { return count; } + } +}
diff --git a/1.9.10/src/perf/perf/UTF8Reader.java b/1.9.10/src/perf/perf/UTF8Reader.java new file mode 100644 index 0000000..e42dfd9 --- /dev/null +++ b/1.9.10/src/perf/perf/UTF8Reader.java
@@ -0,0 +1,367 @@ +package perf; +//package org.codehaus.jackson.io; + + +import java.io.*; + +import org.codehaus.jackson.io.IOContext; + +/** + * Optimized Reader that reads UTF-8 encoded content from an input stream. + * In addition to doing (hopefully) optimal conversion, it can also take + * array of "pre-read" (leftover) bytes; this is necessary when preliminary + * stream/reader is trying to figure out character encoding. + */ +public final class UTF8Reader + extends BaseReader +{ + char mSurrogate = NULL_CHAR; + + /** + * Total read character count; used for error reporting purposes + */ + int mCharCount = 0; + + /** + * Total read byte count; used for error reporting purposes + */ + int mByteCount = 0; + + /* + //////////////////////////////////////// + // Life-cycle + //////////////////////////////////////// + */ + + public UTF8Reader(IOContext ctxt, + InputStream in, byte[] buf, int ptr, int len) + { + super(ctxt, in, buf, ptr, len); + } + + /* + //////////////////////////////////////// + // Public API + //////////////////////////////////////// + */ + + @Override + public int read(char[] cbuf, int start, int len) + throws IOException + { + // Already EOF? + if (mBuffer == null) { + return -1; + } + if (len < 1) { + return len; + } + // Let's then ensure there's enough room... + if (start < 0 || (start+len) > cbuf.length) { + reportBounds(cbuf, start, len); + } + + len += start; + int outPtr = start; + + // Ok, first; do we have a surrogate from last round? + if (mSurrogate != NULL_CHAR) { + cbuf[outPtr++] = mSurrogate; + mSurrogate = NULL_CHAR; + // No need to load more, already got one char + } else { + /* To prevent unnecessary blocking (esp. with network streams), + * we'll only require decoding of a single char + */ + int left = (mLength - mPtr); + + /* So; only need to load more if we can't provide at least + * one more character. We need not do thorough check here, + * but let's check the common cases here: either completely + * empty buffer (left == 0), or one with less than max. byte + * count for a single char, and starting of a multi-byte + * encoding (this leaves possibility of a 2/3-byte char + * that is still fully accessible... but that can be checked + * by the load method) + */ + if (left < 4) { + // Need to load more? + if (left < 1 || mBuffer[mPtr] < 0) { + if (!loadMore(left)) { // (legal) EOF? + return -1; + } + } + } + } + + /* This may look silly, but using a local var is indeed faster + * (if and when HotSpot properly gets things running) than + * member variable... + */ + byte[] buf = mBuffer; + int inPtr = mPtr; + int inBufLen = mLength; + + main_loop: + while (outPtr < len) { + // At this point we have at least one byte available + int c = (int) buf[inPtr++]; + + /* Let's first do the quickie loop for common case; 7-bit + * ascii: + */ + if (c >= 0) { // ascii? can probably loop, then + cbuf[outPtr++] = (char) c; // ok since MSB is never on + + /* Ok, how many such chars could we safely process + * without overruns? (will combine 2 in-loop comparisons + * into just one) + */ + int outMax = (len - outPtr); // max output + int inMax = (inBufLen - inPtr); // max input + int inEnd = inPtr + ((inMax < outMax) ? inMax : outMax); + + ascii_loop: + while (true) { + if (inPtr >= inEnd) { + break main_loop; + } + c = (int) buf[inPtr++]; + if (c < 0) { // multi-byte + break ascii_loop; + } + cbuf[outPtr++] = (char) c; + } + } + + int needed; + + // Ok; if we end here, we got multi-byte combination + if ((c & 0xE0) == 0xC0) { // 2 bytes (0x0080 - 0x07FF) + c = (c & 0x1F); + needed = 1; + } else if ((c & 0xF0) == 0xE0) { // 3 bytes (0x0800 - 0xFFFF) + c = (c & 0x0F); + needed = 2; + } else if ((c & 0xF8) == 0xF0) { + // 4 bytes; double-char BS, with surrogates and all... + c = (c & 0x0F); + needed = 3; + } else { + reportInvalidInitial(c & 0xFF, outPtr-start); + // never gets here... + needed = 1; + } + /* Do we have enough bytes? If not, let's just push back the + * byte and leave, since we have already gotten at least one + * char decoded. This way we will only block (with read from + * input stream) when absolutely necessary. + */ + if ((inBufLen - inPtr) < needed) { + --inPtr; + break main_loop; + } + + int d = (int) buf[inPtr++]; + if ((d & 0xC0) != 0x080) { + reportInvalidOther(d & 0xFF, outPtr-start); + } + c = (c << 6) | (d & 0x3F); + + if (needed > 1) { // needed == 1 means 2 bytes total + d = buf[inPtr++]; // 3rd byte + if ((d & 0xC0) != 0x080) { + reportInvalidOther(d & 0xFF, outPtr-start); + } + c = (c << 6) | (d & 0x3F); + if (needed > 2) { // 4 bytes? (need surrogates) + d = buf[inPtr++]; + if ((d & 0xC0) != 0x080) { + reportInvalidOther(d & 0xFF, outPtr-start); + } + c = (c << 6) | (d & 0x3F); + if (c > LAST_VALID_UNICODE_CHAR) { + reportInvalid(c, outPtr-start, + "(above "+Integer.toHexString(LAST_VALID_UNICODE_CHAR)); + } + /* Ugh. Need to mess with surrogates. Ok; let's inline them + * there, then, if there's room: if only room for one, + * need to save the surrogate for the rainy day... + */ + c -= 0x10000; // to normalize it starting with 0x0 + cbuf[outPtr++] = (char) (0xD800 + (c >> 10)); + // hmmh. can this ever be 0? (not legal, at least?) + c = (0xDC00 | (c & 0x03FF)); + + // Room for second part? + if (outPtr >= len) { // nope + mSurrogate = (char) c; + break main_loop; + } + // sure, let's fall back to normal processing: + } + + /* 08-Jun-2007, TSa: Not sure if it's really legal + * to get surrogate chars here: JSON specs do not + * prevent them, which is different from xml. So + * for now let's not worry about them. If checks + * are needed, can uncomment following: + */ + + /* + else { + // Otherwise, need to check that 3-byte chars are + // legal ones (should not expand to surrogates) + if (c >= 0xD800) { + // But first, let's check max chars: + if (c < 0xE000) { + reportInvalid(c, outPtr-start, "(a surrogate character) "); + } + } + } + */ + } + cbuf[outPtr++] = (char) c; + if (inPtr >= inBufLen) { + break main_loop; + } + } + + mPtr = inPtr; + len = outPtr - start; + mCharCount += len; + return len; + } + + /* + //////////////////////////////////////// + // Internal methods + //////////////////////////////////////// + */ + + private void reportInvalidInitial(int mask, int offset) + throws IOException + { + // input (byte) ptr has been advanced by one, by now: + int bytePos = mByteCount + mPtr - 1; + int charPos = mCharCount + offset + 1; + + throw new CharConversionException("Invalid UTF-8 start byte 0x" + +Integer.toHexString(mask) + +" (at char #"+charPos+", byte #"+bytePos+")"); + } + + private void reportInvalidOther(int mask, int offset) + throws IOException + { + int bytePos = mByteCount + mPtr - 1; + int charPos = mCharCount + offset; + + throw new CharConversionException("Invalid UTF-8 middle byte 0x" + +Integer.toHexString(mask) + +" (at char #"+charPos+", byte #"+bytePos+")"); + } + + private void reportUnexpectedEOF(int gotBytes, int needed) + throws IOException + { + int bytePos = mByteCount + gotBytes; + int charPos = mCharCount; + + throw new CharConversionException("Unexpected EOF in the middle of a multi-byte char: got " + +gotBytes+", needed "+needed + +", at char #"+charPos+", byte #"+bytePos+")"); + } + + private void reportInvalid(int value, int offset, String msg) + throws IOException + { + int bytePos = mByteCount + mPtr - 1; + int charPos = mCharCount + offset; + + throw new CharConversionException("Invalid UTF-8 character 0x" + +Integer.toHexString(value)+msg + +" at char #"+charPos+", byte #"+bytePos+")"); + } + + /** + * @param available Number of "unused" bytes in the input buffer + * + * @return True, if enough bytes were read to allow decoding of at least + * one full character; false if EOF was encountered instead. + */ + private boolean loadMore(int available) + throws IOException + { + mByteCount += (mLength - available); + + // Bytes that need to be moved to the beginning of buffer? + if (available > 0) { + if (mPtr > 0) { + for (int i = 0; i < available; ++i) { + mBuffer[i] = mBuffer[mPtr+i]; + } + mPtr = 0; + } + mLength = available; + } else { + /* Ok; here we can actually reasonably expect an EOF, + * so let's do a separate read right away: + */ + mPtr = 0; + int count = mIn.read(mBuffer); + if (count < 1) { + mLength = 0; + if (count < 0) { // -1 + freeBuffers(); // to help GC? + return false; + } + // 0 count is no good; let's err out + reportStrangeStream(); + } + mLength = count; + } + + /* We now have at least one byte... and that allows us to + * calculate exactly how many bytes we need! + */ + int c = (int) mBuffer[0]; + if (c >= 0) { // single byte (ascii) char... cool, can return + return true; + } + + // Ok, a multi-byte char, let's check how many bytes we'll need: + int needed; + if ((c & 0xE0) == 0xC0) { // 2 bytes (0x0080 - 0x07FF) + needed = 2; + } else if ((c & 0xF0) == 0xE0) { // 3 bytes (0x0800 - 0xFFFF) + needed = 3; + } else if ((c & 0xF8) == 0xF0) { + // 4 bytes; double-char BS, with surrogates and all... + needed = 4; + } else { + reportInvalidInitial(c & 0xFF, 0); + // never gets here... but compiler whines without this: + needed = 1; + } + + /* And then we'll just need to load up to that many bytes; + * if an EOF is hit, that'll be an error. But we need not do + * actual decoding here, just load enough bytes. + */ + while (mLength < needed) { + int count = mIn.read(mBuffer, mLength, mBuffer.length - mLength); + if (count < 1) { + if (count < 0) { // -1, EOF... no good! + freeBuffers(); + reportUnexpectedEOF(mLength, needed); + } + // 0 count is no good; let's err out + reportStrangeStream(); + } + mLength += count; + } + return true; + } +} +
diff --git a/1.9.10/src/sample/sample/BeanWithCursor.java b/1.9.10/src/sample/sample/BeanWithCursor.java new file mode 100644 index 0000000..9babf71 --- /dev/null +++ b/1.9.10/src/sample/sample/BeanWithCursor.java
@@ -0,0 +1,118 @@ +package sample; +// no package, i.e. at root of sample/extra + +import java.io.*; + +import org.codehaus.jackson.*; + +public class BeanWithCursor +{ + // // Helper bean + + public static class TwitterEntry + { + long _id; + String _text; + int _fromUserId, _toUserId; + String _languageCode; + + public TwitterEntry() { } + + public void setId(long id) { _id = id; } + public void setText(String text) { _text = text; } + public void setFromUserId(int id) { _fromUserId = id; } + public void setToUserId(int id) { _toUserId = id; } + public void setLanguageCode(String languageCode) { _languageCode = languageCode; } + + public long getId() { return _id; } + public String getText() { return _text; } + public int getFromUserId() { return _fromUserId; } + public int getToUserId() { return _toUserId; } + public String getLanguageCode() { return _languageCode; } + + @Override + public String toString() { + return "[Tweet, id: "+_id+", text='"+_text+"', from: "+_fromUserId+", to: "+_toUserId+", lang: "+_languageCode+"]"; + } + } + + // // Main test code + + public BeanWithCursor() { } + + private TwitterEntry read(JsonParser jp) + throws IOException + { + // First: verify that we got "Json Object": + if (jp.nextToken() != JsonToken.START_OBJECT) { + throw new IOException("Expected data to start with an Object"); + } + TwitterEntry result = new TwitterEntry(); + // Iterate over object fields: + while (jp.nextToken() != JsonToken.END_OBJECT) { + String fieldName = jp.getCurrentName(); + // Let's move to value + jp.nextToken(); + if (fieldName.equals("id")) { + result.setId(jp.getLongValue()); + } else if (fieldName.equals("text")) { + result.setText(jp.getText()); + } else if (fieldName.equals("fromUserId")) { + result.setFromUserId(jp.getIntValue()); + } else if (fieldName.equals("toUserId")) { + result.setToUserId(jp.getIntValue()); + } else if (fieldName.equals("languageCode")) { + result.setLanguageCode(jp.getText()); + } else { + // ignore, or signal error + throw new IOException("Unrecognized field '"+fieldName+"'"); + } + } + jp.close(); // important to close both parser and underlying File reader + return result; + } + + private void write(JsonGenerator jg, TwitterEntry entry) + throws IOException + { + jg.writeStartObject(); + // can either do "jg.writeFieldName(...) + jg.writeNumber()", or this: + jg.writeNumberField("id", entry.getId()); + jg.writeStringField("text", entry.getText()); + jg.writeNumberField("fromUserId", entry.getFromUserId()); + jg.writeNumberField("toUserId", entry.getToUserId()); + jg.writeStringField("langugeCode", entry.getLanguageCode()); + jg.writeEndObject(); + jg.close(); + } + + private void process(File input) + throws IOException + { + JsonFactory jsonF = new JsonFactory(); + JsonParser jp = jsonF.createJsonParser(input); + TwitterEntry entry = read(jp); + + // let's write to a file, using UTF-8 encoding (only sensible one) + StringWriter strw = new StringWriter(); + JsonGenerator jg = jsonF.createJsonGenerator(strw); + jg.useDefaultPrettyPrinter(); // enable indentation just to make debug/testing easier + + // Here we would modify it... for now, will just (re)indent it + + write(jg, entry); + + System.out.println("Result = ["+strw.toString()+"]"); + } + + public static void main(String[] args) + throws IOException + { + if (args.length != 1) { + System.err.println("Usage: java BeanWithCursor [input-file]"); + System.exit(1); + } + File f = new File(args[0]); + new BeanWithCursor().process(f); + } +}
diff --git a/1.9.10/src/sample/sample/CustomSerializationView.java b/1.9.10/src/sample/sample/CustomSerializationView.java new file mode 100644 index 0000000..51b5533 --- /dev/null +++ b/1.9.10/src/sample/sample/CustomSerializationView.java
@@ -0,0 +1,174 @@ +package sample; +// no package, i.e. at root of sample/extra + +import java.util.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.introspect.BasicBeanDescription; +import org.codehaus.jackson.map.ser.BeanPropertyWriter; +import org.codehaus.jackson.map.ser.BeanSerializerBuilder; +import org.codehaus.jackson.map.ser.CustomSerializerFactory; + +/** + * Example code to show how to make use of underlying mechanisms + * used for implementing standard JsonView implementation, but + * without using <code>\@JsonView</code> annotations. + *<p> + * In this case, we will just want to suppress output of one of + * fields, and tranform value of another. Former could be done + * using other (annotation-based) suppression methods. + *<p> + * Note that for the showed use case this is not the simplest + * solution -- basic custom JsonSerializer implementation would be -- + * it is just to give an idea of kinds of things that can be + * done, and one additional mechanism that allows only partially + * custom handling. This is useful for more complex POJOs, where + * most of default handling is acceptable. + * + * @since 1.4 + */ +public class CustomSerializationView +{ + /* + *********************************************************** + * First helper classes we need + *********************************************************** + */ + + /** + * Simple value class handling of which we want to customize. + */ + static class ViewBean + { + public String name; + public String value; + public String secret; + + public ViewBean(String name, String value, String secret) { + this.name = name; + this.value = value; + this.secret = secret; + } + } + + /** + * And then custom bean property writer that implements + * custom serialization functionality for one of properties + */ + static class UpperCasingWriter + extends BeanPropertyWriter + { + final BeanPropertyWriter _writer; + + /** + * @param w Original unmodified bean property writer that + * we delegate some calls to + */ + public UpperCasingWriter(BeanPropertyWriter w) { + // use "copy constructor" to get defaults + super(w); + _writer = w; + } + + public UpperCasingWriter(BeanPropertyWriter w, JsonSerializer<Object> ser) { + super(w, ser); + _writer = w; + } + + @Override + public void serializeAsField(Object bean, JsonGenerator jgen, SerializerProvider prov) + throws Exception + { + // We know the type (although interface can't expose it) + String value = ((ViewBean) bean).name; + // Convert nulls to "", otherwise upper case + value = (value == null) ? "" : value.toUpperCase(); + jgen.writeStringField("name", value); + } + + @Override + public BeanPropertyWriter withSerializer(JsonSerializer<Object> ser) + { + return new UpperCasingWriter(_writer, ser); + } + } + + /** + * Custom bean factory that is needed to process bean property writers + * to implement custom view handling + */ + public static class CustomBeanFactory + extends CustomSerializerFactory + // (CSF extends BeanSerializerFactory) + { + public CustomBeanFactory() { } + + /** + * Here we will modify serializer such that it has two modes: + * default handling when no JsonView is enabled; and other (custom) + * when viess are enabled. Note that we could also just have forced + * serialization for all cases. + */ + @Override + protected void processViews(SerializationConfig config, BeanSerializerBuilder builder) + { + // Let's use default serializer modification as the baseline + super.processViews(config, builder); + + /* And only change handling of that one bean (more likely, + * you would want to handle all classes in a package, or with + * some name -- this would be less work than having separate + * custom serializer for all classes) + */ + BasicBeanDescription beanDesc = builder.getBeanDescription(); + if (beanDesc.getBeanClass() == ViewBean.class) { + List<BeanPropertyWriter> props = builder.getProperties(); + BeanPropertyWriter[] writers = props.toArray(new BeanPropertyWriter[props.size()]); + for (int i = 0; i < writers.length; ++i) { + String pname = writers[i].getName(); + if ("secret".equals(pname)) { + // remove serializer, filters it out + writers[i] = null; + } else if ("name".equals(pname)) { + // This one we'll just upper case for fun + writers[i] = new UpperCasingWriter(writers[i]); + } + } + // Important: update builder with filtered property definitions + builder.setFilteredProperties(writers); + } + } + } + + /* + *********************************************************** + * Then simple test code + *********************************************************** + */ + + public static void main(String[] args) throws Exception + { + ViewBean bean = new ViewBean("mr bean", "goofy", "secret!"); + ObjectMapper mapper = new ObjectMapper(); + mapper.setSerializerFactory(new CustomBeanFactory()); + + // First, without enabling view handling: + System.out.println("With default serializer: "+mapper.writeValueAsString(bean)); + + // Then with customized view-handling + /* note: View class being passed is irrelevant since we customize handling) + * Also: setting view would not be necessary if we just completely + * overrode handling (we didn't, mostly to show more flexible + * approach: conceivably you could have another way for passing + * your own view id system, using ThreadLocal or some other + * configurable part of <code>SerializationConfig</code> or + * <code>SerializerProvider</code>) + */ + /* note: if we wanted use 'writeValueAsString', would have to call + * 'mapper.getSerializationConfig().setSerializationView(...)' first + */ + String json = mapper.writerWithView(String.class).writeValueAsString(bean); + System.out.println("With custom serializer: "+json); + } +}
diff --git a/1.9.10/src/sample/sample/DynaBean.java b/1.9.10/src/sample/sample/DynaBean.java new file mode 100644 index 0000000..aca5c80 --- /dev/null +++ b/1.9.10/src/sample/sample/DynaBean.java
@@ -0,0 +1,56 @@ +package sample; + +import java.util.HashMap; +import java.util.Map; + +import org.codehaus.jackson.annotate.JsonAnyGetter; +import org.codehaus.jackson.annotate.JsonAnySetter; +import org.codehaus.jackson.annotate.JsonCreator; +import org.codehaus.jackson.annotate.JsonProperty; +import org.codehaus.jackson.map.ObjectMapper; + +/** + * Example of how @JsonAnyGetter and @JsonAnySetter can be used to + * create extensible "beans" (dyna-beans) + * + * @since 1.9 + */ +public class DynaBean +{ + // Two mandatory properties + + public int id; + public String name; + + // and then "other" stuff: + + protected Map<String,Object> other = new HashMap<String,Object>(); + + @JsonCreator + public DynaBean(@JsonProperty("id") int id, @JsonProperty("name") String name) + { + this.id = id; + this.name = name; + } + + @JsonAnyGetter + public Map<String,Object> any() { + return other; + } + + @JsonAnySetter + public void set(String name, Object value) { + other.put(name, value); + } + + public static void main(String[] args) throws Exception + { + DynaBean bean = new DynaBean(13, "Bob"); + bean.set("age", Integer.valueOf(37)); + ObjectMapper mapper = new ObjectMapper(); + String json = mapper.writeValueAsString(bean); + System.out.println("JSON in: "+json); + // should also come back ok + /*DynaBean result =*/ mapper.readValue(json, DynaBean.class); + } +}
diff --git a/1.9.10/src/sample/sample/ParserContextSample.java b/1.9.10/src/sample/sample/ParserContextSample.java new file mode 100644 index 0000000..30f296b --- /dev/null +++ b/1.9.10/src/sample/sample/ParserContextSample.java
@@ -0,0 +1,54 @@ +package sample; + +import java.io.*; + +import org.codehaus.jackson.*; + +public class ParserContextSample +{ + public void run(String[] args) throws IOException + { + if (args.length != 1) { + System.err.println("Usage: java "+getClass().getName()); + System.exit(1); + } + JsonParser jp = new JsonFactory().createJsonParser(new File(args[0])); + JsonToken t; + while ((t = jp.nextToken()) != null) { + System.out.println("Token (at "+jp.getTokenLocation()+"): "+t); + System.out.println(" path = "+getPath(jp.getParsingContext(), t)); + } + } + + private String getPath(JsonStreamContext ctxt, JsonToken currentToken) + { + if (ctxt == null) { + return ""; + } + String desc = getPath(ctxt.getParent(), null); + if (ctxt.inArray()) { + if (currentToken == JsonToken.START_ARRAY) { + desc += "["; + } else { + desc += "[" + ctxt.getCurrentIndex() + "]"; + } + } else if (ctxt.inObject()) { + // we are in object context when object starts, but don't yet have name + if (currentToken != JsonToken.START_OBJECT) { + // dot used unless we are at root context + if (desc.length() > 1) { + desc += "."; + } + desc += ctxt.getCurrentName(); + } + } else { // root... what to add? + desc += "/"; + } + return desc; + } + + public static void main(String[] args) throws IOException { + new ParserContextSample().run(args); + } +} +
diff --git a/1.9.10/src/sample/sample/UserSerializationExample.java b/1.9.10/src/sample/sample/UserSerializationExample.java new file mode 100644 index 0000000..5683656 --- /dev/null +++ b/1.9.10/src/sample/sample/UserSerializationExample.java
@@ -0,0 +1,48 @@ +package sample; +// no package, i.e. at root of sample/extra + +import java.io.*; + +import org.codehaus.jackson.map.*; + +/** + * A very simple example of full Jackson serialization. + */ +public class UserSerializationExample +{ + public static void main(String[] args) + throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + StringWriter sw = new StringWriter(); + mapper.writeValue(sw, new User()); + System.out.println("--- JSON ---"); + System.out.println(sw.toString()); + System.out.println("--- /JSON ---"); + } +} + +class User { + public enum Gender { MALE, FEMALE }; + + public Name getName() { return new Name(); } + public Address getAddress() { return new Address(); } + public boolean isVerified() { return true; } + public Gender getGender() { return Gender.MALE; } + public byte[] getUserImage() throws Exception { return "Foobar!".getBytes(); } +} + +class Name { + public Name() { } + public String getFirst() { return "Santa"; } + public String getLast() { return "Claus"; } +} + +class Address { + public Address() { } + public String getStreet() { return "1 Deadend Street"; } + public String getCity() { return "Mercer Island"; } + public String getState() { return "WA"; } + public int getZip() { return 98040; } + public String getCountry() { return "US"; } +}
diff --git a/1.9.10/src/smile/java/org/codehaus/jackson/smile/SmileBufferRecycler.java b/1.9.10/src/smile/java/org/codehaus/jackson/smile/SmileBufferRecycler.java new file mode 100644 index 0000000..35e30f4 --- /dev/null +++ b/1.9.10/src/smile/java/org/codehaus/jackson/smile/SmileBufferRecycler.java
@@ -0,0 +1,53 @@ +package org.codehaus.jackson.smile; + +/** + * Simple helper class used for implementing simple reuse system for Smile-specific + * buffers that are used. + * + * @param <T> Type of name entries stored in arrays to recycle + * + * @since 1.7 + */ +public class SmileBufferRecycler<T> +{ + public final static int DEFAULT_NAME_BUFFER_LENGTH = 64; + + public final static int DEFAULT_STRING_VALUE_BUFFER_LENGTH = 64; + + protected T[] _seenNamesBuffer; + + protected T[] _seenStringValuesBuffer; + + public SmileBufferRecycler() { } + + public T[] allocSeenNamesBuffer() + { + // 11-Feb-2011, tatu: Used to alloc here; but due to generics, can't easily any more + T[] result = _seenNamesBuffer; + if (result != null) { + // let's ensure we don't retain it here, unless returned + _seenNamesBuffer = null; + // note: caller must have cleaned it up before returning + } + return result; + } + + public T[] allocSeenStringValuesBuffer() + { + // 11-Feb-2011, tatu: Used to alloc here; but due to generics, can't easily any more + T[] result = _seenStringValuesBuffer; + if (result != null) { + _seenStringValuesBuffer = null; + // note: caller must have cleaned it up before returning + } + return result; + } + + public void releaseSeenNamesBuffer(T[] buffer) { + _seenNamesBuffer = buffer; + } + + public void releaseSeenStringValuesBuffer(T[] buffer) { + _seenStringValuesBuffer = buffer; + } +}
diff --git a/1.9.10/src/smile/java/org/codehaus/jackson/smile/SmileConstants.java b/1.9.10/src/smile/java/org/codehaus/jackson/smile/SmileConstants.java new file mode 100644 index 0000000..9e0da3b --- /dev/null +++ b/1.9.10/src/smile/java/org/codehaus/jackson/smile/SmileConstants.java
@@ -0,0 +1,363 @@ +package org.codehaus.jackson.smile; + +/** + * Constants used by {@link SmileGenerator} and {@link SmileParser} + * + * @author tatu + */ +public final class SmileConstants +{ + /* + /********************************************************** + /* Thresholds + /********************************************************** + */ + + /** + * Encoding has special "short" forms for value Strings that can + * be represented by 64 bytes of UTF-8 or less. + */ + public final static int MAX_SHORT_VALUE_STRING_BYTES = 64; + + /** + * Encoding has special "short" forms for field names that can + * be represented by 64 bytes of UTF-8 or less. + */ + public final static int MAX_SHORT_NAME_ASCII_BYTES = 64; + + /** + * Maximum byte length for short non-ASCII names is slightly + * less due to having to reserve bytes 0xF8 and above (but + * we get one more as values 0 and 1 are not valid) + */ + public final static int MAX_SHORT_NAME_UNICODE_BYTES = 56; + + /** + * Longest back reference we use for field names is 10 bits; no point + * in keeping much more around + */ + public final static int MAX_SHARED_NAMES = 1024; + + /** + * Longest back reference we use for short shared String values is 10 bits, + * so up to (1 << 10) values to keep track of. + */ + public final static int MAX_SHARED_STRING_VALUES = 1024; + + /** + * Also: whereas we can refer to names of any length, we will only consider + * text values that are considered "tiny" or "short" (ones encoded with + * length prefix); this value thereby has to be maximum length of Strings + * that can be encoded as such. + */ + public final static int MAX_SHARED_STRING_LENGTH_BYTES = 65; + + /** + * And to make encoding logic tight and simple, we can always + * require that output buffer has this amount of space + * available before encoding possibly short String (3 bytes since + * longest UTF-8 encoded Java char is 3 bytes). + * Two extra bytes need to be reserved as well; first for token indicator, + * and second for terminating null byte (in case it's not a short String after all) + */ + public final static int MIN_BUFFER_FOR_POSSIBLE_SHORT_STRING = 1 + (3 * 65); + + /* + /********************************************************** + /* Byte markers + /********************************************************** + */ + + /** + * We need a byte marker to denote end of variable-length Strings. Although + * null byte is commonly used, let's try to avoid using it since it can't + * be embedded in Web Sockets content (similarly, 0xFF can't). There are + * multiple candidates for bytes UTF-8 can not have; 0xFC is chosen to + * allow reasonable ordering (highest values meaning most significant + * framing function; 0xFF being end-of-content and so on) + */ + public final static int INT_MARKER_END_OF_STRING = 0xFC; + + public final static byte BYTE_MARKER_END_OF_STRING = (byte) INT_MARKER_END_OF_STRING; + + /** + * In addition we can use a marker to allow simple framing; splitting + * of physical data (like file) into distinct logical sections like + * JSON documents. 0xFF makes sense here since it is also used + * as end marker for Web Sockets. + */ + public final static byte BYTE_MARKER_END_OF_CONTENT = (byte) 0xFF; + + /* + /********************************************************** + /* Format header: put smile on your data... + /********************************************************** + */ + + /** + * First byte of data header + */ + public final static byte HEADER_BYTE_1 = (byte) ':'; + + /** + * Second byte of data header + */ + public final static byte HEADER_BYTE_2 = (byte) ')'; + + /** + * Third byte of data header + */ + public final static byte HEADER_BYTE_3 = (byte) '\n'; + + /** + * Current version consists of four zero bits (nibble) + */ + public final static int HEADER_VERSION_0 = 0x0; + + /** + * Fourth byte of data header; contains version nibble, may + * have flags + */ + public final static byte HEADER_BYTE_4 = (HEADER_VERSION_0 << 4); + + /** + * Indicator bit that indicates whether encoded content may + * have Shared names (back references to recently encoded field + * names). If no header available, must be + * processed as if this was set to true. + * If (and only if) header exists, and value is 0, can parser + * omit storing of seen names, as it is guaranteed that no back + * references exist. + */ + public final static int HEADER_BIT_HAS_SHARED_NAMES = 0x01; + + /** + * Indicator bit that indicates whether encoded content may + * have shared String values (back references to recently encoded + * 'short' String values, where short is defined as 64 bytes or less). + * If no header available, can be assumed to be 0 (false). + * If header exists, and bit value is 1, parsers has to store up + * to 1024 most recently seen distinct short String values. + */ + public final static int HEADER_BIT_HAS_SHARED_STRING_VALUES = 0x02; + + /** + * Indicator bit that indicates whether encoded content may + * contain raw (unquoted) binary values. + * If no header available, can be assumed to be 0 (false). + * If header exists, and bit value is 1, parser can not assume that + * specific byte values always have default meaning (specifically, + * content end marker 0xFF and header signature can be contained + * in binary values) + *<p> + * Note that this bit being true does not automatically mean that + * such raw binary content indeed exists; just that it may exist. + * This because header is written before any binary data may be + * written. + */ + public final static int HEADER_BIT_HAS_RAW_BINARY = 0x04; + + /* + /********************************************************** + /* Type prefixes: 3 MSB of token byte + /********************************************************** + */ + + // Shared strings are back references for last 63 short (< 64 byte) string values + // NOTE: 0x00 is reserved, not used with current version (may be used in future) + public final static int TOKEN_PREFIX_SHARED_STRING_SHORT = 0x00; + // literals are put between 0x20 and 0x3F to reserve markers (smiley), along with ints/doubles + //public final static int TOKEN_PREFIX_MISC_NUMBERS = 0x20; + + public final static int TOKEN_PREFIX_TINY_ASCII = 0x40; + public final static int TOKEN_PREFIX_SMALL_ASCII = 0x60; + public final static int TOKEN_PREFIX_TINY_UNICODE = 0x80; + public final static int TOKEN_PREFIX_SHORT_UNICODE = 0xA0; + + // Small ints are 4-bit (-16 to +15) integer constants + public final static int TOKEN_PREFIX_SMALL_INT = 0xC0; + + // And misc types have empty at the end too, to reserve 0xF8 - 0xFF + public final static int TOKEN_PREFIX_MISC_OTHER = 0xE0; + + /* + /********************************************************** + /* Token literals, normal mode + /********************************************************** + */ + + // First, non-structured literals + + public final static byte TOKEN_LITERAL_EMPTY_STRING = 0x20; + public final static byte TOKEN_LITERAL_NULL = 0x21; + public final static byte TOKEN_LITERAL_FALSE = 0x22; + public final static byte TOKEN_LITERAL_TRUE = 0x23; + + // And then structured literals + + public final static byte TOKEN_LITERAL_START_ARRAY = (byte) 0xF8; + public final static byte TOKEN_LITERAL_END_ARRAY = (byte) 0xF9; + public final static byte TOKEN_LITERAL_START_OBJECT = (byte) 0xFA; + public final static byte TOKEN_LITERAL_END_OBJECT = (byte) 0xFB; + + /* + /********************************************************** + /* Subtype constants for misc text/binary types + /********************************************************** + */ + + /** + * Type (for misc, other) used + * for regular integral types (byte/short/int/long) + */ + public final static int TOKEN_MISC_INTEGER = 0x24; + + /** + * Type (for misc, other) used + * for regular floating-point types (float, double) + */ + public final static int TOKEN_MISC_FP = 0x28; + + /** + * Type (for misc, other) used for + * variable length UTF-8 encoded text, when it is known to only contain ASCII chars. + * Note: 2 LSB are reserved for future use; must be zeroes for now + */ + public final static int TOKEN_MISC_LONG_TEXT_ASCII = 0xE0; + + /** + * Type (for misc, other) used + * for variable length UTF-8 encoded text, when it is NOT known to only contain ASCII chars + * (which means it MAY have multi-byte characters) + * Note: 2 LSB are reserved for future use; must be zeroes for now + */ + public final static int TOKEN_MISC_LONG_TEXT_UNICODE = 0xE4; + + /** + * Type (for misc, other) used + * for "safe" (encoded by only using 7 LSB, giving 8/7 expansion ratio). + * This is usually done to ensure that certain bytes are never included + * in encoded data (like 0xFF) + * Note: 2 LSB are reserved for future use; must be zeroes for now + */ + public final static int TOKEN_MISC_BINARY_7BIT = 0xE8; + + /** + * Type (for misc, other) used for shared String values where index + * does not fit in "short" reference range (which is 0 - 30). If so, + * 2 LSB from here and full following byte are used to get 10-bit + * index. Values + */ + public final static int TOKEN_MISC_SHARED_STRING_LONG = 0xEC; + + /** + * Raw binary data marker is specifically chosen as separate from + * other types, since it can have significant impact on framing + * (or rather fast scanning based on structure and framing markers). + */ + public final static int TOKEN_MISC_BINARY_RAW = 0xFD; + + /* + /********************************************************** + /* Modifiers for numeric entries + /********************************************************** + */ + + /** + * Numeric subtype (2 LSB) for {@link #TOKEN_MISC_INTEGER}, + * indicating 32-bit integer (int) + */ + public final static int TOKEN_MISC_INTEGER_32 = 0x00; + + /** + * Numeric subtype (2 LSB) for {@link #TOKEN_MISC_INTEGER}, + * indicating 32-bit integer (long) + */ + public final static int TOKEN_MISC_INTEGER_64 = 0x01; + + /** + * Numeric subtype (2 LSB) for {@link #TOKEN_MISC_INTEGER}, + * indicating {@link java.math.BigInteger} type. + */ + public final static int TOKEN_MISC_INTEGER_BIG = 0x02; + + // Note: type 3 (0xF3) reserved for future use + + /** + * Numeric subtype (2 LSB) for {@link #TOKEN_MISC_FP}, + * indicating 32-bit IEEE single precision floating point number. + */ + public final static int TOKEN_MISC_FLOAT_32 = 0x00; + + /** + * Numeric subtype (2 LSB) for {@link #TOKEN_MISC_FP}, + * indicating 64-bit IEEE double precision floating point number. + */ + public final static int TOKEN_MISC_FLOAT_64 = 0x01; + + /** + * Numeric subtype (2 LSB) for {@link #TOKEN_MISC_FP}, + * indicating {@link java.math.BigDecimal} type. + */ + public final static int TOKEN_MISC_FLOAT_BIG = 0x02; + + // Note: type 3 (0xF7) reserved for future use + + /* + /********************************************************** + /* Token types for keys + /********************************************************** + */ + + /** + * Let's use same code for empty key as for empty String value + */ + public final static byte TOKEN_KEY_EMPTY_STRING = 0x20; + + public final static int TOKEN_PREFIX_KEY_SHARED_LONG = 0x30; + + public final static byte TOKEN_KEY_LONG_STRING = 0x34; + + public final static int TOKEN_PREFIX_KEY_SHARED_SHORT = 0x40; + + public final static int TOKEN_PREFIX_KEY_ASCII = 0x80; + + public final static int TOKEN_PREFIX_KEY_UNICODE = 0xC0; + + /* + /********************************************************** + /* Basic UTF-8 decode/encode table + /********************************************************** + */ + + /** + * Additionally we can combine UTF-8 decoding info into similar + * data table. + * Values indicate "byte length - 1"; meaning -1 is used for + * invalid bytes, 0 for single-byte codes, 1 for 2-byte codes + * and 2 for 3-byte codes. + */ + public final static int[] sUtf8UnitLengths; + static { + int[] table = new int[256]; + for (int c = 128; c < 256; ++c) { + int code; + + // We'll add number of bytes needed for decoding + if ((c & 0xE0) == 0xC0) { // 2 bytes (0x0080 - 0x07FF) + code = 1; + } else if ((c & 0xF0) == 0xE0) { // 3 bytes (0x0800 - 0xFFFF) + code = 2; + } else if ((c & 0xF8) == 0xF0) { + // 4 bytes; double-char with surrogates and all... + code = 3; + } else { + // And -1 seems like a good "universal" error marker... + code = -1; + } + table[c] = code; + } + sUtf8UnitLengths = table; + } +} +
diff --git a/1.9.10/src/smile/java/org/codehaus/jackson/smile/SmileFactory.java b/1.9.10/src/smile/java/org/codehaus/jackson/smile/SmileFactory.java new file mode 100644 index 0000000..b48a62f --- /dev/null +++ b/1.9.10/src/smile/java/org/codehaus/jackson/smile/SmileFactory.java
@@ -0,0 +1,381 @@ +package org.codehaus.jackson.smile; + +import java.io.*; +import java.net.URL; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.format.InputAccessor; +import org.codehaus.jackson.format.MatchStrength; +import org.codehaus.jackson.io.IOContext; + +/** + * Factory used for constructing {@link SmileParser} and {@link SmileGenerator} + * instances; both of which handle + * <a href="http://wiki.fasterxml.com/SmileFormat">Smile</a> encoded data. + *<p> + * Extends {@link JsonFactory} mostly so that users can actually use it in place + * of regular non-Smile factory instances. + *<p> + * Note on using non-byte-based sources/targets (char based, like + * {@link java.io.Reader} and {@link java.io.Writer}): these can not be + * used for Smile-format documents, and thus will either downgrade to + * textual JSON (when parsing), or throw exception (when trying to create + * generator). + * + * @author tatu + * + * @since 1.6 + */ +public class SmileFactory extends JsonFactory +{ + /** + * Name used to identify Smile format. + * (and returned by {@link #getFormatName()} + */ + public final static String FORMAT_NAME_SMILE = "Smile"; + + /** + * Bitfield (set of flags) of all parser features that are enabled + * by default. + */ + final static int DEFAULT_SMILE_PARSER_FEATURE_FLAGS = SmileParser.Feature.collectDefaults(); + + /** + * Bitfield (set of flags) of all generator features that are enabled + * by default. + */ + final static int DEFAULT_SMILE_GENERATOR_FEATURE_FLAGS = SmileGenerator.Feature.collectDefaults(); + + /* + /********************************************************** + /* Configuration + /********************************************************** + */ + + /** + * Whether non-supported methods (ones trying to output using + * char-based targets like {@link java.io.Writer}, for example) + * should be delegated to regular Jackson JSON processing + * (if set to true); or throw {@link UnsupportedOperationException} + * (if set to false) + */ + protected boolean _cfgDelegateToTextual; + + protected int _smileParserFeatures = DEFAULT_SMILE_PARSER_FEATURE_FLAGS; + + protected int _smileGeneratorFeatures = DEFAULT_SMILE_GENERATOR_FEATURE_FLAGS; + + /* + /********************************************************** + /* Factory construction, configuration + /********************************************************** + */ + + /** + * Default constructor used to create factory instances. + * Creation of a factory instance is a light-weight operation, + * but it is still a good idea to reuse limited number of + * factory instances (and quite often just a single instance): + * factories are used as context for storing some reused + * processing objects (such as symbol tables parsers use) + * and this reuse only works within context of a single + * factory instance. + */ + public SmileFactory() { this(null); } + + public SmileFactory(ObjectCodec oc) { super(oc); } + + public void delegateToTextual(boolean state) { + _cfgDelegateToTextual = state; + } + + /* + /********************************************************** + /* Format detection functionality (since 1.8) + /********************************************************** + */ + + @Override + public String getFormatName() + { + return FORMAT_NAME_SMILE; + } + + /** + * Sub-classes need to override this method (as of 1.8) + */ + @Override + public MatchStrength hasFormat(InputAccessor acc) throws IOException + { + return SmileParserBootstrapper.hasSmileFormat(acc); + } + + /* + /********************************************************** + /* Configuration, parser settings + /********************************************************** + */ + + /** + * Method for enabling or disabling specified parser feature + * (check {@link SmileParser.Feature} for list of features) + */ + public final SmileFactory configure(SmileParser.Feature f, boolean state) + { + if (state) { + enable(f); + } else { + disable(f); + } + return this; + } + + /** + * Method for enabling specified parser feature + * (check {@link SmileParser.Feature} for list of features) + */ + public SmileFactory enable(SmileParser.Feature f) { + _smileParserFeatures |= f.getMask(); + return this; + } + + /** + * Method for disabling specified parser features + * (check {@link SmileParser.Feature} for list of features) + */ + public SmileFactory disable(SmileParser.Feature f) { + _smileParserFeatures &= ~f.getMask(); + return this; + } + + /** + * Checked whether specified parser feature is enabled. + */ + public final boolean isEnabled(SmileParser.Feature f) { + return (_smileParserFeatures & f.getMask()) != 0; + } + + /* + /********************************************************** + /* Configuration, generator settings + /********************************************************** + */ + + /** + * Method for enabling or disabling specified generator feature + * (check {@link org.codehaus.jackson.JsonGenerator.Feature} for list of features) + * + * @since 1.2 + */ + public final SmileFactory configure(SmileGenerator.Feature f, boolean state) { + if (state) { + enable(f); + } else { + disable(f); + } + return this; + } + + + /** + * Method for enabling specified generator features + * (check {@link org.codehaus.jackson.JsonGenerator.Feature} for list of features) + */ + public SmileFactory enable(SmileGenerator.Feature f) { + _smileGeneratorFeatures |= f.getMask(); + return this; + } + + /** + * Method for disabling specified generator feature + * (check {@link org.codehaus.jackson.JsonGenerator.Feature} for list of features) + */ + public SmileFactory disable(SmileGenerator.Feature f) { + _smileGeneratorFeatures &= ~f.getMask(); + return this; + } + + /** + * Check whether specified generator feature is enabled. + */ + public final boolean isEnabled(SmileGenerator.Feature f) { + return (_smileGeneratorFeatures & f.getMask()) != 0; + } + + /* + /********************************************************** + /* Overridden parser factory methods + /********************************************************** + */ + + @Override + public SmileParser createJsonParser(File f) + throws IOException, JsonParseException + { + return _createJsonParser(new FileInputStream(f), _createContext(f, true)); + } + + @Override + public SmileParser createJsonParser(URL url) + throws IOException, JsonParseException + { + return _createJsonParser(_optimizedStreamFromURL(url), _createContext(url, true)); + } + + @Override + public SmileParser createJsonParser(InputStream in) + throws IOException, JsonParseException + { + return _createJsonParser(in, _createContext(in, false)); + } + + //public JsonParser createJsonParser(Reader r) + + @Override + public SmileParser createJsonParser(byte[] data) + throws IOException, JsonParseException + { + IOContext ctxt = _createContext(data, true); + return _createJsonParser(data, 0, data.length, ctxt); + } + + @Override + public SmileParser createJsonParser(byte[] data, int offset, int len) + throws IOException, JsonParseException + { + return _createJsonParser(data, offset, len, _createContext(data, true)); + } + + /* + /********************************************************** + /* Overridden generator factory methods + /********************************************************** + */ + + /** + *<p> + * note: co-variant return type + */ + @Override + public SmileGenerator createJsonGenerator(OutputStream out, JsonEncoding enc) + throws IOException + { + return createJsonGenerator(out); + } + + /** + * Since Smile format always uses UTF-8 internally, no encoding need + * to be passed to this method. + */ + @Override + public SmileGenerator createJsonGenerator(OutputStream out) throws IOException + { + // false -> we won't manage the stream unless explicitly directed to + IOContext ctxt = _createContext(out, false); + return _createJsonGenerator(out, ctxt); + } + + /* + /****************************************************** + /* Overridden internal factory methods + /****************************************************** + */ + + //protected IOContext _createContext(Object srcRef, boolean resourceManaged) + + /** + * Overridable factory method that actually instantiates desired + * parser. + */ + @Override + protected SmileParser _createJsonParser(InputStream in, IOContext ctxt) + throws IOException, JsonParseException + { + return new SmileParserBootstrapper(ctxt, in).constructParser(_parserFeatures, + _smileParserFeatures, _objectCodec, _rootByteSymbols); + } + + /** + * Overridable factory method that actually instantiates desired + * parser. + */ + @Override + protected JsonParser _createJsonParser(Reader r, IOContext ctxt) + throws IOException, JsonParseException + { + if (_cfgDelegateToTextual) { + return super._createJsonParser(r, ctxt); + } + throw new UnsupportedOperationException("Can not create generator for non-byte-based target"); + } + + /** + * Overridable factory method that actually instantiates desired + * parser. + */ + @Override + protected SmileParser _createJsonParser(byte[] data, int offset, int len, IOContext ctxt) + throws IOException, JsonParseException + { + return new SmileParserBootstrapper(ctxt, data, offset, len).constructParser(_parserFeatures, + _smileParserFeatures, _objectCodec, _rootByteSymbols); + } + + /** + * Overridable factory method that actually instantiates desired + * generator. + */ + @Override + protected JsonGenerator _createJsonGenerator(Writer out, IOContext ctxt) + throws IOException + { + if (_cfgDelegateToTextual) { + return super._createJsonGenerator(out, ctxt); + } + throw new UnsupportedOperationException("Can not create generator for non-byte-based target"); + } + + //public BufferRecycler _getBufferRecycler() + + @Override + protected Writer _createWriter(OutputStream out, JsonEncoding enc, IOContext ctxt) throws IOException + { + if (_cfgDelegateToTextual) { + return super._createWriter(out, enc, ctxt); + } + throw new UnsupportedOperationException("Can not create generator for non-byte-based target"); + } + + /* + /********************************************************** + /* Internal methods + /********************************************************** + */ + + protected SmileGenerator _createJsonGenerator(OutputStream out, IOContext ctxt) + throws IOException + { + int feats = _smileGeneratorFeatures; + /* One sanity check: MUST write header if shared string values setting is enabled, + * or quoting of binary data disabled. + * But should we force writing, or throw exception, if settings are in conflict? + * For now, let's error out... + */ + SmileGenerator gen = new SmileGenerator(ctxt, _generatorFeatures, feats, _objectCodec, out); + if ((feats & SmileGenerator.Feature.WRITE_HEADER.getMask()) != 0) { + gen.writeHeader(); + } else { + if ((feats & SmileGenerator.Feature.CHECK_SHARED_STRING_VALUES.getMask()) != 0) { + throw new JsonGenerationException( + "Inconsistent settings: WRITE_HEADER disabled, but CHECK_SHARED_STRING_VALUES enabled; can not construct generator" + +" due to possible data loss (either enable WRITE_HEADER, or disable CHECK_SHARED_STRING_VALUES to resolve)"); + } + if ((feats & SmileGenerator.Feature.ENCODE_BINARY_AS_7BIT.getMask()) == 0) { + throw new JsonGenerationException( + "Inconsistent settings: WRITE_HEADER disabled, but ENCODE_BINARY_AS_7BIT disabled; can not construct generator" + +" due to possible data loss (either enable WRITE_HEADER, or ENCODE_BINARY_AS_7BIT to resolve)"); + } + } + return gen; + } +}
diff --git a/1.9.10/src/smile/java/org/codehaus/jackson/smile/SmileGenerator.java b/1.9.10/src/smile/java/org/codehaus/jackson/smile/SmileGenerator.java new file mode 100644 index 0000000..d1c8cdd --- /dev/null +++ b/1.9.10/src/smile/java/org/codehaus/jackson/smile/SmileGenerator.java
@@ -0,0 +1,2132 @@ +package org.codehaus.jackson.smile; + +import java.io.*; +import java.lang.ref.SoftReference; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.Arrays; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.io.IOContext; +import org.codehaus.jackson.io.SerializedString; +import org.codehaus.jackson.impl.JsonGeneratorBase; +import org.codehaus.jackson.impl.JsonWriteContext; + +import static org.codehaus.jackson.smile.SmileConstants.*; + +/** + * {@link JsonGenerator} implementation for the experimental "Binary JSON Infoset". + * + * @author tatu + */ +public class SmileGenerator + extends JsonGeneratorBase +{ + /** + * Enumeration that defines all togglable features for Smile generators. + */ + public enum Feature { + /** + * Whether to write 4-byte header sequence when starting output or not. + * If disabled, no header is written; this may be useful in embedded cases + * where context is enough to know that content is encoded using this format. + * Note, however, that omitting header means that default settings for + * shared names/string values can not be changed. + *<p> + * Default setting is true, meaning that header will be written. + */ + WRITE_HEADER(true), + + /** + * Whether write byte marker that signifies end of logical content segment + * ({@link SmileConstants#BYTE_MARKER_END_OF_CONTENT}) when + * {@link #close} is called or not. This can be useful when outputting + * multiple adjacent logical content segments (documents) into single + * physical output unit (file). + *<p> + * Default setting is false meaning that such marker is not written. + */ + WRITE_END_MARKER(false), + + /** + * Whether to use simple 7-bit per byte encoding for binary content when output. + * This is necessary ensure that byte 0xFF will never be included in content output. + * For other data types this limitation is handled automatically; but since overhead + * for binary data (14% size expansion, processing overhead) is non-negligible, + * it is not enabled by default. If no binary data is output, feature has no effect. + *<p> + * Default setting is true, indicating that binary data is quoted as 7-bit bytes + * instead of written raw. + */ + ENCODE_BINARY_AS_7BIT(true), + + /** + * Whether generator should check if it can "share" field names during generating + * content or not. If enabled, can replace repeating field names with back references, + * which are more compact and should faster to decode. Downside is that there is some + * overhead for writing (need to track existing values, check), as well as decoding. + *<p> + * Since field names tend to repeat quite often, this setting is enabled by default. + */ + CHECK_SHARED_NAMES(true), + + /** + * Whether generator should check if it can "share" short (at most 64 bytes encoded) + * String value during generating + * content or not. If enabled, can replace repeating Short String values with back references, + * which are more compact and should faster to decode. Downside is that there is some + * overhead for writing (need to track existing values, check), as well as decoding. + *<p> + * Since efficiency of this option depends a lot on type of content being produced, + * this option is disabled by default, and should only be enabled if it is likely that + * same values repeat relatively often. + */ + CHECK_SHARED_STRING_VALUES(false) + ; + + protected final boolean _defaultState; + protected final int _mask; + + /** + * Method that calculates bit set (flags) of all features that + * are enabled by default. + */ + public static int collectDefaults() + { + int flags = 0; + for (Feature f : values()) { + if (f.enabledByDefault()) { + flags |= f.getMask(); + } + } + return flags; + } + + private Feature(boolean defaultState) { + _defaultState = defaultState; + _mask = (1 << ordinal()); + } + + public boolean enabledByDefault() { return _defaultState; } + public int getMask() { return _mask; } + } + + /** + * Helper class used for keeping track of possibly shareable String + * references (for field names and/or short String values) + */ + protected final static class SharedStringNode + { + public final String value; + public final int index; + public SharedStringNode next; + + public SharedStringNode(String value, int index, SharedStringNode next) + { + this.value = value; + this.index = index; + this.next = next; + } + } + + /** + * To simplify certain operations, we require output buffer length + * to allow outputting of contiguous 256 character UTF-8 encoded String + * value. Length of the longest UTF-8 code point (from Java char) is 3 bytes, + * and we need both initial token byte and single-byte end marker + * so we get following value. + *<p> + * Note: actually we could live with shorter one; absolute minimum would + * be for encoding 64-character Strings. + */ + private final static int MIN_BUFFER_LENGTH = (3 * 256) + 2; + + protected final static byte TOKEN_BYTE_LONG_STRING_ASCII = (byte) TOKEN_MISC_LONG_TEXT_ASCII; + protected final static byte TOKEN_BYTE_LONG_STRING_UNICODE = (byte) TOKEN_MISC_LONG_TEXT_UNICODE; + + protected final static byte TOKEN_BYTE_INT_32 = (byte) (TOKEN_MISC_INTEGER | TOKEN_MISC_INTEGER_32); + protected final static byte TOKEN_BYTE_INT_64 = (byte) (TOKEN_MISC_INTEGER | TOKEN_MISC_INTEGER_64); + protected final static byte TOKEN_BYTE_BIG_INTEGER = (byte) (TOKEN_MISC_INTEGER | TOKEN_MISC_INTEGER_BIG); + + protected final static byte TOKEN_BYTE_FLOAT_32 = (byte) (TOKEN_MISC_FP | TOKEN_MISC_FLOAT_32); + protected final static byte TOKEN_BYTE_FLOAT_64 = (byte) (TOKEN_MISC_FP | TOKEN_MISC_FLOAT_64); + protected final static byte TOKEN_BYTE_BIG_DECIMAL = (byte) (TOKEN_MISC_FP | TOKEN_MISC_FLOAT_BIG); + + protected final static int SURR1_FIRST = 0xD800; + protected final static int SURR1_LAST = 0xDBFF; + protected final static int SURR2_FIRST = 0xDC00; + protected final static int SURR2_LAST = 0xDFFF; + + protected final static long MIN_INT_AS_LONG = (long) Integer.MIN_VALUE; + protected final static long MAX_INT_AS_LONG = (long) Integer.MAX_VALUE; + + /* + /********************************************************** + /* Configuration + /********************************************************** + */ + + final protected IOContext _ioContext; + + final protected OutputStream _out; + + /** + * Bit flag composed of bits that indicate which + * {@link org.codehaus.jackson.smile.SmileGenerator.Feature}s + * are enabled. + */ + protected int _smileFeatures; + + /** + * Helper object used for low-level recycling of Smile-generator + * specific buffers. + * + * @since 1.7 + */ + final protected SmileBufferRecycler<SharedStringNode> _smileBufferRecycler; + + /* + /********************************************************** + /* Output buffering + /********************************************************** + */ + + /** + * Intermediate buffer in which contents are buffered before + * being written using {@link #_out}. + */ + protected byte[] _outputBuffer; + + /** + * Pointer to the next available byte in {@link #_outputBuffer} + */ + protected int _outputTail = 0; + + /** + * Offset to index after the last valid index in {@link #_outputBuffer}. + * Typically same as length of the buffer. + */ + protected final int _outputEnd; + + /** + * Intermediate buffer in which characters of a String are copied + * before being encoded. + */ + protected char[] _charBuffer; + + protected final int _charBufferLength; + + /** + * Let's keep track of how many bytes have been output, may prove useful + * when debugging. This does <b>not</b> include bytes buffered in + * the output buffer, just bytes that have been written using underlying + * stream writer. + */ + protected int _bytesWritten; + + /* + /********************************************************** + /* Shared String detection + /********************************************************** + */ + + /** + * Raw data structure used for checking whether field name to + * write can be output using back reference or not. + */ + protected SharedStringNode[] _seenNames; + + /** + * Number of entries in {@link #_seenNames}; -1 if no shared name + * detection is enabled + */ + protected int _seenNameCount; + + /** + * Raw data structure used for checking whether String value to + * write can be output using back reference or not. + */ + protected SharedStringNode[] _seenStringValues; + + /** + * Number of entries in {@link #_seenStringValues}; -1 if no shared text value + * detection is enabled + */ + protected int _seenStringValueCount; + + /** + * Flag that indicates whether the output buffer is recycable (and + * needs to be returned to recycler once we are done) or not. + */ + protected boolean _bufferRecyclable; + + /* + /********************************************************** + /* Thread-local recycling + /********************************************************** + */ + + /** + * This <code>ThreadLocal</code> contains a {@link java.lang.ref.SoftRerefence} + * to a buffer recycler used to provide a low-cost + * buffer recycling for Smile-specific buffers. + */ + final protected static ThreadLocal<SoftReference<SmileBufferRecycler<SharedStringNode>>> _smileRecyclerRef + = new ThreadLocal<SoftReference<SmileBufferRecycler<SharedStringNode>>>(); + + /* + /********************************************************** + /* Life-cycle + /********************************************************** + */ + + public SmileGenerator(IOContext ctxt, int jsonFeatures, int smileFeatures, + ObjectCodec codec, OutputStream out) + { + super(jsonFeatures, codec); + _smileFeatures = smileFeatures; + _ioContext = ctxt; + _smileBufferRecycler = _smileBufferRecycler(); + _out = out; + _bufferRecyclable = true; + _outputBuffer = ctxt.allocWriteEncodingBuffer(); + _outputEnd = _outputBuffer.length; + _charBuffer = ctxt.allocConcatBuffer(); + _charBufferLength = _charBuffer.length; + // let's just sanity check to prevent nasty odd errors + if (_outputEnd < MIN_BUFFER_LENGTH) { + throw new IllegalStateException("Internal encoding buffer length ("+_outputEnd + +") too short, must be at least "+MIN_BUFFER_LENGTH); + } + if ((smileFeatures & Feature.CHECK_SHARED_NAMES.getMask()) == 0) { + _seenNames = null; + _seenNameCount = -1; + } else { + _seenNames = _smileBufferRecycler.allocSeenNamesBuffer(); + if (_seenNames == null) { + _seenNames = new SharedStringNode[SmileBufferRecycler.DEFAULT_NAME_BUFFER_LENGTH]; + } + _seenNameCount = 0; + } + + if ((smileFeatures & Feature.CHECK_SHARED_STRING_VALUES.getMask()) == 0) { + _seenStringValues = null; + _seenStringValueCount = -1; + } else { + _seenStringValues = _smileBufferRecycler.allocSeenStringValuesBuffer(); + if (_seenStringValues == null) { + _seenStringValues = new SharedStringNode[SmileBufferRecycler.DEFAULT_STRING_VALUE_BUFFER_LENGTH]; + } + _seenStringValueCount = 0; + } +} + + public SmileGenerator(IOContext ctxt, int jsonFeatures, int smileFeatures, + ObjectCodec codec, OutputStream out, byte[] outputBuffer, int offset, boolean bufferRecyclable) + { + super(jsonFeatures, codec); + _smileFeatures = smileFeatures; + _ioContext = ctxt; + _smileBufferRecycler = _smileBufferRecycler(); + _out = out; + _bufferRecyclable = bufferRecyclable; + _outputTail = offset; + _outputBuffer = outputBuffer; + _outputEnd = _outputBuffer.length; + _charBuffer = ctxt.allocConcatBuffer(); + _charBufferLength = _charBuffer.length; + // let's just sanity check to prevent nasty odd errors + if (_outputEnd < MIN_BUFFER_LENGTH) { + throw new IllegalStateException("Internal encoding buffer length ("+_outputEnd + +") too short, must be at least "+MIN_BUFFER_LENGTH); + } + if ((smileFeatures & Feature.CHECK_SHARED_NAMES.getMask()) == 0) { + _seenNames = null; + _seenNameCount = -1; + } else { + _seenNames = _smileBufferRecycler.allocSeenNamesBuffer(); + if (_seenNames == null) { + _seenNames = new SharedStringNode[SmileBufferRecycler.DEFAULT_NAME_BUFFER_LENGTH]; + } + _seenNameCount = 0; + } + + if ((smileFeatures & Feature.CHECK_SHARED_STRING_VALUES.getMask()) == 0) { + _seenStringValues = null; + _seenStringValueCount = -1; + } else { + _seenStringValues = _smileBufferRecycler.allocSeenStringValuesBuffer(); + if (_seenStringValues == null) { + _seenStringValues = new SharedStringNode[SmileBufferRecycler.DEFAULT_STRING_VALUE_BUFFER_LENGTH]; + } + _seenStringValueCount = 0; + } + } + + /** + * Method that can be called to explicitly write Smile document header. + * Note that usually you do not need to call this for first document to output, + * but rather only if you intend to write multiple root-level documents + * with same generator (and even in that case this is optional thing to do). + * As a result usually only {@link SmileFactory} calls this method. + */ + public void writeHeader() throws IOException + { + int last = HEADER_BYTE_4; + if ((_smileFeatures & Feature.CHECK_SHARED_NAMES.getMask()) != 0) { + last |= SmileConstants.HEADER_BIT_HAS_SHARED_NAMES; + } + if ((_smileFeatures & Feature.CHECK_SHARED_STRING_VALUES.getMask()) != 0) { + last |= SmileConstants.HEADER_BIT_HAS_SHARED_STRING_VALUES; + } + if ((_smileFeatures & Feature.ENCODE_BINARY_AS_7BIT.getMask()) == 0) { + last |= SmileConstants.HEADER_BIT_HAS_RAW_BINARY; + } + _writeBytes(HEADER_BYTE_1, HEADER_BYTE_2, HEADER_BYTE_3, (byte) last); + } + + protected final static SmileBufferRecycler<SharedStringNode> _smileBufferRecycler() + { + SoftReference<SmileBufferRecycler<SharedStringNode>> ref = _smileRecyclerRef.get(); + SmileBufferRecycler<SharedStringNode> br = (ref == null) ? null : ref.get(); + + if (br == null) { + br = new SmileBufferRecycler<SharedStringNode>(); + _smileRecyclerRef.set(new SoftReference<SmileBufferRecycler<SharedStringNode>>(br)); + } + return br; + } + + /* + /********************************************************** + /* Overridden methods, configuration + /********************************************************** + */ + + /** + * No way (or need) to indent anything, so let's block any attempts. + * (should we throw an exception instead?) + */ + @Override + public JsonGenerator useDefaultPrettyPrinter() + { + return this; + } + + /** + * No way (or need) to indent anything, so let's block any attempts. + * (should we throw an exception instead?) + */ + @Override + public JsonGenerator setPrettyPrinter(PrettyPrinter pp) { + return this; + } + + @Override + public Object getOutputTarget() { + return _out; + } + + /* + /********************************************************** + /* Overridden methods, write methods + /********************************************************** + */ + + /* And then methods overridden to make final, streamline some + * aspects... + */ + + @Override + public final void writeFieldName(String name) throws IOException, JsonGenerationException + { + if (_writeContext.writeFieldName(name) == JsonWriteContext.STATUS_EXPECT_VALUE) { + _reportError("Can not write a field name, expecting a value"); + } + _writeFieldName(name); + } + + @Override + public final void writeFieldName(SerializedString name) + throws IOException, JsonGenerationException + { + // Object is a value, need to verify it's allowed + if (_writeContext.writeFieldName(name.getValue()) == JsonWriteContext.STATUS_EXPECT_VALUE) { + _reportError("Can not write a field name, expecting a value"); + } + _writeFieldName(name); + } + + @Override + public final void writeFieldName(SerializableString name) + throws IOException, JsonGenerationException + { + // Object is a value, need to verify it's allowed + if (_writeContext.writeFieldName(name.getValue()) == JsonWriteContext.STATUS_EXPECT_VALUE) { + _reportError("Can not write a field name, expecting a value"); + } + _writeFieldName(name); + } + + @Override + public final void writeStringField(String fieldName, String value) + throws IOException, JsonGenerationException + { + if (_writeContext.writeFieldName(fieldName) == JsonWriteContext.STATUS_EXPECT_VALUE) { + _reportError("Can not write a field name, expecting a value"); + } + _writeFieldName(fieldName); + writeString(value); + } + + /* + /********************************************************** + /* Extended API, configuration + /********************************************************** + */ + + public SmileGenerator enable(Feature f) { + _smileFeatures |= f.getMask(); + return this; + } + + public SmileGenerator disable(Feature f) { + _smileFeatures &= ~f.getMask(); + return this; + } + + public final boolean isEnabled(Feature f) { + return (_smileFeatures & f.getMask()) != 0; + } + + public SmileGenerator configure(Feature f, boolean state) { + if (state) { + enable(f); + } else { + disable(f); + } + return this; + } + + /* + /********************************************************** + /* Extended API, other + /********************************************************** + */ + + /** + * Method for directly inserting specified byte in output at + * current position. + *<p> + * NOTE: only use this method if you really know what you are doing. + */ + public void writeRaw(byte b) throws IOException, JsonGenerationException + { + _writeByte(TOKEN_LITERAL_START_ARRAY); + } + + /** + * Method for directly inserting specified bytes in output at + * current position. + *<p> + * NOTE: only use this method if you really know what you are doing. + */ + public void writeBytes(byte[] data, int offset, int len) throws IOException + { + _writeBytes(data, offset, len); + } + + /* + /********************************************************** + /* Output method implementations, structural + /********************************************************** + */ + + @Override + public final void writeStartArray() throws IOException, JsonGenerationException + { + _verifyValueWrite("start an array"); + _writeContext = _writeContext.createChildArrayContext(); + _writeByte(TOKEN_LITERAL_START_ARRAY); + } + + @Override + public final void writeEndArray() throws IOException, JsonGenerationException + { + if (!_writeContext.inArray()) { + _reportError("Current context not an ARRAY but "+_writeContext.getTypeDesc()); + } + _writeByte(TOKEN_LITERAL_END_ARRAY); + _writeContext = _writeContext.getParent(); + } + + @Override + public final void writeStartObject() throws IOException, JsonGenerationException + { + _verifyValueWrite("start an object"); + _writeContext = _writeContext.createChildObjectContext(); + _writeByte(TOKEN_LITERAL_START_OBJECT); + } + + @Override + public final void writeEndObject() throws IOException, JsonGenerationException + { + if (!_writeContext.inObject()) { + _reportError("Current context not an object but "+_writeContext.getTypeDesc()); + } + _writeContext = _writeContext.getParent(); + _writeByte(TOKEN_LITERAL_END_OBJECT); + } + + private final void _writeFieldName(String name) + throws IOException, JsonGenerationException + { + int len = name.length(); + if (len == 0) { + _writeByte(TOKEN_KEY_EMPTY_STRING); + return; + } + // First: is it something we can share? + if (_seenNameCount >= 0) { + int ix = _findSeenName(name); + if (ix >= 0) { + _writeSharedNameReference(ix); + return; + } + } + if (len > MAX_SHORT_NAME_UNICODE_BYTES) { // can not be a 'short' String; off-line (rare case) + _writeNonShortFieldName(name, len); + return; + } + + // first: ensure we have enough space + if ((_outputTail + MIN_BUFFER_FOR_POSSIBLE_SHORT_STRING) >= _outputEnd) { + _flushBuffer(); + } + // then let's copy String chars to char buffer, faster than using getChar (measured, profiled) + name.getChars(0, len, _charBuffer, 0); + int origOffset = _outputTail; + ++_outputTail; // to reserve space for type token + int byteLen = _shortUTF8Encode(_charBuffer, 0, len); + byte typeToken; + + // ASCII? + if (byteLen == len) { + if (byteLen <= MAX_SHORT_NAME_ASCII_BYTES) { // yes, is short indeed + typeToken = (byte) ((TOKEN_PREFIX_KEY_ASCII - 1) + byteLen); + } else { // longer albeit ASCII + typeToken = TOKEN_KEY_LONG_STRING; + // and we will need String end marker byte + _outputBuffer[_outputTail++] = BYTE_MARKER_END_OF_STRING; + } + } else { // not all ASCII + if (byteLen <= MAX_SHORT_NAME_UNICODE_BYTES) { // yes, is short indeed + // note: since 2 is smaller allowed length, offset differs from one used for + typeToken = (byte) ((TOKEN_PREFIX_KEY_UNICODE - 2) + byteLen); + } else { // nope, longer non-ASCII Strings + typeToken = TOKEN_KEY_LONG_STRING; + // and we will need String end marker byte + _outputBuffer[_outputTail++] = BYTE_MARKER_END_OF_STRING; + } + } + // and then sneak in type token now that know the details + _outputBuffer[origOffset] = typeToken; + // Also, keep track if we can use back-references (shared names) + if (_seenNameCount >= 0) { + _addSeenName(name); + } + } + + private final void _writeNonShortFieldName(final String name, final int len) + throws IOException, JsonGenerationException + { + _writeByte(TOKEN_KEY_LONG_STRING); + // can we still make a temp copy? + if (len > _charBufferLength) { // nah, not even that + _slowUTF8Encode(name); + } else { // yep. + name.getChars(0, len, _charBuffer, 0); + // but will encoded version fit in buffer? + int maxLen = len + len + len; + if (maxLen <= _outputBuffer.length) { // yes indeed + if ((_outputTail + maxLen) >= _outputEnd) { + _flushBuffer(); + } + _shortUTF8Encode(_charBuffer, 0, len); + } else { // nope, need bit slower variant + _mediumUTF8Encode(_charBuffer, 0, len); + } + } + if (_seenNameCount >= 0) { + _addSeenName(name); + } + if (_outputTail >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = BYTE_MARKER_END_OF_STRING; + } + + protected final void _writeFieldName(SerializableString name) + throws IOException, JsonGenerationException + { + final int charLen = name.charLength(); + if (charLen == 0) { + _writeByte(TOKEN_KEY_EMPTY_STRING); + return; + } + final byte[] bytes = name.asUnquotedUTF8(); + final int byteLen = bytes.length; + if (byteLen != charLen) { + _writeFieldNameUnicode(name, bytes); + return; + } + // Then: is it something we can share? + if (_seenNameCount >= 0) { + int ix = _findSeenName(name.getValue()); + if (ix >= 0) { + _writeSharedNameReference(ix); + return; + } + } + + // Common case: short ASCII name that fits in buffer as is + if (byteLen <= MAX_SHORT_NAME_ASCII_BYTES) { + // output buffer is bigger than what we need, always, so + if ((_outputTail + byteLen) >= _outputEnd) { // need marker byte and actual bytes + _flushBuffer(); + } + _outputBuffer[_outputTail++] = (byte) ((TOKEN_PREFIX_KEY_ASCII - 1) + byteLen); + System.arraycopy(bytes, 0, _outputBuffer, _outputTail, byteLen); + _outputTail += byteLen; + } else { + _writeLongAsciiFieldName(bytes); + } + // Also, keep track if we can use back-references (shared names) + if (_seenNameCount >= 0) { + _addSeenName(name.getValue()); + } + } + + private final void _writeLongAsciiFieldName(byte[] bytes) + throws IOException, JsonGenerationException + { + final int byteLen = bytes.length; + if (_outputTail >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = TOKEN_KEY_LONG_STRING; + // Ok. Enough room? + if ((_outputTail + byteLen + 1) < _outputEnd) { + System.arraycopy(bytes, 0, _outputBuffer, _outputTail, byteLen); + _outputTail += byteLen; + } else { + _flushBuffer(); + // either way, do intermediate copy if name is relatively short + // Need to copy? + if (byteLen < MIN_BUFFER_LENGTH) { + System.arraycopy(bytes, 0, _outputBuffer, _outputTail, byteLen); + _outputTail += byteLen; + } else { + // otherwise, just write as is + if (_outputTail > 0) { + _flushBuffer(); + } + _out.write(bytes, 0, byteLen); + } + } + _outputBuffer[_outputTail++] = BYTE_MARKER_END_OF_STRING; + } + + protected final void _writeFieldNameUnicode(SerializableString name, byte[] bytes) + throws IOException, JsonGenerationException + { + // Then: is it something we can share? + if (_seenNameCount >= 0) { + int ix = _findSeenName(name.getValue()); + if (ix >= 0) { + _writeSharedNameReference(ix); + return; + } + } + + final int byteLen = bytes.length; + + // Common case: short Unicode name that fits in output buffer + if (byteLen <= MAX_SHORT_NAME_UNICODE_BYTES) { + if ((_outputTail + byteLen) >= _outputEnd) { // need marker byte and actual bytes + _flushBuffer(); + } + // note: since 2 is smaller allowed length, offset differs from one used for + _outputBuffer[_outputTail++] = (byte) ((TOKEN_PREFIX_KEY_UNICODE - 2) + byteLen); + + System.arraycopy(bytes, 0, _outputBuffer, _outputTail, byteLen); + _outputTail += byteLen; + // Also, keep track if we can use back-references (shared names) + if (_seenNameCount >= 0) { + _addSeenName(name.getValue()); + } + return; + } + if (_outputTail >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = TOKEN_KEY_LONG_STRING; + // Ok. Enough room? + if ((_outputTail + byteLen + 1) < _outputEnd) { + System.arraycopy(bytes, 0, _outputBuffer, _outputTail, byteLen); + _outputTail += byteLen; + } else { + _flushBuffer(); + // either way, do intermediate copy if name is relatively short + // Need to copy? + if (byteLen < MIN_BUFFER_LENGTH) { + System.arraycopy(bytes, 0, _outputBuffer, _outputTail, byteLen); + _outputTail += byteLen; + } else { + // otherwise, just write as is + if (_outputTail > 0) { + _flushBuffer(); + } + _out.write(bytes, 0, byteLen); + } + } + _outputBuffer[_outputTail++] = BYTE_MARKER_END_OF_STRING; + // Also, keep track if we can use back-references (shared names) + if (_seenNameCount >= 0) { + _addSeenName(name.getValue()); + } + } + + private final void _writeSharedNameReference(int ix) + throws IOException,JsonGenerationException + { + // 03-Mar-2011, tatu: Related to [JACKSON-525], let's add a sanity check here + if (ix >= _seenNameCount) { + throw new IllegalArgumentException("Internal error: trying to write shared name with index "+ix + +"; but have only seen "+_seenNameCount+" so far!"); + } + if (ix < 64) { + _writeByte((byte) (TOKEN_PREFIX_KEY_SHARED_SHORT + ix)); + } else { + _writeBytes(((byte) (TOKEN_PREFIX_KEY_SHARED_LONG + (ix >> 8))), (byte) ix); + } + } + + /* + /********************************************************** + /* Output method implementations, textual + /********************************************************** + */ + + @Override + public void writeString(String text) throws IOException,JsonGenerationException + { + if (text == null) { + writeNull(); + return; + } + _verifyValueWrite("write String value"); + int len = text.length(); + if (len == 0) { + _writeByte(TOKEN_LITERAL_EMPTY_STRING); + return; + } + // Longer string handling off-lined + if (len > MAX_SHARED_STRING_LENGTH_BYTES) { + _writeNonSharedString(text, len); + return; + } + // Then: is it something we can share? + if (_seenStringValueCount >= 0) { + int ix = _findSeenStringValue(text); + if (ix >= 0) { + _writeSharedStringValueReference(ix); + return; + } + } + + // possibly short string (but not necessarily) + // first: ensure we have enough space + if ((_outputTail + MIN_BUFFER_FOR_POSSIBLE_SHORT_STRING) >= _outputEnd) { + _flushBuffer(); + } + // then let's copy String chars to char buffer, faster than using getChar (measured, profiled) + text.getChars(0, len, _charBuffer, 0); + int origOffset = _outputTail; + ++_outputTail; // to leave room for type token + int byteLen = _shortUTF8Encode(_charBuffer, 0, len); + if (byteLen <= MAX_SHORT_VALUE_STRING_BYTES) { // yes, is short indeed + // plus keep reference, if it could be shared: + if (_seenStringValueCount >= 0) { + _addSeenStringValue(text); + } + if (byteLen == len) { // and all ASCII + _outputBuffer[origOffset] = (byte) ((TOKEN_PREFIX_TINY_ASCII - 1) + byteLen); + } else { // not just ASCII + // note: since length 1 can not be used here, value range is offset by 2, not 1 + _outputBuffer[origOffset] = (byte) ((TOKEN_PREFIX_TINY_UNICODE - 2) + byteLen); + } + } else { // nope, longer String + _outputBuffer[origOffset] = (byteLen == len) ? TOKEN_BYTE_LONG_STRING_ASCII : TOKEN_BYTE_LONG_STRING_UNICODE; + // and we will need String end marker byte + _outputBuffer[_outputTail++] = BYTE_MARKER_END_OF_STRING; + } + } + + private final void _writeSharedStringValueReference(int ix) + throws IOException,JsonGenerationException + { + // 03-Mar-2011, tatu: Related to [JACKSON-525], let's add a sanity check here + if (ix >= _seenStringValueCount) { + throw new IllegalArgumentException("Internal error: trying to write shared String value with index "+ix + +"; but have only seen "+_seenStringValueCount+" so far!"); + } + if (ix < 31) { // add 1, as byte 0 is omitted + _writeByte((byte) (TOKEN_PREFIX_SHARED_STRING_SHORT + 1 + ix)); + } else { + _writeBytes(((byte) (TOKEN_MISC_SHARED_STRING_LONG + (ix >> 8))), (byte) ix); + } + } + + /** + * Helper method called to handle cases where String value to write is known + * to be long enough not to be shareable. + */ + private final void _writeNonSharedString(final String text, final int len) + throws IOException,JsonGenerationException + { + // First: can we at least make a copy to char[]? + if (len > _charBufferLength) { // nope; need to skip copy step (alas; this is slower) + _writeByte(TOKEN_BYTE_LONG_STRING_UNICODE); + _slowUTF8Encode(text); + _writeByte(BYTE_MARKER_END_OF_STRING); + return; + } + text.getChars(0, len, _charBuffer, 0); + // Expansion can be 3x for Unicode; and then there's type byte and end marker, so: + int maxLen = len + len + len + 2; + // Next: does it always fit within output buffer? + if (maxLen > _outputBuffer.length) { // nope + // can't rewrite type buffer, so can't speculate it might be all-ASCII + _writeByte(TOKEN_BYTE_LONG_STRING_UNICODE); + _mediumUTF8Encode(_charBuffer, 0, len); + _writeByte(BYTE_MARKER_END_OF_STRING); + return; + } + + if ((_outputTail + maxLen) >= _outputEnd) { + _flushBuffer(); + } + int origOffset = _outputTail; + // can't say for sure if it's ASCII or Unicode, so: + _writeByte(TOKEN_BYTE_LONG_STRING_ASCII); + int byteLen = _shortUTF8Encode(_charBuffer, 0, len); + // If not ASCII, fix type: + if (byteLen > len) { + _outputBuffer[origOffset] = TOKEN_BYTE_LONG_STRING_UNICODE; + } + _outputBuffer[_outputTail++] = BYTE_MARKER_END_OF_STRING; + } + + @Override + public void writeString(char[] text, int offset, int len) throws IOException, JsonGenerationException + { + // Shared strings are tricky; easiest to just construct String, call the other method + if (len <= MAX_SHARED_STRING_LENGTH_BYTES && _seenStringValueCount >= 0 && len > 0) { + writeString(new String(text, offset, len)); + return; + } + _verifyValueWrite("write String value"); + if (len == 0) { + _writeByte(TOKEN_LITERAL_EMPTY_STRING); + return; + } + if (len <= MAX_SHORT_VALUE_STRING_BYTES) { // possibly short strings (not necessarily) + // first: ensure we have enough space + if ((_outputTail + MIN_BUFFER_FOR_POSSIBLE_SHORT_STRING) >= _outputEnd) { + _flushBuffer(); + } + int origOffset = _outputTail; + ++_outputTail; // to leave room for type token + int byteLen = _shortUTF8Encode(text, offset, offset+len); + byte typeToken; + if (byteLen <= MAX_SHORT_VALUE_STRING_BYTES) { // yes, is short indeed + if (byteLen == len) { // and all ASCII + typeToken = (byte) ((TOKEN_PREFIX_TINY_ASCII - 1) + byteLen); + } else { // not just ASCII + typeToken = (byte) ((TOKEN_PREFIX_TINY_UNICODE - 2) + byteLen); + } + } else { // nope, longer non-ASCII Strings + typeToken = TOKEN_BYTE_LONG_STRING_UNICODE; + // and we will need String end marker byte + _outputBuffer[_outputTail++] = BYTE_MARKER_END_OF_STRING; + } + // and then sneak in type token now that know the details + _outputBuffer[origOffset] = typeToken; + } else { // "long" String, never shared + // but might still fit within buffer? + int maxLen = len + len + len + 2; + if (maxLen <= _outputBuffer.length) { // yes indeed + if ((_outputTail + maxLen) >= _outputEnd) { + _flushBuffer(); + } + int origOffset = _outputTail; + _writeByte(TOKEN_BYTE_LONG_STRING_UNICODE); + int byteLen = _shortUTF8Encode(text, offset, offset+len); + // if it's ASCII, let's revise our type determination (to help decoder optimize) + if (byteLen == len) { + _outputBuffer[origOffset] = TOKEN_BYTE_LONG_STRING_ASCII; + } + _outputBuffer[_outputTail++] = BYTE_MARKER_END_OF_STRING; + } else { + _writeByte(TOKEN_BYTE_LONG_STRING_UNICODE); + _mediumUTF8Encode(text, offset, offset+len); + _writeByte(BYTE_MARKER_END_OF_STRING); + } + } + } + + @Override + public final void writeString(SerializableString sstr) + throws IOException, JsonGenerationException + { + _verifyValueWrite("write String value"); + // First: is it empty? + String str = sstr.getValue(); + int len = str.length(); + if (len == 0) { + _writeByte(TOKEN_LITERAL_EMPTY_STRING); + return; + } + // Second: something we can share? + if (len <= MAX_SHARED_STRING_LENGTH_BYTES && _seenStringValueCount >= 0) { + int ix = _findSeenStringValue(str); + if (ix >= 0) { + _writeSharedStringValueReference(ix); + return; + } + } + // If not, use pre-encoded version + byte[] raw = sstr.asUnquotedUTF8(); + final int byteLen = raw.length; + + if (byteLen <= MAX_SHORT_VALUE_STRING_BYTES) { // short string + // first: ensure we have enough space + if ((_outputTail + byteLen + 1) >= _outputEnd) { + _flushBuffer(); + } + // ASCII or Unicode? + int typeToken = (byteLen == len) + ? ((TOKEN_PREFIX_TINY_ASCII - 1) + byteLen) + : ((TOKEN_PREFIX_TINY_UNICODE - 2) + byteLen) + ; + _outputBuffer[_outputTail++] = (byte) typeToken; + System.arraycopy(raw, 0, _outputBuffer, _outputTail, byteLen); + _outputTail += byteLen; + // plus keep reference, if it could be shared: + if (_seenStringValueCount >= 0) { + _addSeenStringValue(sstr.getValue()); + } + } else { // "long" String, never shared + // but might still fit within buffer? + byte typeToken = (byteLen == len) ? TOKEN_BYTE_LONG_STRING_ASCII : TOKEN_BYTE_LONG_STRING_UNICODE; + _writeByte(typeToken); + _writeBytes(raw, 0, raw.length); + _writeByte(BYTE_MARKER_END_OF_STRING); + } + } + + @Override + public void writeRawUTF8String(byte[] text, int offset, int len) + throws IOException, JsonGenerationException + { + _verifyValueWrite("write String value"); + // first: is it empty String? + if (len == 0) { + _writeByte(TOKEN_LITERAL_EMPTY_STRING); + return; + } + // Sanity check: shared-strings incompatible with raw String writing + if (_seenStringValueCount >= 0) { + throw new UnsupportedOperationException("Can not use direct UTF-8 write methods when 'Feature.CHECK_SHARED_STRING_VALUES' enabled"); + } + /* Other practical limitation is that we do not really know if it might be + * ASCII or not; and figuring it out is rather slow. So, best we can do is + * to declare we do not know it is ASCII (i.e. "is Unicode"). + */ + if (len <= MAX_SHARED_STRING_LENGTH_BYTES) { // up to 65 Unicode bytes + // first: ensure we have enough space + if ((_outputTail + len) >= _outputEnd) { // bytes, plus one for type indicator + _flushBuffer(); + } + /* 11-Feb-2011, tatu: As per [JACKSON-492], mininum length for "Unicode" + * String is 2; 1 byte length must be ASCII. + */ + if (len == 1) { + _outputBuffer[_outputTail++] = TOKEN_PREFIX_TINY_ASCII; // length of 1 cancels out (len-1) + _outputBuffer[_outputTail++] = text[offset]; + } else { + _outputBuffer[_outputTail++] = (byte) ((TOKEN_PREFIX_TINY_UNICODE - 2) + len); + System.arraycopy(text, offset, _outputBuffer, _outputTail, len); + _outputTail += len; + } + } else { // "long" String + // but might still fit within buffer? + int maxLen = len + len + len + 2; + if (maxLen <= _outputBuffer.length) { // yes indeed + if ((_outputTail + maxLen) >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = TOKEN_BYTE_LONG_STRING_UNICODE; + System.arraycopy(text, offset, _outputBuffer, _outputTail, len); + _outputTail += len; + _outputBuffer[_outputTail++] = BYTE_MARKER_END_OF_STRING; + } else { + _writeByte(TOKEN_BYTE_LONG_STRING_UNICODE); + _writeBytes(text, offset, len); + _writeByte(BYTE_MARKER_END_OF_STRING); + } + } + } + + @Override + public final void writeUTF8String(byte[] text, int offset, int len) + throws IOException, JsonGenerationException + { + // Since no escaping is needed, same as 'writeRawUTF8String' + writeRawUTF8String(text, offset, len); + } + + /* + /********************************************************** + /* Output method implementations, unprocessed ("raw") + /********************************************************** + */ + + @Override + public void writeRaw(String text) throws IOException, JsonGenerationException { + throw _notSupported(); + } + + @Override + public void writeRaw(String text, int offset, int len) throws IOException, JsonGenerationException { + throw _notSupported(); + } + + @Override + public void writeRaw(char[] text, int offset, int len) throws IOException, JsonGenerationException { + throw _notSupported(); + } + + @Override + public void writeRaw(char c) throws IOException, JsonGenerationException { + throw _notSupported(); + } + + @Override + public void writeRawValue(String text) throws IOException, JsonGenerationException { + throw _notSupported(); + } + + @Override + public void writeRawValue(String text, int offset, int len) throws IOException, JsonGenerationException { + throw _notSupported(); + } + + @Override + public void writeRawValue(char[] text, int offset, int len) throws IOException, JsonGenerationException { + throw _notSupported(); + } + + /* + /********************************************************** + /* Output method implementations, base64-encoded binary + /********************************************************** + */ + + @Override + public void writeBinary(Base64Variant b64variant, byte[] data, int offset, int len) throws IOException, JsonGenerationException + { + if (data == null) { + writeNull(); + return; + } + _verifyValueWrite("write Binary value"); + if (this.isEnabled(Feature.ENCODE_BINARY_AS_7BIT)) { + _writeByte((byte) TOKEN_MISC_BINARY_7BIT); + _write7BitBinaryWithLength(data, offset, len); + } else { + _writeByte((byte) TOKEN_MISC_BINARY_RAW ); + _writePositiveVInt(len); + // raw is dead simple of course: + _writeBytes(data, offset, len); + } + } + + /* + /********************************************************** + /* Output method implementations, primitive + /********************************************************** + */ + + @Override + public void writeBoolean(boolean state) throws IOException, JsonGenerationException + { + _verifyValueWrite("write boolean value"); + if (state) { + _writeByte(TOKEN_LITERAL_TRUE); + } else { + _writeByte(TOKEN_LITERAL_FALSE); + } + } + + @Override + public void writeNull() throws IOException, JsonGenerationException + { + _verifyValueWrite("write null value"); + _writeByte(TOKEN_LITERAL_NULL); + } + + @Override + public void writeNumber(int i) throws IOException, JsonGenerationException + { + _verifyValueWrite("write number"); + // First things first: let's zigzag encode number + i = SmileUtil.zigzagEncode(i); + // tiny (single byte) or small (type + 6-bit value) number? + if (i <= 0x3F && i >= 0) { + if (i <= 0x1F) { // tiny + _writeByte((byte) (TOKEN_PREFIX_SMALL_INT + i)); + return; + } + // nope, just small, 2 bytes (type, 1-byte zigzag value) for 6 bit value + _writeBytes(TOKEN_BYTE_INT_32, (byte) (0x80 + i)); + return; + } + // Ok: let's find minimal representation then + byte b0 = (byte) (0x80 + (i & 0x3F)); + i >>>= 6; + if (i <= 0x7F) { // 13 bits is enough (== 3 byte total encoding) + _writeBytes(TOKEN_BYTE_INT_32, (byte) i, b0); + return; + } + byte b1 = (byte) (i & 0x7F); + i >>= 7; + if (i <= 0x7F) { + _writeBytes(TOKEN_BYTE_INT_32, (byte) i, b1, b0); + return; + } + byte b2 = (byte) (i & 0x7F); + i >>= 7; + if (i <= 0x7F) { + _writeBytes(TOKEN_BYTE_INT_32, (byte) i, b2, b1, b0); + return; + } + // no, need all 5 bytes + byte b3 = (byte) (i & 0x7F); + _writeBytes(TOKEN_BYTE_INT_32, (byte) (i >> 7), b3, b2, b1, b0); + } + + @Override + public void writeNumber(long l) throws IOException, JsonGenerationException + { + // First: maybe 32 bits is enough? + if (l <= MAX_INT_AS_LONG && l >= MIN_INT_AS_LONG) { + writeNumber((int) l); + return; + } + _verifyValueWrite("write number"); + // Then let's zigzag encode it + + l = SmileUtil.zigzagEncode(l); + // Ok, well, we do know that 5 lowest-significant bytes are needed + int i = (int) l; + // 4 can be extracted from lower int + byte b0 = (byte) (0x80 + (i & 0x3F)); // sign bit set in the last byte + byte b1 = (byte) ((i >> 6) & 0x7F); + byte b2 = (byte) ((i >> 13) & 0x7F); + byte b3 = (byte) ((i >> 20) & 0x7F); + // fifth one is split between ints: + l >>>= 27; + byte b4 = (byte) (((int) l) & 0x7F); + + // which may be enough? + i = (int) (l >> 7); + if (i == 0) { + _writeBytes(TOKEN_BYTE_INT_64, b4, b3, b2, b1, b0); + return; + } + + if (i <= 0x7F) { + _writeBytes(TOKEN_BYTE_INT_64, (byte) i); + _writeBytes(b4, b3, b2, b1, b0); + return; + } + byte b5 = (byte) (i & 0x7F); + i >>= 7; + if (i <= 0x7F) { + _writeBytes(TOKEN_BYTE_INT_64, (byte) i); + _writeBytes(b5, b4, b3, b2, b1, b0); + return; + } + byte b6 = (byte) (i & 0x7F); + i >>= 7; + if (i <= 0x7F) { + _writeBytes(TOKEN_BYTE_INT_64, (byte) i, b6); + _writeBytes(b5, b4, b3, b2, b1, b0); + return; + } + byte b7 = (byte) (i & 0x7F); + i >>= 7; + if (i <= 0x7F) { + _writeBytes(TOKEN_BYTE_INT_64, (byte) i, b7, b6); + _writeBytes(b5, b4, b3, b2, b1, b0); + return; + } + byte b8 = (byte) (i & 0x7F); + i >>= 7; + // must be done, with 10 bytes! (9 * 7 + 6 == 69 bits; only need 63) + _writeBytes(TOKEN_BYTE_INT_64, (byte) i, b8, b7, b6); + _writeBytes(b5, b4, b3, b2, b1, b0); + } + + @Override + public void writeNumber(BigInteger v) throws IOException, JsonGenerationException + { + if (v == null) { + writeNull(); + return; + } + _verifyValueWrite("write number"); + // quite simple: type, and then VInt-len prefixed 7-bit encoded binary data: + _writeByte(TOKEN_BYTE_BIG_INTEGER); + byte[] data = v.toByteArray(); + _write7BitBinaryWithLength(data, 0, data.length); + } + + @Override + public void writeNumber(double d) throws IOException, JsonGenerationException + { + // Ok, now, we needed token type byte plus 10 data bytes (7 bits each) + _ensureRoomForOutput(11); + _verifyValueWrite("write number"); + /* 17-Apr-2010, tatu: could also use 'doubleToIntBits', but it seems more accurate to use + * exact representation; and possibly faster. However, if there are cases + * where collapsing of NaN was needed (for non-Java clients), this can + * be changed + */ + long l = Double.doubleToRawLongBits(d); + _outputBuffer[_outputTail++] = TOKEN_BYTE_FLOAT_64; + // Handle first 29 bits (single bit first, then 4 x 7 bits) + int hi5 = (int) (l >>> 35); + _outputBuffer[_outputTail+4] = (byte) (hi5 & 0x7F); + hi5 >>= 7; + _outputBuffer[_outputTail+3] = (byte) (hi5 & 0x7F); + hi5 >>= 7; + _outputBuffer[_outputTail+2] = (byte) (hi5 & 0x7F); + hi5 >>= 7; + _outputBuffer[_outputTail+1] = (byte) (hi5 & 0x7F); + hi5 >>= 7; + _outputBuffer[_outputTail] = (byte) hi5; + _outputTail += 5; + // Then split byte (one that crosses lo/hi int boundary), 7 bits + { + int mid = (int) (l >> 28); + _outputBuffer[_outputTail++] = (byte) (mid & 0x7F); + } + // and then last 4 bytes (28 bits) + int lo4 = (int) l; + _outputBuffer[_outputTail+3] = (byte) (lo4 & 0x7F); + lo4 >>= 7; + _outputBuffer[_outputTail+2] = (byte) (lo4 & 0x7F); + lo4 >>= 7; + _outputBuffer[_outputTail+1] = (byte) (lo4 & 0x7F); + lo4 >>= 7; + _outputBuffer[_outputTail] = (byte) (lo4 & 0x7F); + _outputTail += 4; + } + + @Override + public void writeNumber(float f) throws IOException, JsonGenerationException + { + // Ok, now, we needed token type byte plus 5 data bytes (7 bits each) + _ensureRoomForOutput(6); + _verifyValueWrite("write number"); + + /* 17-Apr-2010, tatu: could also use 'floatToIntBits', but it seems more accurate to use + * exact representation; and possibly faster. However, if there are cases + * where collapsing of NaN was needed (for non-Java clients), this can + * be changed + */ + int i = Float.floatToRawIntBits(f); + _outputBuffer[_outputTail++] = TOKEN_BYTE_FLOAT_32; + _outputBuffer[_outputTail+4] = (byte) (i & 0x7F); + i >>= 7; + _outputBuffer[_outputTail+3] = (byte) (i & 0x7F); + i >>= 7; + _outputBuffer[_outputTail+2] = (byte) (i & 0x7F); + i >>= 7; + _outputBuffer[_outputTail+1] = (byte) (i & 0x7F); + i >>= 7; + _outputBuffer[_outputTail] = (byte) (i & 0x7F); + _outputTail += 5; + } + + @Override + public void writeNumber(BigDecimal dec) throws IOException, JsonGenerationException + { + if (dec == null) { + writeNull(); + return; + } + _verifyValueWrite("write number"); + _writeByte(TOKEN_BYTE_BIG_DECIMAL); + int scale = dec.scale(); + // Ok, first output scale as VInt + _writeSignedVInt(scale); + BigInteger unscaled = dec.unscaledValue(); + byte[] data = unscaled.toByteArray(); + // And then binary data in "safe" mode (7-bit values) + _write7BitBinaryWithLength(data, 0, data.length); + } + + @Override + public void writeNumber(String encodedValue) throws IOException,JsonGenerationException, UnsupportedOperationException + { + /* 17-Apr-2010, tatu: Could try parsing etc; but for now let's not bother, it could + * just be some non-standard representation that caller wants to pass + */ + throw _notSupported(); + } + + /* + /********************************************************** + /* Implementations for other methods + /********************************************************** + */ + + @Override + protected final void _verifyValueWrite(String typeMsg) + throws IOException, JsonGenerationException + { + int status = _writeContext.writeValue(); + if (status == JsonWriteContext.STATUS_EXPECT_NAME) { + _reportError("Can not "+typeMsg+", expecting field name"); + } + } + + /* + /********************************************************** + /* Low-level output handling + /********************************************************** + */ + + @Override + public final void flush() throws IOException + { + _flushBuffer(); + if (isEnabled(JsonGenerator.Feature.FLUSH_PASSED_TO_STREAM)) { + _out.flush(); + } + } + + @Override + public void close() throws IOException + { + /* 05-Dec-2008, tatu: To add [JACKSON-27], need to close open + * scopes. + */ + // First: let's see that we still have buffers... + if (_outputBuffer != null + && isEnabled(JsonGenerator.Feature.AUTO_CLOSE_JSON_CONTENT)) { + while (true) { + JsonStreamContext ctxt = getOutputContext(); + if (ctxt.inArray()) { + writeEndArray(); + } else if (ctxt.inObject()) { + writeEndObject(); + } else { + break; + } + } + } + boolean wasClosed = _closed; + super.close(); + + if (!wasClosed && isEnabled(Feature.WRITE_END_MARKER)) { + _writeByte(BYTE_MARKER_END_OF_CONTENT); + } + _flushBuffer(); + + if (_ioContext.isResourceManaged() || isEnabled(JsonGenerator.Feature.AUTO_CLOSE_TARGET)) { + _out.close(); + } else { + // If we can't close it, we should at least flush + _out.flush(); + } + // Internal buffer(s) generator has can now be released as well + _releaseBuffers(); + } + + /* + /********************************************************** + /* Internal methods, UTF-8 encoding + /********************************************************** + */ + + /** + * Helper method called when the whole character sequence is known to + * fit in the output buffer regardless of UTF-8 expansion. + */ + private final int _shortUTF8Encode(char[] str, int i, int end) + { + // First: let's see if it's all ASCII: that's rather fast + int ptr = _outputTail; + final byte[] outBuf = _outputBuffer; + do { + int c = str[i]; + if (c > 0x7F) { + return _shortUTF8Encode2(str, i, end, ptr); + } + outBuf[ptr++] = (byte) c; + } while (++i < end); + int codedLen = ptr - _outputTail; + _outputTail = ptr; + return codedLen; + } + + /** + * Helper method called when the whole character sequence is known to + * fit in the output buffer, but not all characters are single-byte (ASCII) + * characters. + */ + private final int _shortUTF8Encode2(char[] str, int i, int end, int outputPtr) + { + final byte[] outBuf = _outputBuffer; + while (i < end) { + int c = str[i++]; + if (c <= 0x7F) { + outBuf[outputPtr++] = (byte) c; + continue; + } + // Nope, multi-byte: + if (c < 0x800) { // 2-byte + outBuf[outputPtr++] = (byte) (0xc0 | (c >> 6)); + outBuf[outputPtr++] = (byte) (0x80 | (c & 0x3f)); + continue; + } + // 3 or 4 bytes (surrogate) + // Surrogates? + if (c < SURR1_FIRST || c > SURR2_LAST) { // nope, regular 3-byte character + outBuf[outputPtr++] = (byte) (0xe0 | (c >> 12)); + outBuf[outputPtr++] = (byte) (0x80 | ((c >> 6) & 0x3f)); + outBuf[outputPtr++] = (byte) (0x80 | (c & 0x3f)); + continue; + } + // Yup, a surrogate pair + if (c > SURR1_LAST) { // must be from first range; second won't do + _throwIllegalSurrogate(c); + } + // ... meaning it must have a pair + if (i >= end) { + _throwIllegalSurrogate(c); + } + c = _convertSurrogate(c, str[i++]); + if (c > 0x10FFFF) { // illegal in JSON as well as in XML + _throwIllegalSurrogate(c); + } + outBuf[outputPtr++] = (byte) (0xf0 | (c >> 18)); + outBuf[outputPtr++] = (byte) (0x80 | ((c >> 12) & 0x3f)); + outBuf[outputPtr++] = (byte) (0x80 | ((c >> 6) & 0x3f)); + outBuf[outputPtr++] = (byte) (0x80 | (c & 0x3f)); + } + int codedLen = outputPtr - _outputTail; + _outputTail = outputPtr; + return codedLen; + } + + private void _slowUTF8Encode(String str) throws IOException + { + final int len = str.length(); + int inputPtr = 0; + final int bufferEnd = _outputEnd - 4; + + output_loop: + for (; inputPtr < len; ) { + /* First, let's ensure we can output at least 4 bytes + * (longest UTF-8 encoded codepoint): + */ + if (_outputTail >= bufferEnd) { + _flushBuffer(); + } + int c = str.charAt(inputPtr++); + // And then see if we have an ASCII char: + if (c <= 0x7F) { // If so, can do a tight inner loop: + _outputBuffer[_outputTail++] = (byte)c; + // Let's calc how many ASCII chars we can copy at most: + int maxInCount = (len - inputPtr); + int maxOutCount = (bufferEnd - _outputTail); + + if (maxInCount > maxOutCount) { + maxInCount = maxOutCount; + } + maxInCount += inputPtr; + ascii_loop: + while (true) { + if (inputPtr >= maxInCount) { // done with max. ascii seq + continue output_loop; + } + c = str.charAt(inputPtr++); + if (c > 0x7F) { + break ascii_loop; + } + _outputBuffer[_outputTail++] = (byte) c; + } + } + + // Nope, multi-byte: + if (c < 0x800) { // 2-byte + _outputBuffer[_outputTail++] = (byte) (0xc0 | (c >> 6)); + _outputBuffer[_outputTail++] = (byte) (0x80 | (c & 0x3f)); + } else { // 3 or 4 bytes + // Surrogates? + if (c < SURR1_FIRST || c > SURR2_LAST) { + _outputBuffer[_outputTail++] = (byte) (0xe0 | (c >> 12)); + _outputBuffer[_outputTail++] = (byte) (0x80 | ((c >> 6) & 0x3f)); + _outputBuffer[_outputTail++] = (byte) (0x80 | (c & 0x3f)); + continue; + } + // Yup, a surrogate: + if (c > SURR1_LAST) { // must be from first range + _throwIllegalSurrogate(c); + } + // and if so, followed by another from next range + if (inputPtr >= len) { + _throwIllegalSurrogate(c); + } + c = _convertSurrogate(c, str.charAt(inputPtr++)); + if (c > 0x10FFFF) { // illegal, as per RFC 4627 + _throwIllegalSurrogate(c); + } + _outputBuffer[_outputTail++] = (byte) (0xf0 | (c >> 18)); + _outputBuffer[_outputTail++] = (byte) (0x80 | ((c >> 12) & 0x3f)); + _outputBuffer[_outputTail++] = (byte) (0x80 | ((c >> 6) & 0x3f)); + _outputBuffer[_outputTail++] = (byte) (0x80 | (c & 0x3f)); + } + } + } + + private void _mediumUTF8Encode(char[] str, int inputPtr, int inputEnd) throws IOException + { + final int bufferEnd = _outputEnd - 4; + + output_loop: + while (inputPtr < inputEnd) { + /* First, let's ensure we can output at least 4 bytes + * (longest UTF-8 encoded codepoint): + */ + if (_outputTail >= bufferEnd) { + _flushBuffer(); + } + int c = str[inputPtr++]; + // And then see if we have an ASCII char: + if (c <= 0x7F) { // If so, can do a tight inner loop: + _outputBuffer[_outputTail++] = (byte)c; + // Let's calc how many ASCII chars we can copy at most: + int maxInCount = (inputEnd - inputPtr); + int maxOutCount = (bufferEnd - _outputTail); + + if (maxInCount > maxOutCount) { + maxInCount = maxOutCount; + } + maxInCount += inputPtr; + ascii_loop: + while (true) { + if (inputPtr >= maxInCount) { // done with max. ascii seq + continue output_loop; + } + c = str[inputPtr++]; + if (c > 0x7F) { + break ascii_loop; + } + _outputBuffer[_outputTail++] = (byte) c; + } + } + + // Nope, multi-byte: + if (c < 0x800) { // 2-byte + _outputBuffer[_outputTail++] = (byte) (0xc0 | (c >> 6)); + _outputBuffer[_outputTail++] = (byte) (0x80 | (c & 0x3f)); + } else { // 3 or 4 bytes + // Surrogates? + if (c < SURR1_FIRST || c > SURR2_LAST) { + _outputBuffer[_outputTail++] = (byte) (0xe0 | (c >> 12)); + _outputBuffer[_outputTail++] = (byte) (0x80 | ((c >> 6) & 0x3f)); + _outputBuffer[_outputTail++] = (byte) (0x80 | (c & 0x3f)); + continue; + } + // Yup, a surrogate: + if (c > SURR1_LAST) { // must be from first range + _throwIllegalSurrogate(c); + } + // and if so, followed by another from next range + if (inputPtr >= inputEnd) { + _throwIllegalSurrogate(c); + } + c = _convertSurrogate(c, str[inputPtr++]); + if (c > 0x10FFFF) { // illegal, as per RFC 4627 + _throwIllegalSurrogate(c); + } + _outputBuffer[_outputTail++] = (byte) (0xf0 | (c >> 18)); + _outputBuffer[_outputTail++] = (byte) (0x80 | ((c >> 12) & 0x3f)); + _outputBuffer[_outputTail++] = (byte) (0x80 | ((c >> 6) & 0x3f)); + _outputBuffer[_outputTail++] = (byte) (0x80 | (c & 0x3f)); + } + } + } + + /** + * Method called to calculate UTF codepoint, from a surrogate pair. + */ + private int _convertSurrogate(int firstPart, int secondPart) + { + // Ok, then, is the second part valid? + if (secondPart < SURR2_FIRST || secondPart > SURR2_LAST) { + throw new IllegalArgumentException("Broken surrogate pair: first char 0x"+Integer.toHexString(firstPart)+", second 0x"+Integer.toHexString(secondPart)+"; illegal combination"); + } + return 0x10000 + ((firstPart - SURR1_FIRST) << 10) + (secondPart - SURR2_FIRST); + } + + private void _throwIllegalSurrogate(int code) + { + if (code > 0x10FFFF) { // over max? + throw new IllegalArgumentException("Illegal character point (0x"+Integer.toHexString(code)+") to output; max is 0x10FFFF as per RFC 4627"); + } + if (code >= SURR1_FIRST) { + if (code <= SURR1_LAST) { // Unmatched first part (closing without second part?) + throw new IllegalArgumentException("Unmatched first part of surrogate pair (0x"+Integer.toHexString(code)+")"); + } + throw new IllegalArgumentException("Unmatched second part of surrogate pair (0x"+Integer.toHexString(code)+")"); + } + // should we ever get this? + throw new IllegalArgumentException("Illegal character point (0x"+Integer.toHexString(code)+") to output"); + } + + /* + /********************************************************** + /* Internal methods, writing bytes + /********************************************************** + */ + + private final void _ensureRoomForOutput(int needed) throws IOException + { + if ((_outputTail + needed) >= _outputEnd) { + _flushBuffer(); + } + } + + private final void _writeByte(byte b) throws IOException + { + if (_outputTail >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = b; + } + + private final void _writeBytes(byte b1, byte b2) throws IOException + { + if ((_outputTail + 1) >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = b1; + _outputBuffer[_outputTail++] = b2; + } + + private final void _writeBytes(byte b1, byte b2, byte b3) throws IOException + { + if ((_outputTail + 2) >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = b1; + _outputBuffer[_outputTail++] = b2; + _outputBuffer[_outputTail++] = b3; + } + + private final void _writeBytes(byte b1, byte b2, byte b3, byte b4) throws IOException + { + if ((_outputTail + 3) >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = b1; + _outputBuffer[_outputTail++] = b2; + _outputBuffer[_outputTail++] = b3; + _outputBuffer[_outputTail++] = b4; + } + + private final void _writeBytes(byte b1, byte b2, byte b3, byte b4, byte b5) throws IOException + { + if ((_outputTail + 4) >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = b1; + _outputBuffer[_outputTail++] = b2; + _outputBuffer[_outputTail++] = b3; + _outputBuffer[_outputTail++] = b4; + _outputBuffer[_outputTail++] = b5; + } + + private final void _writeBytes(byte b1, byte b2, byte b3, byte b4, byte b5, byte b6) throws IOException + { + if ((_outputTail + 5) >= _outputEnd) { + _flushBuffer(); + } + _outputBuffer[_outputTail++] = b1; + _outputBuffer[_outputTail++] = b2; + _outputBuffer[_outputTail++] = b3; + _outputBuffer[_outputTail++] = b4; + _outputBuffer[_outputTail++] = b5; + _outputBuffer[_outputTail++] = b6; + } + + private final void _writeBytes(byte[] data, int offset, int len) throws IOException + { + if (len == 0) { + return; + } + if ((_outputTail + len) >= _outputEnd) { + _writeBytesLong(data, offset, len); + return; + } + // common case, non-empty, fits in just fine: + System.arraycopy(data, offset, _outputBuffer, _outputTail, len); + _outputTail += len; + } + + private final void _writeBytesLong(byte[] data, int offset, int len) throws IOException + { + if (_outputTail >= _outputEnd) { + _flushBuffer(); + } + while (true) { + int currLen = Math.min(len, (_outputEnd - _outputTail)); + System.arraycopy(data, offset, _outputBuffer, _outputTail, currLen); + _outputTail += currLen; + if ((len -= currLen) == 0) { + break; + } + offset += currLen; + _flushBuffer(); + } + } + + /** + * Helper method for writing a 32-bit positive (really 31-bit then) value. + * Value is NOT zigzag encoded (since there is no sign bit to worry about) + */ + private void _writePositiveVInt(int i) throws IOException + { + // At most 5 bytes (4 * 7 + 6 bits == 34 bits) + _ensureRoomForOutput(5); + byte b0 = (byte) (0x80 + (i & 0x3F)); + i >>= 6; + if (i <= 0x7F) { // 6 or 13 bits is enough (== 2 or 3 byte total encoding) + if (i > 0) { + _outputBuffer[_outputTail++] = (byte) i; + } + _outputBuffer[_outputTail++] = b0; + return; + } + byte b1 = (byte) (i & 0x7F); + i >>= 7; + if (i <= 0x7F) { + _outputBuffer[_outputTail++] = (byte) i; + _outputBuffer[_outputTail++] = b1; + _outputBuffer[_outputTail++] = b0; + } else { + byte b2 = (byte) (i & 0x7F); + i >>= 7; + if (i <= 0x7F) { + _outputBuffer[_outputTail++] = (byte) i; + _outputBuffer[_outputTail++] = b2; + _outputBuffer[_outputTail++] = b1; + _outputBuffer[_outputTail++] = b0; + } else { + byte b3 = (byte) (i & 0x7F); + _outputBuffer[_outputTail++] = (byte) (i >> 7); + _outputBuffer[_outputTail++] = b3; + _outputBuffer[_outputTail++] = b2; + _outputBuffer[_outputTail++] = b1; + _outputBuffer[_outputTail++] = b0; + } + } + } + + /** + * Helper method for writing 32-bit signed value, using + * "zig zag encoding" (see protocol buffers for explanation -- basically, + * sign bit is moved as LSB, rest of value shifted left by one) + * coupled with basic variable length encoding + */ + private void _writeSignedVInt(int input) throws IOException + { + _writePositiveVInt(SmileUtil.zigzagEncode(input)); + } + + protected void _write7BitBinaryWithLength(byte[] data, int offset, int len) throws IOException + { + _writePositiveVInt(len); + // first, let's handle full 7-byte chunks + while (len >= 7) { + if ((_outputTail + 8) >= _outputEnd) { + _flushBuffer(); + } + int i = data[offset++]; // 1st byte + _outputBuffer[_outputTail++] = (byte) ((i >> 1) & 0x7F); + i = (i << 8) | (data[offset++] & 0xFF); // 2nd + _outputBuffer[_outputTail++] = (byte) ((i >> 2) & 0x7F); + i = (i << 8) | (data[offset++] & 0xFF); // 3rd + _outputBuffer[_outputTail++] = (byte) ((i >> 3) & 0x7F); + i = (i << 8) | (data[offset++] & 0xFF); // 4th + _outputBuffer[_outputTail++] = (byte) ((i >> 4) & 0x7F); + i = (i << 8) | (data[offset++] & 0xFF); // 5th + _outputBuffer[_outputTail++] = (byte) ((i >> 5) & 0x7F); + i = (i << 8) | (data[offset++] & 0xFF); // 6th + _outputBuffer[_outputTail++] = (byte) ((i >> 6) & 0x7F); + i = (i << 8) | (data[offset++] & 0xFF); // 7th + _outputBuffer[_outputTail++] = (byte) ((i >> 7) & 0x7F); + _outputBuffer[_outputTail++] = (byte) (i & 0x7F); + len -= 7; + } + // and then partial piece, if any + if (len > 0) { + // up to 6 bytes to output, resulting in at most 7 bytes (which can encode 49 bits) + if ((_outputTail + 7) >= _outputEnd) { + _flushBuffer(); + } + int i = data[offset++]; + _outputBuffer[_outputTail++] = (byte) ((i >> 1) & 0x7F); + if (len > 1) { + i = ((i & 0x01) << 8) | (data[offset++] & 0xFF); // 2nd + _outputBuffer[_outputTail++] = (byte) ((i >> 2) & 0x7F); + if (len > 2) { + i = ((i & 0x03) << 8) | (data[offset++] & 0xFF); // 3rd + _outputBuffer[_outputTail++] = (byte) ((i >> 3) & 0x7F); + if (len > 3) { + i = ((i & 0x07) << 8) | (data[offset++] & 0xFF); // 4th + _outputBuffer[_outputTail++] = (byte) ((i >> 4) & 0x7F); + if (len > 4) { + i = ((i & 0x0F) << 8) | (data[offset++] & 0xFF); // 5th + _outputBuffer[_outputTail++] = (byte) ((i >> 5) & 0x7F); + if (len > 5) { + i = ((i & 0x1F) << 8) | (data[offset++] & 0xFF); // 6th + _outputBuffer[_outputTail++] = (byte) ((i >> 6) & 0x7F); + _outputBuffer[_outputTail++] = (byte) (i & 0x3F); // last 6 bits + } else { + _outputBuffer[_outputTail++] = (byte) (i & 0x1F); // last 5 bits + } + } else { + _outputBuffer[_outputTail++] = (byte) (i & 0x0F); // last 4 bits + } + } else { + _outputBuffer[_outputTail++] = (byte) (i & 0x07); // last 3 bits + } + } else { + _outputBuffer[_outputTail++] = (byte) (i & 0x03); // last 2 bits + } + } else { + _outputBuffer[_outputTail++] = (byte) (i & 0x01); // last bit + } + } + } + + /* + /********************************************************** + /* Internal methods, buffer handling + /********************************************************** + */ + + @Override + protected void _releaseBuffers() + { + byte[] buf = _outputBuffer; + if (buf != null && _bufferRecyclable) { + _outputBuffer = null; + _ioContext.releaseWriteEncodingBuffer(buf); + } + char[] cbuf = _charBuffer; + if (cbuf != null) { + _charBuffer = null; + _ioContext.releaseConcatBuffer(cbuf); + } + /* Ok: since clearing up of larger arrays is much slower, + * let's only recycle default-sized buffers... + */ + { + SharedStringNode[] nameBuf = _seenNames; + if (nameBuf != null && nameBuf.length == SmileBufferRecycler.DEFAULT_NAME_BUFFER_LENGTH) { + _seenNames = null; + /* 28-Jun-2011, tatu: With 1.9, caller needs to clear the buffer; and note + * that since it's a hash area, must clear all + */ + if (_seenNameCount > 0) { + Arrays.fill(nameBuf, null); + } + _smileBufferRecycler.releaseSeenNamesBuffer(nameBuf); + } + } + { + SharedStringNode[] valueBuf = _seenStringValues; + if (valueBuf != null && valueBuf.length == SmileBufferRecycler.DEFAULT_STRING_VALUE_BUFFER_LENGTH) { + _seenStringValues = null; + /* 28-Jun-2011, tatu: With 1.9, caller needs to clear the buffer; and note + * that since it's a hash area, must clear all + */ + if (_seenStringValueCount > 0) { + Arrays.fill(valueBuf, null); + } + _smileBufferRecycler.releaseSeenStringValuesBuffer(valueBuf); + } + } + } + + protected final void _flushBuffer() throws IOException + { + if (_outputTail > 0) { + _bytesWritten += _outputTail; + _out.write(_outputBuffer, 0, _outputTail); + _outputTail = 0; + } + } + + /* + /********************************************************** + /* Internal methods, handling shared string "maps" + /********************************************************** + */ + + private final int _findSeenName(String name) + { + int hash = name.hashCode(); + SharedStringNode head = _seenNames[hash & (_seenNames.length-1)]; + if (head == null) { + return -1; + } + SharedStringNode node = head; + // first, identity match; assuming most of the time we get intern()ed String + // And do unrolled initial check; 90+% likelihood head node has all info we need: + if (node.value == name) { + return node.index; + } + while ((node = node.next) != null) { + if (node.value == name) { + return node.index; + } + } + // If not, equality check; we already know head is not null + node = head; + do { + String value = node.value; + if (value.hashCode() == hash && value.equals(name)) { + return node.index; + } + node = node.next; + } while (node != null); + return -1; + } + + private final void _addSeenName(String name) + { + // first: do we need to expand? + if (_seenNameCount == _seenNames.length) { + if (_seenNameCount == MAX_SHARED_NAMES) { // we are too full, restart from empty + Arrays.fill(_seenNames, null); + _seenNameCount = 0; + } else { // we always start with modest default size (like 64), so expand to full + SharedStringNode[] old = _seenNames; + _seenNames = new SharedStringNode[MAX_SHARED_NAMES]; + final int mask = MAX_SHARED_NAMES-1; + for (SharedStringNode node : old) { + for (; node != null; node = node.next) { + int ix = node.value.hashCode() & mask; + node.next = _seenNames[ix]; + _seenNames[ix] = node; + } + } + } + } + // other than that, just slap it there + int ix = name.hashCode() & (_seenNames.length-1); + _seenNames[ix] = new SharedStringNode(name, _seenNameCount, _seenNames[ix]); + ++_seenNameCount; + } + + private final int _findSeenStringValue(String text) + { + int hash = text.hashCode(); + SharedStringNode head = _seenStringValues[hash & (_seenStringValues.length-1)]; + if (head != null) { + SharedStringNode node = head; + // first, identity match; assuming most of the time we get intern()ed String + do { + if (node.value == text) { + return node.index; + } + node = node.next; + } while (node != null); + // and then comparison, if no match yet + node = head; + do { + String value = node.value; + if (value.hashCode() == hash && value.equals(text)) { + return node.index; + } + node = node.next; + } while (node != null); + } + return -1; + } + + private final void _addSeenStringValue(String text) + { + // first: do we need to expand? + if (_seenStringValueCount == _seenStringValues.length) { + if (_seenStringValueCount == MAX_SHARED_STRING_VALUES) { // we are too full, restart from empty + Arrays.fill(_seenStringValues, null); + _seenStringValueCount = 0; + } else { // we always start with modest default size (like 64), so expand to full + SharedStringNode[] old = _seenStringValues; + _seenStringValues = new SharedStringNode[MAX_SHARED_STRING_VALUES]; + final int mask = MAX_SHARED_STRING_VALUES-1; + for (SharedStringNode node : old) { + for (; node != null; node = node.next) { + int ix = node.value.hashCode() & mask; + node.next = _seenStringValues[ix]; + _seenStringValues[ix] = node; + } + } + } + } + // other than that, just slap it there + int ix = text.hashCode() & (_seenStringValues.length-1); + _seenStringValues[ix] = new SharedStringNode(text, _seenStringValueCount, _seenStringValues[ix]); + ++_seenStringValueCount; + } + + /* + /********************************************************** + /* Internal methods, error reporting + /********************************************************** + */ + + /** + * Method for accessing offset of the next byte within the whole output + * stream that this generator has produced. + */ + protected long outputOffset() { + return _bytesWritten + _outputTail; + } + + protected UnsupportedOperationException _notSupported() { + return new UnsupportedOperationException(); + } +}
diff --git a/1.9.10/src/smile/java/org/codehaus/jackson/smile/SmileParser.java b/1.9.10/src/smile/java/org/codehaus/jackson/smile/SmileParser.java new file mode 100644 index 0000000..cf908e3 --- /dev/null +++ b/1.9.10/src/smile/java/org/codehaus/jackson/smile/SmileParser.java
@@ -0,0 +1,2553 @@ +package org.codehaus.jackson.smile; + +import static org.codehaus.jackson.smile.SmileConstants.BYTE_MARKER_END_OF_STRING; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.lang.ref.SoftReference; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.Arrays; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.impl.JsonParserBase; +import org.codehaus.jackson.io.IOContext; +import org.codehaus.jackson.sym.BytesToNameCanonicalizer; +import org.codehaus.jackson.sym.Name; + +public class SmileParser + extends JsonParserBase +{ + /** + * Enumeration that defines all togglable features for Smile generators. + */ + public enum Feature { + /** + * Feature that determines whether 4-byte Smile header is mandatory in input, + * or optional. If enabled, it means that only input that starts with the header + * is accepted as valid; if disabled, header is optional. In latter case,r + * settings for content are assumed to be defaults. + */ + REQUIRE_HEADER(true) + ; + + final boolean _defaultState; + final int _mask; + + /** + * Method that calculates bit set (flags) of all features that + * are enabled by default. + */ + public static int collectDefaults() + { + int flags = 0; + for (Feature f : values()) { + if (f.enabledByDefault()) { + flags |= f.getMask(); + } + } + return flags; + } + + private Feature(boolean defaultState) { + _defaultState = defaultState; + _mask = (1 << ordinal()); + } + + public boolean enabledByDefault() { return _defaultState; } + public int getMask() { return _mask; } + } + + private final static int[] NO_INTS = new int[0]; + + private final static String[] NO_STRINGS = new String[0]; + + /* + /********************************************************** + /* Configuration + /********************************************************** + */ + + /** + * Codec used for data binding when (if) requested. + */ + protected ObjectCodec _objectCodec; + + /** + * Flag that indicates whether content can legally have raw (unquoted) + * binary data. Since this information is included both in header and + * in actual binary data blocks there is redundancy, and we want to + * ensure settings are compliant. Using application may also want to + * know this setting in case it does some direct (random) access. + */ + protected boolean _mayContainRawBinary; + + /** + * Helper object used for low-level recycling of Smile-generator + * specific buffers. + * + * @since 1.7 + */ + final protected SmileBufferRecycler<String> _smileBufferRecycler; + + /* + /********************************************************** + /* Input source config, state (from ex StreamBasedParserBase) + /********************************************************** + */ + + /** + * Input stream that can be used for reading more content, if one + * in use. May be null, if input comes just as a full buffer, + * or if the stream has been closed. + */ + protected InputStream _inputStream; + + /** + * Current buffer from which data is read; generally data is read into + * buffer from input source, but in some cases pre-loaded buffer + * is handed to the parser. + */ + protected byte[] _inputBuffer; + + /** + * Flag that indicates whether the input buffer is recycable (and + * needs to be returned to recycler once we are done) or not. + *<p> + * If it is not, it also means that parser can NOT modify underlying + * buffer. + */ + protected boolean _bufferRecyclable; + + /* + /********************************************************** + /* Additional parsing state + /********************************************************** + */ + + /** + * Flag that indicates that the current token has not yet + * been fully processed, and needs to be finished for + * some access (or skipped to obtain the next token) + */ + protected boolean _tokenIncomplete = false; + + /** + * Type byte of the current token + */ + protected int _typeByte; + + /** + * Specific flag that is set when we encountered a 32-bit + * floating point value; needed since numeric super classes do + * not track distinction between float and double, but Smile + * format does, and we want to retain that separation. + */ + protected boolean _got32BitFloat; + + /* + /********************************************************** + /* Symbol handling, decoding + /********************************************************** + */ + + /** + * Symbol table that contains field names encountered so far + */ + final protected BytesToNameCanonicalizer _symbols; + + /** + * Temporary buffer used for name parsing. + */ + protected int[] _quadBuffer = NO_INTS; + + /** + * Quads used for hash calculation + */ + protected int _quad1, _quad2; + + /** + * Array of recently seen field names, which may be back referenced + * by later fields. + * Defaults set to enable handling even if no header found. + */ + protected String[] _seenNames = NO_STRINGS; + + protected int _seenNameCount = 0; + + /** + * Array of recently seen field names, which may be back referenced + * by later fields + * Defaults set to disable handling if no header found. + */ + protected String[] _seenStringValues = null; + + protected int _seenStringValueCount = -1; + + /* + /********************************************************** + /* Thread-local recycling + /********************************************************** + */ + + /** + * <code>ThreadLocal</code> contains a {@link java.lang.ref.SoftRerefence} + * to a buffer recycler used to provide a low-cost + * buffer recycling for Smile-specific buffers. + */ + final protected static ThreadLocal<SoftReference<SmileBufferRecycler<String>>> _smileRecyclerRef + = new ThreadLocal<SoftReference<SmileBufferRecycler<String>>>(); + + /* + /********************************************************** + /* Life-cycle + /********************************************************** + */ + + public SmileParser(IOContext ctxt, int parserFeatures, int smileFeatures, + ObjectCodec codec, + BytesToNameCanonicalizer sym, + InputStream in, byte[] inputBuffer, int start, int end, + boolean bufferRecyclable) + { + super(ctxt, parserFeatures); + _objectCodec = codec; + _symbols = sym; + + _inputStream = in; + _inputBuffer = inputBuffer; + _inputPtr = start; + _inputEnd = end; + _bufferRecyclable = bufferRecyclable; + + _tokenInputRow = -1; + _tokenInputCol = -1; + _smileBufferRecycler = _smileBufferRecycler(); + } + + @Override + public ObjectCodec getCodec() { + return _objectCodec; + } + + @Override + public void setCodec(ObjectCodec c) { + _objectCodec = c; + } + + /** + * Helper method called when it looks like input might contain the signature; + * and it is necessary to detect and handle signature to get configuration + * information it might have. + * + * @return True if valid signature was found and handled; false if not + */ + protected boolean handleSignature(boolean consumeFirstByte, boolean throwException) + throws IOException, JsonParseException + { + if (consumeFirstByte) { + ++_inputPtr; + } + if (_inputPtr >= _inputEnd) { + loadMoreGuaranteed(); + } + if (_inputBuffer[_inputPtr] != SmileConstants.HEADER_BYTE_2) { + if (throwException) { + _reportError("Malformed content: signature not valid, starts with 0x3a but followed by 0x" + +Integer.toHexString(_inputBuffer[_inputPtr])+", not 0x29"); + } + return false; + } + if (++_inputPtr >= _inputEnd) { + loadMoreGuaranteed(); + } + if (_inputBuffer[_inputPtr] != SmileConstants.HEADER_BYTE_3) { + if (throwException) { + _reportError("Malformed content: signature not valid, starts with 0x3a, 0x29, but followed by 0x" + +Integer.toHexString(_inputBuffer[_inputPtr])+", not 0xA"); + } + return false; + } + // Good enough; just need version info from 4th byte... + if (++_inputPtr >= _inputEnd) { + loadMoreGuaranteed(); + } + int ch = _inputBuffer[_inputPtr++]; + int versionBits = (ch >> 4) & 0x0F; + // but failure with version number is fatal, can not ignore + if (versionBits != SmileConstants.HEADER_VERSION_0) { + _reportError("Header version number bits (0x"+Integer.toHexString(versionBits)+") indicate unrecognized version; only 0x0 handled by parser"); + } + + // can avoid tracking names, if explicitly disabled + if ((ch & SmileConstants.HEADER_BIT_HAS_SHARED_NAMES) == 0) { + _seenNames = null; + _seenNameCount = -1; + } + // conversely, shared string values must be explicitly enabled + if ((ch & SmileConstants.HEADER_BIT_HAS_SHARED_STRING_VALUES) != 0) { + _seenStringValues = NO_STRINGS; + _seenStringValueCount = 0; + } + _mayContainRawBinary = ((ch & SmileConstants.HEADER_BIT_HAS_RAW_BINARY) != 0); + return true; + } + + /** + * @since 1.7 + */ + protected final static SmileBufferRecycler<String> _smileBufferRecycler() + { + SoftReference<SmileBufferRecycler<String>> ref = _smileRecyclerRef.get(); + SmileBufferRecycler<String> br = (ref == null) ? null : ref.get(); + + if (br == null) { + br = new SmileBufferRecycler<String>(); + _smileRecyclerRef.set(new SoftReference<SmileBufferRecycler<String>>(br)); + } + return br; + } + + /* + /********************************************************** + /* Former StreamBasedParserBase methods + /********************************************************** + */ + + @Override + public int releaseBuffered(OutputStream out) throws IOException + { + int count = _inputEnd - _inputPtr; + if (count < 1) { + return 0; + } + // let's just advance ptr to end + int origPtr = _inputPtr; + out.write(_inputBuffer, origPtr, count); + return count; + } + + @Override + public Object getInputSource() { + return _inputStream; + } + + /** + * Overridden since we do not really have character-based locations, + * but we do have byte offset to specify. + */ + @Override + public JsonLocation getTokenLocation() + { + return new JsonLocation(_ioContext.getSourceReference(), + _tokenInputTotal, // bytes + -1, -1, -1); // char offset, line, column + } + + /** + * Overridden since we do not really have character-based locations, + * but we do have byte offset to specify. + */ + @Override + public JsonLocation getCurrentLocation() + { + long byteOffset = _currInputProcessed + _inputPtr; + return new JsonLocation(_ioContext.getSourceReference(), + byteOffset, // bytes + -1, -1, (int) byteOffset); // char offset, line, column + } + + /* + /********************************************************** + /* Low-level reading, other + /********************************************************** + */ + + @Override + protected final boolean loadMore() + throws IOException + { + _currInputProcessed += _inputEnd; + //_currInputRowStart -= _inputEnd; + + if (_inputStream != null) { + int count = _inputStream.read(_inputBuffer, 0, _inputBuffer.length); + if (count > 0) { + _inputPtr = 0; + _inputEnd = count; + return true; + } + // End of input + _closeInput(); + // Should never return 0, so let's fail + if (count == 0) { + throw new IOException("InputStream.read() returned 0 characters when trying to read "+_inputBuffer.length+" bytes"); + } + } + return false; + } + + /** + * Helper method that will try to load at least specified number bytes in + * input buffer, possible moving existing data around if necessary + * + * @since 1.6 + */ + protected final boolean _loadToHaveAtLeast(int minAvailable) + throws IOException + { + // No input stream, no leading (either we are closed, or have non-stream input source) + if (_inputStream == null) { + return false; + } + // Need to move remaining data in front? + int amount = _inputEnd - _inputPtr; + if (amount > 0 && _inputPtr > 0) { + _currInputProcessed += _inputPtr; + //_currInputRowStart -= _inputPtr; + System.arraycopy(_inputBuffer, _inputPtr, _inputBuffer, 0, amount); + _inputEnd = amount; + } else { + _inputEnd = 0; + } + _inputPtr = 0; + while (_inputEnd < minAvailable) { + int count = _inputStream.read(_inputBuffer, _inputEnd, _inputBuffer.length - _inputEnd); + if (count < 1) { + // End of input + _closeInput(); + // Should never return 0, so let's fail + if (count == 0) { + throw new IOException("InputStream.read() returned 0 characters when trying to read "+amount+" bytes"); + } + return false; + } + _inputEnd += count; + } + return true; + } + + @Override + protected void _closeInput() throws IOException + { + /* 25-Nov-2008, tatus: As per [JACKSON-16] we are not to call close() + * on the underlying InputStream, unless we "own" it, or auto-closing + * feature is enabled. + */ + if (_inputStream != null) { + if (_ioContext.isResourceManaged() || isEnabled(JsonParser.Feature.AUTO_CLOSE_SOURCE)) { + _inputStream.close(); + } + _inputStream = null; + } + } + + /* + /********************************************************** + /* Overridden methods + /********************************************************** + */ + + @Override + protected void _finishString() throws IOException, JsonParseException + { + // should never be called; but must be defined for superclass + _throwInternal(); + } + + @Override + public void close() throws IOException + { + super.close(); + // Merge found symbols, if any: + _symbols.release(); + } + + @Override + public boolean hasTextCharacters() + { + if (_currToken == JsonToken.VALUE_STRING) { + // yes; is or can be made available efficiently as char[] + return _textBuffer.hasTextAsCharacters(); + } + if (_currToken == JsonToken.FIELD_NAME) { + // not necessarily; possible but: + return _nameCopied; + } + // other types, no benefit from accessing as char[] + return false; + } + + /** + * Method called to release internal buffers owned by the base + * reader. This may be called along with {@link #_closeInput} (for + * example, when explicitly closing this reader instance), or + * separately (if need be). + */ + @Override + protected void _releaseBuffers() throws IOException + { + super._releaseBuffers(); + if (_bufferRecyclable) { + byte[] buf = _inputBuffer; + if (buf != null) { + _inputBuffer = null; + _ioContext.releaseReadIOBuffer(buf); + } + } + { + String[] nameBuf = _seenNames; + if (nameBuf != null && nameBuf.length > 0) { + _seenNames = null; + /* 28-Jun-2011, tatu: With 1.9, caller needs to clear the buffer; + * but we only need to clear up to count as it is not a hash area + */ + if (_seenNameCount > 0) { + Arrays.fill(nameBuf, 0, _seenNameCount, null); + } + _smileBufferRecycler.releaseSeenNamesBuffer(nameBuf); + } + } + { + String[] valueBuf = _seenStringValues; + if (valueBuf != null && valueBuf.length > 0) { + _seenStringValues = null; + /* 28-Jun-2011, tatu: With 1.9, caller needs to clear the buffer; + * but we only need to clear up to count as it is not a hash area + */ + if (_seenStringValueCount > 0) { + Arrays.fill(valueBuf, 0, _seenStringValueCount, null); + } + _smileBufferRecycler.releaseSeenStringValuesBuffer(valueBuf); + } + } + } + + /* + /********************************************************** + /* Extended API + /********************************************************** + */ + + public boolean mayContainRawBinary() { + return _mayContainRawBinary; + } + + /* + /********************************************************** + /* JsonParser impl + /********************************************************** + */ + + @Override + public JsonToken nextToken() throws IOException, JsonParseException + { + _numTypesValid = NR_UNKNOWN; + // For longer tokens (text, binary), we'll only read when requested + if (_tokenIncomplete) { + _skipIncomplete(); + } + _tokenInputTotal = _currInputProcessed + _inputPtr; + // also: clear any data retained so far + _binaryValue = null; + // Two main modes: values, and field names. + if (_parsingContext.inObject() && _currToken != JsonToken.FIELD_NAME) { + return (_currToken = _handleFieldName()); + } + if (_inputPtr >= _inputEnd) { + if (!loadMore()) { + _handleEOF(); + /* NOTE: here we can and should close input, release buffers, + * since this is "hard" EOF, not a boundary imposed by + * header token. + */ + close(); + return (_currToken = null); + } + } + int ch = _inputBuffer[_inputPtr++]; + _typeByte = ch; + switch ((ch >> 5) & 0x7) { + case 0: // short shared string value reference + if (ch == 0) { // important: this is invalid, don't accept + _reportError("Invalid token byte 0x00"); + } + return _handleSharedString(ch-1); + + case 1: // simple literals, numbers + { + int typeBits = ch & 0x1F; + if (typeBits < 4) { + switch (typeBits) { + case 0x00: + _textBuffer.resetWithEmpty(); + return (_currToken = JsonToken.VALUE_STRING); + case 0x01: + return (_currToken = JsonToken.VALUE_NULL); + case 0x02: // false + return (_currToken = JsonToken.VALUE_FALSE); + default: // 0x03 == true + return (_currToken = JsonToken.VALUE_TRUE); + } + } + // next 3 bytes define subtype + if (typeBits < 8) { // VInt (zigzag), BigInteger + if ((typeBits & 0x3) <= 0x2) { // 0x3 reserved (should never occur) + _tokenIncomplete = true; + _numTypesValid = 0; + return (_currToken = JsonToken.VALUE_NUMBER_INT); + } + break; + } + if (typeBits < 12) { // floating-point + int subtype = typeBits & 0x3; + if (subtype <= 0x2) { // 0x3 reserved (should never occur) + _tokenIncomplete = true; + _numTypesValid = 0; + _got32BitFloat = (subtype == 0); + return (_currToken = JsonToken.VALUE_NUMBER_FLOAT); + } + break; + } + if (typeBits == 0x1A) { // == 0x3A == ':' -> possibly header signature for next chunk? + if (handleSignature(false, false)) { + /* Ok, now; end-marker and header both imply doc boundary and a + * 'null token'; but if both are seen, they are collapsed. + * We can check this by looking at current token; if it's null, + * need to get non-null token + */ + if (_currToken == null) { + return nextToken(); + } + return (_currToken = null); + } + } + _reportError("Unrecognized token byte 0x3A (malformed segment header?"); + } + // and everything else is reserved, for now + break; + case 2: // tiny ASCII + // fall through + case 3: // short ASCII + // fall through + case 4: // tiny Unicode + // fall through + case 5: // short Unicode + // No need to decode, unless we have to keep track of back-references (for shared string values) + _currToken = JsonToken.VALUE_STRING; + if (_seenStringValueCount >= 0) { // shared text values enabled + _addSeenStringValue(); + } else { + _tokenIncomplete = true; + } + return _currToken; + case 6: // small integers; zigzag encoded + _numberInt = SmileUtil.zigzagDecode(ch & 0x1F); + _numTypesValid = NR_INT; + return (_currToken = JsonToken.VALUE_NUMBER_INT); + case 7: // binary/long-text/long-shared/start-end-markers + switch (ch & 0x1F) { + case 0x00: // long variable length ASCII + case 0x04: // long variable length unicode + _tokenIncomplete = true; + return (_currToken = JsonToken.VALUE_STRING); + case 0x08: // binary, 7-bit + _tokenIncomplete = true; + return (_currToken = JsonToken.VALUE_EMBEDDED_OBJECT); + case 0x0C: // long shared string + case 0x0D: + case 0x0E: + case 0x0F: + if (_inputPtr >= _inputEnd) { + loadMoreGuaranteed(); + } + return _handleSharedString(((ch & 0x3) << 8) + (_inputBuffer[_inputPtr++] & 0xFF)); + case 0x18: // START_ARRAY + _parsingContext = _parsingContext.createChildArrayContext(-1, -1); + return (_currToken = JsonToken.START_ARRAY); + case 0x19: // END_ARRAY + if (!_parsingContext.inArray()) { + _reportMismatchedEndMarker(']', '}'); + } + _parsingContext = _parsingContext.getParent(); + return (_currToken = JsonToken.END_ARRAY); + case 0x1A: // START_OBJECT + _parsingContext = _parsingContext.createChildObjectContext(-1, -1); + return (_currToken = JsonToken.START_OBJECT); + case 0x1B: // not used in this mode; would be END_OBJECT + _reportError("Invalid type marker byte 0xFB in value mode (would be END_OBJECT in key mode)"); + case 0x1D: // binary, raw + _tokenIncomplete = true; + return (_currToken = JsonToken.VALUE_EMBEDDED_OBJECT); + case 0x1F: // 0xFF, end of content + return (_currToken = null); + } + break; + } + // If we get this far, type byte is corrupt + _reportError("Invalid type marker byte 0x"+Integer.toHexString(ch & 0xFF)+" for expected value token"); + return null; + } + + private final JsonToken _handleSharedString(int index) + throws IOException, JsonParseException + { + if (index >= _seenStringValueCount) { + _reportInvalidSharedStringValue(index); + } + _textBuffer.resetWithString(_seenStringValues[index]); + return (_currToken = JsonToken.VALUE_STRING); + } + + private final void _addSeenStringValue() + throws IOException, JsonParseException + { + _finishToken(); + if (_seenStringValueCount < _seenStringValues.length) { + // !!! TODO: actually only store char[], first time around? + _seenStringValues[_seenStringValueCount++] = _textBuffer.contentsAsString(); + return; + } + _expandSeenStringValues(); + } + + private final void _expandSeenStringValues() + { + String[] oldShared = _seenStringValues; + int len = oldShared.length; + String[] newShared; + if (len == 0) { + newShared = _smileBufferRecycler.allocSeenStringValuesBuffer(); + if (newShared == null) { + newShared = new String[SmileBufferRecycler.DEFAULT_STRING_VALUE_BUFFER_LENGTH]; + } + } else if (len == SmileConstants.MAX_SHARED_STRING_VALUES) { // too many? Just flush... + newShared = oldShared; + _seenStringValueCount = 0; // could also clear, but let's not yet bother + } else { + int newSize = (len == SmileBufferRecycler.DEFAULT_NAME_BUFFER_LENGTH) ? 256 : SmileConstants.MAX_SHARED_STRING_VALUES; + newShared = new String[newSize]; + System.arraycopy(oldShared, 0, newShared, 0, oldShared.length); + } + _seenStringValues = newShared; + _seenStringValues[_seenStringValueCount++] = _textBuffer.contentsAsString(); + } + + @Override + public String getCurrentName() throws IOException, JsonParseException + { + return _parsingContext.getCurrentName(); + } + + @Override + public NumberType getNumberType() + throws IOException, JsonParseException + { + if (_got32BitFloat) { + return NumberType.FLOAT; + } + return super.getNumberType(); + } + + /* + /********************************************************** + /* Public API, traversal, nextXxxValue/nextFieldName + /********************************************************** + */ + + @Override + public boolean nextFieldName(SerializableString str) + throws IOException, JsonParseException + { + // Two parsing modes; can only succeed if expecting field name, so handle that first: + if (_parsingContext.inObject() && _currToken != JsonToken.FIELD_NAME) { + byte[] nameBytes = str.asQuotedUTF8(); + final int byteLen = nameBytes.length; + // need room for type byte, name bytes, possibly end marker, so: + if ((_inputPtr + byteLen + 1) < _inputEnd) { // maybe... + int ptr = _inputPtr; + int ch = _inputBuffer[ptr++]; + _typeByte = ch; + main_switch: + switch ((ch >> 6) & 3) { + case 0: // misc, including end marker + switch (ch) { + case 0x20: // empty String as name, legal if unusual + _currToken = JsonToken.FIELD_NAME; + _inputPtr = ptr; + _parsingContext.setCurrentName(""); + return (byteLen == 0); + case 0x30: // long shared + case 0x31: + case 0x32: + case 0x33: + { + int index = ((ch & 0x3) << 8) + (_inputBuffer[ptr++] & 0xFF); + if (index >= _seenNameCount) { + _reportInvalidSharedName(index); + } + String name = _seenNames[index]; + _parsingContext.setCurrentName(name); + _inputPtr = ptr; + _currToken = JsonToken.FIELD_NAME; + return (name.equals(str.getValue())); + } + //case 0x34: // long ASCII/Unicode name; let's not even try... + } + break; + case 1: // short shared, can fully process + { + int index = (ch & 0x3F); + if (index >= _seenNameCount) { + _reportInvalidSharedName(index); + } + _parsingContext.setCurrentName(_seenNames[index]); + String name = _seenNames[index]; + _parsingContext.setCurrentName(name); + _inputPtr = ptr; + _currToken = JsonToken.FIELD_NAME; + return (name.equals(str.getValue())); + } + case 2: // short ASCII + { + int len = 1 + (ch & 0x3f); + if (len == byteLen) { + int i = 0; + for (; i < len; ++i) { + if (nameBytes[i] != _inputBuffer[ptr+i]) { + break main_switch; + } + } + // yes, does match... + _inputPtr = ptr + len; + final String name = str.getValue(); + if (_seenNames != null) { + if (_seenNameCount >= _seenNames.length) { + _seenNames = _expandSeenNames(_seenNames); + } + _seenNames[_seenNameCount++] = name; + } + _parsingContext.setCurrentName(name); + _currToken = JsonToken.FIELD_NAME; + return true; + } + } + break; + case 3: // short Unicode + // all valid, except for 0xFF + { + int len = (ch & 0x3F); + if (len > 0x37) { + if (len == 0x3B) { + _currToken = JsonToken.END_OBJECT; + if (!_parsingContext.inObject()) { + _reportMismatchedEndMarker('}', ']'); + } + _inputPtr = ptr; + _parsingContext = _parsingContext.getParent(); + return false; + } + // error, but let's not worry about that here + break; + } + len += 2; // values from 2 to 57... + if (len == byteLen) { + int i = 0; + for (; i < len; ++i) { + if (nameBytes[i] != _inputBuffer[ptr+i]) { + break main_switch; + } + } + // yes, does match... + _inputPtr = ptr + len; + final String name = str.getValue(); + if (_seenNames != null) { + if (_seenNameCount >= _seenNames.length) { + _seenNames = _expandSeenNames(_seenNames); + } + _seenNames[_seenNameCount++] = name; + } + _parsingContext.setCurrentName(name); + _currToken = JsonToken.FIELD_NAME; + return true; + } + } + break; + } + } + // otherwise fall back to default processing: + JsonToken t = _handleFieldName(); + _currToken = t; + return (t == JsonToken.FIELD_NAME) && str.getValue().equals(_parsingContext.getCurrentName()); + } + // otherwise just fall back to default handling; should occur rarely + return (nextToken() == JsonToken.FIELD_NAME) && str.getValue().equals(getCurrentName()); + } + + @Override + public String nextTextValue() + throws IOException, JsonParseException + { + // can't get text value if expecting name, so + if (!_parsingContext.inObject() || _currToken == JsonToken.FIELD_NAME) { + if (_tokenIncomplete) { + _skipIncomplete(); + } + int ptr = _inputPtr; + if (ptr >= _inputEnd) { + if (!loadMore()) { + _handleEOF(); + close(); + _currToken = null; + return null; + } + ptr = _inputPtr; + } + int ch = _inputBuffer[ptr++]; + _tokenInputTotal = _currInputProcessed + _inputPtr; + + // also: clear any data retained so far + _binaryValue = null; + _typeByte = ch; + + switch ((ch >> 5) & 0x7) { + case 0: // short shared string value reference + if (ch == 0) { // important: this is invalid, don't accept + _reportError("Invalid token byte 0x00"); + } + // _handleSharedString... + { + --ch; + if (ch >= _seenStringValueCount) { + _reportInvalidSharedStringValue(ch); + } + _inputPtr = ptr; + String text = _seenStringValues[ch]; + _textBuffer.resetWithString(text); + _currToken = JsonToken.VALUE_STRING; + return text; + } + + case 1: // simple literals, numbers + { + int typeBits = ch & 0x1F; + if (typeBits == 0x00) { + _inputPtr = ptr; + _textBuffer.resetWithEmpty(); + _currToken = JsonToken.VALUE_STRING; + return ""; + } + } + break; + case 2: // tiny ASCII + // fall through + case 3: // short ASCII + _currToken = JsonToken.VALUE_STRING; + _inputPtr = ptr; + _decodeShortAsciiValue(1 + (ch & 0x3F)); + { + // No need to decode, unless we have to keep track of back-references (for shared string values) + String text; + if (_seenStringValueCount >= 0) { // shared text values enabled + if (_seenStringValueCount < _seenStringValues.length) { + text = _textBuffer.contentsAsString(); + _seenStringValues[_seenStringValueCount++] = text; + } else { + _expandSeenStringValues(); + text = _textBuffer.contentsAsString(); + } + } else { + text = _textBuffer.contentsAsString(); + } + return text; + } + + case 4: // tiny Unicode + // fall through + case 5: // short Unicode + _currToken = JsonToken.VALUE_STRING; + _inputPtr = ptr; + _decodeShortUnicodeValue(2 + (ch & 0x3F)); + { + // No need to decode, unless we have to keep track of back-references (for shared string values) + String text; + if (_seenStringValueCount >= 0) { // shared text values enabled + if (_seenStringValueCount < _seenStringValues.length) { + text = _textBuffer.contentsAsString(); + _seenStringValues[_seenStringValueCount++] = text; + } else { + _expandSeenStringValues(); + text = _textBuffer.contentsAsString(); + } + } else { + text = _textBuffer.contentsAsString(); + } + return text; + } + case 6: // small integers; zigzag encoded + break; + case 7: // binary/long-text/long-shared/start-end-markers + // TODO: support longer strings too? + /* + switch (ch & 0x1F) { + case 0x00: // long variable length ASCII + case 0x04: // long variable length unicode + _tokenIncomplete = true; + return (_currToken = JsonToken.VALUE_STRING); + case 0x08: // binary, 7-bit + break main; + case 0x0C: // long shared string + case 0x0D: + case 0x0E: + case 0x0F: + if (_inputPtr >= _inputEnd) { + loadMoreGuaranteed(); + } + return _handleSharedString(((ch & 0x3) << 8) + (_inputBuffer[_inputPtr++] & 0xFF)); + } + break; + */ + break; + } + } + // otherwise fall back to generic handling: + return (nextToken() == JsonToken.VALUE_STRING) ? getText() : null; + } + + @Override + public int nextIntValue(int defaultValue) + throws IOException, JsonParseException + { + if (nextToken() == JsonToken.VALUE_NUMBER_INT) { + return getIntValue(); + } + return defaultValue; + } + + @Override + public long nextLongValue(long defaultValue) + throws IOException, JsonParseException + { + if (nextToken() == JsonToken.VALUE_NUMBER_INT) { + return getLongValue(); + } + return defaultValue; + } + + @Override + public Boolean nextBooleanValue() + throws IOException, JsonParseException + { + switch (nextToken()) { + case VALUE_TRUE: + return Boolean.TRUE; + case VALUE_FALSE: + return Boolean.FALSE; + } + return null; + } + + /* + /********************************************************** + /* Public API, access to token information, text + /********************************************************** + */ + + /** + * Method for accessing textual representation of the current event; + * if no current event (before first call to {@link #nextToken}, or + * after encountering end-of-input), returns null. + * Method can be called for any event. + */ + @Override + public String getText() + throws IOException, JsonParseException + { + if (_tokenIncomplete) { + _tokenIncomplete = false; + // Let's inline part of "_finishToken", common case + int tb = _typeByte; + int type = (tb >> 5) & 0x7; + if (type == 2 || type == 3) { // tiny & short ASCII + _decodeShortAsciiValue(1 + (tb & 0x3F)); + return _textBuffer.contentsAsString(); + } + if (type == 4 || type == 5) { // tiny & short Unicode + // short unicode; note, lengths 2 - 65 (off-by-one compared to ASCII) + _decodeShortUnicodeValue(2 + (tb & 0x3F)); + return _textBuffer.contentsAsString(); + } + _finishToken(); + } + if (_currToken == JsonToken.VALUE_STRING) { + return _textBuffer.contentsAsString(); + } + JsonToken t = _currToken; + if (t == null) { // null only before/after document + return null; + } + if (t == JsonToken.FIELD_NAME) { + return _parsingContext.getCurrentName(); + } + if (t.isNumeric()) { + // TODO: optimize? + return getNumberValue().toString(); + } + return _currToken.asString(); + } + + @Override + public char[] getTextCharacters() + throws IOException, JsonParseException + { + if (_currToken != null) { // null only before/after document + if (_tokenIncomplete) { + _finishToken(); + } + switch (_currToken) { + case VALUE_STRING: + return _textBuffer.getTextBuffer(); + case FIELD_NAME: + if (!_nameCopied) { + String name = _parsingContext.getCurrentName(); + int nameLen = name.length(); + if (_nameCopyBuffer == null) { + _nameCopyBuffer = _ioContext.allocNameCopyBuffer(nameLen); + } else if (_nameCopyBuffer.length < nameLen) { + _nameCopyBuffer = new char[nameLen]; + } + name.getChars(0, nameLen, _nameCopyBuffer, 0); + _nameCopied = true; + } + return _nameCopyBuffer; + + // fall through + case VALUE_NUMBER_INT: + case VALUE_NUMBER_FLOAT: + // TODO: optimize + return getNumberValue().toString().toCharArray(); + + default: + return _currToken.asCharArray(); + } + } + return null; + } + + @Override + public int getTextLength() + throws IOException, JsonParseException + { + if (_currToken != null) { // null only before/after document + if (_tokenIncomplete) { + _finishToken(); + } + switch (_currToken) { + case VALUE_STRING: + return _textBuffer.size(); + case FIELD_NAME: + return _parsingContext.getCurrentName().length(); + // fall through + case VALUE_NUMBER_INT: + case VALUE_NUMBER_FLOAT: + // TODO: optimize + return getNumberValue().toString().length(); + + default: + return _currToken.asCharArray().length; + } + } + return 0; + } + + @Override + public int getTextOffset() throws IOException, JsonParseException + { + return 0; + } + + /* + /********************************************************** + /* Public API, access to token information, binary + /********************************************************** + */ + + @Override + public byte[] getBinaryValue(Base64Variant b64variant) + throws IOException, JsonParseException + { + if (_tokenIncomplete) { + _finishToken(); + } + if (_currToken != JsonToken.VALUE_EMBEDDED_OBJECT ) { + // Todo, maybe: support base64 for text? + _reportError("Current token ("+_currToken+") not VALUE_EMBEDDED_OBJECT, can not access as binary"); + } + return _binaryValue; + } + + @Override + public Object getEmbeddedObject() + throws IOException, JsonParseException + { + if (_tokenIncomplete) { + _finishToken(); + } + if (_currToken == JsonToken.VALUE_EMBEDDED_OBJECT ) { + return _binaryValue; + } + return super.getEmbeddedObject(); + } + + /* NOTE: must still implement just because 1.9.0 - 1.9.2 did require + * its implementation (and we'll try to avoid introducing binary + * incompatibilities); however, should be deleted from 2.0 + */ + // @Deprecated + protected byte[] _decodeBase64(Base64Variant b64variant) + throws IOException, JsonParseException + { + // Should never get called, but must be defined for base class + _throwInternal(); + return null; + } + + /* + /********************************************************** + /* Internal methods, field name parsing + /********************************************************** + */ + + /** + * Method that handles initial token type recognition for token + * that has to be either FIELD_NAME or END_OBJECT. + */ + protected final JsonToken _handleFieldName() throws IOException, JsonParseException + { + if (_inputPtr >= _inputEnd) { + loadMoreGuaranteed(); + } + int ch = _inputBuffer[_inputPtr++]; + // is this needed? + _typeByte = ch; + switch ((ch >> 6) & 3) { + case 0: // misc, including end marker + switch (ch) { + case 0x20: // empty String as name, legal if unusual + _parsingContext.setCurrentName(""); + return JsonToken.FIELD_NAME; + case 0x30: // long shared + case 0x31: + case 0x32: + case 0x33: + { + if (_inputPtr >= _inputEnd) { + loadMoreGuaranteed(); + } + int index = ((ch & 0x3) << 8) + (_inputBuffer[_inputPtr++] & 0xFF); + if (index >= _seenNameCount) { + _reportInvalidSharedName(index); + } + _parsingContext.setCurrentName(_seenNames[index]); + } + return JsonToken.FIELD_NAME; + case 0x34: // long ASCII/Unicode name + _handleLongFieldName(); + return JsonToken.FIELD_NAME; + } + break; + case 1: // short shared, can fully process + { + int index = (ch & 0x3F); + if (index >= _seenNameCount) { + _reportInvalidSharedName(index); + } + _parsingContext.setCurrentName(_seenNames[index]); + } + return JsonToken.FIELD_NAME; + case 2: // short ASCII + { + int len = 1 + (ch & 0x3f); + String name; + Name n = _findDecodedFromSymbols(len); + if (n != null) { + name = n.getName(); + _inputPtr += len; + } else { + name = _decodeShortAsciiName(len); + name = _addDecodedToSymbols(len, name); + } + if (_seenNames != null) { + if (_seenNameCount >= _seenNames.length) { + _seenNames = _expandSeenNames(_seenNames); + } + _seenNames[_seenNameCount++] = name; + } + _parsingContext.setCurrentName(name); + } + return JsonToken.FIELD_NAME; + case 3: // short Unicode + // all valid, except for 0xFF + ch &= 0x3F; + { + if (ch > 0x37) { + if (ch == 0x3B) { + if (!_parsingContext.inObject()) { + _reportMismatchedEndMarker('}', ']'); + } + _parsingContext = _parsingContext.getParent(); + return JsonToken.END_OBJECT; + } + } else { + final int len = ch + 2; // values from 2 to 57... + String name; + Name n = _findDecodedFromSymbols(len); + if (n != null) { + name = n.getName(); + _inputPtr += len; + } else { + name = _decodeShortUnicodeName(len); + name = _addDecodedToSymbols(len, name); + } + if (_seenNames != null) { + if (_seenNameCount >= _seenNames.length) { + _seenNames = _expandSeenNames(_seenNames); + } + _seenNames[_seenNameCount++] = name; + } + _parsingContext.setCurrentName(name); + return JsonToken.FIELD_NAME; + } + } + break; + } + // Other byte values are illegal + _reportError("Invalid type marker byte 0x"+Integer.toHexString(_typeByte)+" for expected field name (or END_OBJECT marker)"); + return null; + } + + /** + * Method called to try to expand shared name area to fit one more potentially + * shared String. If area is already at its biggest size, will just clear + * the area (by setting next-offset to 0) + */ + private final String[] _expandSeenNames(String[] oldShared) + { + int len = oldShared.length; + String[] newShared; + if (len == 0) { + newShared = _smileBufferRecycler.allocSeenNamesBuffer(); + if (newShared == null) { + newShared = new String[SmileBufferRecycler.DEFAULT_NAME_BUFFER_LENGTH]; + } + } else if (len == SmileConstants.MAX_SHARED_NAMES) { // too many? Just flush... + newShared = oldShared; + _seenNameCount = 0; // could also clear, but let's not yet bother + } else { + int newSize = (len == SmileBufferRecycler.DEFAULT_STRING_VALUE_BUFFER_LENGTH) ? 256 : SmileConstants.MAX_SHARED_NAMES; + newShared = new String[newSize]; + System.arraycopy(oldShared, 0, newShared, 0, oldShared.length); + } + return newShared; + } + + private final String _addDecodedToSymbols(int len, String name) + { + if (len < 5) { + return _symbols.addName(name, _quad1, 0).getName(); + } + if (len < 9) { + return _symbols.addName(name, _quad1, _quad2).getName(); + } + int qlen = (len + 3) >> 2; + return _symbols.addName(name, _quadBuffer, qlen).getName(); + } + + private final String _decodeShortAsciiName(int len) + throws IOException, JsonParseException + { + // note: caller ensures we have enough bytes available + char[] outBuf = _textBuffer.emptyAndGetCurrentSegment(); + int outPtr = 0; + final byte[] inBuf = _inputBuffer; + int inPtr = _inputPtr; + + // loop unrolling seems to help here: + for (int inEnd = inPtr + len - 3; inPtr < inEnd; ) { + outBuf[outPtr++] = (char) inBuf[inPtr++]; + outBuf[outPtr++] = (char) inBuf[inPtr++]; + outBuf[outPtr++] = (char) inBuf[inPtr++]; + outBuf[outPtr++] = (char) inBuf[inPtr++]; + } + int left = (len & 3); + if (left > 0) { + outBuf[outPtr++] = (char) inBuf[inPtr++]; + if (left > 1) { + outBuf[outPtr++] = (char) inBuf[inPtr++]; + if (left > 2) { + outBuf[outPtr++] = (char) inBuf[inPtr++]; + } + } + } + _inputPtr = inPtr; + _textBuffer.setCurrentLength(len); + return _textBuffer.contentsAsString(); + } + + /** + * Helper method used to decode short Unicode string, length for which actual + * length (in bytes) is known + * + * @param len Length between 1 and 64 + */ + private final String _decodeShortUnicodeName(int len) + throws IOException, JsonParseException + { + // note: caller ensures we have enough bytes available + int outPtr = 0; + char[] outBuf = _textBuffer.emptyAndGetCurrentSegment(); + int inPtr = _inputPtr; + _inputPtr += len; + final int[] codes = SmileConstants.sUtf8UnitLengths; + final byte[] inBuf = _inputBuffer; + for (int end = inPtr + len; inPtr < end; ) { + int i = inBuf[inPtr++] & 0xFF; + int code = codes[i]; + if (code != 0) { + // trickiest one, need surrogate handling + switch (code) { + case 1: + i = ((i & 0x1F) << 6) | (inBuf[inPtr++] & 0x3F); + break; + case 2: + i = ((i & 0x0F) << 12) + | ((inBuf[inPtr++] & 0x3F) << 6) + | (inBuf[inPtr++] & 0x3F); + break; + case 3: + i = ((i & 0x07) << 18) + | ((inBuf[inPtr++] & 0x3F) << 12) + | ((inBuf[inPtr++] & 0x3F) << 6) + | (inBuf[inPtr++] & 0x3F); + // note: this is the codepoint value; need to split, too + i -= 0x10000; + outBuf[outPtr++] = (char) (0xD800 | (i >> 10)); + i = 0xDC00 | (i & 0x3FF); + break; + default: // invalid + _reportError("Invalid byte "+Integer.toHexString(i)+" in short Unicode text block"); + } + } + outBuf[outPtr++] = (char) i; + } + _textBuffer.setCurrentLength(outPtr); + return _textBuffer.contentsAsString(); + } + + // note: slightly edited copy of UTF8StreamParser.addName() + private final Name _decodeLongUnicodeName(int[] quads, int byteLen, int quadLen) + throws IOException, JsonParseException + { + int lastQuadBytes = byteLen & 3; + // Ok: must decode UTF-8 chars. No other validation SHOULD be needed (except bounds checks?) + /* Note: last quad is not correctly aligned (leading zero bytes instead + * need to shift a bit, instead of trailing). Only need to shift it + * for UTF-8 decoding; need revert for storage (since key will not + * be aligned, to optimize lookup speed) + */ + int lastQuad; + + if (lastQuadBytes < 4) { + lastQuad = quads[quadLen-1]; + // 8/16/24 bit left shift + quads[quadLen-1] = (lastQuad << ((4 - lastQuadBytes) << 3)); + } else { + lastQuad = 0; + } + + char[] cbuf = _textBuffer.emptyAndGetCurrentSegment(); + int cix = 0; + + for (int ix = 0; ix < byteLen; ) { + int ch = quads[ix >> 2]; // current quad, need to shift+mask + int byteIx = (ix & 3); + ch = (ch >> ((3 - byteIx) << 3)) & 0xFF; + ++ix; + + if (ch > 127) { // multi-byte + int needed; + if ((ch & 0xE0) == 0xC0) { // 2 bytes (0x0080 - 0x07FF) + ch &= 0x1F; + needed = 1; + } else if ((ch & 0xF0) == 0xE0) { // 3 bytes (0x0800 - 0xFFFF) + ch &= 0x0F; + needed = 2; + } else if ((ch & 0xF8) == 0xF0) { // 4 bytes; double-char with surrogates and all... + ch &= 0x07; + needed = 3; + } else { // 5- and 6-byte chars not valid chars + _reportInvalidInitial(ch); + needed = ch = 1; // never really gets this far + } + if ((ix + needed) > byteLen) { + _reportInvalidEOF(" in long field name"); + } + + // Ok, always need at least one more: + int ch2 = quads[ix >> 2]; // current quad, need to shift+mask + byteIx = (ix & 3); + ch2 = (ch2 >> ((3 - byteIx) << 3)); + ++ix; + + if ((ch2 & 0xC0) != 0x080) { + _reportInvalidOther(ch2); + } + ch = (ch << 6) | (ch2 & 0x3F); + if (needed > 1) { + ch2 = quads[ix >> 2]; + byteIx = (ix & 3); + ch2 = (ch2 >> ((3 - byteIx) << 3)); + ++ix; + + if ((ch2 & 0xC0) != 0x080) { + _reportInvalidOther(ch2); + } + ch = (ch << 6) | (ch2 & 0x3F); + if (needed > 2) { // 4 bytes? (need surrogates on output) + ch2 = quads[ix >> 2]; + byteIx = (ix & 3); + ch2 = (ch2 >> ((3 - byteIx) << 3)); + ++ix; + if ((ch2 & 0xC0) != 0x080) { + _reportInvalidOther(ch2 & 0xFF); + } + ch = (ch << 6) | (ch2 & 0x3F); + } + } + if (needed > 2) { // surrogate pair? once again, let's output one here, one later on + ch -= 0x10000; // to normalize it starting with 0x0 + if (cix >= cbuf.length) { + cbuf = _textBuffer.expandCurrentSegment(); + } + cbuf[cix++] = (char) (0xD800 + (ch >> 10)); + ch = 0xDC00 | (ch & 0x03FF); + } + } + if (cix >= cbuf.length) { + cbuf = _textBuffer.expandCurrentSegment(); + } + cbuf[cix++] = (char) ch; + } + + // Ok. Now we have the character array, and can construct the String + String baseName = new String(cbuf, 0, cix); + // And finally, un-align if necessary + if (lastQuadBytes < 4) { + quads[quadLen-1] = lastQuad; + } + return _symbols.addName(baseName, quads, quadLen); + } + + private final void _handleLongFieldName() throws IOException, JsonParseException + { + // First: gather quads we need, looking for end marker + final byte[] inBuf = _inputBuffer; + int quads = 0; + int bytes = 0; + int q = 0; + + while (true) { + if (_inputPtr >= _inputEnd) { + loadMoreGuaranteed(); + } + byte b = inBuf[_inputPtr++]; + if (BYTE_MARKER_END_OF_STRING == b) { + bytes = 0; + break; + } + q = ((int) b) & 0xFF; + if (_inputPtr >= _inputEnd) { + loadMoreGuaranteed(); + } + b = inBuf[_inputPtr++]; + if (BYTE_MARKER_END_OF_STRING == b) { + bytes = 1; + break; + } + q = (q << 8) | (b & 0xFF); + if (_inputPtr >= _inputEnd) { + loadMoreGuaranteed(); + } + b = inBuf[_inputPtr++]; + if (BYTE_MARKER_END_OF_STRING == b) { + bytes = 2; + break; + } + q = (q << 8) | (b & 0xFF); + if (_inputPtr >= _inputEnd) { + loadMoreGuaranteed(); + } + b = inBuf[_inputPtr++]; + if (BYTE_MARKER_END_OF_STRING == b) { + bytes = 3; + break; + } + q = (q << 8) | (b & 0xFF); + if (quads >= _quadBuffer.length) { + _quadBuffer = _growArrayTo(_quadBuffer, _quadBuffer.length + 256); // grow by 1k + } + _quadBuffer[quads++] = q; + } + // and if we have more bytes, append those too + int byteLen = (quads << 2); + if (bytes > 0) { + if (quads >= _quadBuffer.length) { + _quadBuffer = _growArrayTo(_quadBuffer, _quadBuffer.length + 256); + } + _quadBuffer[quads++] = q; + byteLen += bytes; + } + + // Know this name already? + String name; + Name n = _symbols.findName(_quadBuffer, quads); + if (n != null) { + name = n.getName(); + } else { + name = _decodeLongUnicodeName(_quadBuffer, byteLen, quads).getName(); + } + if (_seenNames != null) { + if (_seenNameCount >= _seenNames.length) { + _seenNames = _expandSeenNames(_seenNames); + } + _seenNames[_seenNameCount++] = name; + } + _parsingContext.setCurrentName(name); + } + + /** + * Helper method for trying to find specified encoded UTF-8 byte sequence + * from symbol table; if successful avoids actual decoding to String + */ + private final Name _findDecodedFromSymbols(int len) + throws IOException, JsonParseException + { + if ((_inputEnd - _inputPtr) < len) { + _loadToHaveAtLeast(len); + } + // First: maybe we already have this name decoded? + if (len < 5) { + int inPtr = _inputPtr; + final byte[] inBuf = _inputBuffer; + int q = inBuf[inPtr] & 0xFF; + if (--len > 0) { + q = (q << 8) + (inBuf[++inPtr] & 0xFF); + if (--len > 0) { + q = (q << 8) + (inBuf[++inPtr] & 0xFF); + if (--len > 0) { + q = (q << 8) + (inBuf[++inPtr] & 0xFF); + } + } + } + _quad1 = q; + return _symbols.findName(q); + } + if (len < 9) { + int inPtr = _inputPtr; + final byte[] inBuf = _inputBuffer; + // First quadbyte is easy + int q1 = (inBuf[inPtr] & 0xFF) << 8; + q1 += (inBuf[++inPtr] & 0xFF); + q1 <<= 8; + q1 += (inBuf[++inPtr] & 0xFF); + q1 <<= 8; + q1 += (inBuf[++inPtr] & 0xFF); + int q2 = (inBuf[++inPtr] & 0xFF); + len -= 5; + if (len > 0) { + q2 = (q2 << 8) + (inBuf[++inPtr] & 0xFF); + if (--len > 0) { + q2 = (q2 << 8) + (inBuf[++inPtr] & 0xFF); + if (--len > 0) { + q2 = (q2 << 8) + (inBuf[++inPtr] & 0xFF); + } + } + } + _quad1 = q1; + _quad2 = q2; + return _symbols.findName(q1, q2); + } + return _findDecodedMedium(len); + } + + /** + * Method for locating names longer than 8 bytes (in UTF-8) + */ + private final Name _findDecodedMedium(int len) + throws IOException, JsonParseException + { + // first, need enough buffer to store bytes as ints: + { + int bufLen = (len + 3) >> 2; + if (bufLen > _quadBuffer.length) { + _quadBuffer = _growArrayTo(_quadBuffer, bufLen); + } + } + // then decode, full quads first + int offset = 0; + int inPtr = _inputPtr; + final byte[] inBuf = _inputBuffer; + do { + int q = (inBuf[inPtr++] & 0xFF) << 8; + q |= inBuf[inPtr++] & 0xFF; + q <<= 8; + q |= inBuf[inPtr++] & 0xFF; + q <<= 8; + q |= inBuf[inPtr++] & 0xFF; + _quadBuffer[offset++] = q; + } while ((len -= 4) > 3); + // and then leftovers + if (len > 0) { + int q = inBuf[inPtr] & 0xFF; + if (--len > 0) { + q = (q << 8) + (inBuf[++inPtr] & 0xFF); + if (--len > 0) { + q = (q << 8) + (inBuf[++inPtr] & 0xFF); + } + } + _quadBuffer[offset++] = q; + } + return _symbols.findName(_quadBuffer, offset); + } + + private static int[] _growArrayTo(int[] arr, int minSize) + { + int[] newArray = new int[minSize + 4]; + if (arr != null) { + // !!! TODO: JDK 1.6, Arrays.copyOf + System.arraycopy(arr, 0, newArray, 0, arr.length); + } + return newArray; + } + + /* + /********************************************************** + /* Internal methods, secondary parsing + /********************************************************** + */ + + @Override + protected void _parseNumericValue(int expType) + throws IOException, JsonParseException + { + if (_tokenIncomplete) { + int tb = _typeByte; + // ensure we got a numeric type with value that is lazily parsed + if (((tb >> 5) & 0x7) != 1) { + _reportError("Current token ("+_currToken+") not numeric, can not use numeric value accessors"); + } + _tokenIncomplete = false; + _finishNumberToken(tb); + } + } + + /** + * Method called to finish parsing of a token so that token contents + * are retriable + */ + protected void _finishToken() + throws IOException, JsonParseException + { + _tokenIncomplete = false; + int tb = _typeByte; + + int type = ((tb >> 5) & 0x7); + if (type == 1) { // simple literals, numbers + _finishNumberToken(tb); + return; + } + if (type <= 3) { // tiny & short ASCII + _decodeShortAsciiValue(1 + (tb & 0x3F)); + return; + } + if (type <= 5) { // tiny & short Unicode + // short unicode; note, lengths 2 - 65 (off-by-one compared to ASCII) + _decodeShortUnicodeValue(2 + (tb & 0x3F)); + return; + } + if (type == 7) { + tb &= 0x1F; + // next 3 bytes define subtype + switch (tb >> 2) { + case 0: // long variable length ASCII + _decodeLongAscii(); + return; + case 1: // long variable length unicode + _decodeLongUnicode(); + return; + case 2: // binary, 7-bit + _binaryValue = _read7BitBinaryWithLength(); + return; + case 7: // binary, raw + _finishRawBinary(); + return; + } + } + // sanity check + _throwInternal(); + } + + protected final void _finishNumberToken(int tb) + throws IOException, JsonParseException + { + tb &= 0x1F; + int type = (tb >> 2); + if (type == 1) { // VInt (zigzag) or BigDecimal + int subtype = tb & 0x03; + if (subtype == 0) { // (v)int + _finishInt(); + } else if (subtype == 1) { // (v)long + _finishLong(); + } else if (subtype == 2) { + _finishBigInteger(); + } else { + _throwInternal(); + } + return; + } + if (type == 2) { // other numbers + switch (tb & 0x03) { + case 0: // float + _finishFloat(); + return; + case 1: // double + _finishDouble(); + return; + case 2: // big-decimal + _finishBigDecimal(); + return; + } + } + _throwInternal(); + } + + /* + /********************************************************** + /* Internal methods, secondary Number parsing + /********************************************************** + */ + + private final void _finishInt() throws IOException, JsonParseException + { + if (_inputPtr >= _inputEnd) { + loadMoreGuaranteed(); + } + int value = _inputBuffer[_inputPtr++]; + int i; + if (value < 0) { // 6 bits + value &= 0x3F; + } else { + if (_inputPtr >= _inputEnd) { + loadMoreGuaranteed(); + } + i = _inputBuffer[_inputPtr++]; + if (i >= 0) { // 13 bits + value = (value << 7) + i; + if (_inputPtr >= _inputEnd) { + loadMoreGuaranteed(); + } + i = _inputBuffer[_inputPtr++]; + if (i >= 0) { + value = (value << 7) + i; + if (_inputPtr >= _inputEnd) { + loadMoreGuaranteed(); + } + i = _inputBuffer[_inputPtr++]; + if (i >= 0) { + value = (value << 7) + i; + // and then we must get negative + if (_inputPtr >= _inputEnd) { + loadMoreGuaranteed(); + } + i = _inputBuffer[_inputPtr++]; + if (i >= 0) { + _reportError("Corrupt input; 32-bit VInt extends beyond 5 data bytes"); + } + } + } + } + value = (value << 6) + (i & 0x3F); + } + _numberInt = SmileUtil.zigzagDecode(value); + _numTypesValid = NR_INT; + } + + private final void _finishLong() + throws IOException, JsonParseException + { + // Ok, first, will always get 4 full data bytes first; 1 was already passed + long l = (long) _fourBytesToInt(); + // and loop for the rest + while (true) { + if (_inputPtr >= _inputEnd) { + loadMoreGuaranteed(); + } + int value = _inputBuffer[_inputPtr++]; + if (value < 0) { + l = (l << 6) + (value & 0x3F); + _numberLong = SmileUtil.zigzagDecode(l); + _numTypesValid = NR_LONG; + return; + } + l = (l << 7) + value; + } + } + + private final void _finishBigInteger() + throws IOException, JsonParseException + { + byte[] raw = _read7BitBinaryWithLength(); + _numberBigInt = new BigInteger(raw); + _numTypesValid = NR_BIGINT; + } + + private final void _finishFloat() + throws IOException, JsonParseException + { + // just need 5 bytes to get int32 first; all are unsigned + int i = _fourBytesToInt(); + if (_inputPtr >= _inputEnd) { + loadMoreGuaranteed(); + } + i = (i << 7) + _inputBuffer[_inputPtr++]; + float f = Float.intBitsToFloat(i); + _numberDouble = (double) f; + _numTypesValid = NR_DOUBLE; + } + + private final void _finishDouble() + throws IOException, JsonParseException + { + // ok; let's take two sets of 4 bytes (each is int) + long hi = _fourBytesToInt(); + long value = (hi << 28) + (long) _fourBytesToInt(); + // and then remaining 2 bytes + if (_inputPtr >= _inputEnd) { + loadMoreGuaranteed(); + } + value = (value << 7) + _inputBuffer[_inputPtr++]; + if (_inputPtr >= _inputEnd) { + loadMoreGuaranteed(); + } + value = (value << 7) + _inputBuffer[_inputPtr++]; + _numberDouble = Double.longBitsToDouble(value); + _numTypesValid = NR_DOUBLE; + } + + private final int _fourBytesToInt() + throws IOException, JsonParseException + { + if (_inputPtr >= _inputEnd) { + loadMoreGuaranteed(); + } + int i = _inputBuffer[_inputPtr++]; // first 7 bits + if (_inputPtr >= _inputEnd) { + loadMoreGuaranteed(); + } + i = (i << 7) + _inputBuffer[_inputPtr++]; // 14 bits + if (_inputPtr >= _inputEnd) { + loadMoreGuaranteed(); + } + i = (i << 7) + _inputBuffer[_inputPtr++]; // 21 + if (_inputPtr >= _inputEnd) { + loadMoreGuaranteed(); + } + return (i << 7) + _inputBuffer[_inputPtr++]; + } + + private final void _finishBigDecimal() + throws IOException, JsonParseException + { + int scale = SmileUtil.zigzagDecode(_readUnsignedVInt()); + byte[] raw = _read7BitBinaryWithLength(); + _numberBigDecimal = new BigDecimal(new BigInteger(raw), scale); + _numTypesValid = NR_BIGDECIMAL; + } + + private final int _readUnsignedVInt() + throws IOException, JsonParseException + { + int value = 0; + while (true) { + if (_inputPtr >= _inputEnd) { + loadMoreGuaranteed(); + } + int i = _inputBuffer[_inputPtr++]; + if (i < 0) { // last byte + value = (value << 6) + (i & 0x3F); + return value; + } + value = (value << 7) + i; + } + } + + private final byte[] _read7BitBinaryWithLength() + throws IOException, JsonParseException + { + int byteLen = _readUnsignedVInt(); + byte[] result = new byte[byteLen]; + int ptr = 0; + int lastOkPtr = byteLen - 7; + + // first, read all 7-by-8 byte chunks + while (ptr <= lastOkPtr) { + if ((_inputEnd - _inputPtr) < 8) { + _loadToHaveAtLeast(8); + } + int i1 = (_inputBuffer[_inputPtr++] << 25) + + (_inputBuffer[_inputPtr++] << 18) + + (_inputBuffer[_inputPtr++] << 11) + + (_inputBuffer[_inputPtr++] << 4); + int x = _inputBuffer[_inputPtr++]; + i1 += x >> 3; + int i2 = ((x & 0x7) << 21) + + (_inputBuffer[_inputPtr++] << 14) + + (_inputBuffer[_inputPtr++] << 7) + + _inputBuffer[_inputPtr++]; + // Ok: got our 7 bytes, just need to split, copy + result[ptr++] = (byte)(i1 >> 24); + result[ptr++] = (byte)(i1 >> 16); + result[ptr++] = (byte)(i1 >> 8); + result[ptr++] = (byte)i1; + result[ptr++] = (byte)(i2 >> 16); + result[ptr++] = (byte)(i2 >> 8); + result[ptr++] = (byte)i2; + } + // and then leftovers: n+1 bytes to decode n bytes + int toDecode = (result.length - ptr); + if (toDecode > 0) { + if ((_inputEnd - _inputPtr) < (toDecode+1)) { + _loadToHaveAtLeast(toDecode+1); + } + int value = _inputBuffer[_inputPtr++]; + for (int i = 1; i < toDecode; ++i) { + value = (value << 7) + _inputBuffer[_inputPtr++]; + result[ptr++] = (byte) (value >> (7 - i)); + } + // last byte is different, has remaining 1 - 6 bits, right-aligned + value <<= toDecode; + result[ptr] = (byte) (value + _inputBuffer[_inputPtr++]); + } + return result; + } + + /* + /********************************************************** + /* Internal methods, secondary String parsing + /********************************************************** + */ + + protected final void _decodeShortAsciiValue(int len) + throws IOException, JsonParseException + { + if ((_inputEnd - _inputPtr) < len) { + _loadToHaveAtLeast(len); + } + // Note: we count on fact that buffer must have at least 'len' (<= 64) empty char slots + final char[] outBuf = _textBuffer.emptyAndGetCurrentSegment(); + int outPtr = 0; + final byte[] inBuf = _inputBuffer; + int inPtr = _inputPtr; + + // loop unrolling SHOULD be faster (as with _decodeShortAsciiName), but somehow + // is NOT; as per testing, benchmarking... very weird. + /* + for (int inEnd = inPtr + len - 3; inPtr < inEnd; ) { + outBuf[outPtr++] = (char) inBuf[inPtr++]; + outBuf[outPtr++] = (char) inBuf[inPtr++]; + outBuf[outPtr++] = (char) inBuf[inPtr++]; + outBuf[outPtr++] = (char) inBuf[inPtr++]; + } + int left = (len & 3); + if (left > 0) { + outBuf[outPtr++] = (char) inBuf[inPtr++]; + if (left > 1) { + outBuf[outPtr++] = (char) inBuf[inPtr++]; + if (left > 2) { + outBuf[outPtr++] = (char) inBuf[inPtr++]; + } + } + } + */ + + // meaning: regular tight loop is no slower, typically faster here: + for (final int end = inPtr + len; inPtr < end; ++inPtr) { + outBuf[outPtr++] = (char) inBuf[inPtr]; + } + + _inputPtr = inPtr; + _textBuffer.setCurrentLength(len); + } + + protected final void _decodeShortUnicodeValue(int len) + throws IOException, JsonParseException + { + if ((_inputEnd - _inputPtr) < len) { + _loadToHaveAtLeast(len); + } + int outPtr = 0; + char[] outBuf = _textBuffer.emptyAndGetCurrentSegment(); + int inPtr = _inputPtr; + _inputPtr += len; + final int[] codes = SmileConstants.sUtf8UnitLengths; + final byte[] inputBuf = _inputBuffer; + for (int end = inPtr + len; inPtr < end; ) { + int i = inputBuf[inPtr++] & 0xFF; + int code = codes[i]; + if (code != 0) { + // trickiest one, need surrogate handling + switch (code) { + case 1: + i = ((i & 0x1F) << 6) | (inputBuf[inPtr++] & 0x3F); + break; + case 2: + i = ((i & 0x0F) << 12) + | ((inputBuf[inPtr++] & 0x3F) << 6) + | (inputBuf[inPtr++] & 0x3F); + break; + case 3: + i = ((i & 0x07) << 18) + | ((inputBuf[inPtr++] & 0x3F) << 12) + | ((inputBuf[inPtr++] & 0x3F) << 6) + | (inputBuf[inPtr++] & 0x3F); + // note: this is the codepoint value; need to split, too + i -= 0x10000; + outBuf[outPtr++] = (char) (0xD800 | (i >> 10)); + i = 0xDC00 | (i & 0x3FF); + break; + default: // invalid + _reportError("Invalid byte "+Integer.toHexString(i)+" in short Unicode text block"); + } + } + outBuf[outPtr++] = (char) i; + } + _textBuffer.setCurrentLength(outPtr); + } + + private final void _decodeLongAscii() + throws IOException, JsonParseException + { + int outPtr = 0; + char[] outBuf = _textBuffer.emptyAndGetCurrentSegment(); + main_loop: + while (true) { + if (_inputPtr >= _inputEnd) { + loadMoreGuaranteed(); + } + int inPtr = _inputPtr; + int left = _inputEnd - inPtr; + if (outPtr >= outBuf.length) { + outBuf = _textBuffer.finishCurrentSegment(); + outPtr = 0; + } + left = Math.min(left, outBuf.length - outPtr); + do { + byte b = _inputBuffer[inPtr++]; + if (b == SmileConstants.BYTE_MARKER_END_OF_STRING) { + _inputPtr = inPtr; + break main_loop; + } + outBuf[outPtr++] = (char) b; + } while (--left > 0); + _inputPtr = inPtr; + } + _textBuffer.setCurrentLength(outPtr); + } + + private final void _decodeLongUnicode() + throws IOException, JsonParseException + { + int outPtr = 0; + char[] outBuf = _textBuffer.emptyAndGetCurrentSegment(); + final int[] codes = SmileConstants.sUtf8UnitLengths; + int c; + final byte[] inputBuffer = _inputBuffer; + + main_loop: + while (true) { + // First the tight ASCII loop: + ascii_loop: + while (true) { + int ptr = _inputPtr; + if (ptr >= _inputEnd) { + loadMoreGuaranteed(); + ptr = _inputPtr; + } + if (outPtr >= outBuf.length) { + outBuf = _textBuffer.finishCurrentSegment(); + outPtr = 0; + } + int max = _inputEnd; + { + int max2 = ptr + (outBuf.length - outPtr); + if (max2 < max) { + max = max2; + } + } + while (ptr < max) { + c = (int) inputBuffer[ptr++] & 0xFF; + if (codes[c] != 0) { + _inputPtr = ptr; + break ascii_loop; + } + outBuf[outPtr++] = (char) c; + } + _inputPtr = ptr; + } + // Ok: end marker, escape or multi-byte? + if (c == SmileConstants.INT_MARKER_END_OF_STRING) { + break main_loop; + } + + switch (codes[c]) { + case 1: // 2-byte UTF + c = _decodeUtf8_2(c); + break; + case 2: // 3-byte UTF + if ((_inputEnd - _inputPtr) >= 2) { + c = _decodeUtf8_3fast(c); + } else { + c = _decodeUtf8_3(c); + } + break; + case 3: // 4-byte UTF + c = _decodeUtf8_4(c); + // Let's add first part right away: + outBuf[outPtr++] = (char) (0xD800 | (c >> 10)); + if (outPtr >= outBuf.length) { + outBuf = _textBuffer.finishCurrentSegment(); + outPtr = 0; + } + c = 0xDC00 | (c & 0x3FF); + // And let the other char output down below + break; + default: + // Is this good enough error message? + _reportInvalidChar(c); + } + // Need more room? + if (outPtr >= outBuf.length) { + outBuf = _textBuffer.finishCurrentSegment(); + outPtr = 0; + } + // Ok, let's add char to output: + outBuf[outPtr++] = (char) c; + } + _textBuffer.setCurrentLength(outPtr); + } + + private final void _finishRawBinary() + throws IOException, JsonParseException + { + int byteLen = _readUnsignedVInt(); + _binaryValue = new byte[byteLen]; + if (_inputPtr >= _inputEnd) { + loadMoreGuaranteed(); + } + int ptr = 0; + while (true) { + int toAdd = Math.min(byteLen, _inputEnd - _inputPtr); + System.arraycopy(_inputBuffer, _inputPtr, _binaryValue, ptr, toAdd); + _inputPtr += toAdd; + ptr += toAdd; + byteLen -= toAdd; + if (byteLen <= 0) { + return; + } + loadMoreGuaranteed(); + } + } + + /* + /********************************************************** + /* Internal methods, skipping + /********************************************************** + */ + + /** + * Method called to skip remainders of an incomplete token, when + * contents themselves will not be needed any more + */ + protected void _skipIncomplete() throws IOException, JsonParseException + { + _tokenIncomplete = false; + int tb = _typeByte; + switch ((tb >> 5) & 0x7) { + case 1: // simple literals, numbers + tb &= 0x1F; + // next 3 bytes define subtype + switch (tb >> 2) { + case 1: // VInt (zigzag) + // easy, just skip until we see sign bit... (should we try to limit damage?) + switch (tb & 0x3) { + case 1: // vlong + _skipBytes(4); // min 5 bytes + // fall through + case 0: // vint + while (true) { + final int end = _inputEnd; + final byte[] buf = _inputBuffer; + while (_inputPtr < end) { + if (buf[_inputPtr++] < 0) { + return; + } + } + loadMoreGuaranteed(); + } + case 2: // big-int + // just has binary data + _skip7BitBinary(); + return; + } + break; + case 2: // other numbers + switch (tb & 0x3) { + case 0: // float + _skipBytes(5); + return; + case 1: // double + _skipBytes(10); + return; + case 2: // big-decimal + // first, skip scale + _readUnsignedVInt(); + // then length-prefixed binary serialization + _skip7BitBinary(); + return; + } + break; + } + break; + case 2: // tiny ASCII + // fall through + case 3: // short ASCII + _skipBytes(1 + (tb & 0x3F)); + return; + case 4: // tiny unicode + // fall through + case 5: // short unicode + _skipBytes(2 + (tb & 0x3F)); + return; + case 7: + tb &= 0x1F; + // next 3 bytes define subtype + switch (tb >> 2) { + case 0: // long variable length ASCII + case 1: // long variable length unicode + /* Doesn't matter which one, just need to find the end marker + * (note: can potentially skip invalid UTF-8 too) + */ + while (true) { + final int end = _inputEnd; + final byte[] buf = _inputBuffer; + while (_inputPtr < end) { + if (buf[_inputPtr++] == BYTE_MARKER_END_OF_STRING) { + return; + } + } + loadMoreGuaranteed(); + } + // never gets here + case 2: // binary, 7-bit + _skip7BitBinary(); + return; + case 7: // binary, raw + _skipBytes(_readUnsignedVInt()); + return; + } + } + _throwInternal(); + } + + protected void _skipBytes(int len) + throws IOException, JsonParseException + { + while (true) { + int toAdd = Math.min(len, _inputEnd - _inputPtr); + _inputPtr += toAdd; + len -= toAdd; + if (len <= 0) { + return; + } + loadMoreGuaranteed(); + } + } + + /** + * Helper method for skipping length-prefixed binary data + * section + */ + protected void _skip7BitBinary() + throws IOException, JsonParseException + { + int origBytes = _readUnsignedVInt(); + // Ok; 8 encoded bytes for 7 payload bytes first + int chunks = origBytes / 7; + int encBytes = chunks * 8; + // and for last 0 - 6 bytes, last+1 (except none if no leftovers) + origBytes -= 7 * chunks; + if (origBytes > 0) { + encBytes += 1 + origBytes; + } + _skipBytes(encBytes); + } + + /* + /********************************************************** + /* Internal methods, UTF8 decoding + /********************************************************** + */ + + private final int _decodeUtf8_2(int c) + throws IOException, JsonParseException + { + if (_inputPtr >= _inputEnd) { + loadMoreGuaranteed(); + } + int d = (int) _inputBuffer[_inputPtr++]; + if ((d & 0xC0) != 0x080) { + _reportInvalidOther(d & 0xFF, _inputPtr); + } + return ((c & 0x1F) << 6) | (d & 0x3F); + } + + private final int _decodeUtf8_3(int c1) + throws IOException, JsonParseException + { + if (_inputPtr >= _inputEnd) { + loadMoreGuaranteed(); + } + c1 &= 0x0F; + int d = (int) _inputBuffer[_inputPtr++]; + if ((d & 0xC0) != 0x080) { + _reportInvalidOther(d & 0xFF, _inputPtr); + } + int c = (c1 << 6) | (d & 0x3F); + if (_inputPtr >= _inputEnd) { + loadMoreGuaranteed(); + } + d = (int) _inputBuffer[_inputPtr++]; + if ((d & 0xC0) != 0x080) { + _reportInvalidOther(d & 0xFF, _inputPtr); + } + c = (c << 6) | (d & 0x3F); + return c; + } + + private final int _decodeUtf8_3fast(int c1) + throws IOException, JsonParseException + { + c1 &= 0x0F; + int d = (int) _inputBuffer[_inputPtr++]; + if ((d & 0xC0) != 0x080) { + _reportInvalidOther(d & 0xFF, _inputPtr); + } + int c = (c1 << 6) | (d & 0x3F); + d = (int) _inputBuffer[_inputPtr++]; + if ((d & 0xC0) != 0x080) { + _reportInvalidOther(d & 0xFF, _inputPtr); + } + c = (c << 6) | (d & 0x3F); + return c; + } + + /** + * @return Character value <b>minus 0x10000</c>; this so that caller + * can readily expand it to actual surrogates + */ + private final int _decodeUtf8_4(int c) + throws IOException, JsonParseException + { + if (_inputPtr >= _inputEnd) { + loadMoreGuaranteed(); + } + int d = (int) _inputBuffer[_inputPtr++]; + if ((d & 0xC0) != 0x080) { + _reportInvalidOther(d & 0xFF, _inputPtr); + } + c = ((c & 0x07) << 6) | (d & 0x3F); + + if (_inputPtr >= _inputEnd) { + loadMoreGuaranteed(); + } + d = (int) _inputBuffer[_inputPtr++]; + if ((d & 0xC0) != 0x080) { + _reportInvalidOther(d & 0xFF, _inputPtr); + } + c = (c << 6) | (d & 0x3F); + if (_inputPtr >= _inputEnd) { + loadMoreGuaranteed(); + } + d = (int) _inputBuffer[_inputPtr++]; + if ((d & 0xC0) != 0x080) { + _reportInvalidOther(d & 0xFF, _inputPtr); + } + + /* note: won't change it to negative here, since caller + * already knows it'll need a surrogate + */ + return ((c << 6) | (d & 0x3F)) - 0x10000; + } + + /* + /********************************************************** + /* Internal methods, error reporting + /********************************************************** + */ + + protected void _reportInvalidSharedName(int index) throws IOException + { + if (_seenNames == null) { + _reportError("Encountered shared name reference, even though document header explicitly declared no shared name references are included"); + } + _reportError("Invalid shared name reference "+index+"; only got "+_seenNameCount+" names in buffer (invalid content)"); + } + + protected void _reportInvalidSharedStringValue(int index) throws IOException + { + if (_seenStringValues == null) { + _reportError("Encountered shared text value reference, even though document header did not declared shared text value references may be included"); + } + _reportError("Invalid shared text value reference "+index+"; only got "+_seenStringValueCount+" names in buffer (invalid content)"); + } + + protected void _reportInvalidChar(int c) throws JsonParseException + { + // Either invalid WS or illegal UTF-8 start char + if (c < ' ') { + _throwInvalidSpace(c); + } + _reportInvalidInitial(c); + } + + protected void _reportInvalidInitial(int mask) + throws JsonParseException + { + _reportError("Invalid UTF-8 start byte 0x"+Integer.toHexString(mask)); + } + + protected void _reportInvalidOther(int mask) + throws JsonParseException + { + _reportError("Invalid UTF-8 middle byte 0x"+Integer.toHexString(mask)); + } + + protected void _reportInvalidOther(int mask, int ptr) + throws JsonParseException + { + _inputPtr = ptr; + _reportInvalidOther(mask); + } +} +
diff --git a/1.9.10/src/smile/java/org/codehaus/jackson/smile/SmileParserBootstrapper.java b/1.9.10/src/smile/java/org/codehaus/jackson/smile/SmileParserBootstrapper.java new file mode 100644 index 0000000..d8bd1b2 --- /dev/null +++ b/1.9.10/src/smile/java/org/codehaus/jackson/smile/SmileParserBootstrapper.java
@@ -0,0 +1,274 @@ +package org.codehaus.jackson.smile; + +import java.io.*; + +import org.codehaus.jackson.JsonLocation; +import org.codehaus.jackson.JsonParseException; +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.ObjectCodec; +import org.codehaus.jackson.format.InputAccessor; +import org.codehaus.jackson.format.MatchStrength; +import org.codehaus.jackson.io.IOContext; +import org.codehaus.jackson.sym.BytesToNameCanonicalizer; + +import static org.codehaus.jackson.smile.SmileConstants.*; + +/** + * Simple bootstrapper version used with Smile format parser. + */ +public class SmileParserBootstrapper +{ + /* + /********************************************************** + /* Configuration + /********************************************************** + */ + + final IOContext _context; + + final InputStream _in; + + /* + /********************************************************** + /* Input buffering + /********************************************************** + */ + + final byte[] _inputBuffer; + + private int _inputPtr; + + private int _inputEnd; + + /** + * Flag that indicates whether buffer above is to be recycled + * after being used or not. + */ + private final boolean _bufferRecyclable; + + /* + /********************************************************** + /* Input location + /********************************************************** + */ + + /** + * Current number of input units (bytes or chars) that were processed in + * previous blocks, + * before contents of current input buffer. + *<p> + * Note: includes possible BOMs, if those were part of the input. + */ + protected int _inputProcessed; + + /* + /********************************************************** + /* Data gathered + /********************************************************** + */ + + /* + /********************************************************** + /* Life-cycle + /********************************************************** + */ + + public SmileParserBootstrapper(IOContext ctxt, InputStream in) + { + _context = ctxt; + _in = in; + _inputBuffer = ctxt.allocReadIOBuffer(); + _inputEnd = _inputPtr = 0; + _inputProcessed = 0; + _bufferRecyclable = true; + } + + public SmileParserBootstrapper(IOContext ctxt, byte[] inputBuffer, int inputStart, int inputLen) + { + _context = ctxt; + _in = null; + _inputBuffer = inputBuffer; + _inputPtr = inputStart; + _inputEnd = (inputStart + inputLen); + // Need to offset this for correct location info + _inputProcessed = -inputStart; + _bufferRecyclable = false; + } + + public SmileParser constructParser(int generalParserFeatures, int smileFeatures, + ObjectCodec codec, BytesToNameCanonicalizer rootByteSymbols) + throws IOException, JsonParseException + { + boolean intern = JsonParser.Feature.INTERN_FIELD_NAMES.enabledIn(generalParserFeatures); + BytesToNameCanonicalizer can = rootByteSymbols.makeChild(true, intern); + // We just need a single byte, really, to know if it starts with header + ensureLoaded(1); + SmileParser p = new SmileParser(_context, generalParserFeatures, smileFeatures, + codec, can, + _in, _inputBuffer, _inputPtr, _inputEnd, _bufferRecyclable); + boolean hadSig = false; + if (_inputPtr < _inputEnd) { // only false for empty doc + if (_inputBuffer[_inputPtr] == SmileConstants.HEADER_BYTE_1) { + // need to ensure it gets properly handled so caller won't see the signature + hadSig = p.handleSignature(true, true); + } + } + if (!hadSig && (smileFeatures & SmileParser.Feature.REQUIRE_HEADER.getMask()) != 0) { + // Ok, first, let's see if it looks like plain JSON... + String msg; + + byte firstByte = (_inputPtr < _inputEnd) ? _inputBuffer[_inputPtr] : 0; + if (firstByte == '{' || firstByte == '[') { + msg = "Input does not start with Smile format header (first byte = 0x" + +Integer.toHexString(firstByte & 0xFF)+") -- rather, it starts with '"+((char) firstByte) + +"' (plain JSON input?) -- can not parse"; + } else { + msg = "Input does not start with Smile format header (first byte = 0x" + +Integer.toHexString(firstByte & 0xFF)+") and parser has REQUIRE_HEADER enabled: can not parse"; + } + throw new JsonParseException(msg, JsonLocation.NA); + } + return p; + } + + /* + /********************************************************** + /* Encoding detection for data format auto-detection + /********************************************************** + */ + + /** + * Helper + * + * @since 1.8 + */ + public static MatchStrength hasSmileFormat(InputAccessor acc) throws IOException + { + // Ok: ideally we start with the header -- if so, we are golden + if (!acc.hasMoreBytes()) { + return MatchStrength.INCONCLUSIVE; + } + // We always need at least two bytes to determine, so + byte b1 = acc.nextByte(); + if (!acc.hasMoreBytes()) { + return MatchStrength.INCONCLUSIVE; + } + byte b2 = acc.nextByte(); + + // First: do we see 3 "magic bytes"? If so, we are golden + if (b1 == SmileConstants.HEADER_BYTE_1) { // yeah, looks like marker + if (b2 != SmileConstants.HEADER_BYTE_2) { + return MatchStrength.NO_MATCH; + } + if (!acc.hasMoreBytes()) { + return MatchStrength.INCONCLUSIVE; + } + return (acc.nextByte() == SmileConstants.HEADER_BYTE_3) ? + MatchStrength.FULL_MATCH : MatchStrength.NO_MATCH; + } + // Otherwise: ideally either Object or Array: + if (b1 == SmileConstants.TOKEN_LITERAL_START_OBJECT) { + /* Object is bit easier, because now we need to get new name; i.e. can + * rule out name back-refs + */ + if (b2 == SmileConstants.TOKEN_KEY_LONG_STRING) { + return MatchStrength.SOLID_MATCH; + } + int ch = (int) b2 & 0xFF; + if (ch >= 0x80 && ch < 0xF8) { + return MatchStrength.SOLID_MATCH; + } + return MatchStrength.NO_MATCH; + } + // Array bit trickier + if (b1 == SmileConstants.TOKEN_LITERAL_START_ARRAY) { + if (!acc.hasMoreBytes()) { + return MatchStrength.INCONCLUSIVE; + } + /* For arrays, we will actually accept much wider range of values (including + * things that could otherwise collide) + */ + if (likelySmileValue(b2) || possibleSmileValue(b2, true)) { + return MatchStrength.SOLID_MATCH; + } + return MatchStrength.NO_MATCH; + } + // Scalar values are pretty weak, albeit possible; require more certain match, consider it weak: + if (likelySmileValue(b1) || possibleSmileValue(b2, false)) { + return MatchStrength.SOLID_MATCH; + } + return MatchStrength.NO_MATCH; + } + + private static boolean likelySmileValue(byte b) + { + int ch = (int) b & 0xFF; + if (ch >= 0xE0) { // good range for known values + switch (ch) { + case TOKEN_MISC_LONG_TEXT_ASCII: // 0xE0 + case TOKEN_MISC_LONG_TEXT_UNICODE: // 0xE4 + case TOKEN_MISC_BINARY_7BIT: // 0xE8 + case TOKEN_LITERAL_START_ARRAY: // 0xF8 + case TOKEN_LITERAL_START_OBJECT: // 0xFA + return true; + } + // Others will not work (end object/array; reserved; shared strings) + return false; + } + // ASCII ctrl char range is pretty good match too + if (ch >= 0x80 && ch <= 0x9F) { + return true; + } + return false; + } + + /** + * @param lenient Whether to consider more speculative matches or not + * (typically true when there is context like start-array) + */ + private static boolean possibleSmileValue(byte b, boolean lenient) + { + int ch = (int) b & 0xFF; + // note: we know that likely matches have been handled already, so... + if (ch >= 0x80) { + return (ch <= 0xE0); + } + if (lenient) { + if (ch >= 0x40) { // tiny/short ASCII + return true; + } + if (ch >- 0x20) { // various constants + return (ch < 0x2C); // many reserved bytes that can't be seen + } + } + return false; + } + + /* + /********************************************************** + /* Internal methods, raw input access + /********************************************************** + */ + + protected boolean ensureLoaded(int minimum) + throws IOException + { + if (_in == null) { // block source; nothing more to load + return false; + } + + /* Let's assume here buffer has enough room -- this will always + * be true for the limited used this method gets + */ + int gotten = (_inputEnd - _inputPtr); + while (gotten < minimum) { + int count = _in.read(_inputBuffer, _inputEnd, _inputBuffer.length - _inputEnd); + if (count < 1) { + return false; + } + _inputEnd += count; + gotten += count; + } + return true; + } +}
diff --git a/1.9.10/src/smile/java/org/codehaus/jackson/smile/SmileUtil.java b/1.9.10/src/smile/java/org/codehaus/jackson/smile/SmileUtil.java new file mode 100644 index 0000000..9dbe0ce --- /dev/null +++ b/1.9.10/src/smile/java/org/codehaus/jackson/smile/SmileUtil.java
@@ -0,0 +1,46 @@ +package org.codehaus.jackson.smile; + +/** + * Class for miscellaneous helper methods. + */ +public class SmileUtil +{ + public static int zigzagEncode(int input) { + // Canonical version: + //return (input << 1) ^ (input >> 31); + // but this is even better + if (input < 0) { + return (input << 1) ^ -1; + } + return (input << 1); + } + + public static int zigzagDecode(int encoded) { + // canonical: + //return (encoded >>> 1) ^ (-(encoded & 1)); + if ((encoded & 1) == 0) { // positive + return (encoded >>> 1); + } + // negative + return (encoded >>> 1) ^ -1; + } + + public static long zigzagEncode(long input) { + // Canonical version + //return (input << 1) ^ (input >> 63); + if (input < 0L) { + return (input << 1) ^ -1L; + } + return (input << 1); + } + + public static long zigzagDecode(long encoded) { + // canonical: + //return (encoded >>> 1) ^ (-(encoded & 1)); + if ((encoded & 1) == 0) { // positive + return (encoded >>> 1); + } + // negative + return (encoded >>> 1) ^ -1L; + } +}
diff --git a/1.9.10/src/smile/java/org/codehaus/jackson/smile/Tool.java b/1.9.10/src/smile/java/org/codehaus/jackson/smile/Tool.java new file mode 100644 index 0000000..e30b628 --- /dev/null +++ b/1.9.10/src/smile/java/org/codehaus/jackson/smile/Tool.java
@@ -0,0 +1,161 @@ +package org.codehaus.jackson.smile; + +import java.io.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.smile.SmileFactory; + +/** + * Simple command-line utility that can be used to encode JSON as Smile, or + * decode JSON from Smile: direction is indicated by single command-line + * option of either "-e" (encode) or "-d" (decode). + * + * @author tatu + * + * @since 1.6.2 + */ +public class Tool +{ + public final static String SUFFIX = ".lzf"; + + public final JsonFactory jsonFactory; + public final SmileFactory smileFactory; + + public Tool() + { + jsonFactory = new JsonFactory(); + smileFactory = new SmileFactory(); + // check all shared refs (-> small size); add header, not trailing marker; do not use raw binary + smileFactory.configure(SmileGenerator.Feature.CHECK_SHARED_NAMES, true); + smileFactory.configure(SmileGenerator.Feature.CHECK_SHARED_STRING_VALUES, true); + smileFactory.configure(SmileGenerator.Feature.ENCODE_BINARY_AS_7BIT, true); + smileFactory.configure(SmileGenerator.Feature.WRITE_HEADER, true); + smileFactory.configure(SmileGenerator.Feature.WRITE_END_MARKER, false); + // also: do not require header + smileFactory.configure(SmileParser.Feature.REQUIRE_HEADER, false); + } + + private void process(String[] args) throws IOException + { + String oper = null; + String filename = null; + + if (args.length == 2) { + oper = args[0]; + filename = args[1]; + } else if (args.length == 1) { + oper = args[0]; + } else { + showUsage(); + } + + boolean encode = "-e".equals(oper); + if (encode) { + encode(inputStream(filename)); + } else if ("-d".equals(oper)) { + decode(inputStream(filename)); + } else if ("-v".equals(oper)) { + // need to read twice (encode, verify/compare) + verify(inputStream(filename), inputStream(filename)); + } else { + showUsage(); + } + } + + private InputStream inputStream(String filename) throws IOException + { + // if no argument given, read from stdin + if (filename == null) { + return System.in; + } + File src = new File(filename); + if (!src.exists()) { + System.err.println("File '"+filename+"' does not exist."); + System.exit(1); + } + return new FileInputStream(src); + } + + private void decode(InputStream in) throws IOException + { + JsonParser jp = smileFactory.createJsonParser(in); + JsonGenerator jg = jsonFactory.createJsonGenerator(System.out, JsonEncoding.UTF8); + + while (true) { + /* Just one trick: since Smile can have segments (multiple 'documents' in output + * stream), we should not stop at first end marker, only bail out if two are seen + */ + if (jp.nextToken() == null) { + if (jp.nextToken() == null) { + break; + } + } + jg.copyCurrentEvent(jp); + } + jp.close(); + jg.close(); + } + + private void encode(InputStream in) throws IOException + { + JsonParser jp = jsonFactory.createJsonParser(in); + JsonGenerator jg = smileFactory.createJsonGenerator(System.out, JsonEncoding.UTF8); + while ((jp.nextToken()) != null) { + jg.copyCurrentEvent(jp); + } + jp.close(); + jg.close(); + } + + private void verify(InputStream in, InputStream in2) throws IOException + { + JsonParser jp = jsonFactory.createJsonParser(in); + ByteArrayOutputStream bytes = new ByteArrayOutputStream(4000); + JsonGenerator jg = smileFactory.createJsonGenerator(bytes, JsonEncoding.UTF8); + + // First, read, encode in memory buffer + while ((jp.nextToken()) != null) { + jg.copyCurrentEvent(jp); + } + jp.close(); + jg.close(); + + // and then re-read both, verify + jp = jsonFactory.createJsonParser(in2); + byte[] smile = bytes.toByteArray(); + JsonParser jp2 = smileFactory.createJsonParser(smile); + + JsonToken t; + int count = 0; + while ((t = jp.nextToken()) != null) { + JsonToken t2 = jp2.nextToken(); + ++count; + if (t != t2) { + throw new IOException("Input and encoded differ, token #"+count+"; expected "+t+", got "+t2); + } + // also, need to have same texts... + String text1 = jp.getText(); + String text2 = jp2.getText(); + if (!text1.equals(text2)) { + throw new IOException("Input and encoded differ, token #"+count+"; expected text '"+text1+"', got '"+text2+"'"); + } + } + + System.out.println("OK: verified "+count+" tokens (from "+smile.length+" bytes of Smile encoded data), input and encoded contents are identical"); + } + + protected void showUsage() + { + System.err.println("Usage: java "+getClass().getName()+" -e/-d [file]"); + System.err.println(" (if no file given, reads from stdin -- always writes to stdout)"); + System.err.println(" -d: decode Smile encoded input as JSON"); + System.err.println(" -e: encode JSON (text) input as Smile"); + System.err.println(" -v: encode JSON (text) input as Smile; read back, verify, do not write out"); + System.exit(1); + } + + public static void main(String[] args) throws IOException { + new Tool().process(args); + } + +}
diff --git a/1.9.10/src/smile/java/org/codehaus/jackson/smile/package-info.java b/1.9.10/src/smile/java/org/codehaus/jackson/smile/package-info.java new file mode 100644 index 0000000..82d4a5e --- /dev/null +++ b/1.9.10/src/smile/java/org/codehaus/jackson/smile/package-info.java
@@ -0,0 +1,10 @@ +/** + * Package that contains experimental implementation of + * "Binary-Encoded JSON-Like" data format handlers (parser, + * generator, factory produce both, supporting constants). + *<p> + * See <a href="http://wiki.fasterxml.com/SmileFormat">Smile format specification</a> for more details. + * + * @since 1.6 + */ +package org.codehaus.jackson.smile;
diff --git a/1.9.10/src/test/main/BaseTest.java b/1.9.10/src/test/main/BaseTest.java new file mode 100644 index 0000000..dd818d6 --- /dev/null +++ b/1.9.10/src/test/main/BaseTest.java
@@ -0,0 +1,411 @@ +package main; + +import java.io.*; +import java.util.Arrays; + +import junit.framework.TestCase; + +import org.codehaus.jackson.*; + +//import static org.junit.Assert.*; + +public abstract class BaseTest + extends TestCase +{ + /* + /********************************************************** + /* Some sample documents: + /********************************************************** + */ + + protected final static int SAMPLE_SPEC_VALUE_WIDTH = 800; + protected final static int SAMPLE_SPEC_VALUE_HEIGHT = 600; + protected final static String SAMPLE_SPEC_VALUE_TITLE = "View from 15th Floor"; + protected final static String SAMPLE_SPEC_VALUE_TN_URL = "http://www.example.com/image/481989943"; + protected final static int SAMPLE_SPEC_VALUE_TN_HEIGHT = 125; + protected final static String SAMPLE_SPEC_VALUE_TN_WIDTH = "100"; + protected final static int SAMPLE_SPEC_VALUE_TN_ID1 = 116; + protected final static int SAMPLE_SPEC_VALUE_TN_ID2 = 943; + protected final static int SAMPLE_SPEC_VALUE_TN_ID3 = 234; + protected final static int SAMPLE_SPEC_VALUE_TN_ID4 = 38793; + + protected final static String SAMPLE_DOC_JSON_SPEC = + "{\n" + +" \"Image\" : {\n" + +" \"Width\" : "+SAMPLE_SPEC_VALUE_WIDTH+",\n" + +" \"Height\" : "+SAMPLE_SPEC_VALUE_HEIGHT+"," + +"\"Title\" : \""+SAMPLE_SPEC_VALUE_TITLE+"\",\n" + +" \"Thumbnail\" : {\n" + +" \"Url\" : \""+SAMPLE_SPEC_VALUE_TN_URL+"\",\n" + +"\"Height\" : "+SAMPLE_SPEC_VALUE_TN_HEIGHT+",\n" + +" \"Width\" : \""+SAMPLE_SPEC_VALUE_TN_WIDTH+"\"\n" + +" },\n" + +" \"IDs\" : ["+SAMPLE_SPEC_VALUE_TN_ID1+","+SAMPLE_SPEC_VALUE_TN_ID2+","+SAMPLE_SPEC_VALUE_TN_ID3+","+SAMPLE_SPEC_VALUE_TN_ID4+"]\n" + +" }" + +"}" + ; + + /* + /********************************************************** + /* Helper classes (beans) + /********************************************************** + */ + + /** + * Sample class from Jackson tutorial ("JacksonInFiveMinutes") + */ + protected static class FiveMinuteUser { + public enum Gender { MALE, FEMALE }; + + public static class Name + { + private String _first, _last; + + public Name() { } + public Name(String f, String l) { + _first = f; + _last = l; + } + + public String getFirst() { return _first; } + public String getLast() { return _last; } + + public void setFirst(String s) { _first = s; } + public void setLast(String s) { _last = s; } + + @Override + public boolean equals(Object o) + { + if (o == this) return true; + if (o == null || o.getClass() != getClass()) return false; + Name other = (Name) o; + return _first.equals(other._first) && _last.equals(other._last); + } + } + + private Gender _gender; + private Name _name; + private boolean _isVerified; + private byte[] _userImage; + + public FiveMinuteUser() { } + + public FiveMinuteUser(String first, String last, boolean verified, Gender g, byte[] data) + { + _name = new Name(first, last); + _isVerified = verified; + _gender = g; + _userImage = data; + } + + public Name getName() { return _name; } + public boolean isVerified() { return _isVerified; } + public Gender getGender() { return _gender; } + public byte[] getUserImage() { return _userImage; } + + public void setName(Name n) { _name = n; } + public void setVerified(boolean b) { _isVerified = b; } + public void setGender(Gender g) { _gender = g; } + public void setUserImage(byte[] b) { _userImage = b; } + + @Override + public boolean equals(Object o) + { + if (o == this) return true; + if (o == null || o.getClass() != getClass()) return false; + FiveMinuteUser other = (FiveMinuteUser) o; + if (_isVerified != other._isVerified) return false; + if (_gender != other._gender) return false; + if (!_name.equals(other._name)) return false; + byte[] otherImage = other._userImage; + if (otherImage.length != _userImage.length) return false; + for (int i = 0, len = _userImage.length; i < len; ++i) { + if (_userImage[i] != otherImage[i]) { + return false; + } + } + return true; + } + } + + /* + /********************************************************** + /* High-level helpers + /********************************************************** + */ + + protected void verifyJsonSpecSampleDoc(JsonParser jp, boolean verifyContents) + throws IOException + { + verifyJsonSpecSampleDoc(jp, verifyContents, true); + } + + protected void verifyJsonSpecSampleDoc(JsonParser jp, boolean verifyContents, + boolean requireNumbers) + throws IOException + { + if (!jp.hasCurrentToken()) { + jp.nextToken(); + } + assertToken(JsonToken.START_OBJECT, jp.getCurrentToken()); // main object + + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); // 'Image' + if (verifyContents) { + verifyFieldName(jp, "Image"); + } + + assertToken(JsonToken.START_OBJECT, jp.nextToken()); // 'image' object + + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); // 'Width' + if (verifyContents) { + verifyFieldName(jp, "Width"); + } + + verifyIntToken(jp.nextToken(), requireNumbers); + if (verifyContents) { + verifyIntValue(jp, SAMPLE_SPEC_VALUE_WIDTH); + } + + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); // 'Height' + if (verifyContents) { + verifyFieldName(jp, "Height"); + } + + verifyIntToken(jp.nextToken(), requireNumbers); + if (verifyContents) { + verifyIntValue(jp, SAMPLE_SPEC_VALUE_HEIGHT); + } + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); // 'Title' + if (verifyContents) { + verifyFieldName(jp, "Title"); + } + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + assertEquals(SAMPLE_SPEC_VALUE_TITLE, getAndVerifyText(jp)); + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); // 'Thumbnail' + if (verifyContents) { + verifyFieldName(jp, "Thumbnail"); + } + + assertToken(JsonToken.START_OBJECT, jp.nextToken()); // 'thumbnail' object + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); // 'Url' + if (verifyContents) { + verifyFieldName(jp, "Url"); + } + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + if (verifyContents) { + assertEquals(SAMPLE_SPEC_VALUE_TN_URL, getAndVerifyText(jp)); + } + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); // 'Height' + if (verifyContents) { + verifyFieldName(jp, "Height"); + } + verifyIntToken(jp.nextToken(), requireNumbers); + if (verifyContents) { + verifyIntValue(jp, SAMPLE_SPEC_VALUE_TN_HEIGHT); + } + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); // 'Width' + if (verifyContents) { + verifyFieldName(jp, "Width"); + } + // Width value is actually a String in the example + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + if (verifyContents) { + assertEquals(SAMPLE_SPEC_VALUE_TN_WIDTH, getAndVerifyText(jp)); + } + + assertToken(JsonToken.END_OBJECT, jp.nextToken()); // 'thumbnail' object + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); // 'IDs' + assertToken(JsonToken.START_ARRAY, jp.nextToken()); // 'ids' array + verifyIntToken(jp.nextToken(), requireNumbers); // ids[0] + if (verifyContents) { + verifyIntValue(jp, SAMPLE_SPEC_VALUE_TN_ID1); + } + verifyIntToken(jp.nextToken(), requireNumbers); // ids[1] + if (verifyContents) { + verifyIntValue(jp, SAMPLE_SPEC_VALUE_TN_ID2); + } + verifyIntToken(jp.nextToken(), requireNumbers); // ids[2] + if (verifyContents) { + verifyIntValue(jp, SAMPLE_SPEC_VALUE_TN_ID3); + } + verifyIntToken(jp.nextToken(), requireNumbers); // ids[3] + if (verifyContents) { + verifyIntValue(jp, SAMPLE_SPEC_VALUE_TN_ID4); + } + assertToken(JsonToken.END_ARRAY, jp.nextToken()); // 'ids' array + + assertToken(JsonToken.END_OBJECT, jp.nextToken()); // 'image' object + + assertToken(JsonToken.END_OBJECT, jp.nextToken()); // main object + } + + private void verifyIntToken(JsonToken t, boolean requireNumbers) + { + if (t == JsonToken.VALUE_NUMBER_INT) { + return; + } + if (requireNumbers) { // to get error + assertToken(JsonToken.VALUE_NUMBER_INT, t); + } + // if not number, must be String + if (t != JsonToken.VALUE_STRING) { + fail("Expected INT or STRING value, got "+t); + } + } + + protected void verifyFieldName(JsonParser jp, String expName) + throws IOException + { + assertEquals(expName, jp.getText()); + assertEquals(expName, jp.getCurrentName()); + } + + protected void verifyIntValue(JsonParser jp, long expValue) + throws IOException + { + // First, via textual + assertEquals(String.valueOf(expValue), jp.getText()); + } + + /** + * Method that checks whether Unit tests appear to run from Ant build + * scripts. + * + * @since 1.6 + */ + protected static boolean runsFromAnt() { + return "true".equals(System.getProperty("FROM_ANT")); + } + + /* + /********************************************************** + /* Parser/generator construction + /********************************************************** + */ + + protected JsonParser createParserUsingReader(String input) + throws IOException, JsonParseException + { + return createParserUsingReader(new JsonFactory(), input); + } + + protected JsonParser createParserUsingReader(JsonFactory f, String input) + throws IOException, JsonParseException + { + return f.createJsonParser(new StringReader(input)); + } + + protected JsonParser createParserUsingStream(String input, String encoding) + throws IOException, JsonParseException + { + return createParserUsingStream(new JsonFactory(), input, encoding); + } + + protected JsonParser createParserUsingStream(JsonFactory f, + String input, String encoding) + throws IOException, JsonParseException + { + + /* 23-Apr-2008, tatus: UTF-32 is not supported by JDK, have to + * use our own codec too (which is not optimal since there's + * a chance both encoder and decoder might have bugs, but ones + * that cancel each other out or such) + */ + byte[] data; + if (encoding.equalsIgnoreCase("UTF-32")) { + data = encodeInUTF32BE(input); + } else { + data = input.getBytes(encoding); + } + InputStream is = new ByteArrayInputStream(data); + return f.createJsonParser(is); + } + + /* + /********************************************************** + /* Additional assertion methods + /********************************************************** + */ + + protected void assertToken(JsonToken expToken, JsonToken actToken) + { + if (actToken != expToken) { + fail("Expected token "+expToken+", current token "+actToken); + } + } + + protected void assertToken(JsonToken expToken, JsonParser jp) + { + assertToken(expToken, jp.getCurrentToken()); + } + + protected void assertType(Object ob, Class<?> expType) + { + if (ob == null) { + fail("Expected an object of type "+expType.getName()+", got null"); + } + Class<?> cls = ob.getClass(); + if (!expType.isAssignableFrom(cls)) { + fail("Expected type "+expType.getName()+", got "+cls.getName()); + } + } + + protected void verifyException(Throwable e, String... matches) + { + String msg = e.getMessage(); + String lmsg = (msg == null) ? "" : msg.toLowerCase(); + for (String match : matches) { + String lmatch = match.toLowerCase(); + if (lmsg.indexOf(lmatch) >= 0) { + return; + } + } + fail("Expected an exception with one of substrings ("+Arrays.asList(matches)+"): got one with message \""+msg+"\""); + } + + /** + * Method that gets textual contents of the current token using + * available methods, and ensures results are consistent, before + * returning them + */ + protected String getAndVerifyText(JsonParser jp) + throws IOException, JsonParseException + { + // Ok, let's verify other accessors + int actLen = jp.getTextLength(); + char[] ch = jp.getTextCharacters(); + String str2 = new String(ch, jp.getTextOffset(), actLen); + String str = jp.getText(); + + if (str.length() != actLen) { + fail("Internal problem (jp.token == "+jp.getCurrentToken()+"): jp.getText().length() ['"+str+"'] == "+str.length()+"; jp.getTextLength() == "+actLen); + } + assertEquals("String access via getText(), getTextXxx() must be the same", str, str2); + + return str; + } + + /* + /********************************************************** + /* And other helpers + /********************************************************** + */ + + protected byte[] encodeInUTF32BE(String input) + { + int len = input.length(); + byte[] result = new byte[len * 4]; + int ptr = 0; + for (int i = 0; i < len; ++i, ptr += 4) { + char c = input.charAt(i); + result[ptr] = result[ptr+1] = (byte) 0; + result[ptr+2] = (byte) (c >> 8); + result[ptr+3] = (byte) c; + } + return result; + } + + public String quote(String str) { + return '"'+str+'"'; + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/failing/TestAbstractParentChild.java b/1.9.10/src/test/org/codehaus/jackson/failing/TestAbstractParentChild.java new file mode 100644 index 0000000..eb349c8 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/failing/TestAbstractParentChild.java
@@ -0,0 +1,70 @@ +package org.codehaus.jackson.failing; + +import org.codehaus.jackson.annotate.JsonBackReference; +import org.codehaus.jackson.annotate.JsonManagedReference; +import org.codehaus.jackson.annotate.JsonSubTypes; +import org.codehaus.jackson.annotate.JsonTypeInfo; +import org.codehaus.jackson.annotate.JsonTypeName; +import org.codehaus.jackson.annotate.JsonTypeInfo.Id; +import org.codehaus.jackson.map.BaseMapTest; +import org.codehaus.jackson.map.ObjectMapper; + +/** + * Currently (1.8) parent/child dependencies do not work in + * combination with abstract types; they should, but fixing this + * require major changes to handling of both features. + */ +public class TestAbstractParentChild extends BaseMapTest +{ + @JsonTypeInfo(use=Id.NAME) + @JsonSubTypes({@JsonSubTypes.Type(ConcreteNode.class)}) + static abstract class AbstractNode + { + public String id; + + @JsonManagedReference public AbstractNode next; + @JsonBackReference public AbstractNode prev; + } + + @JsonTypeName("concrete") + static class ConcreteNode extends AbstractNode { + public ConcreteNode() { } + public ConcreteNode(String id) { this.id = id; } + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + /* 22-Sep-2010, tatu: This is for [JACKSON-368]. Easy to reproduce the issue, + * but alas not nearly as easy to resolve. Problem is that AbstractDeserializer + * has little knowledge of actual type, and so linkage can not be made statically. + */ + public void testAbstract() throws Exception + { + AbstractNode parent = new ConcreteNode("p"); + AbstractNode child = new ConcreteNode("c"); + parent.next = child; + child.prev = parent; + + // serialization ought to be ok + ObjectMapper mapper = new ObjectMapper(); + String json = mapper.writeValueAsString(parent); + + AbstractNode root = null; + try { + root = mapper.readValue(json, AbstractNode.class); + } catch (IllegalArgumentException e) { + fail("Did not expect an exception; got: "+e.getMessage()); + } + assertEquals(ConcreteNode.class, root.getClass()); + assertEquals("p", root.id); + assertNull(root.prev); + AbstractNode leaf = root.next; + assertNotNull(leaf); + assertEquals("c", leaf.id); + assertSame(parent, leaf.prev); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/failing/TestDelegatingCreators.java b/1.9.10/src/test/org/codehaus/jackson/failing/TestDelegatingCreators.java new file mode 100644 index 0000000..252a043 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/failing/TestDelegatingCreators.java
@@ -0,0 +1,48 @@ +package org.codehaus.jackson.failing; + +import org.codehaus.jackson.annotate.JsonCreator; +import org.codehaus.jackson.map.BaseMapTest; +import org.codehaus.jackson.map.InjectableValues; +import org.codehaus.jackson.map.JsonMappingException; +import org.codehaus.jackson.map.ObjectMapper; +import org.codehaus.jackson.map.annotate.JacksonInject; + +public class TestDelegatingCreators extends BaseMapTest +{ + // for [JACKSON-711]; should allow delegate-based one(s) too + static class CtorBean711 + { + protected String name; + protected int age; + + @JsonCreator + public CtorBean711(@JacksonInject String n, int a) + { + name = n; + age = a; + } + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + // As per [JACKSON-711]: should also work with delegate model (single non-annotated arg) + public void testWithCtorAndDelegate() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.setInjectableValues(new InjectableValues.Std() + .addValue(String.class, "Pooka") + ); + CtorBean711 bean = null; + try { + bean = mapper.readValue("38", CtorBean711.class); + } catch (JsonMappingException e) { + fail("Did not expect problems, got: "+e.getMessage()); + } + assertEquals(38, bean.age); + assertEquals("Pooka", bean.name); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/failing/TestGenericsBounded.java b/1.9.10/src/test/org/codehaus/jackson/failing/TestGenericsBounded.java new file mode 100644 index 0000000..5337568 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/failing/TestGenericsBounded.java
@@ -0,0 +1,38 @@ +package org.codehaus.jackson.failing; + +import java.util.*; + +import org.codehaus.jackson.map.*; + +public class TestGenericsBounded + extends BaseMapTest +{ + protected static abstract class Base<T> { + public T inconsequential = null; + } + + protected static abstract class BaseData<T> { + public T dataObj; + } + + protected static class Child extends Base<Long> { + public static class ChildData extends BaseData<List<String>> { } + } + + /* + /******************************************************* + /* Unit tests + /******************************************************* + */ + + // Reproducing issue 743 + public void testIssue743() throws Exception + { + String s3 = "{\"dataObj\" : [ \"one\", \"two\", \"three\" ] }"; + ObjectMapper m = new ObjectMapper(); + + Child.ChildData d = m.readValue(s3, Child.ChildData.class); + assertNotNull(d.dataObj); + assertEquals(3, d.dataObj.size()); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/failing/TestMrbeanNestedGeneric.java b/1.9.10/src/test/org/codehaus/jackson/failing/TestMrbeanNestedGeneric.java new file mode 100644 index 0000000..c879b88 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/failing/TestMrbeanNestedGeneric.java
@@ -0,0 +1,65 @@ +package org.codehaus.jackson.failing; + +import java.util.List; + +import org.codehaus.jackson.map.BaseMapTest; +import org.codehaus.jackson.map.ObjectMapper; +import org.codehaus.jackson.mrbean.MrBeanModule; +import org.codehaus.jackson.type.TypeReference; + +/** + * Tests to verify whether generic declarations are properly handled by Mr Bean. + * Currently (1.8) this is not the case, and fix is non-trivial; not impossible, + * just quite difficult. + */ +public class TestMrbeanNestedGeneric extends BaseMapTest +{ + // For [JACKSON-479] + public interface ResultWrapper<T> { + T getValue(); + } + + public interface Results<T> { + Long getTotal(); + List<T> getRecords(); + } + public interface Dog { + String getName(); + String getBreed(); + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + // For [JACKSON-479] + public void testTypeReferenceNestedGeneric() throws Exception + { + final ObjectMapper mapper = new ObjectMapper(); + mapper.registerModule(new MrBeanModule()); + final String JSON = "{\"value\":{\"breed\":\"Poodle\",\"name\":\"Rekku\"}}"; + + final ResultWrapper<Dog> result = mapper.readValue(JSON, new TypeReference<ResultWrapper<Dog>>() { }); + Object ob = result.getValue(); + assertEquals(Dog.class, ob.getClass()); + } + + // For [JACKSON-479] + public void testTypeReferenceNestedGenericList() throws Exception + { + final ObjectMapper mapper = new ObjectMapper(); + mapper.registerModule(new MrBeanModule()); + + final String JSON = "{\"records\":[{\"breed\":\"Mountain Cur\",\"name\":\"Fido\"}],\n" + +"\"total\":1}"; + + final Results<Dog> result = mapper.readValue(JSON, new TypeReference<Results<Dog>>() { }); + + List<?> records = result.getRecords(); + assertEquals(1, records.size()); + assertEquals(Dog.class, records.get(0).getClass()); + } + +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/failing/TestSerializationFiltering.java b/1.9.10/src/test/org/codehaus/jackson/failing/TestSerializationFiltering.java new file mode 100644 index 0000000..9a769d7 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/failing/TestSerializationFiltering.java
@@ -0,0 +1,50 @@ +package org.codehaus.jackson.failing; + +import java.util.HashMap; +import java.util.Map; + +import org.codehaus.jackson.annotate.JsonAnyGetter; +import org.codehaus.jackson.map.BaseMapTest; +import org.codehaus.jackson.map.ObjectMapper; +import org.codehaus.jackson.map.annotate.JsonFilter; +import org.codehaus.jackson.map.ser.FilterProvider; +import org.codehaus.jackson.map.ser.impl.SimpleBeanPropertyFilter; +import org.codehaus.jackson.map.ser.impl.SimpleFilterProvider; + +/** + * Currently (1.8) generic filtering does not work for "any getter": it should, + * ideally, so here's the test. + */ +public class TestSerializationFiltering extends BaseMapTest +{ + @JsonFilter("anyFilter") + public static class AnyBean + { + private Map<String, String> properties = new HashMap<String, String>(); + { + properties.put("a", "1"); + properties.put("b", "2"); + } + + @JsonAnyGetter + public Map<String, String> anyProperties() + { + return properties; + } + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + // should also work for @JsonAnyGetter, as per [JACKSON-516] + public void testAnyGetterFiltering() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + FilterProvider prov = new SimpleFilterProvider().addFilter("anyFilter", + SimpleBeanPropertyFilter.filterOutAllExcept("b")); + assertEquals("{\"a\":\"1\"}", mapper.writer(prov).writeValueAsString(new AnyBean())); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/format/TestJsonFormatDetection.java b/1.9.10/src/test/org/codehaus/jackson/format/TestJsonFormatDetection.java new file mode 100644 index 0000000..c7cfd4a --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/format/TestJsonFormatDetection.java
@@ -0,0 +1,89 @@ +package org.codehaus.jackson.format; + +import java.io.*; + +import org.codehaus.jackson.*; + +public class TestJsonFormatDetection extends main.BaseTest +{ + public void testSimpleValidArray() throws Exception + { + JsonFactory jsonF = new JsonFactory(); + DataFormatDetector detector = new DataFormatDetector(jsonF); + final String ARRAY_JSON = "[ 1, 2 ]"; + DataFormatMatcher matcher = detector.findFormat(new ByteArrayInputStream(ARRAY_JSON.getBytes("UTF-8"))); + // should have match + assertTrue(matcher.hasMatch()); + assertEquals("JSON", matcher.getMatchedFormatName()); + assertSame(jsonF, matcher.getMatch()); + // no "certain" match with JSON, but solid: + assertEquals(MatchStrength.SOLID_MATCH, matcher.getMatchStrength()); + // and thus: + JsonParser jp = matcher.createParserWithMatch(); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + assertNull(jp.nextToken()); + jp.close(); + } + + public void testSimpleValidObject() throws Exception + { + JsonFactory jsonF = new JsonFactory(); + DataFormatDetector detector = new DataFormatDetector(jsonF); + final String JSON = "{ \"field\" : true }"; + DataFormatMatcher matcher = detector.findFormat(new ByteArrayInputStream(JSON.getBytes("UTF-8"))); + // should have match + assertTrue(matcher.hasMatch()); + assertEquals("JSON", matcher.getMatchedFormatName()); + assertSame(jsonF, matcher.getMatch()); + // no "certain" match with JSON, but solid: + assertEquals(MatchStrength.SOLID_MATCH, matcher.getMatchStrength()); + // and thus: + JsonParser jp = matcher.createParserWithMatch(); + assertToken(JsonToken.START_OBJECT, jp.nextToken()); + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals("field", jp.getCurrentName()); + assertToken(JsonToken.VALUE_TRUE, jp.nextToken()); + assertToken(JsonToken.END_OBJECT, jp.nextToken()); + assertNull(jp.nextToken()); + jp.close(); + } + + /** + * While JSON String is not a strong match alone, it should + * be detected unless some better match is available + */ + public void testSimpleValidString() throws Exception + { + JsonFactory jsonF = new JsonFactory(); + DataFormatDetector detector = new DataFormatDetector(jsonF); + final String JSON = "\"JSON!\""; + DataFormatMatcher matcher = detector.findFormat(new ByteArrayInputStream(JSON.getBytes("UTF-8"))); + // should have match + assertTrue(matcher.hasMatch()); + assertEquals("JSON", matcher.getMatchedFormatName()); + assertSame(jsonF, matcher.getMatch()); + assertEquals(MatchStrength.WEAK_MATCH, matcher.getMatchStrength()); + JsonParser jp = matcher.createParserWithMatch(); + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + assertEquals("JSON!", jp.getText()); + assertNull(jp.nextToken()); + jp.close(); + } + + public void testSimpleInvalid() throws Exception + { + DataFormatDetector detector = new DataFormatDetector(new JsonFactory()); + final String NON_JSON = "<root />"; + DataFormatMatcher matcher = detector.findFormat(new ByteArrayInputStream(NON_JSON.getBytes("UTF-8"))); + // should not have match + assertFalse(matcher.hasMatch()); + // and thus: + assertEquals(MatchStrength.INCONCLUSIVE, matcher.getMatchStrength()); + // also: + assertNull(matcher.createParserWithMatch()); + } + +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/impl/TestBase64Codec.java b/1.9.10/src/test/org/codehaus/jackson/impl/TestBase64Codec.java new file mode 100644 index 0000000..54645f6 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/impl/TestBase64Codec.java
@@ -0,0 +1,58 @@ +package org.codehaus.jackson.impl; + +import org.junit.Assert; + +import org.codehaus.jackson.*; + +public class TestBase64Codec + extends main.BaseTest +{ + public void testProps() + { + Base64Variant std = Base64Variants.MIME; + // let's verify basic props of std cocec + assertEquals("MIME", std.getName()); + assertEquals("MIME", std.toString()); + assertTrue(std.usesPadding()); + assertFalse(std.usesPaddingChar('X')); + assertEquals('=', std.getPaddingChar()); + assertTrue(std.usesPaddingChar('=')); + assertEquals((byte) '=', std.getPaddingByte()); + assertEquals(76, std.getMaxLineLength()); + } + + public void testCharEncoding() throws Exception + { + Base64Variant std = Base64Variants.MIME; + assertEquals(Base64Variant.BASE64_VALUE_INVALID, std.decodeBase64Char('?')); + assertEquals(Base64Variant.BASE64_VALUE_INVALID, std.decodeBase64Char((int) '?')); + assertEquals(Base64Variant.BASE64_VALUE_INVALID, std.decodeBase64Char((byte) '?')); + + assertEquals(0, std.decodeBase64Char('A')); + assertEquals(1, std.decodeBase64Char((int) 'B')); + assertEquals(2, std.decodeBase64Char((byte)'C')); + + assertEquals('/', std.encodeBase64BitsAsChar(63)); + assertEquals((byte) 'b', std.encodeBase64BitsAsByte(27)); + + String EXP_STR = "HwdJ"; + int TRIPLET = 0x1F0749; + StringBuilder sb = new StringBuilder(); + std.encodeBase64Chunk(sb, TRIPLET); + assertEquals(EXP_STR, sb.toString()); + + byte[] exp = EXP_STR.getBytes("UTF-8"); + byte[] act = new byte[exp.length]; + std.encodeBase64Chunk(TRIPLET, act, 0); + Assert.assertArrayEquals(exp, act); + } + + public void testErrors() throws Exception + { + try { + new Base64Variant("foobar", "xyz", false, '!', 24); + } catch (IllegalArgumentException iae) { + verifyException(iae, "length must be exactly"); + } + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/impl/TestBase64Parsing.java b/1.9.10/src/test/org/codehaus/jackson/impl/TestBase64Parsing.java new file mode 100644 index 0000000..7b42201 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/impl/TestBase64Parsing.java
@@ -0,0 +1,81 @@ +package org.codehaus.jackson.impl; + +import static org.junit.Assert.assertArrayEquals; + +import java.io.*; + +import org.codehaus.jackson.*; + +public class TestBase64Parsing + extends main.BaseTest +{ + public void testBase64UsingInputStream() throws Exception + { + _testBase64Text(true); + } + + public void testBase64UsingReader() throws Exception + { + _testBase64Text(false); + } + + /* + /********************************************************** + /* Test helper methods + /********************************************************** + */ + + // Test for [JACKSON-631] + public void _testBase64Text(boolean useBytes) throws Exception + { + // let's actually iterate over sets of encoding modes, lengths + + final int[] LENS = { 1, 2, 3, 4, 7, 9, 32, 33, 34, 35 }; + final Base64Variant[] VARIANTS = { + Base64Variants.MIME, + Base64Variants.MIME_NO_LINEFEEDS, + Base64Variants.MODIFIED_FOR_URL, + Base64Variants.PEM + }; + + JsonFactory jsonFactory = new JsonFactory(); + final ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + StringWriter chars = null; + for (int len : LENS) { + byte[] input = new byte[len]; + for (int i = 0; i < input.length; ++i) { + input[i] = (byte) i; + } + for (Base64Variant variant : VARIANTS) { + JsonGenerator jgen; + if (useBytes) { + bytes.reset(); + jgen = jsonFactory.createJsonGenerator(bytes, JsonEncoding.UTF8); + } else { + chars = new StringWriter(); + jgen = jsonFactory.createJsonGenerator(chars); + } + jgen.writeBinary(variant, input, 0, input.length); + jgen.close(); + JsonParser jp; + if (useBytes) { + jp = jsonFactory.createJsonParser(bytes.toByteArray()); + } else { + jp = jsonFactory.createJsonParser(chars.toString()); + } + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + byte[] data = null; + try { + data = jp.getBinaryValue(variant); + } catch (Exception e) { + throw new IOException("Failed (variant "+variant+", data length "+len+"): "+e.getMessage(), e); + } + assertNotNull(data); + assertArrayEquals(data, input); + assertNull(jp.nextToken()); + jp.close(); + } + } + } + +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/impl/TestByteBasedSymbols.java b/1.9.10/src/test/org/codehaus/jackson/impl/TestByteBasedSymbols.java new file mode 100644 index 0000000..3da1bbf --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/impl/TestByteBasedSymbols.java
@@ -0,0 +1,139 @@ +package org.codehaus.jackson.impl; + +import java.io.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.sym.Name; +import org.codehaus.jackson.sym.BytesToNameCanonicalizer; + +/** + * Unit test(s) to verify that handling of (byte-based) symbol tables + * is working. Created to verify fix to [JACKSON-5] (although not very + * good at catching it...). + */ +public class TestByteBasedSymbols + extends main.BaseTest +{ + final static String[] FIELD_NAMES = new String[] { + "a", "b", "c", "x", "y", "b13", "abcdefg", "a123", + "a0", "b0", "c0", "d0", "e0", "f0", "g0", "h0", + "x2", "aa", "ba", "ab", "b31", "___x", "aX", "xxx", + "a2", "b2", "c2", "d2", "e2", "f2", "g2", "h2", + "a3", "b3", "c3", "d3", "e3", "f3", "g3", "h3", + "a1", "b1", "c1", "d1", "e1", "f1", "g1", "h1", + }; + + /** + * This unit test checks that [JACKSON-5] is fixed; if not, a + * symbol table corruption should result in odd problems. + */ + public void testSharedSymbols() + throws Exception + { + // MUST share a single json factory + JsonFactory jf = new JsonFactory(); + + /* First things first: parse a dummy doc to populate + * shared symbol table with some stuff + */ + String DOC0 = "{ \"a\" : 1, \"x\" : [ ] }"; + JsonParser jp0 = createParser(jf, DOC0); + + /* Important: don't close, don't traverse past end. + * This is needed to create partial still-in-use symbol + * table... + */ + while (jp0.nextToken() != JsonToken.START_ARRAY) { } + + String doc1 = createDoc(FIELD_NAMES, true); + String doc2 = createDoc(FIELD_NAMES, false); + + // Let's run it twice... shouldn't matter + for (int x = 0; x < 2; ++x) { + JsonParser jp1 = createParser(jf, doc1); + JsonParser jp2 = createParser(jf, doc2); + + assertToken(JsonToken.START_OBJECT, jp1.nextToken()); + assertToken(JsonToken.START_OBJECT, jp2.nextToken()); + + int len = FIELD_NAMES.length; + for (int i = 0; i < len; ++i) { + assertToken(JsonToken.FIELD_NAME, jp1.nextToken()); + assertToken(JsonToken.FIELD_NAME, jp2.nextToken()); + assertEquals(FIELD_NAMES[i], jp1.getCurrentName()); + assertEquals(FIELD_NAMES[len-(i+1)], jp2.getCurrentName()); + assertToken(JsonToken.VALUE_NUMBER_INT, jp1.nextToken()); + assertToken(JsonToken.VALUE_NUMBER_INT, jp2.nextToken()); + assertEquals(i, jp1.getIntValue()); + assertEquals(i, jp2.getIntValue()); + } + + assertToken(JsonToken.END_OBJECT, jp1.nextToken()); + assertToken(JsonToken.END_OBJECT, jp2.nextToken()); + + jp1.close(); + jp2.close(); + } + } + + public void testAuxMethods() + throws Exception + { + final int A_BYTES = 0x41414141; // "AAAA" + final int B_BYTES = 0x42424242; // "BBBB" + + BytesToNameCanonicalizer nc = BytesToNameCanonicalizer.createRoot() + .makeChild(true, true); + assertNull(nc.findName(A_BYTES)); + assertNull(nc.findName(A_BYTES, B_BYTES)); + + nc.addName("AAAA", new int[] { A_BYTES }, 1); + Name n1 = nc.findName(A_BYTES); + assertNotNull(n1); + assertEquals("AAAA", n1.getName()); + nc.addName("AAAABBBB", new int[] { A_BYTES, B_BYTES }, 2); + Name n2 = nc.findName(A_BYTES, B_BYTES); + assertEquals("AAAABBBB", n2.getName()); + assertNotNull(n2); + + /* and let's then just exercise this method so it gets covered; + * it's only used for debugging. + */ + assertNotNull(nc.toString()); + } + + /* + //////////////////////////////////////////// + // Helper methods + //////////////////////////////////////////// + */ + + protected JsonParser createParser(JsonFactory jf, String input) + throws IOException, JsonParseException + { + byte[] data = input.getBytes("UTF-8"); + InputStream is = new ByteArrayInputStream(data); + return jf.createJsonParser(is); + } + + private String createDoc(String[] fieldNames, boolean add) + { + StringBuilder sb = new StringBuilder(); + sb.append("{ "); + + int len = fieldNames.length; + for (int i = 0; i < len; ++i) { + if (i > 0) { + sb.append(", "); + } + sb.append('"'); + sb.append(add ? fieldNames[i] : fieldNames[len - (i+1)]); + sb.append("\" : "); + sb.append(i); + } + sb.append(" }"); + return sb.toString(); + } +} + +
diff --git a/1.9.10/src/test/org/codehaus/jackson/impl/TestCustomEscaping.java b/1.9.10/src/test/org/codehaus/jackson/impl/TestCustomEscaping.java new file mode 100644 index 0000000..67700ea --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/impl/TestCustomEscaping.java
@@ -0,0 +1,183 @@ +package org.codehaus.jackson.impl; + +import java.io.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.io.CharacterEscapes; +import org.codehaus.jackson.io.SerializedString; +import org.codehaus.jackson.map.ObjectMapper; + +public class TestCustomEscaping extends main.BaseTest +{ + final static int TWO_BYTE_ESCAPED = 0x111; + final static int THREE_BYTE_ESCAPED = 0x1111; + + final static SerializedString TWO_BYTE_ESCAPED_STRING = new SerializedString("&111;"); + final static SerializedString THREE_BYTE_ESCAPED_STRING = new SerializedString("&1111;"); + + /* + /******************************************************** + /* Helper types + /******************************************************** + */ + + /** + * Trivial simple custom escape definition set. + */ + static class MyEscapes extends CharacterEscapes + { + + private final int[] _asciiEscapes; + + public MyEscapes() { + _asciiEscapes = standardAsciiEscapesForJSON(); + _asciiEscapes['a'] = 'A'; // to basically give us "\A" + _asciiEscapes['b'] = CharacterEscapes.ESCAPE_STANDARD; // too force "\u0062" + _asciiEscapes['d'] = CharacterEscapes.ESCAPE_CUSTOM; + } + + @Override + public int[] getEscapeCodesForAscii() { + return _asciiEscapes; + } + + @Override + public SerializableString getEscapeSequence(int ch) + { + if (ch == 'd') { + return new SerializedString("[D]"); + } + if (ch == TWO_BYTE_ESCAPED) { + return TWO_BYTE_ESCAPED_STRING; + } + if (ch == THREE_BYTE_ESCAPED) { + return THREE_BYTE_ESCAPED_STRING; + } + return null; + } + } + + /* + /******************************************************** + /* Unit tests + /******************************************************** + */ + + /** + * Test to ensure that it is possible to force escaping + * of non-ASCII characters. + * Related to [JACKSON-102] + */ + public void testAboveAsciiEscapeWithReader() throws Exception + { + _testEscapeAboveAscii(false); // reader + } + + public void testAboveAsciiEscapeWithUTF8Stream() throws Exception + { + _testEscapeAboveAscii(true); // stream (utf-8) + } + + // // // Tests for [JACKSON-106] + + public void testEscapeCustomWithReader() throws Exception + { + _testEscapeCustom(false); // reader + } + + public void testEscapeCustomWithUTF8Stream() throws Exception + { + _testEscapeCustom(true); // stream (utf-8) + } + + // for [JACKSON-672] + public void testEscapingViaMapper() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.configure(JsonGenerator.Feature.ESCAPE_NON_ASCII, true); + assertEquals(quote("\\u0101"), mapper.writeValueAsString(String.valueOf((char) 257))); + } + + /* + /******************************************************** + /* Secondary test methods + /******************************************************** + */ + + private void _testEscapeAboveAscii(boolean useStream) throws Exception + { + JsonFactory f = new JsonFactory(); + final String VALUE = "chars: [\u00A0]/[\u1234]"; + final String KEY = "fun:\u0088:\u3456"; + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + JsonGenerator jgen; + + // First: output normally; should not add escaping + if (useStream) { + jgen = f.createJsonGenerator(bytes, JsonEncoding.UTF8); + } else { + jgen = f.createJsonGenerator(new OutputStreamWriter(bytes, "UTF-8")); + } + jgen.writeStartArray(); + jgen.writeString(VALUE); + jgen.writeEndArray(); + jgen.close(); + String json = bytes.toString("UTF-8"); + + assertEquals("["+quote(VALUE)+"]", json); + + // And then with forced ASCII; first, values + + bytes = new ByteArrayOutputStream(); + if (useStream) { + jgen = f.createJsonGenerator(bytes, JsonEncoding.UTF8); + } else { + jgen = f.createJsonGenerator(new OutputStreamWriter(bytes, "UTF-8")); + } + jgen.enable(JsonGenerator.Feature.ESCAPE_NON_ASCII); + jgen.writeStartArray(); + jgen.writeString(VALUE); + jgen.writeEndArray(); + jgen.close(); + json = bytes.toString("UTF-8"); + assertEquals("["+quote("chars: [\\u00A0]/[\\u1234]")+"]", json); + + // and then keys + bytes = new ByteArrayOutputStream(); + if (useStream) { + jgen = f.createJsonGenerator(bytes, JsonEncoding.UTF8); + } else { + jgen = f.createJsonGenerator(new OutputStreamWriter(bytes, "UTF-8")); + } + jgen.enable(JsonGenerator.Feature.ESCAPE_NON_ASCII); + jgen.writeStartObject(); + jgen.writeFieldName(KEY); + jgen.writeBoolean(true); + jgen.writeEndObject(); + jgen.close(); + json = bytes.toString("UTF-8"); + assertEquals("{"+quote("fun:\\u0088:\\u3456")+":true}", json); + } + + private void _testEscapeCustom(boolean useStream) throws Exception + { + JsonFactory f = new JsonFactory().setCharacterEscapes(new MyEscapes()); + final String STR_IN = "[abcd/"+((char) TWO_BYTE_ESCAPED)+"/"+((char) THREE_BYTE_ESCAPED)+"]"; + final String STR_OUT = "[\\A\\u0062c[D]/"+TWO_BYTE_ESCAPED_STRING+"/"+THREE_BYTE_ESCAPED_STRING+"]"; + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + JsonGenerator jgen; + + // First: output normally; should not add escaping + if (useStream) { + jgen = f.createJsonGenerator(bytes, JsonEncoding.UTF8); + } else { + jgen = f.createJsonGenerator(new OutputStreamWriter(bytes, "UTF-8")); + } + jgen.writeStartObject(); + jgen.writeStringField(STR_IN, STR_IN); + jgen.writeEndObject(); + jgen.close(); + String json = bytes.toString("UTF-8"); + assertEquals("{"+quote(STR_OUT)+":"+quote(STR_OUT)+"}", json); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/impl/TestDecorators.java b/1.9.10/src/test/org/codehaus/jackson/impl/TestDecorators.java new file mode 100644 index 0000000..79ec0ef --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/impl/TestDecorators.java
@@ -0,0 +1,114 @@ +package org.codehaus.jackson.impl; + +import java.io.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.io.IOContext; +import org.codehaus.jackson.io.InputDecorator; +import org.codehaus.jackson.io.OutputDecorator; + +/** + * Unit tests to verify that input and output decorators work as + * expected + * + * @since 1.8 + */ +public class TestDecorators extends main.BaseTest +{ + /* + /********************************************************** + /* Helper classes + /********************************************************** + */ + + static class SimpleInputDecorator extends InputDecorator + { + @Override + public InputStream decorate(IOContext ctxt, InputStream in) + throws IOException + { + return new ByteArrayInputStream("123".getBytes("UTF-8")); + } + + @Override + public InputStream decorate(IOContext ctxt, byte[] src, int offset, int length) + throws IOException + { + return new ByteArrayInputStream("456".getBytes("UTF-8")); + } + + @Override + public Reader decorate(IOContext ctxt, Reader src) { + return new StringReader("789"); + } + } + + static class SimpleOutputDecorator extends OutputDecorator + { + @Override + public OutputStream decorate(IOContext ctxt, OutputStream out) throws IOException + { + out.write("123".getBytes("UTF-8")); + out.flush(); + return new ByteArrayOutputStream(); + } + + @Override + public Writer decorate(IOContext ctxt, Writer w) throws IOException + { + w.write("567"); + w.flush(); + return new StringWriter(); + } + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + public void testInputDecoration() throws IOException + { + JsonFactory f = new JsonFactory(); + f.setInputDecorator(new SimpleInputDecorator()); + JsonParser jp; + // first test with Reader + jp = f.createJsonParser(new StringReader("{ }")); + // should be overridden; + assertEquals(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(789, jp.getIntValue()); + jp.close(); + + // similarly with InputStream + jp = f.createJsonParser(new ByteArrayInputStream("[ ]".getBytes("UTF-8"))); + // should be overridden; + assertEquals(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(123, jp.getIntValue()); + jp.close(); + + // and with raw bytes + jp = f.createJsonParser("[ ]".getBytes("UTF-8")); + // should be overridden; + assertEquals(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(456, jp.getIntValue()); + jp.close(); + } + + public void testOutputDecoration() throws IOException + { + JsonFactory f = new JsonFactory(); + f.setOutputDecorator(new SimpleOutputDecorator()); + JsonGenerator jg; + + StringWriter sw = new StringWriter(); + jg = f.createJsonGenerator(sw); + jg.close(); + assertEquals("567", sw.toString()); + + ByteArrayOutputStream out = new ByteArrayOutputStream(); + jg = f.createJsonGenerator(out, JsonEncoding.UTF8); + jg.close(); + assertEquals("123", out.toString("UTF-8")); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/impl/TestJsonParser.java b/1.9.10/src/test/org/codehaus/jackson/impl/TestJsonParser.java new file mode 100644 index 0000000..c73c0b2 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/impl/TestJsonParser.java
@@ -0,0 +1,546 @@ +package org.codehaus.jackson.impl; + +import org.codehaus.jackson.*; + +import java.io.*; +import java.util.*; + +/** + * Set of basic unit tests for verifying that the basic parser + * functionality works as expected. + */ +public class TestJsonParser + extends main.BaseTest +{ + public void testConfig() throws Exception + { + JsonParser jp = createParserUsingReader("[ ]"); + jp.enable(JsonParser.Feature.AUTO_CLOSE_SOURCE); + assertTrue(jp.isEnabled(JsonParser.Feature.AUTO_CLOSE_SOURCE)); + jp.disable(JsonParser.Feature.AUTO_CLOSE_SOURCE); + assertFalse(jp.isEnabled(JsonParser.Feature.AUTO_CLOSE_SOURCE)); + + jp.configure(JsonParser.Feature.AUTO_CLOSE_SOURCE, true); + assertTrue(jp.isEnabled(JsonParser.Feature.AUTO_CLOSE_SOURCE)); + jp.configure(JsonParser.Feature.AUTO_CLOSE_SOURCE, false); + assertFalse(jp.isEnabled(JsonParser.Feature.AUTO_CLOSE_SOURCE)); + + assertTrue(jp.isEnabled(JsonParser.Feature.INTERN_FIELD_NAMES)); + jp.configure(JsonParser.Feature.INTERN_FIELD_NAMES, false); + assertFalse(jp.isEnabled(JsonParser.Feature.INTERN_FIELD_NAMES)); + jp.configure(JsonParser.Feature.INTERN_FIELD_NAMES, true); + assertTrue(jp.isEnabled(JsonParser.Feature.INTERN_FIELD_NAMES)); + } + + @SuppressWarnings("deprecation") + public void testConfigDeprecated() throws Exception + { + JsonParser jp = createParserUsingReader("[ ]"); + // and then deprecated methods + jp.enableFeature(JsonParser.Feature.AUTO_CLOSE_SOURCE); + assertTrue(jp.isFeatureEnabled(JsonParser.Feature.AUTO_CLOSE_SOURCE)); + jp.disableFeature(JsonParser.Feature.AUTO_CLOSE_SOURCE); + assertFalse(jp.isFeatureEnabled(JsonParser.Feature.AUTO_CLOSE_SOURCE)); + jp.setFeature(JsonParser.Feature.AUTO_CLOSE_SOURCE, true); + assertTrue(jp.isFeatureEnabled(JsonParser.Feature.AUTO_CLOSE_SOURCE)); + } + + public void testInterningWithStreams() throws Exception + { + _testIntern(true, true, "a"); + _testIntern(true, false, "b"); + } + + public void testInterningWithReaders() throws Exception + { + _testIntern(false, true, "c"); + _testIntern(false, false, "d"); + } + + private void _testIntern(boolean useStream, boolean enableIntern, String expName) throws IOException + { + JsonFactory f = new JsonFactory(); + f.configure(JsonParser.Feature.INTERN_FIELD_NAMES, enableIntern); + assertEquals(enableIntern, f.isEnabled(JsonParser.Feature.INTERN_FIELD_NAMES)); + final String JSON = "{ \""+expName+"\" : 1}"; + JsonParser jp = useStream ? + createParserUsingStream(f, JSON, "UTF-8") : createParserUsingReader(f, JSON); + + assertEquals(enableIntern, jp.isEnabled(JsonParser.Feature.INTERN_FIELD_NAMES)); + + assertToken(JsonToken.START_OBJECT, jp.nextToken()); + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + // needs to be same of cours + String actName = jp.getCurrentName(); + assertEquals(expName, actName); + if (enableIntern) { + assertSame(expName, actName); + } else { + assertNotSame(expName, actName); + } + jp.close(); + } + + public void testTokenAccess() throws Exception + { + JsonParser jp = createParserUsingReader("[ ]"); + assertNull(jp.getCurrentToken()); + jp.clearCurrentToken(); + assertNull(jp.getCurrentToken()); + assertNull(jp.getEmbeddedObject()); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + assertToken(JsonToken.START_ARRAY, jp.getCurrentToken()); + jp.clearCurrentToken(); + assertNull(jp.getCurrentToken()); + + + // Also: no codec defined by default + try { + jp.readValueAsTree(); + fail("Should get exception without codec"); + } catch (IllegalStateException e) { + verifyException(e, "No ObjectCodec defined"); + } + + jp.close(); + } + + /** + * This basic unit test verifies that example given in the Json + * specification (RFC-4627 or later) is properly parsed at + * high-level, without verifying values. + */ + public void testSpecExampleSkipping() + throws Exception + { + doTestSpec(false); + } + + /** + * Unit test that verifies that the spec example JSON is completely + * parsed, and proper values are given for contents of all + * events/tokens. + */ + public void testSpecExampleFully() + throws Exception + { + doTestSpec(true); + } + + /** + * Unit test that verifies that 3 basic keywords (null, true, false) + * are properly parsed in various contexts. + */ + public void testKeywords() + throws Exception + { + final String DOC = "{\n" + +"\"key1\" : null,\n" + +"\"key2\" : true,\n" + +"\"key3\" : false,\n" + +"\"key4\" : [ false, null, true ]\n" + +"}" + ; + + JsonParser jp = createParserUsingStream(DOC, "UTF-8"); + + JsonStreamContext ctxt = jp.getParsingContext(); + assertTrue(ctxt.inRoot()); + assertFalse(ctxt.inArray()); + assertFalse(ctxt.inObject()); + assertEquals(0, ctxt.getEntryCount()); + assertEquals(0, ctxt.getCurrentIndex()); + + /* Before advancing to content, we should have following + * default state... + */ + assertFalse(jp.hasCurrentToken()); + assertNull(jp.getText()); + assertNull(jp.getTextCharacters()); + assertEquals(0, jp.getTextLength()); + // not sure if this is defined but: + assertEquals(0, jp.getTextOffset()); + + assertToken(JsonToken.START_OBJECT, jp.nextToken()); + + assertTrue(jp.hasCurrentToken()); + JsonLocation loc = jp.getTokenLocation(); + assertNotNull(loc); + assertEquals(1, loc.getLineNr()); + assertEquals(1, loc.getColumnNr()); + + ctxt = jp.getParsingContext(); + assertFalse(ctxt.inRoot()); + assertFalse(ctxt.inArray()); + assertTrue(ctxt.inObject()); + assertEquals(0, ctxt.getEntryCount()); + assertEquals(0, ctxt.getCurrentIndex()); + + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + verifyFieldName(jp, "key1"); + assertEquals(2, jp.getTokenLocation().getLineNr()); + + ctxt = jp.getParsingContext(); + assertFalse(ctxt.inRoot()); + assertFalse(ctxt.inArray()); + assertTrue(ctxt.inObject()); + assertEquals(1, ctxt.getEntryCount()); + assertEquals(0, ctxt.getCurrentIndex()); + + assertToken(JsonToken.VALUE_NULL, jp.nextToken()); + + ctxt = jp.getParsingContext(); + assertEquals(1, ctxt.getEntryCount()); + assertEquals(0, ctxt.getCurrentIndex()); + + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + verifyFieldName(jp, "key2"); + ctxt = jp.getParsingContext(); + assertEquals(2, ctxt.getEntryCount()); + assertEquals(1, ctxt.getCurrentIndex()); + + assertToken(JsonToken.VALUE_TRUE, jp.nextToken()); + + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + verifyFieldName(jp, "key3"); + assertToken(JsonToken.VALUE_FALSE, jp.nextToken()); + + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + verifyFieldName(jp, "key4"); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + assertToken(JsonToken.VALUE_FALSE, jp.nextToken()); + assertToken(JsonToken.VALUE_NULL, jp.nextToken()); + assertToken(JsonToken.VALUE_TRUE, jp.nextToken()); + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + + assertToken(JsonToken.END_OBJECT, jp.nextToken()); + } + + public void testInvalidKeywords() throws Exception + { + _testInvalidKeywords(true); + _testInvalidKeywords(false); + } + + private void _testInvalidKeywords(boolean useStream) throws Exception + { + doTestInvalidKeyword1(useStream, "nul"); + doTestInvalidKeyword1(useStream, "nulla"); + doTestInvalidKeyword1(useStream, "fal"); + doTestInvalidKeyword3(useStream, "False"); + doTestInvalidKeyword1(useStream, "falsett0"); + doTestInvalidKeyword1(useStream, "tr"); + doTestInvalidKeyword1(useStream, "truE"); + doTestInvalidKeyword1(useStream, "trueenough"); + } + + public void testSkipping() + throws Exception + { + String DOC = + "[ 1, 3, [ true, null ], 3, { \"a\":\"b\" }, [ [ ] ], { } ]"; + ; + JsonParser jp = createParserUsingStream(DOC, "UTF-8"); + + // First, skipping of the whole thing + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + jp.skipChildren(); + assertEquals(JsonToken.END_ARRAY, jp.getCurrentToken()); + JsonToken t = jp.nextToken(); + if (t != null) { + fail("Expected null at end of doc, got "+t); + } + jp.close(); + + // Then individual ones + jp = createParserUsingStream(DOC, "UTF-8"); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + jp.skipChildren(); + // shouldn't move + assertToken(JsonToken.VALUE_NUMBER_INT, jp.getCurrentToken()); + assertEquals(1, jp.getIntValue()); + + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + // then skip array + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + jp.skipChildren(); + assertToken(JsonToken.END_ARRAY, jp.getCurrentToken()); + + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertToken(JsonToken.START_OBJECT, jp.nextToken()); + jp.skipChildren(); + assertToken(JsonToken.END_OBJECT, jp.getCurrentToken()); + + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + jp.skipChildren(); + assertToken(JsonToken.END_ARRAY, jp.getCurrentToken()); + + assertToken(JsonToken.START_OBJECT, jp.nextToken()); + jp.skipChildren(); + assertToken(JsonToken.END_OBJECT, jp.getCurrentToken()); + + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + + jp.close(); + } + + public void testNameEscaping() throws IOException + { + _testNameEscaping(false); + _testNameEscaping(true); + } + + private void _testNameEscaping(boolean useStream) throws IOException + { + final Map<String,String> NAME_MAP = new LinkedHashMap<String,String>(); + NAME_MAP.put("", ""); + NAME_MAP.put("\\\"funny\\\"", "\"funny\""); + NAME_MAP.put("\\\\", "\\"); + NAME_MAP.put("\\r", "\r"); + NAME_MAP.put("\\n", "\n"); + NAME_MAP.put("\\t", "\t"); + NAME_MAP.put("\\r\\n", "\r\n"); + NAME_MAP.put("\\\"\\\"", "\"\""); + NAME_MAP.put("Line\\nfeed", "Line\nfeed"); + NAME_MAP.put("Yet even longer \\\"name\\\"!", "Yet even longer \"name\"!"); + + JsonFactory jf = new JsonFactory(); + int entry = 0; + for (Map.Entry<String,String> en : NAME_MAP.entrySet()) { + ++entry; + String input = en.getKey(); + String expResult = en.getValue(); + final String DOC = "{ \""+input+"\":null}"; + JsonParser jp = useStream ? + jf.createJsonParser(new ByteArrayInputStream(DOC.getBytes("UTF-8"))) + : jf.createJsonParser(new StringReader(DOC)); + + assertToken(JsonToken.START_OBJECT, jp.nextToken()); + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + // first, sanity check (field name == getText() + String act = jp.getCurrentName(); + assertEquals(act, getAndVerifyText(jp)); + if (!expResult.equals(act)) { + String msg = "Failed for name #"+entry+"/"+NAME_MAP.size(); + if (expResult.length() != act.length()) { + fail(msg+": exp length "+expResult.length()+", actual "+act.length()); + } + assertEquals(msg, expResult, act); + } + assertToken(JsonToken.VALUE_NULL, jp.nextToken()); + assertToken(JsonToken.END_OBJECT, jp.nextToken()); + jp.close(); + } + } + + /** + * Unit test that verifies that long text segments are handled + * correctly; mostly to stress-test underlying segment-based + * text buffer(s). + */ + public void testLongText() throws Exception + { + final int LEN = 96000; + StringBuilder sb = new StringBuilder(LEN + 100); + Random r = new Random(99); + while (sb.length() < LEN) { + sb.append(r.nextInt()); + sb.append(" xyz foo"); + if (r.nextBoolean()) { + sb.append(" and \"bar\""); + } else if (r.nextBoolean()) { + sb.append(" [whatever].... "); + } else { + // Let's try some more 'exotic' chars + sb.append(" UTF-8-fu: try this {\u00E2/\u0BF8/\uA123!} (look funny?)"); + } + if (r.nextBoolean()) { + if (r.nextBoolean()) { + sb.append('\n'); + } else if (r.nextBoolean()) { + sb.append('\r'); + } else { + sb.append("\r\n"); + } + } + } + final String VALUE = sb.toString(); + + JsonFactory jf = new JsonFactory(); + + // Let's use real generator to get json done right + StringWriter sw = new StringWriter(LEN + (LEN >> 2)); + JsonGenerator jg = jf.createJsonGenerator(sw); + jg.writeStartObject(); + jg.writeFieldName("doc"); + jg.writeString(VALUE); + jg.writeEndObject(); + jg.close(); + + final String DOC = sw.toString(); + + for (int type = 0; type < 3; ++type) { + JsonParser jp; + + switch (type) { + default: + jp = jf.createJsonParser(DOC.getBytes("UTF-8")); + break; + case 1: + jp = jf.createJsonParser(DOC); + break; + case 2: // NEW: let's also exercise UTF-32... + jp = jf.createJsonParser(encodeInUTF32BE(DOC)); + break; + } + assertToken(JsonToken.START_OBJECT, jp.nextToken()); + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals("doc", jp.getCurrentName()); + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + + String act = getAndVerifyText(jp); + if (act.length() != VALUE.length()) { + fail("Expected length "+VALUE.length()+", got "+act.length()); + } + if (!act.equals(VALUE)) { + fail("Long text differs"); + } + + // should still know the field name + assertEquals("doc", jp.getCurrentName()); + assertToken(JsonToken.END_OBJECT, jp.nextToken()); + jp.close(); + } + } + + /** + * Simple unit test that verifies that passing in a byte array + * as source works as expected. + */ + public void testBytesAsSource() throws Exception + { + String JSON = "[ 1, 2, 3, 4 ]"; + byte[] b = JSON.getBytes("UTF-8"); + int offset = 50; + int len = b.length; + byte[] src = new byte[offset + len + offset]; + + System.arraycopy(b, 0, src, offset, len); + + JsonFactory jf = new JsonFactory(); + JsonParser jp = jf.createJsonParser(src, offset, len); + + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(1, jp.getIntValue()); + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(2, jp.getIntValue()); + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(3, jp.getIntValue()); + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(4, jp.getIntValue()); + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + assertNull(jp.nextToken()); + + jp.close(); + } + + // [JACKSON-632] + public void testUtf8BOMHandling() throws Exception + { + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + // first, write BOM: + bytes.write(0xEF); + bytes.write(0xBB); + bytes.write(0xBF); + bytes.write("[ 1 ]".getBytes("UTF-8")); + JsonFactory jf = new JsonFactory(); + JsonParser jp = jf.createJsonParser(bytes.toByteArray()); + assertEquals(JsonToken.START_ARRAY, jp.nextToken()); + // should also have skipped first 3 bytes of BOM; but do we have offset available? + /* + JsonLocation loc = jp.getTokenLocation(); + assertEquals(3, loc.getByteOffset()); + assertEquals(-1, loc.getCharOffset()); + */ + } + + /* + /********************************************************** + /* Helper methods + /********************************************************** + */ + + private void doTestSpec(boolean verify) + throws IOException + { + // First, using a StringReader: + doTestSpecIndividual(null, verify); + + // Then with streams using supported encodings: + doTestSpecIndividual("UTF-8", verify); + doTestSpecIndividual("UTF-16BE", verify); + doTestSpecIndividual("UTF-16LE", verify); + + /* Hmmh. UTF-32 is harder only because JDK doesn't come with + * a codec for it. Can't test it yet using this method + */ + doTestSpecIndividual("UTF-32", verify); + } + + private void doTestSpecIndividual(String enc, boolean verify) + throws IOException + { + String doc = SAMPLE_DOC_JSON_SPEC; + JsonParser jp; + + if (enc == null) { + jp = createParserUsingReader(doc); + } else { + jp = createParserUsingStream(doc, enc); + } + verifyJsonSpecSampleDoc(jp, verify); + jp.close(); + } + + private void doTestInvalidKeyword1(boolean useStream, String value) + throws IOException + { + final String doc = "{ \"key1\" : "+value+" }"; + JsonParser jp = useStream ? createParserUsingStream(doc, "UTF-8") + : this.createParserUsingReader(doc); + assertToken(JsonToken.START_OBJECT, jp.nextToken()); + /* 24-Nov-2008, tatu: Note that depending on parser impl, we may + * get the exception early or late... + */ + try { + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + jp.nextToken(); + fail("Expected an exception for malformed value keyword"); + } catch (JsonParseException jex) { + verifyException(jex, "Unrecognized token"); + } + } + + private void doTestInvalidKeyword3(boolean useStream, String value) + throws IOException + { + final String doc = "{ \"key1\" : "+value+" }"; + JsonParser jp = useStream ? createParserUsingStream(doc, "UTF-8") + : this.createParserUsingReader(doc); + assertToken(JsonToken.START_OBJECT, jp.nextToken()); + /* 24-Nov-2008, tatu: Note that depending on parser impl, we may + * get the exception early or late... + */ + try { + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + jp.nextToken(); + fail("Expected an exception for malformed value keyword"); + } catch (JsonParseException jex) { + verifyException(jex, "expected a valid value"); + } + } +} +
diff --git a/1.9.10/src/test/org/codehaus/jackson/impl/TestJsonParserBinary.java b/1.9.10/src/test/org/codehaus/jackson/impl/TestJsonParserBinary.java new file mode 100644 index 0000000..2bef7c3 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/impl/TestJsonParserBinary.java
@@ -0,0 +1,153 @@ +package org.codehaus.jackson.impl; + +import java.io.*; + +import org.codehaus.jackson.*; + +import static org.junit.Assert.*; + +/** + * Tests for verifying that accessing base64 encoded content works ok. + */ +public class TestJsonParserBinary + extends main.BaseTest +{ + /* + /********************************************************************** + /* Unit tests + /********************************************************************** + */ + + public void testSimple() + throws IOException + { + // let's test reader (char) based first, then stream (byte) + _testSimple(false); + _testSimple(true); + } + + public void testInArray() + throws IOException + { + // let's test reader (char) based first, then stream (byte) + _testInArray(false); + _testInArray(true); + } + + public void testWithEscaped() throws IOException + { + // let's test reader (char) based first, then stream (byte) + _testEscaped(false); + _testEscaped(true); + } + + /* + /********************************************************************** + /* Actual test methods + /********************************************************************** + */ + + private void _testSimple(boolean useStream) + throws IOException + { + /* The usual sample input string, from Thomas Hobbes's "Leviathan" + * (via Wikipedia) + */ + final String RESULT = "Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure."; + final byte[] RESULT_BYTES = RESULT.getBytes("US-ASCII"); + + // And here's what should produce it... + final String INPUT_STR = + "TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlz" ++"IHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2Yg" ++"dGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGlu" ++"dWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRo" ++"ZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4=" + ; + + final String DOC = "\""+INPUT_STR+"\""; + JsonParser jp = _getParser(DOC, useStream); + + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + byte[] data = jp.getBinaryValue(); + assertNotNull(data); + assertArrayEquals(RESULT_BYTES, data); + } + + private void _testInArray(boolean useStream) + throws IOException + { + JsonFactory jf = new JsonFactory(); + + final int entryCount = 7; + + StringWriter sw = new StringWriter(); + JsonGenerator jg = jf.createJsonGenerator(sw); + jg.writeStartArray(); + + byte[][] entries = new byte[entryCount][]; + for (int i = 0; i < entryCount; ++i) { + byte[] b = new byte[200 + i * 100]; + for (int x = 0; x < b.length; ++x) { + b[x] = (byte) (i + x); + } + entries[i] = b; + jg.writeBinary(b); + } + + jg.writeEndArray(); + jg.close(); + + JsonParser jp = _getParser(sw.toString(), useStream); + + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + + for (int i = 0; i < entryCount; ++i) { + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + byte[] b = jp.getBinaryValue(); + assertArrayEquals(entries[i], b); + } + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + } + + private void _testEscaped(boolean useStream) throws IOException + { + // Input: "Test!" -> "VGVzdCE=" + + // First, try with embedded linefeed half-way through: + + String DOC = quote("VGVz\\ndCE="); // note: must double-quote to get linefeed + JsonParser jp = _getParser(DOC, useStream); + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + byte[] b = jp.getBinaryValue(); + assertEquals("Test!", new String(b, "US-ASCII")); + assertNull(jp.nextToken()); + jp.close(); + + // and then with escaped chars +// DOC = quote("V\\u0047V\\u007AdCE="); // note: must escape backslash... + DOC = quote("V\\u0047V\\u007AdCE="); // note: must escape backslash... + jp = _getParser(DOC, useStream); + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + b = jp.getBinaryValue(); + assertEquals("Test!", new String(b, "US-ASCII")); + assertNull(jp.nextToken()); + jp.close(); + } + + /* + /********************************************************************** + /* Other helper methods + /********************************************************************** + */ + + private JsonParser _getParser(String doc, boolean useStream) + throws IOException + { + JsonFactory jf = new JsonFactory(); + if (useStream) { + return jf.createJsonParser(doc.getBytes("UTF-8")); + } + return jf.createJsonParser(new StringReader(doc)); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/impl/TestNextXxx.java b/1.9.10/src/test/org/codehaus/jackson/impl/TestNextXxx.java new file mode 100644 index 0000000..131688f --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/impl/TestNextXxx.java
@@ -0,0 +1,102 @@ +package org.codehaus.jackson.impl; + +import java.io.ByteArrayInputStream; +import java.io.StringReader; + +import org.codehaus.jackson.JsonFactory; +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.JsonToken; +import org.codehaus.jackson.SerializableString; +import org.codehaus.jackson.io.SerializedString; + +public class TestNextXxx + extends main.BaseTest +{ + // [JACKSON-653] + public void testIsNextTokenName() throws Exception + { + _testIsNextTokenName1(false); + _testIsNextTokenName1(true); + _testIsNextTokenName2(false); + _testIsNextTokenName2(true); + } + + private void _testIsNextTokenName1(boolean useStream) throws Exception + { + final String DOC = "{\"name\":123,\"name2\":14,\"x\":\"name\"}"; + JsonFactory jf = new JsonFactory(); + JsonParser jp = useStream ? + jf.createJsonParser(new ByteArrayInputStream(DOC.getBytes("UTF-8"))) + : jf.createJsonParser(new StringReader(DOC)); + SerializedString NAME = new SerializedString("name"); + assertFalse(jp.nextFieldName(NAME)); + assertToken(JsonToken.START_OBJECT, jp.getCurrentToken()); + assertTrue(jp.nextFieldName(NAME)); + assertToken(JsonToken.FIELD_NAME, jp.getCurrentToken()); + assertEquals(NAME.getValue(), jp.getCurrentName()); + assertEquals(NAME.getValue(), jp.getText()); + assertFalse(jp.nextFieldName(NAME)); + assertToken(JsonToken.VALUE_NUMBER_INT, jp.getCurrentToken()); + assertEquals(123, jp.getIntValue()); + + assertFalse(jp.nextFieldName(NAME)); + assertToken(JsonToken.FIELD_NAME, jp.getCurrentToken()); + assertEquals("name2", jp.getCurrentName()); + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + + assertFalse(jp.nextFieldName(NAME)); + assertToken(JsonToken.FIELD_NAME, jp.getCurrentToken()); + assertEquals("x", jp.getCurrentName()); + + assertFalse(jp.nextFieldName(NAME)); + assertToken(JsonToken.VALUE_STRING, jp.getCurrentToken()); + + assertFalse(jp.nextFieldName(NAME)); + assertToken(JsonToken.END_OBJECT, jp.getCurrentToken()); + + assertFalse(jp.nextFieldName(NAME)); + assertNull(jp.getCurrentToken()); + + jp.close(); + } + + private void _testIsNextTokenName2(boolean useStream) throws Exception + { + final String DOC = "{\"name\":123,\"name2\":14,\"x\":\"name\"}"; + JsonFactory jf = new JsonFactory(); + JsonParser jp = useStream ? + jf.createJsonParser(new ByteArrayInputStream(DOC.getBytes("UTF-8"))) + : jf.createJsonParser(new StringReader(DOC)); + SerializableString NAME = new SerializedString("name"); + assertFalse(jp.nextFieldName(NAME)); + assertToken(JsonToken.START_OBJECT, jp.getCurrentToken()); + assertTrue(jp.nextFieldName(NAME)); + assertToken(JsonToken.FIELD_NAME, jp.getCurrentToken()); + assertEquals(NAME.getValue(), jp.getCurrentName()); + assertEquals(NAME.getValue(), jp.getText()); + assertFalse(jp.nextFieldName(NAME)); + assertToken(JsonToken.VALUE_NUMBER_INT, jp.getCurrentToken()); + assertEquals(123, jp.getIntValue()); + + assertFalse(jp.nextFieldName(NAME)); + assertToken(JsonToken.FIELD_NAME, jp.getCurrentToken()); + assertEquals("name2", jp.getCurrentName()); + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + + assertFalse(jp.nextFieldName(NAME)); + assertToken(JsonToken.FIELD_NAME, jp.getCurrentToken()); + assertEquals("x", jp.getCurrentName()); + + assertFalse(jp.nextFieldName(NAME)); + assertToken(JsonToken.VALUE_STRING, jp.getCurrentToken()); + + assertFalse(jp.nextFieldName(NAME)); + assertToken(JsonToken.END_OBJECT, jp.getCurrentToken()); + + assertFalse(jp.nextFieldName(NAME)); + assertNull(jp.getCurrentToken()); + + jp.close(); + } + +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/impl/TestParserNonStandard.java b/1.9.10/src/test/org/codehaus/jackson/impl/TestParserNonStandard.java new file mode 100644 index 0000000..0a2943d --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/impl/TestParserNonStandard.java
@@ -0,0 +1,449 @@ +package org.codehaus.jackson.impl; + +import org.codehaus.jackson.*; + +public class TestParserNonStandard + extends main.BaseTest +{ + // // // And then tests to verify [JACKSON-69]: + + public void testSimpleUnquoted() throws Exception + { + _testSimpleUnquoted(false); + _testSimpleUnquoted(true); + } + + public void testLargeUnquoted() throws Exception + { + _testLargeUnquoted(false); + _testLargeUnquoted(true); + } + + public void testSingleQuotesDefault() throws Exception + { + _testSingleQuotesDefault(false); + _testSingleQuotesDefault(true); + } + + public void testSingleQuotesEnabled() throws Exception + { + _testSingleQuotesEnabled(false); + _testSingleQuotesEnabled(true); + _testSingleQuotesEscaped(false); + _testSingleQuotesEscaped(true); + } + + // Test for [JACKSON-267], allowing '@' as name char, for unquoted names + public void testNonStandardNameChars() throws Exception + { + _testNonStandardNameChars(false); + _testNonStandardNameChars(true); + } + + // Test for [JACKSON-300] + public void testNonStandardAnyCharQuoting() throws Exception + { + _testNonStandarBackslashQuoting(false); + _testNonStandarBackslashQuoting(true); + } + + // Test for [JACKSON-358] + public void testLeadingZeroesUTF8() throws Exception { + _testLeadingZeroes(true, false); + _testLeadingZeroes(true, true); + } + + public void testLeadingZeroesReader() throws Exception { + _testLeadingZeroes(false, false); + _testLeadingZeroes(false, true); + } + + // [JACKSON-142]: allow NaN + public void testAllowNaN() throws Exception { + _testAllowNaN(false); + _testAllowNaN(true); + } + + // [JACKSON-142]: allow +Inf/-Inf + public void testAllowInfinity() throws Exception { + _testAllowInf(false); + _testAllowInf(true); + } + + /* + /**************************************************************** + /* Secondary test methods + /**************************************************************** + */ + + private void _testLargeUnquoted(boolean useStream) throws Exception + { + StringBuilder sb = new StringBuilder(5000); + sb.append("[\n"); + //final int REPS = 2000; + final int REPS = 1050; + for (int i = 0; i < REPS; ++i) { + if (i > 0) { + sb.append(','); + if ((i & 7) == 0) { + sb.append('\n'); + } + } + sb.append("{"); + sb.append("abc").append(i&127).append(':'); + sb.append((i & 1) != 0); + sb.append("}\n"); + } + sb.append("]"); + String JSON = sb.toString(); + JsonFactory f = new JsonFactory(); + f.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true); + JsonParser jp = useStream ? + createParserUsingStream(f, JSON, "UTF-8") + : createParserUsingReader(f, JSON) + ; + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + for (int i = 0; i < REPS; ++i) { + assertToken(JsonToken.START_OBJECT, jp.nextToken()); + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals("abc"+(i&127), jp.getCurrentName()); + assertToken(((i&1) != 0) ? JsonToken.VALUE_TRUE : JsonToken.VALUE_FALSE, jp.nextToken()); + assertToken(JsonToken.END_OBJECT, jp.nextToken()); + } + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + } + + + private void _testSimpleUnquoted(boolean useStream) throws Exception + { + final String JSON = "{ a : 1, _foo:true, $:\"money!\", \" \":null }"; + JsonFactory f = new JsonFactory(); + f.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true); + JsonParser jp = useStream ? + createParserUsingStream(f, JSON, "UTF-8") + : createParserUsingReader(f, JSON) + ; + + assertToken(JsonToken.START_OBJECT, jp.nextToken()); + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals("a", jp.getCurrentName()); + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals("_foo", jp.getCurrentName()); + assertToken(JsonToken.VALUE_TRUE, jp.nextToken()); + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals("$", jp.getCurrentName()); + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + assertEquals("money!", jp.getText()); + + // and then regular quoted one should still work too: + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals(" ", jp.getCurrentName()); + + assertToken(JsonToken.VALUE_NULL, jp.nextToken()); + + assertToken(JsonToken.END_OBJECT, jp.nextToken()); + } + + /** + * Test to verify that the default parser settings do not + * accept single-quotes for String values (field names, + * textual values) + */ + private void _testSingleQuotesDefault(boolean useStream) throws Exception + { + JsonFactory f = new JsonFactory(); + // First, let's see that by default they are not allowed + String JSON = "[ 'text' ]"; + JsonParser jp = useStream ? createParserUsingStream(f, JSON, "UTF-8") + : createParserUsingReader(f, JSON); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + try { + jp.nextToken(); + fail("Expected exception"); + } catch (JsonParseException e) { + verifyException(e, "Unexpected character ('''"); + } + + JSON = "{ 'a':1 }"; + jp = useStream ? createParserUsingStream(f, JSON, "UTF-8") + : createParserUsingReader(f, JSON); + assertToken(JsonToken.START_OBJECT, jp.nextToken()); + try { + jp.nextToken(); + fail("Expected exception"); + } catch (JsonParseException e) { + verifyException(e, "Unexpected character ('''"); + } + } + + /** + * Test to verify [JACKSON-173], optional handling of + * single quotes, to allow handling invalid (but, alas, common) + * JSON. + */ + private void _testSingleQuotesEnabled(boolean useStream) throws Exception + { + JsonFactory f = new JsonFactory(); + f.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true); + + String JSON = "{ 'a' : 1, \"foobar\": 'b', '_abcde1234':'d', '\"' : '\"\"', '':'' }"; + JsonParser jp = useStream ? createParserUsingStream(f, JSON, "UTF-8") + : createParserUsingReader(f, JSON); + + assertToken(JsonToken.START_OBJECT, jp.nextToken()); + + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals("a", jp.getText()); + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals("1", jp.getText()); + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals("foobar", jp.getText()); + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + assertEquals("b", jp.getText()); + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals("_abcde1234", jp.getText()); + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + assertEquals("d", jp.getText()); + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals("\"", jp.getText()); + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + //assertEquals("\"\"", jp.getText()); + + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals("", jp.getText()); + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + assertEquals("", jp.getText()); + + assertToken(JsonToken.END_OBJECT, jp.nextToken()); + } + + // test to verify that we implicitly allow escaping of apostrophe [JACKSON-548] + private void _testSingleQuotesEscaped(boolean useStream) throws Exception + { + JsonFactory f = new JsonFactory(); + f.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true); + + String JSON = "[ '16\\'' ]"; + JsonParser jp = useStream ? createParserUsingStream(f, JSON, "UTF-8") + : createParserUsingReader(f, JSON); + + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + assertEquals("16'", jp.getText()); + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + } + + private void _testNonStandardNameChars(boolean useStream) throws Exception + { + JsonFactory f = new JsonFactory(); + f.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true); + String JSON = "{ @type : \"mytype\", #color : 123, *error* : true, " + +" hyphen-ated : \"yes\", me+my : null" + +"}"; + JsonParser jp = useStream ? createParserUsingStream(f, JSON, "UTF-8") + : createParserUsingReader(f, JSON); + + assertToken(JsonToken.START_OBJECT, jp.nextToken()); + + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals("@type", jp.getText()); + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + assertEquals("mytype", jp.getText()); + + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals("#color", jp.getText()); + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(123, jp.getIntValue()); + + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals("*error*", jp.getText()); + assertToken(JsonToken.VALUE_TRUE, jp.nextToken()); + + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals("hyphen-ated", jp.getText()); + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + assertEquals("yes", jp.getText()); + + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals("me+my", jp.getText()); + assertToken(JsonToken.VALUE_NULL, jp.nextToken()); + + assertToken(JsonToken.END_OBJECT, jp.nextToken()); + jp.close(); + } + + private void _testNonStandarBackslashQuoting(boolean useStream) throws Exception + { + // first: verify that we get an exception + JsonFactory f = new JsonFactory(); + assertFalse(f.isEnabled(JsonParser.Feature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER)); + final String JSON = quote("\\'"); + JsonParser jp = useStream ? createParserUsingStream(f, JSON, "UTF-8") + : createParserUsingReader(f, JSON); + try { + jp.nextToken(); + jp.getText(); + fail("Should have thrown an exception for doc <"+JSON+">"); + } catch (JsonParseException e) { + verifyException(e, "unrecognized character escape"); + } + // and then verify it's ok... + f.configure(JsonParser.Feature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER, true); + assertTrue(f.isEnabled(JsonParser.Feature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER)); + jp = useStream ? createParserUsingStream(f, JSON, "UTF-8") + : createParserUsingReader(f, JSON); + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + assertEquals("'", jp.getText()); + } + + private void _testLeadingZeroes(boolean useStream, boolean appendSpace) throws Exception + { + // first: verify that we get an exception + JsonFactory f = new JsonFactory(); + assertFalse(f.isEnabled(JsonParser.Feature.ALLOW_NUMERIC_LEADING_ZEROS)); + String JSON = "00003"; + if (appendSpace) { + JSON += " "; + } + JsonParser jp = useStream ? createParserUsingStream(f, JSON, "UTF-8") + : createParserUsingReader(f, JSON); + try { + jp.nextToken(); + jp.getText(); + fail("Should have thrown an exception for doc <"+JSON+">"); + } catch (JsonParseException e) { + verifyException(e, "invalid numeric value"); + } + + // and then verify it's ok when enabled + f.configure(JsonParser.Feature.ALLOW_NUMERIC_LEADING_ZEROS, true); + assertTrue(f.isEnabled(JsonParser.Feature.ALLOW_NUMERIC_LEADING_ZEROS)); + jp = useStream ? createParserUsingStream(f, JSON, "UTF-8") + : createParserUsingReader(f, JSON); + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(3, jp.getIntValue()); + assertEquals("3", jp.getText()); + jp.close(); + + // Plus, also: verify that leading zero magnitude is ok: + JSON = "0"+Integer.MAX_VALUE; + if (appendSpace) { + JSON += " "; + } + jp = useStream ? createParserUsingStream(f, JSON, "UTF-8") : createParserUsingReader(f, JSON); + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(String.valueOf(Integer.MAX_VALUE), jp.getText()); + assertEquals(Integer.MAX_VALUE, jp.getIntValue()); + Number nr = jp.getNumberValue(); + assertSame(Integer.class, nr.getClass()); + jp.close(); + } + + private void _testAllowNaN(boolean useStream) throws Exception + { + final String JSON = "[ NaN]"; + JsonFactory f = new JsonFactory(); + assertFalse(f.isEnabled(JsonParser.Feature.ALLOW_NON_NUMERIC_NUMBERS)); + + // without enabling, should get an exception + JsonParser jp = useStream ? createParserUsingStream(f, JSON, "UTF-8") + : createParserUsingReader(f, JSON); + + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + try { + jp.nextToken(); + fail("Expected exception"); + } catch (Exception e) { + verifyException(e, "non-standard"); + } + + // we can enable it dynamically (impl detail) + f.configure(JsonParser.Feature.ALLOW_NON_NUMERIC_NUMBERS, true); + jp = useStream ? createParserUsingStream(f, JSON, "UTF-8") + : createParserUsingReader(f, JSON); + + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + assertToken(JsonToken.VALUE_NUMBER_FLOAT, jp.nextToken()); + double d = jp.getDoubleValue(); + assertTrue(Double.isNaN(d)); + assertEquals("NaN", jp.getText()); + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + jp.close(); + + // finally, should also work with skipping + f.configure(JsonParser.Feature.ALLOW_NON_NUMERIC_NUMBERS, true); + jp = useStream ? createParserUsingStream(f, JSON, "UTF-8") + : createParserUsingReader(f, JSON); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + assertToken(JsonToken.VALUE_NUMBER_FLOAT, jp.nextToken()); + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + jp.close(); + } + + private void _testAllowInf(boolean useStream) throws Exception + { + final String JSON = "[ -INF, +INF, +Infinity,-Infinity ]"; + JsonFactory f = new JsonFactory(); + assertFalse(f.isEnabled(JsonParser.Feature.ALLOW_NON_NUMERIC_NUMBERS)); + + // without enabling, should get an exception + JsonParser jp = useStream ? createParserUsingStream(f, JSON, "UTF-8") + : createParserUsingReader(f, JSON); + + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + try { + jp.nextToken(); + fail("Expected exception"); + } catch (Exception e) { + verifyException(e, "Non-standard token '-INF'"); + } + + f.configure(JsonParser.Feature.ALLOW_NON_NUMERIC_NUMBERS, true); + jp = useStream ? createParserUsingStream(f, JSON, "UTF-8") + : createParserUsingReader(f, JSON); + + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + + assertToken(JsonToken.VALUE_NUMBER_FLOAT, jp.nextToken()); + double d = jp.getDoubleValue(); + assertEquals("-INF", jp.getText()); + assertTrue(Double.isInfinite(d)); + assertTrue(d == Double.NEGATIVE_INFINITY); + + assertToken(JsonToken.VALUE_NUMBER_FLOAT, jp.nextToken()); + d = jp.getDoubleValue(); + assertEquals("+INF", jp.getText()); + assertTrue(Double.isInfinite(d)); + assertTrue(d == Double.POSITIVE_INFINITY); + + assertToken(JsonToken.VALUE_NUMBER_FLOAT, jp.nextToken()); + d = jp.getDoubleValue(); + assertEquals("+Infinity", jp.getText()); + assertTrue(Double.isInfinite(d)); + assertTrue(d == Double.POSITIVE_INFINITY); + + assertToken(JsonToken.VALUE_NUMBER_FLOAT, jp.nextToken()); + d = jp.getDoubleValue(); + assertEquals("-Infinity", jp.getText()); + assertTrue(Double.isInfinite(d)); + assertTrue(d == Double.NEGATIVE_INFINITY); + + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + jp.close(); + + // finally, should also work with skipping + f.configure(JsonParser.Feature.ALLOW_NON_NUMERIC_NUMBERS, true); + jp = useStream ? createParserUsingStream(f, JSON, "UTF-8") + : createParserUsingReader(f, JSON); + + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + assertToken(JsonToken.VALUE_NUMBER_FLOAT, jp.nextToken()); + assertToken(JsonToken.VALUE_NUMBER_FLOAT, jp.nextToken()); + assertToken(JsonToken.VALUE_NUMBER_FLOAT, jp.nextToken()); + assertToken(JsonToken.VALUE_NUMBER_FLOAT, jp.nextToken()); + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + + jp.close(); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/impl/TestUtf8Generator.java b/1.9.10/src/test/org/codehaus/jackson/impl/TestUtf8Generator.java new file mode 100644 index 0000000..c4e12c3 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/impl/TestUtf8Generator.java
@@ -0,0 +1,28 @@ +package org.codehaus.jackson.impl; + +import java.io.ByteArrayOutputStream; + +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.io.IOContext; +import org.codehaus.jackson.util.BufferRecycler; + +import main.BaseTest; + +public class TestUtf8Generator + extends BaseTest +{ + public void testUtf8Issue462() throws Exception + { + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + IOContext ioc = new IOContext(new BufferRecycler(), bytes, true); + JsonGenerator gen = new Utf8Generator(ioc, 0, null, bytes); + String str = "Natuurlijk is alles gelukt en weer een tevreden klant\uD83D\uDE04"; + int length = 4000 - 38; + + for (int i = 1; i <= length; ++i) { + gen.writeNumber(1); + } + gen.writeString(str); + gen.flush(); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/impl/TestUtf8Parser.java b/1.9.10/src/test/org/codehaus/jackson/impl/TestUtf8Parser.java new file mode 100644 index 0000000..a7c7771 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/impl/TestUtf8Parser.java
@@ -0,0 +1,171 @@ +package org.codehaus.jackson.impl; + +import main.BaseTest; + +import org.codehaus.jackson.*; + +import java.io.*; +import java.util.Random; + +/** + * Set of basic unit tests for verifying that the basic parser + * functionality works as expected. + */ +public class TestUtf8Parser + extends BaseTest +{ + final static String[] UTF8_2BYTE_STRINGS = new String[] { + /* This may look funny, but UTF8 scanner has fairly + * elaborate decoding machinery, and it is indeed + * necessary to try out various combinations... + */ + "b", "A\u00D8", "abc", "c3p0", + "12345", "......", "Long\u00FAer", + "Latin1-fully-\u00BE-develop\u00A8d", + "Some very long name, ridiculously long actually to see that buffer expansion works: \u00BF?" + }; + + final static String[] UTF8_3BYTE_STRINGS = new String[] { + "\uC823?", "A\u400F", "1\u1234?", + "Ab123\u4034", + "Even-longer:\uC023" + }; + + public void testEmptyName() + throws Exception + { + final String DOC = "{ \"\" : \"\" }"; + + JsonParser jp = createParserUsingStream(DOC, "UTF-8"); + assertToken(JsonToken.START_OBJECT, jp.nextToken()); + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals("", jp.getCurrentName()); + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + assertEquals("", jp.getText()); + assertToken(JsonToken.END_OBJECT, jp.nextToken()); + jp.close(); + } + + public void testUtf8Name2Bytes() + throws Exception + { + final String[] NAMES = UTF8_2BYTE_STRINGS; + + for (int i = 0; i < NAMES.length; ++i) { + String NAME = NAMES[i]; + String DOC = "{ \""+NAME+"\" : 0 }"; + JsonParser jp = createParserUsingStream(DOC, "UTF-8"); + assertToken(JsonToken.START_OBJECT, jp.nextToken()); + + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals(NAME, jp.getCurrentName()); + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + // should retain name during value entry, too + assertEquals(NAME, jp.getCurrentName()); + + assertToken(JsonToken.END_OBJECT, jp.nextToken()); + jp.close(); + } + } + + public void testUtf8Name3Bytes() throws Exception + { + final String[] NAMES = UTF8_3BYTE_STRINGS; + + for (int i = 0; i < NAMES.length; ++i) { + String NAME = NAMES[i]; + String DOC = "{ \""+NAME+"\" : true }"; + + JsonParser jp = createParserUsingStream(DOC, "UTF-8"); + assertToken(JsonToken.START_OBJECT, jp.nextToken()); + + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals(NAME, jp.getCurrentName()); + assertToken(JsonToken.VALUE_TRUE, jp.nextToken()); + assertEquals(NAME, jp.getCurrentName()); + + assertToken(JsonToken.END_OBJECT, jp.nextToken()); + + jp.close(); + } + } + + // How about tests for Surrogate-Pairs? + + public void testUtf8StringTrivial() throws Exception + { + String[] VALUES = UTF8_2BYTE_STRINGS; + for (int i = 0; i < VALUES.length; ++i) { + String VALUE = VALUES[i]; + String DOC = "[ \""+VALUE+"\" ]"; + JsonParser jp = createParserUsingStream(DOC, "UTF-8"); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + String act = getAndVerifyText(jp); + if (act.length() != VALUE.length()) { + fail("Failed for value #"+(i+1)+"/"+VALUES.length+": length was "+act.length()+", should be "+VALUE.length()); + } + assertEquals(VALUE, act); + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + jp.close(); + } + + VALUES = UTF8_3BYTE_STRINGS; + for (int i = 0; i < VALUES.length; ++i) { + String VALUE = VALUES[i]; + String DOC = "[ \""+VALUE+"\" ]"; + JsonParser jp = createParserUsingStream(DOC, "UTF-8"); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + assertEquals(VALUE, getAndVerifyText(jp)); + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + jp.close(); + } + } + + public void testUtf8StringValue() throws Exception + { + Random r = new Random(13); + //int LEN = 72000; + int LEN = 720; + StringBuilder sb = new StringBuilder(LEN + 20); + while (sb.length() < LEN) { + int c; + if (r.nextBoolean()) { // ascii + c = 32 + (r.nextInt() & 0x3F); + if (c == '"' || c == '\\') { + c = ' '; + } + } else if (r.nextBoolean()) { // 2-byte + c = 160 + (r.nextInt() & 0x3FF); + } else if (r.nextBoolean()) { // 3-byte (non-surrogate) + c = 8000 + (r.nextInt() & 0x7FFF); + } else { // surrogates (2 chars) + int value = r.nextInt() & 0x3FFFF; // 20-bit, ~ 1 million + sb.append((char) (0xD800 + (value >> 10))); + c = (0xDC00 + (value & 0x3FF)); + + } + sb.append((char) c); + } + + ByteArrayOutputStream bout = new ByteArrayOutputStream(LEN); + OutputStreamWriter out = new OutputStreamWriter(bout, "UTF-8"); + out.write("[\""); + String VALUE = sb.toString(); + out.write(VALUE); + out.write("\"]"); + out.close(); + + byte[] data = bout.toByteArray(); + + JsonParser jp = new JsonFactory().createJsonParser(new ByteArrayInputStream(data)); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + String act = jp.getText(); + + assertEquals(VALUE.length(), act.length()); + assertEquals(VALUE, act); + jp.close(); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/io/TestIOContext.java b/1.9.10/src/test/org/codehaus/jackson/io/TestIOContext.java new file mode 100644 index 0000000..601c0db --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/io/TestIOContext.java
@@ -0,0 +1,92 @@ +package org.codehaus.jackson.io; + +import org.codehaus.jackson.util.BufferRecycler; + +public class TestIOContext + extends main.BaseTest +{ + public void testAllocations() throws Exception + { + IOContext ctxt = new IOContext(new BufferRecycler(), "N/A", true); + + /* I/O Read buffer */ + + // First succeeds: + assertNotNull(ctxt.allocReadIOBuffer()); + // second fails + try { + ctxt.allocReadIOBuffer(); + } catch (IllegalStateException e) { + verifyException(e, "second time"); + } + // Also: can't succeed with different buffer + try { + ctxt.releaseReadIOBuffer(new byte[1]); + } catch (IllegalArgumentException e) { + verifyException(e, "not owned"); + } + // but call with null is a NOP for convenience + ctxt.releaseReadIOBuffer(null); + + /* I/O Write buffer */ + + assertNotNull(ctxt.allocWriteEncodingBuffer()); + try { + ctxt.allocWriteEncodingBuffer(); + } catch (IllegalStateException e) { + verifyException(e, "second time"); + } + try { + ctxt.releaseWriteEncodingBuffer(new byte[1]); + } catch (IllegalArgumentException e) { + verifyException(e, "not owned"); + } + ctxt.releaseWriteEncodingBuffer(null); + + /* Token (read) buffer */ + + assertNotNull(ctxt.allocTokenBuffer()); + try { + ctxt.allocTokenBuffer(); + } catch (IllegalStateException e) { + verifyException(e, "second time"); + } + try { + ctxt.releaseTokenBuffer(new char[1]); + } catch (IllegalArgumentException e) { + verifyException(e, "not owned"); + } + ctxt.releaseTokenBuffer(null); + + /* Concat (write?) buffer */ + + assertNotNull(ctxt.allocConcatBuffer()); + try { + ctxt.allocConcatBuffer(); + } catch (IllegalStateException e) { + verifyException(e, "second time"); + } + try { + ctxt.releaseConcatBuffer(new char[1]); + } catch (IllegalArgumentException e) { + verifyException(e, "not owned"); + } + ctxt.releaseConcatBuffer(null); + + /* NameCopy (write?) buffer */ + + assertNotNull(ctxt.allocNameCopyBuffer(100)); + try { + ctxt.allocNameCopyBuffer(100); + } catch (IllegalStateException e) { + verifyException(e, "second time"); + } + try { + ctxt.releaseNameCopyBuffer(new char[1]); + } catch (IllegalArgumentException e) { + verifyException(e, "not owned"); + } + ctxt.releaseNameCopyBuffer(null); + } +} +
diff --git a/1.9.10/src/test/org/codehaus/jackson/io/TestJsonStringEncoder.java b/1.9.10/src/test/org/codehaus/jackson/io/TestJsonStringEncoder.java new file mode 100644 index 0000000..14670d3 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/io/TestJsonStringEncoder.java
@@ -0,0 +1,96 @@ +package org.codehaus.jackson.io; + +import java.io.StringWriter; +import java.util.Random; + +import static org.junit.Assert.*; + +import org.codehaus.jackson.*; + +public class TestJsonStringEncoder + extends main.BaseTest +{ + public void testQuoteAsString() throws Exception + { + JsonStringEncoder encoder = new JsonStringEncoder(); + char[] result = encoder.quoteAsString("foobar"); + assertArrayEquals("foobar".toCharArray(), result); + result = encoder.quoteAsString("\"x\""); + assertArrayEquals("\\\"x\\\"".toCharArray(), result); + } + + // For [JACKSON-853] + public void testQuoteLongAsString() throws Exception + { + JsonStringEncoder encoder = new JsonStringEncoder(); + StringBuilder sb = new StringBuilder(); + StringBuilder sb2 = new StringBuilder(); + for (int i = 0; i < 1111; ++i) { + sb.append('"'); + sb2.append("\\\""); + } + String input = sb.toString(); + String exp = sb2.toString(); + char[] result = encoder.quoteAsString(input); + assertEquals(2*input.length(), result.length); + assertEquals(exp, new String(result)); + + } + + public void testQuoteAsUTF8() throws Exception + { + // In this case, let's actually use existing JsonGenerator to produce expected values + JsonFactory f = new JsonFactory(); + JsonStringEncoder encoder = new JsonStringEncoder(); + int[] lengths = new int[] { + 5, 19, 200, 7000, 21000, 37000 + }; + for (int length : lengths) { + String str = generateRandom(length); + StringWriter sw = new StringWriter(length*2); + JsonGenerator jgen = f.createJsonGenerator(sw); + jgen.writeString(str); + jgen.close(); + String encoded = sw.toString(); + // ok, except need to remove surrounding quotes + encoded = encoded.substring(1, encoded.length() - 1); + byte[] expected = encoded.getBytes("UTF-8"); + byte[] actual = encoder.quoteAsUTF8(str); + assertArrayEquals(expected, actual); + } + } + + public void testEncodeAsUTF8() throws Exception + { + JsonStringEncoder encoder = new JsonStringEncoder(); + String[] strings = new String[] { + "a", "foobar", "p\u00f6ll\u00f6", "\"foo\"", + generateRandom(200), + generateRandom(5000), + generateRandom(39000) + }; + for (String str : strings) { + assertArrayEquals(str.getBytes("UTF-8"), encoder.encodeAsUTF8(str)); + } + } + + /* + /********************************************************** + /* Helper methods + /********************************************************** + */ + + + private String generateRandom(int length) + { + StringBuilder sb = new StringBuilder(length); + Random rnd = new Random(length); + for (int i = 0; i < length; ++i) { + // let's limit it not to include surrogate pairs: + char ch = (char) rnd.nextInt(0xCFFF); + sb.append(ch); + } + return sb.toString(); + } +} +
diff --git a/1.9.10/src/test/org/codehaus/jackson/io/TestMergedStream.java b/1.9.10/src/test/org/codehaus/jackson/io/TestMergedStream.java new file mode 100644 index 0000000..466e490 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/io/TestMergedStream.java
@@ -0,0 +1,50 @@ +package org.codehaus.jackson.io; + +import java.io.*; + +import org.codehaus.jackson.JsonEncoding; +import org.codehaus.jackson.util.BufferRecycler; + +public class TestMergedStream + extends main.BaseTest +{ + public void testSimple() throws Exception + { + BufferRecycler rec = new BufferRecycler(); + IOContext ctxt = new IOContext(rec, null, false); + // bit complicated; must use recyclable buffer... + byte[] first = ctxt.allocReadIOBuffer(); + System.arraycopy("ABCDE".getBytes("UTF-8"), 0, first, 99, 5); + byte[] second = "FGHIJ".getBytes("UTF-8"); + + assertNull(ctxt.getSourceReference()); + assertFalse(ctxt.isResourceManaged()); + ctxt.setEncoding(JsonEncoding.UTF8); + MergedStream ms = new MergedStream(ctxt, new ByteArrayInputStream(second), + first, 99, 99+5); + // Ok, first, should have 5 bytes from first buffer: + assertEquals(5, ms.available()); + // not supported when there's buffered stuff... + assertFalse(ms.markSupported()); + // so this won't work, but shouldn't throw exception + ms.mark(1); + assertEquals((byte) 'A', ms.read()); + assertEquals(3, ms.skip(3)); + byte[] buffer = new byte[5]; + /* Ok, now, code is allowed to return anywhere between 1 and 3, + * but we now it will return 1... + */ + assertEquals(1, ms.read(buffer, 1, 3)); + assertEquals((byte) 'E', buffer[1]); + // So let's read bit more + assertEquals(3, ms.read(buffer, 0, 3)); + assertEquals((byte) 'F', buffer[0]); + assertEquals((byte) 'G', buffer[1]); + assertEquals((byte) 'H', buffer[2]); + assertEquals(2, ms.available()); + // And then skip the reset + assertEquals(2, ms.skip(200)); + + ms.close(); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/io/TestUTF8Writer.java b/1.9.10/src/test/org/codehaus/jackson/io/TestUTF8Writer.java new file mode 100644 index 0000000..266b64a --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/io/TestUTF8Writer.java
@@ -0,0 +1,58 @@ +package org.codehaus.jackson.io; + +import java.io.*; + +import org.codehaus.jackson.util.BufferRecycler; + +public class TestUTF8Writer + extends main.BaseTest +{ + public void testSimple() throws Exception + { + BufferRecycler rec = new BufferRecycler(); + IOContext ctxt = new IOContext(rec, null, false); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + UTF8Writer w = new UTF8Writer(ctxt, out); + + String str = "AB\u00A0\u1AE9\uFFFC"; + char[] ch = str.toCharArray(); + + // Let's write 3 times, using different methods + w.write(str); + + w.append(ch[0]); + w.write(ch[1]); + w.write(ch, 2, 3); + + w.write(str, 0, str.length()); + w.close(); + + // and thus should have 3 times contents + byte[] data = out.toByteArray(); + assertEquals(3*10, data.length); + String act = out.toString("UTF-8"); + assertEquals(15, act.length()); + + assertEquals(3 * str.length(), act.length()); + assertEquals(str+str+str, act); + } + + public void testFlushAfterClose() throws Exception + { + BufferRecycler rec = new BufferRecycler(); + IOContext ctxt = new IOContext(rec, null, false); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + UTF8Writer w = new UTF8Writer(ctxt, out); + + w.write('X'); + + w.close(); + assertEquals(1, out.size()); + + // and this ought to be fine... + w.flush(); + // as well as some more... + w.close(); + w.flush(); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/jaxb/BaseJaxbTest.java b/1.9.10/src/test/org/codehaus/jackson/jaxb/BaseJaxbTest.java new file mode 100644 index 0000000..a599d63 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/jaxb/BaseJaxbTest.java
@@ -0,0 +1,35 @@ +package org.codehaus.jackson.jaxb; + +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.introspect.JacksonAnnotationIntrospector; +import org.codehaus.jackson.xc.JaxbAnnotationIntrospector; + +public abstract class BaseJaxbTest + extends org.codehaus.jackson.map.BaseMapTest +{ + protected BaseJaxbTest() { } + + /* + ************************************************************** + * Helper methods + ************************************************************** + */ + + protected ObjectMapper getJaxbMapper() + { + ObjectMapper mapper = new ObjectMapper(); + AnnotationIntrospector intr = new JaxbAnnotationIntrospector(); + mapper.setAnnotationIntrospector(intr); + return mapper; + } + + protected ObjectMapper getJaxbAndJacksonMapper() + { + ObjectMapper mapper = new ObjectMapper(); + AnnotationIntrospector intr = new AnnotationIntrospector.Pair(new JaxbAnnotationIntrospector(), + new JacksonAnnotationIntrospector()); + mapper.setAnnotationIntrospector(intr); + return mapper; + } + +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/jaxb/CommonAttributes.java b/1.9.10/src/test/org/codehaus/jackson/jaxb/CommonAttributes.java new file mode 100644 index 0000000..3875e13 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/jaxb/CommonAttributes.java
@@ -0,0 +1,53 @@ +package org.codehaus.jackson.jaxb; + +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAnyAttribute; +import javax.xml.bind.annotation.XmlAttribute; +import java.net.URI; +import java.util.HashMap; +import java.util.Map; + +/** + * Attributes common across all atom types + * + * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a> + * @version $Revision$ + */ +@XmlAccessorType(XmlAccessType.PROPERTY) +public class CommonAttributes +{ + private String language; + private URI base; + + + private Map<?,?> extensionAttributes = new HashMap<String,String>(); + + @XmlAttribute(name = "lang", namespace = "http://www.w3.org/XML/1998/namespace") + public String getLanguage() + { + return language; + } + + public void setLanguage(String language) + { + this.language = language; + } + + @XmlAttribute(namespace = "http://www.w3.org/XML/1998/namespace") + public URI getBase() + { + return base; + } + + public void setBase(URI base) + { + this.base = base; + } + + @XmlAnyAttribute + public Map<?,?> getExtensionAttributes() + { + return extensionAttributes; + } +} \ No newline at end of file
diff --git a/1.9.10/src/test/org/codehaus/jackson/jaxb/Content.java b/1.9.10/src/test/org/codehaus/jackson/jaxb/Content.java new file mode 100644 index 0000000..aa64b44 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/jaxb/Content.java
@@ -0,0 +1,202 @@ +package org.codehaus.jackson.jaxb; + +import java.net.URI; +import java.util.ArrayList; +import java.util.List; +import javax.ws.rs.core.MediaType; +import javax.xml.bind.annotation.*; + +import org.w3c.dom.Element; + +/** + * <p>Represents an atom:content element.</p> + * <p/> + * <p>Per RFC4287:</p> + * <p/> + * <pre> + * The "atom:content" element either contains or links to the content of + * the entry. The content of atom:content is Language-Sensitive. + * <p/> + * atomInlineTextContent = + * element atom:content { + * atomCommonAttributes, + * attribute type { "text" | "html" }?, + * (text)* + * } + * <p/> + * atomInlineXHTMLContent = + * element atom:content { + * atomCommonAttributes, + * attribute type { "xhtml" }, + * xhtmlDiv + * } + * atomInlineOtherContent = + * element atom:content { + * atomCommonAttributes, + * attribute type { atomMediaType }?, + * (text|anyElement)* + * } + * <p/> + * atomOutOfLineContent = + * element atom:content { + * atomCommonAttributes, + * attribute type { atomMediaType }?, + * attribute src { atomUri }, + * empty + * } + * <p/> + * atomContent = atomInlineTextContent + * | atomInlineXHTMLContent + * | atomInlineOtherContent + * | atomOutOfLineContent + * <p/> + * </pre> + * + * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a> + * @version $Revision$ + */ +@XmlRootElement(name = "content") +@XmlAccessorType(XmlAccessType.PROPERTY) +public class Content extends CommonAttributes +{ + + private String type; + + private MediaType mediaType; + + private String text; + + private Element element; + + private URI src; + + private List<Object> value; + + protected Object jaxbObject; + + @XmlAnyElement + @XmlMixed + public List<Object> getValue() + { + return value; + } + + public void setValue(List<Object> value) + { + this.value = value; + } + + @XmlAttribute + public URI getSrc() + { + return src; + } + + public void setSrc(URI src) + { + this.src = src; + } + + /** + * Mime type of the content + */ + @XmlTransient + public MediaType getType() + { + if (mediaType == null) + { + if (type.equals("html")) mediaType = MediaType.TEXT_HTML_TYPE; + else if (type.equals("text")) mediaType = MediaType.TEXT_PLAIN_TYPE; + else if (type.equals("xhtml")) mediaType = MediaType.APPLICATION_XHTML_XML_TYPE; + else mediaType = MediaType.valueOf(type); + } + return mediaType; + } + + public void setType(MediaType type) + { + mediaType = type; + if (type.equals(MediaType.TEXT_PLAIN_TYPE)) this.type = "text"; + else if (type.equals(MediaType.TEXT_HTML_TYPE)) this.type = "html"; + else if (type.equals(MediaType.APPLICATION_XHTML_XML_TYPE)) this.type = "xhtml"; + else this.type = type.toString(); + } + + @XmlAttribute(name = "type") + public String getRawType() + { + return type; + } + + + public void setRawType(String type) + { + this.type = type; + } + + + /** + * If content is text, return it as a String. Otherwise, if content is not text this will return null. + */ + @XmlTransient + public String getText() + { + if (value == null) return null; + if (value.size() == 0) return null; + if (text != null) return text; + StringBuffer buf = new StringBuffer(); + for (Object obj : value) + { + if (obj instanceof String) buf.append(obj.toString()); + } + text = buf.toString(); + return text; + } + + /** + * Set content as text + * + * @param text + */ + public void setText(String text) + { + if (value == null) value = new ArrayList<Object>(); + if (this.text != null && value != null) value.clear(); + this.text = text; + value.add(text); + } + + /** + * Get content as an XML Element if the content is XML. Otherwise, this will just return null. + */ + @XmlTransient + public Element getElement() + { + if (value == null) return null; + if (element != null) return element; + for (Object obj : value) + { + if (obj instanceof Element) + { + element = (Element) obj; + return element; + } + } + return null; + } + + /** + * Set the content to an XML Element + * + * @param element + */ + public void setElement(Element element) + { + if (value == null) value = new ArrayList<Object>(); + if (this.element != null && value != null) value.clear(); + this.element = element; + value.add(element); + + } + +} \ No newline at end of file
diff --git a/1.9.10/src/test/org/codehaus/jackson/jaxb/EntryType.java b/1.9.10/src/test/org/codehaus/jackson/jaxb/EntryType.java new file mode 100644 index 0000000..dd27968 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/jaxb/EntryType.java
@@ -0,0 +1,34 @@ +package org.codehaus.jackson.jaxb; + +/** + * @author Ryan Heaton + */ +public class EntryType<K, V> { + + private K key; + private V value; + + public EntryType() { + } + + public EntryType(K key, V value) { + this.key = key; + this.value = value; + } + + public K getKey() { + return key; + } + + public void setKey(K key) { + this.key = key; + } + + public V getValue() { + return value; + } + + public void setValue(V value) { + this.value = value; + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/jaxb/MapAdapter.java b/1.9.10/src/test/org/codehaus/jackson/jaxb/MapAdapter.java new file mode 100644 index 0000000..1cd89c3 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/jaxb/MapAdapter.java
@@ -0,0 +1,35 @@ +package org.codehaus.jackson.jaxb; + +import javax.xml.bind.annotation.adapters.XmlAdapter; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +public class MapAdapter<K, V> extends XmlAdapter<MapType<K, V>, Map<K, V>> { + /** + * {@inheritDoc} + */ + @Override + public MapType<K, V> marshal(Map<K, V> v) throws Exception { + + final List<EntryType<K, V>> theEntries = new + LinkedList<EntryType<K, V>>(); + for (final Map.Entry<K, V> anEntry : v.entrySet()) { + theEntries.add(new EntryType<K, V>(anEntry.getKey(), anEntry.getValue())); + } + return new MapType<K, V>(theEntries); + } + + /** + * {@inheritDoc} + */ + @Override + public Map<K, V> unmarshal(MapType<K, V> v) throws Exception { + final Map<K, V> theMap = new HashMap<K, V>(); + for (final EntryType<K, V> anEntry : v.getEntries()) { + theMap.put(anEntry.getKey(), anEntry.getValue()); + } + return theMap; + } +} \ No newline at end of file
diff --git a/1.9.10/src/test/org/codehaus/jackson/jaxb/MapType.java b/1.9.10/src/test/org/codehaus/jackson/jaxb/MapType.java new file mode 100644 index 0000000..e574265 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/jaxb/MapType.java
@@ -0,0 +1,28 @@ +package org.codehaus.jackson.jaxb; + +import org.codehaus.jackson.jaxb.EntryType; + +import java.util.List; + +/** + * @author Ryan Heaton + */ +public class MapType<K,V> { + + public List<EntryType<K, V>> entries; + + public MapType() { + } + + public MapType(List<EntryType<K, V>> theEntries) { + this.entries = theEntries; + } + + public List<EntryType<K, V>> getEntries() { + return entries; + } + + public void setEntries(List<EntryType<K, V>> entries) { + this.entries = entries; + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/jaxb/ObjectContainingAMap.java b/1.9.10/src/test/org/codehaus/jackson/jaxb/ObjectContainingAMap.java new file mode 100644 index 0000000..10ea4a8 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/jaxb/ObjectContainingAMap.java
@@ -0,0 +1,21 @@ +package org.codehaus.jackson.jaxb; + +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; +import java.util.Map; + +/** + * @author Ryan Heaton + */ +public class ObjectContainingAMap { + + private Map<String, String> myMap; + + @XmlJavaTypeAdapter( MapAdapter.class ) + public Map<String, String> getMyMap() { + return myMap; + } + + public void setMyMap(Map<String, String> myMap) { + this.myMap = myMap; + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/jaxb/TestAccessType.java b/1.9.10/src/test/org/codehaus/jackson/jaxb/TestAccessType.java new file mode 100644 index 0000000..9ae0189 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/jaxb/TestAccessType.java
@@ -0,0 +1,97 @@ +package org.codehaus.jackson.jaxb; + +import java.util.Date; + +import javax.xml.bind.annotation.*; +import javax.xml.bind.annotation.adapters.XmlAdapter; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; + +import org.codehaus.jackson.map.*; + +/** + * Unit test(s) written for [JACKSON-303]; we should be able to detect setter + * even though it is not annotated, because there is matching annotated getter. + */ +public class TestAccessType + extends BaseJaxbTest +{ + /* + /********************************************************** + /* Helper beans + /********************************************************** + */ + + @XmlRootElement(name = "model") + @XmlAccessorType(XmlAccessType.NONE) + public static class SimpleNamed + { + protected String name; + + @XmlElement + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + } + + @XmlAccessorType(XmlAccessType.FIELD) + @XmlType(name = "LoggedActivity") + public static class Bean288 + { + @XmlElement(required = true, type = String.class) + @XmlJavaTypeAdapter(MyAdapter.class) + @XmlSchemaType(name = "date") + public Date date; + } + + public static class MyAdapter + extends XmlAdapter<String, Date> + { + @Override + public String marshal(Date arg) throws Exception { + return "String="+arg.getTime(); + } + @Override + public Date unmarshal(String arg0) throws Exception { + return new Date(Long.parseLong(arg0)); + } + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + public void testXmlElementTypeDeser() throws Exception + { + ObjectMapper mapper = getJaxbMapper(); + + SimpleNamed originalModel = new SimpleNamed(); + originalModel.setName("Foobar"); + String json = mapper.writeValueAsString(originalModel); + SimpleNamed result = null; + try { + result = mapper.readValue(json, SimpleNamed.class); + } catch (Exception ie) { + fail("Failed to deserialize '"+json+"': "+ie.getMessage()); + } + if (!"Foobar".equals(result.name)) { + fail("Failed, JSON == '"+json+"')"); + } + } + + public void testForJackson288() throws Exception + { + final long TIMESTAMP = 12345678L; + ObjectMapper mapper = getJaxbMapper(); + Bean288 bean = mapper.readValue("{\"date\":"+TIMESTAMP+"}", Bean288.class); + assertNotNull(bean); + Date d = bean.date; + assertNotNull(d); + assertEquals(TIMESTAMP, d.getTime()); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/jaxb/TestAdaptedMapType.java b/1.9.10/src/test/org/codehaus/jackson/jaxb/TestAdaptedMapType.java new file mode 100644 index 0000000..3af8eaa --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/jaxb/TestAdaptedMapType.java
@@ -0,0 +1,30 @@ +package org.codehaus.jackson.jaxb; + +import junit.framework.TestCase; +import org.codehaus.jackson.map.ObjectMapper; +import org.codehaus.jackson.xc.JaxbAnnotationIntrospector; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.util.HashMap; + +/** + * @author Ryan Heaton + */ +public class TestAdaptedMapType extends TestCase { + + public void testJacksonAdaptedMapType() throws Exception { + ObjectContainingAMap obj = new ObjectContainingAMap(); + obj.setMyMap(new HashMap<String, String>()); + obj.getMyMap().put("this", "that"); + obj.getMyMap().put("how", "here"); + + ObjectMapper mapper = new ObjectMapper(); + mapper.getDeserializationConfig().withAnnotationIntrospector(new JaxbAnnotationIntrospector()); + mapper.getSerializationConfig().withAnnotationIntrospector(new JaxbAnnotationIntrospector()); + ByteArrayOutputStream bytesOut = new ByteArrayOutputStream(); + mapper.writeValue(bytesOut, obj); + obj = mapper.readValue(new ByteArrayInputStream(bytesOut.toByteArray()), ObjectContainingAMap.class); + assertNotNull(obj.getMyMap()); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/jaxb/TestAdapters.java b/1.9.10/src/test/org/codehaus/jackson/jaxb/TestAdapters.java new file mode 100644 index 0000000..479254a --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/jaxb/TestAdapters.java
@@ -0,0 +1,166 @@ +package org.codehaus.jackson.jaxb; + +import java.util.*; + +import javax.xml.bind.annotation.*; +import javax.xml.bind.annotation.adapters.XmlAdapter; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; + +import org.codehaus.jackson.map.ObjectMapper; + +/** + * Unit tests for checking that JAXB type adapters work (to some + * degree, anyway). + * Related to issues [JACKSON-288], [JACKSON-411] + * + * @author tsaloranta + * + * @since 1.6.3 + */ +public class TestAdapters extends BaseJaxbTest +{ + public static class SillyAdapter extends XmlAdapter<String, Date> + { + public SillyAdapter() { } + + @Override + public Date unmarshal(String date) throws Exception { + return new Date(29L); + } + + @Override + public String marshal(Date date) throws Exception { + return "XXX"; + } + } + + static class Bean + { + @XmlJavaTypeAdapter(SillyAdapter.class) + public Date value; + + public Bean() { } + public Bean(long l) { value = new Date(l); } + } + + // For [JACKSON-288] + + static class Bean288 { + public List<Person> persons; + + public Bean288() { } + public Bean288(String str) { + persons = new ArrayList<Person>(); + persons.add(new Person(str)); + } + } + + static class Person + { + public String name; + + @XmlElement(required = true, type = String.class) + @XmlJavaTypeAdapter(DateAdapter.class) + protected Calendar date; + + public Person() { } + public Person(String n) { + name = n; + date = Calendar.getInstance(); + date.setTime(new Date(0L)); + } + } + + public static class DateAdapter + extends XmlAdapter<String, Calendar> + { + public DateAdapter() { } + + @Override + public Calendar unmarshal(String value) { + return (javax.xml.bind.DatatypeConverter.parseDateTime(value)); + } + + @Override + public String marshal(Calendar value) { + if (value == null) { + return null; + } + return (javax.xml.bind.DatatypeConverter.printDateTime(value)); + } + } + + // [JACKSON-656] + + @XmlAccessorType(XmlAccessType.FIELD) + @XmlType(name = "Paging", propOrder = { "numFound" }) + public static class Bean656 { + @XmlElement(type = String.class) + @XmlJavaTypeAdapter(Adapter1.class) + @XmlSchemaType(name = "long") + protected Long numFound; + + public Long getNumFound() { + return numFound; + } + + public void setNumFound(Long value) { + this.numFound = value; + } + } + + public static class Adapter1 extends XmlAdapter<String, Long> { + @Override + public Long unmarshal(String value) { + return ((long) javax.xml.bind.DatatypeConverter.parseLong(value)); + } + + @Override + public String marshal(Long value) { + if (value == null) { + return null; + } + return (javax.xml.bind.DatatypeConverter.printLong((long) (long) value)); + } + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + public void testSimpleAdapterSerialization() throws Exception + { + Bean bean = new Bean(123L); + assertEquals("{\"value\":\"XXX\"}", getJaxbMapper().writeValueAsString(bean)); + } + + public void testSimpleAdapterDeserialization() throws Exception + { + Bean bean = getJaxbMapper().readValue("{\"value\":\"abc\"}", Bean.class); + assertNotNull(bean.value); + assertEquals(29L, bean.value.getTime()); + } + + // [JACKSON-288] + public void testDateAdapter() throws Exception + { + Bean288 input = new Bean288("test"); + ObjectMapper mapper = getJaxbMapper(); + String json = mapper.writeValueAsString(input); + Bean288 output = mapper.readValue(json, Bean288.class); + assertNotNull(output); + } + + // [JACKSON-656] + + public void testJackson656() throws Exception + { + Bean656 bean = new Bean656(); + bean.setNumFound(3232l); + ObjectMapper mapper = getJaxbMapper(); + String json = mapper.writeValueAsString(bean); + assertEquals("{\"numFound\":\"3232\"}", json); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/jaxb/TestAnnotationPriority.java b/1.9.10/src/test/org/codehaus/jackson/jaxb/TestAnnotationPriority.java new file mode 100644 index 0000000..08419c4 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/jaxb/TestAnnotationPriority.java
@@ -0,0 +1,56 @@ +package org.codehaus.jackson.jaxb; + +import javax.xml.bind.annotation.XmlElement; + +import org.codehaus.jackson.map.ObjectMapper; + +/** + * Unit test(s) to verify that annotations from super classes and + * interfaces are properly used (for example, wrt [JACKSON-450]) + */ +public class TestAnnotationPriority extends BaseJaxbTest +{ + /* + /********************************************************** + /* Helper beans + /********************************************************** + */ + + public interface Identifiable { + public String getId(); + public void setId(String i); + } + + static abstract class IdBase + { + protected String id; + + protected IdBase(String id) { this.id = id; } + + @XmlElement(name="name") + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + } + + static class IdBean extends IdBase implements Identifiable { + public IdBean(String id) { super(id); } + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + public void testInterfacesAndClasses() throws Exception + { + ObjectMapper mapper = getJaxbMapper(); + String json = mapper.writeValueAsString(new IdBean("foo")); + assertEquals("{\"name\":\"foo\"}", json); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/jaxb/TestCyclicTypes.java b/1.9.10/src/test/org/codehaus/jackson/jaxb/TestCyclicTypes.java new file mode 100644 index 0000000..881edbd --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/jaxb/TestCyclicTypes.java
@@ -0,0 +1,65 @@ +package org.codehaus.jackson.jaxb; + +import java.util.*; + +import javax.xml.bind.annotation.*; + +import org.codehaus.jackson.map.BaseMapTest; + +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.xc.JaxbAnnotationIntrospector; + +/** + * Simple unit tests to verify that it is possible to handle + * potentially cyclic structures, as long as object graph itself + * is not cyclic. This is the case for directed hierarchies like + * trees and DAGs. + */ +public class TestCyclicTypes + extends BaseMapTest +{ + /* + /********************************************************** + /* Helper bean classes + /********************************************************** + */ + + @XmlAccessorType(XmlAccessType.PUBLIC_MEMBER) + static class Bean + { + private Bean _next; + final String _name; + + public Bean(Bean next, String name) { + _next = next; + _name = name; + } + + public Bean getNext() { return _next; } + public String getName() { return _name; } + + public void assignNext(Bean n) { _next = n; } + } + + /* + /********************************************************** + /* Types + /********************************************************** + */ + + /* Added to check for [JACKSON-171], i.e. that type its being + * cyclic is not a problem (instances are). + */ + public void testWithJAXB() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.setAnnotationIntrospector(new JaxbAnnotationIntrospector()); + Bean bean = new Bean(null, "abx"); + + Map<String,Object> results = writeAndMap(mapper, bean); + assertEquals(2, results.size()); + assertEquals("abx", results.get("name")); + assertTrue(results.containsKey("next")); + assertNull(results.get("next")); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/jaxb/TestDeserializerCaching.java b/1.9.10/src/test/org/codehaus/jackson/jaxb/TestDeserializerCaching.java new file mode 100644 index 0000000..d783d7e --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/jaxb/TestDeserializerCaching.java
@@ -0,0 +1,86 @@ +package org.codehaus.jackson.jaxb; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.deser.BeanDeserializer; +import org.codehaus.jackson.map.deser.BeanDeserializerModifier; +import org.codehaus.jackson.map.introspect.BasicBeanDescription; +import org.codehaus.jackson.xc.JaxbAnnotationIntrospector; + +/** + * Unit test(s) for [JACKSON-472] + */ +public class TestDeserializerCaching extends BaseJaxbTest +{ + /* + /********************************************************** + /* Helper beans + /********************************************************** + */ + + static class MyBeanModule extends Module { + @Override public String getModuleName() { + return "MyBeanModule"; + } + + @Override public Version version() { + return new Version(1,0,0, null); + } + + @Override public void setupModule(SetupContext context) { + context.addBeanDeserializerModifier(new MyBeanDeserializerModifier()); + } + } + + static class MyBeanDeserializer extends BeanDeserializer { + public MyBeanDeserializer(BeanDeserializer src) { + super(src); + } + } + + static class MyBean { + public MyType value1; + public MyType value2; + public MyType value3; + } + + static class MyType { + public String name; + public String value; + } + + static class MyBeanDeserializerModifier extends BeanDeserializerModifier + { + static int count = 0; + + @Override + public JsonDeserializer<?> modifyDeserializer(DeserializationConfig config, + BasicBeanDescription beanDesc, JsonDeserializer<?> deserializer) + { + if (MyType.class.isAssignableFrom(beanDesc.getBeanClass())) { + count++; + return new MyBeanDeserializer((BeanDeserializer)deserializer); + } + return super.modifyDeserializer(config, beanDesc, deserializer); + } + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + public void testCaching() throws Exception + { + final String JSON = "{\"value1\" : {\"name\" : \"fruit\", \"value\" : \"apple\"},\n" + +"\"value2\" : {\"name\" : \"color\", \"value\" : \"red\"},\n" + +"\"value3\" : {\"name\" : \"size\", \"value\" : \"small\"}}" + ; + ObjectMapper mapper = new ObjectMapper(); + mapper.setAnnotationIntrospector(new JaxbAnnotationIntrospector()); + mapper.registerModule(new MyBeanModule()); + mapper.readValue(JSON, MyBean.class); + assertEquals(1, MyBeanDeserializerModifier.count); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/jaxb/TestDomElementSerialization.java b/1.9.10/src/test/org/codehaus/jackson/jaxb/TestDomElementSerialization.java new file mode 100644 index 0000000..4280586 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/jaxb/TestDomElementSerialization.java
@@ -0,0 +1,97 @@ +package org.codehaus.jackson.jaxb; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import javax.xml.parsers.DocumentBuilderFactory; +import java.io.ByteArrayInputStream; +import java.io.StringWriter; + +import org.codehaus.jackson.Version; +import org.codehaus.jackson.map.BeanDescription; +import org.codehaus.jackson.map.BeanProperty; +import org.codehaus.jackson.map.JsonSerializer; +import org.codehaus.jackson.map.ObjectMapper; +import org.codehaus.jackson.map.SerializationConfig; +import org.codehaus.jackson.map.Serializers; +import org.codehaus.jackson.map.module.SimpleModule; +import org.codehaus.jackson.type.JavaType; +import org.codehaus.jackson.xc.DomElementJsonDeserializer; +import org.codehaus.jackson.xc.DomElementJsonSerializer; + +/** + * @author Ryan Heaton + */ +public class TestDomElementSerialization extends BaseJaxbTest +{ + /* + /********************************************************** + /* Helper classes + /********************************************************** + */ + + private final static class DomModule extends SimpleModule + { + public DomModule() + { + super("DomModule", Version.unknownVersion()); + addDeserializer(Element.class, new DomElementJsonDeserializer()); + /* 19-Feb-2011, tatu: Note: since SimpleModule does not support "generic" + * serializers, need to add bit more code here. + */ + //testModule.addSerializer(new DomElementJsonSerializer()); + } + + @Override + public void setupModule(SetupContext context) + { + super.setupModule(context); + context.addSerializers(new DomSerializers()); + } + } + + private final static class DomSerializers extends Serializers.Base + { + @Override + public JsonSerializer<?> findSerializer(SerializationConfig config, + JavaType type, BeanDescription beanDesc, BeanProperty property) + { + if (Element.class.isAssignableFrom(type.getRawClass())) { + return new DomElementJsonSerializer(); + } + return null; + } + } + + /* + /********************************************************** + /* Test methods + /********************************************************** + */ + + public void testBasicDomElementSerializationDeserialization() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.registerModule(new DomModule()); + + StringBuilder builder = new StringBuilder() + .append("<document xmlns=\"urn:hello\" att1=\"value1\" att2=\"value2\">") + .append("<childel>howdy</childel>") + .append("</document>"); + + DocumentBuilderFactory bf = DocumentBuilderFactory.newInstance(); + bf.setNamespaceAware(true); + Document document = bf.newDocumentBuilder().parse(new ByteArrayInputStream(builder.toString().getBytes("utf-8"))); + StringWriter jsonElement = new StringWriter(); + mapper.writeValue(jsonElement, document.getDocumentElement()); + + Element el = mapper.readValue(jsonElement.toString(), Element.class); + assertEquals(3, el.getAttributes().getLength()); + assertEquals("value1", el.getAttributeNS(null, "att1")); + assertEquals("value2", el.getAttributeNS(null, "att2")); + assertEquals(1, el.getChildNodes().getLength()); + assertEquals("childel", el.getChildNodes().item(0).getLocalName()); + assertEquals("urn:hello", el.getChildNodes().item(0).getNamespaceURI()); + assertEquals("howdy", el.getChildNodes().item(0).getTextContent()); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/jaxb/TestElementWrapper.java b/1.9.10/src/test/org/codehaus/jackson/jaxb/TestElementWrapper.java new file mode 100644 index 0000000..0fca453 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/jaxb/TestElementWrapper.java
@@ -0,0 +1,69 @@ +package org.codehaus.jackson.jaxb; + +import java.util.*; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElementWrapper; + +import org.codehaus.jackson.map.ObjectMapper; + +/** + * Unit tests to verify handling of @XmlElementWrapper annotation. + * + * @since 1.7 + */ +public class TestElementWrapper extends BaseJaxbTest +{ + /* + /********************************************************** + /* Helper beans + /********************************************************** + */ + + // Beans for [JACKSON-436] + static class Person { + @XmlElementWrapper + @XmlElement(type=Phone.class) + public Collection<IPhone> phones; + } + + interface IPhone { + public String getNumber(); + } + + static class Phone implements IPhone + { + private String number; + + public Phone() { } + + public Phone(String number) { this.number = number; } + @Override + public String getNumber() { return number; } + public void setNumber(String number) { this.number = number; } + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + // [JACKSON-436] + public void testWrapperWithCollection() throws Exception + { + ObjectMapper mapper = getJaxbMapper(); + Collection<IPhone> phones = new HashSet<IPhone>(); + phones.add(new Phone("555-6666")); + Person p = new Person(); + p.phones = phones; + + String json = mapper.writeValueAsString(p); +// System.out.println("JSON == "+json); + + Person result = mapper.readValue(json, Person.class); + assertNotNull(result.phones); + assertEquals(1, result.phones.size()); + assertEquals("555-6666", result.phones.iterator().next().getNumber()); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/jaxb/TestIntrospectorPair.java b/1.9.10/src/test/org/codehaus/jackson/jaxb/TestIntrospectorPair.java new file mode 100644 index 0000000..020aa74 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/jaxb/TestIntrospectorPair.java
@@ -0,0 +1,313 @@ +package org.codehaus.jackson.jaxb; + +import java.util.*; + +import javax.xml.bind.annotation.*; + +import org.codehaus.jackson.annotate.*; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.introspect.AnnotatedClass; +import org.codehaus.jackson.map.introspect.JacksonAnnotationIntrospector; +import org.codehaus.jackson.map.type.TypeFactory; +import org.codehaus.jackson.type.JavaType; +import org.codehaus.jackson.xc.JaxbAnnotationIntrospector; + +/** + * Simple testing that <code>AnnotationIntrospector.Pair</code> works as + * expected, when used with Jackson and JAXB-based introspector. + * + * @author Tatu Saloranta + */ +@SuppressWarnings("deprecation") +public class TestIntrospectorPair + extends org.codehaus.jackson.map.BaseMapTest +{ + final static AnnotationIntrospector _jacksonAI = new JacksonAnnotationIntrospector(); + final static AnnotationIntrospector _jaxbAI = new JaxbAnnotationIntrospector(); + + public TestIntrospectorPair() { super(); } + + /* + /********************************************************** + /* Helper beans + /********************************************************** + */ + + /** + * Simple test bean for verifying basic field detection and property + * naming annotation handling + */ + @SuppressWarnings("unused") + @XmlAccessorType(XmlAccessType.PUBLIC_MEMBER) + static class NamedBean + { + @JsonProperty + private String jackson = "1"; + + @XmlElement(name="jaxb") + protected String jaxb = "2"; + + @JsonProperty("bothJackson") + @XmlElement(name="bothJaxb") + private String bothString = "3"; + + + public String notAGetter() { return "xyz"; } + } + + /** + * Another bean for verifying details of property naming + */ + @XmlAccessorType(XmlAccessType.PUBLIC_MEMBER) + static class NamedBean2 + { + @JsonProperty("") + @XmlElement(name="jaxb") + public String foo = "abc"; + + @JsonProperty("jackson") + @XmlElement() + public String getBar() { return "123"; } + + // JAXB, alas, requires setters for all properties too + public void setBar(String v) { } + } + + /** + * And a bean to check how "ignore" annotations work with + * various combinations of annotation introspectors + */ + @XmlAccessorType(XmlAccessType.PUBLIC_MEMBER) + @JsonWriteNullProperties + static class IgnoreBean + { + @JsonIgnore + public int getNumber() { return 13; } + + @XmlTransient + public String getText() { return "abc"; } + + public boolean getAny() { return true; } + } + + @XmlAccessorType(XmlAccessType.PUBLIC_MEMBER) + static class IgnoreFieldBean + { + @JsonIgnore public int number = 7; + @XmlTransient public String text = "123"; + public boolean any = true; + } + + @XmlAccessorType(XmlAccessType.PUBLIC_MEMBER) + @XmlRootElement(name="test", namespace="urn:whatever") + static class NamespaceBean + { + public String string; + } + + // Testing [JACKSON-495] + static class CreatorBean { + @JsonCreator + public CreatorBean(@JsonProperty("name") String name) { + ; + } + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + public void testSimple() throws Exception + { + ObjectMapper mapper; + AnnotationIntrospector pair; + Map<String,Object> result; + + mapper = new ObjectMapper(); + // first: test with Jackson/Jaxb pair (jackson having precedence) + pair = new AnnotationIntrospector.Pair(_jacksonAI, _jaxbAI); + mapper.getSerializationConfig().setAnnotationIntrospector(pair); + + result = writeAndMap(mapper, new NamedBean()); + assertEquals(3, result.size()); + assertEquals("1", result.get("jackson")); + assertEquals("2", result.get("jaxb")); + // jackson one should have priority + assertEquals("3", result.get("bothJackson")); + + mapper = new ObjectMapper(); + pair = new AnnotationIntrospector.Pair(_jaxbAI, _jacksonAI); + mapper.getSerializationConfig().setAnnotationIntrospector(pair); + + result = writeAndMap(mapper, new NamedBean()); + assertEquals(3, result.size()); + assertEquals("1", result.get("jackson")); + assertEquals("2", result.get("jaxb")); + // JAXB one should have priority + assertEquals("3", result.get("bothJaxb")); + } + + public void testProperties() throws Exception + { + AnnotationIntrospector pair = new AnnotationIntrospector.Pair(_jacksonAI, _jaxbAI); + assertTrue(pair.isHandled(NamespaceBean.class.getAnnotation(XmlRootElement.class))); + assertTrue(pair.isHandled(IgnoreBean.class.getAnnotation(JsonWriteNullProperties.class))); + + /* won't work without actually getting class annotations etc + AnnotatedConstructor con = new AnnotatedConstructor(getClass().getConstructor(), null, null); + assertFalse(pair.isIgnorableConstructor(con)); + */ + } + + public void testNaming() throws Exception + { + ObjectMapper mapper; + AnnotationIntrospector pair; + Map<String,Object> result; + + mapper = new ObjectMapper(); + // first: test with Jackson/Jaxb pair (jackson having precedence) + pair = new AnnotationIntrospector.Pair(_jacksonAI, _jaxbAI); + mapper.getSerializationConfig().setAnnotationIntrospector(pair); + + result = writeAndMap(mapper, new NamedBean2()); + assertEquals(2, result.size()); + // order shouldn't really matter here... + assertEquals("123", result.get("jackson")); + assertEquals("abc", result.get("jaxb")); + + mapper = new ObjectMapper(); + pair = new AnnotationIntrospector.Pair(_jaxbAI, _jacksonAI); + mapper.getSerializationConfig().setAnnotationIntrospector(pair); + + result = writeAndMap(mapper, new NamedBean2()); + /* Hmmh. Not 100% sure what JAXB would dictate.... thus... + */ + assertEquals(2, result.size()); + assertEquals("abc", result.get("jaxb")); + //assertEquals("123", result.get("jackson")); + } + + public void testSimpleIgnore() throws Exception + { + // first: only Jackson introspector (default) + ObjectMapper mapper = new ObjectMapper(); + Map<String,Object> result = writeAndMap(mapper, new IgnoreBean()); + assertEquals(2, result.size()); + assertEquals("abc", result.get("text")); + assertEquals(Boolean.TRUE, result.get("any")); + + // Then JAXB only + mapper = new ObjectMapper(); + mapper.getSerializationConfig().setAnnotationIntrospector(_jaxbAI); + + // jackson one should have priority + result = writeAndMap(mapper, new IgnoreBean()); + assertEquals(2, result.size()); + assertEquals(Integer.valueOf(13), result.get("number")); + assertEquals(Boolean.TRUE, result.get("any")); + + // then both, Jackson first + mapper = new ObjectMapper(); + mapper.getSerializationConfig().setAnnotationIntrospector(new AnnotationIntrospector.Pair(_jacksonAI, _jaxbAI)); + + result = writeAndMap(mapper, new IgnoreBean()); + assertEquals(1, result.size()); + assertEquals(Boolean.TRUE, result.get("any")); + + // then both, JAXB first + mapper = new ObjectMapper(); + mapper.getSerializationConfig().setAnnotationIntrospector(new AnnotationIntrospector.Pair(_jaxbAI, _jacksonAI)); + + result = writeAndMap(mapper, new IgnoreBean()); + assertEquals(1, result.size()); + assertEquals(Boolean.TRUE, result.get("any")); + } + + public void testSimpleFieldIgnore() throws Exception + { + ObjectMapper mapper; + + // first: only Jackson introspector (default) + mapper = new ObjectMapper(); + Map<String,Object> result = writeAndMap(mapper, new IgnoreFieldBean()); + assertEquals(2, result.size()); + assertEquals("123", result.get("text")); + assertEquals(Boolean.TRUE, result.get("any")); + + // Then JAXB only + mapper = new ObjectMapper(); + mapper.getSerializationConfig().setAnnotationIntrospector(_jaxbAI); + + // jackson one should have priority + result = writeAndMap(mapper, new IgnoreFieldBean()); + assertEquals(2, result.size()); + assertEquals(Integer.valueOf(7), result.get("number")); + assertEquals(Boolean.TRUE, result.get("any")); + + // then both, Jackson first + mapper = new ObjectMapper(); + mapper.getSerializationConfig().setAnnotationIntrospector(new AnnotationIntrospector.Pair(_jacksonAI, _jaxbAI)); + + result = writeAndMap(mapper, new IgnoreFieldBean()); + assertEquals(1, result.size()); + assertEquals(Boolean.TRUE, result.get("any")); + + // then both, JAXB first + mapper = new ObjectMapper(); + mapper.getSerializationConfig().setAnnotationIntrospector(new AnnotationIntrospector.Pair(_jaxbAI, _jacksonAI)); + + result = writeAndMap(mapper, new IgnoreFieldBean()); + assertEquals(1, result.size()); + assertEquals(Boolean.TRUE, result.get("any")); + } + + public void testSimpleOther() throws Exception + { + // Let's use Jackson+JAXB comb + AnnotationIntrospector ann = new AnnotationIntrospector.Pair(_jacksonAI, _jaxbAI); + + AnnotatedClass testClass = AnnotatedClass.construct(NamedBean.class, ann, null); + assertNull(ann.findCachability(testClass)); + //assertNull(ann.findSerializationInclusion(testClass, null)); + + JavaType type = TypeFactory.type(Object.class); + assertNull(ann.findDeserializationType(testClass, type, null)); + assertNull(ann.findDeserializationContentType(testClass, type, null)); + assertNull(ann.findDeserializationKeyType(testClass, type, null)); + assertNull(ann.findSerializationType(testClass)); + + assertNull(ann.findDeserializer(testClass)); + assertNull(ann.findContentDeserializer(testClass)); + assertNull(ann.findKeyDeserializer(testClass)); + + assertFalse(ann.hasCreatorAnnotation(testClass)); + } + + public void testRootName() throws Exception + { + // first: test with Jackson/Jaxb pair (jackson having precedence) + AnnotationIntrospector pair = new AnnotationIntrospector.Pair(_jacksonAI, _jaxbAI); + assertNull(pair.findRootName(AnnotatedClass.construct(NamedBean.class, pair, null))); + assertEquals("test", pair.findRootName(AnnotatedClass.construct(NamespaceBean.class, pair, null))); + + // then reverse; should make no difference + pair = new AnnotationIntrospector.Pair(_jaxbAI, _jacksonAI); + assertNull(pair.findRootName(AnnotatedClass.construct(NamedBean.class, pair, null))); + assertEquals("test", pair.findRootName(AnnotatedClass.construct(NamespaceBean.class, pair, null))); + } + + /** + * Test that will just use Jackson annotations, but did trigger [JACKSON-495] due to a bug + * in JAXB annotation introspector. + */ + public void testIssue495() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.getDeserializationConfig().setAnnotationIntrospector(new AnnotationIntrospector.Pair(_jacksonAI, _jaxbAI)); + CreatorBean bean = mapper.readValue("{\"name\":\"foo\"}", CreatorBean.class); + assertNotNull(bean); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/jaxb/TestJaxbAnnotationIntrospector.java b/1.9.10/src/test/org/codehaus/jackson/jaxb/TestJaxbAnnotationIntrospector.java new file mode 100644 index 0000000..2786980 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/jaxb/TestJaxbAnnotationIntrospector.java
@@ -0,0 +1,392 @@ +package org.codehaus.jackson.jaxb; + +import java.io.StringWriter; +import java.util.*; +import java.util.Map.Entry; + +import javax.xml.bind.annotation.*; +import javax.xml.bind.annotation.adapters.XmlAdapter; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; +import javax.xml.namespace.QName; + +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.map.AnnotationIntrospector; +import org.codehaus.jackson.map.ObjectMapper; +import org.codehaus.jackson.map.SerializationConfig; +import org.codehaus.jackson.map.introspect.AnnotatedClass; +import org.codehaus.jackson.xc.JaxbAnnotationIntrospector; + +/** + * Tests for verifying that JAXB annotation based introspector + * implementation works as expected + * + * @author Ryan Heaton + * @author Tatu Saloranta + */ +public class TestJaxbAnnotationIntrospector + extends BaseJaxbTest +{ + /* + /**************************************************** + /* Helper beans + /**************************************************** + */ + + public static enum EnumExample { + + @XmlEnumValue("Value One") + VALUE1 + } + + public static class JaxbExample + { + + private String attributeProperty; + private String elementProperty; + private List<String> wrappedElementProperty; + private EnumExample enumProperty; + private QName qname; + private QName qname1; + private String propertyToIgnore; + + @XmlJavaTypeAdapter(QNameAdapter.class) + public QName getQname() + { + return qname; + } + + public void setQname(QName qname) + { + this.qname = qname; + } + + public QName getQname1() + { + return qname1; + } + + public void setQname1(QName qname1) + { + this.qname1 = qname1; + } + + @XmlAttribute(name="myattribute") + public String getAttributeProperty() + { + return attributeProperty; + } + + public void setAttributeProperty(String attributeProperty) + { + this.attributeProperty = attributeProperty; + } + + @XmlElement(name="myelement") + public String getElementProperty() + { + return elementProperty; + } + + public void setElementProperty(String elementProperty) + { + this.elementProperty = elementProperty; + } + + @XmlElementWrapper(name="mywrapped") + public List<String> getWrappedElementProperty() + { + return wrappedElementProperty; + } + + public void setWrappedElementProperty(List<String> wrappedElementProperty) + { + this.wrappedElementProperty = wrappedElementProperty; + } + + public EnumExample getEnumProperty() + { + return enumProperty; + } + + public void setEnumProperty(EnumExample enumProperty) + { + this.enumProperty = enumProperty; + } + + @XmlTransient + public String getPropertyToIgnore() + { + return propertyToIgnore; + } + + public void setPropertyToIgnore(String propertyToIgnore) + { + this.propertyToIgnore = propertyToIgnore; + } + } + + public static class QNameAdapter extends XmlAdapter<String, QName> { + + @Override + public QName unmarshal(String v) throws Exception + { + return QName.valueOf(v); + } + + @Override + public String marshal(QName v) throws Exception + { + return (v == null) ? null : v.toString(); + } + } + + @XmlAccessorType(XmlAccessType.PUBLIC_MEMBER) + public static class SimpleBean + { + @XmlElement + protected String jaxb = "1"; + + @XmlElement + protected String jaxb2 = "2"; + + @SuppressWarnings("unused") + @XmlElement(name="jaxb3") + private String oddName = "3"; + + public String notAGetter() { return "xyz"; } + + @XmlTransient + public int foobar = 3; + } + + @SuppressWarnings("unused") + @XmlAccessorType(XmlAccessType.FIELD) + public static class SimpleBean2 { + + protected String jaxb = "1"; + private String jaxb2 = "2"; + @XmlElement(name="jaxb3") + private String oddName = "3"; + + } + + @XmlAccessorType(XmlAccessType.PUBLIC_MEMBER) + @XmlRootElement(namespace="urn:class") + static class NamespaceBean + { + @XmlElement(namespace="urn:method") + public String string; + } + + @XmlRootElement(name="test") + static class RootNameBean { } + + @XmlAccessorOrder(XmlAccessOrder.ALPHABETICAL) + public static class AlphaBean + { + public int c = 3; + public int a = 1; + public int b = 2; + } + + public static class KeyValuePair { + private String key; + private String value; + public KeyValuePair() {} + public String getKey() { + return key; + } + public void setKey(String key) { + this.key = key; + } + public String getValue() { + return value; + } + public void setValue(String value) { + this.value = value; + }; + } + + public static class JAXBMapAdapter extends XmlAdapter<List<KeyValuePair>,Map<String, String>> { + + @Override + public List<KeyValuePair> marshal(Map<String, String> arg0) throws Exception { + List<KeyValuePair> keyValueList = new ArrayList<KeyValuePair>(); + for(Entry<String, String> entry : arg0.entrySet()) { + KeyValuePair keyValuePair = new KeyValuePair(); + keyValuePair.setKey(entry.getKey()); + keyValuePair.setValue(entry.getValue()); + keyValueList.add(keyValuePair); + } + return keyValueList; + } + @Override + public Map<String, String> unmarshal(List<KeyValuePair> arg0) throws Exception + { + HashMap<String, String> hashMap = new HashMap<String, String>(); + for (int i = 0; i < arg0.size(); i++) { + hashMap.put(arg0.get(i).getKey(), arg0.get(i).getValue()); + } + return hashMap; + } + } + + @XmlRootElement + @XmlAccessorType(XmlAccessType.FIELD) + public static class ParentJAXBBean + { + @XmlJavaTypeAdapter(JAXBMapAdapter.class) + private Map<String, String> params = new HashMap<String, String>(); + + public Map<String, String> getParams() { + return params; + } + + public void setParams(Map<String, String> params) { + this.params = params; + } + + } + + // Beans for [JACKSON-256] + + @XmlRootElement + static class BeanWithNillable { + public Nillable X; + } + + @XmlRootElement + static class Nillable { + @XmlElement (name="Z", nillable=true) + Integer Z; + } + + /* + /**************************************************** + /* Unit tests + /**************************************************** + */ + + public void testDetection() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.setAnnotationIntrospector(new JaxbAnnotationIntrospector()); + + Map<String,Object> result = writeAndMap(mapper, new SimpleBean()); + assertEquals(3, result.size()); + assertEquals("1", result.get("jaxb")); + assertEquals("2", result.get("jaxb2")); + assertEquals("3", result.get("jaxb3")); + + result = writeAndMap(mapper, new SimpleBean2()); + assertEquals(3, result.size()); + assertEquals("1", result.get("jaxb")); + assertEquals("2", result.get("jaxb2")); + assertEquals("3", result.get("jaxb3")); + } + + /** + * tests getting serializer/deserializer instances. + */ + public void testSerializeDeserializeWithJaxbAnnotations() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.setAnnotationIntrospector(new JaxbAnnotationIntrospector()); + mapper.enable(SerializationConfig.Feature.INDENT_OUTPUT); + JaxbExample ex = new JaxbExample(); + QName qname = new QName("urn:hi", "hello"); + ex.setQname(qname); + QName qname1 = new QName("urn:hi", "hello1"); + ex.setQname1(qname1); + ex.setAttributeProperty("attributeValue"); + ex.setElementProperty("elementValue"); + ex.setWrappedElementProperty(Arrays.asList("wrappedElementValue")); + ex.setEnumProperty(EnumExample.VALUE1); + ex.setPropertyToIgnore("ignored"); + StringWriter writer = new StringWriter(); + mapper.writeValue(writer, ex); + writer.flush(); + writer.close(); + + String json = writer.toString(); + + // uncomment to see what the json looks like. + // System.out.println(json); + + //make sure the json is written out correctly. + JsonNode node = mapper.readValue(json, JsonNode.class); + assertEquals(qname.toString(), node.get("qname").asText()); + JsonNode attr = node.get("myattribute"); + assertNotNull(attr); + assertEquals("attributeValue", attr.asText()); + assertEquals("elementValue", node.get("myelement").asText()); + assertEquals(1, node.get("mywrapped").size()); + assertEquals("wrappedElementValue", node.get("mywrapped").get(0).asText()); + assertEquals("Value One", node.get("enumProperty").asText()); + assertNull(node.get("propertyToIgnore")); + + //now make sure it gets deserialized correctly. + JaxbExample readEx = mapper.readValue(json, JaxbExample.class); + assertEquals(ex.qname, readEx.qname); + assertEquals(ex.qname1, readEx.qname1); + assertEquals(ex.attributeProperty, readEx.attributeProperty); + assertEquals(ex.elementProperty, readEx.elementProperty); + assertEquals(ex.wrappedElementProperty, readEx.wrappedElementProperty); + assertEquals(ex.enumProperty, readEx.enumProperty); + assertNull(readEx.propertyToIgnore); + } + + public void testRootNameAccess() throws Exception + { + AnnotationIntrospector ai = new JaxbAnnotationIntrospector(); + // If no @XmlRootElement, should get null (unless pkg has etc) + assertNull(ai.findRootName(AnnotatedClass.construct(SimpleBean.class, ai, null))); + // With @XmlRootElement, but no name, empty String + assertEquals("", ai.findRootName(AnnotatedClass.construct(NamespaceBean.class, ai, null))); + // and otherwise explicit name + assertEquals("test", ai.findRootName(AnnotatedClass.construct(RootNameBean.class, ai, null))); + } + + // JAXB can specify that properties are to be written in alphabetic order... + public void testSerializationAlphaOrdering() throws Exception + { + ObjectMapper mapper = getJaxbMapper(); + assertEquals("{\"a\":1,\"b\":2,\"c\":3}", serializeAsString(mapper, new AlphaBean())); + } + + // Test for [JACKSON-256], thanks John. + // @since 1.5 + public void testWriteNulls() throws Exception + { + ObjectMapper mapper = getJaxbMapper(); + BeanWithNillable bean = new BeanWithNillable(); + bean.X = new Nillable(); + assertEquals("{\"X\":{\"Z\":null}}", serializeAsString(mapper, bean)); + } + + public void testAdapter() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.setAnnotationIntrospector(new JaxbAnnotationIntrospector()); + mapper.setAnnotationIntrospector(new JaxbAnnotationIntrospector()); + mapper.enable(SerializationConfig.Feature.INDENT_OUTPUT); + ParentJAXBBean parentJaxbBean = new ParentJAXBBean(); + HashMap<String, String> params = new HashMap<String, String>(); + params.put("sampleKey", "sampleValue"); + parentJaxbBean.setParams(params); + + StringWriter writer = new StringWriter(); + mapper.writeValue(writer, parentJaxbBean); + writer.flush(); + writer.close(); + + String json = writer.toString(); + + // uncomment to see what the json looks like. + //System.out.println(json); + + //now make sure it gets deserialized correctly. + ParentJAXBBean readEx = mapper.readValue(json, ParentJAXBBean.class); + assertEquals("sampleValue", readEx.getParams().get("sampleKey")); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/jaxb/TestJaxbAutoDetect.java b/1.9.10/src/test/org/codehaus/jackson/jaxb/TestJaxbAutoDetect.java new file mode 100644 index 0000000..3e37a13 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/jaxb/TestJaxbAutoDetect.java
@@ -0,0 +1,155 @@ +package org.codehaus.jackson.jaxb; + +import java.io.*; +import java.math.BigDecimal; +import java.util.Map; + +import javax.xml.bind.annotation.*; + +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.introspect.JacksonAnnotationIntrospector; +import org.codehaus.jackson.xc.JaxbAnnotationIntrospector; + +/** + * Tests for verifying auto-detection settings with JAXB annotations. + * + * @author Tatu Saloranta + */ +public class TestJaxbAutoDetect + extends org.codehaus.jackson.map.BaseMapTest +{ + /* + /********************************************************** + /* Helper beans + /********************************************************** + */ + + /* Bean for testing problem [JACKSON-183]: with normal + * auto-detect enabled, 2 fields visible; if disabled, just 1. + * NOTE: should NOT include "XmlAccessorType", since it will + * have priority over global defaults + */ + static class Jackson183Bean { + public String getA() { return "a"; } + + @XmlElement public String getB() { return "b"; } + + // JAXB (or Bean introspection) mandates use of matching setters... + public void setA(String str) { } + public void setB(String str) { } + } + + static class Identified + { + Object id; + + @XmlAttribute(name="id") + public Object getIdObject() { + return id; + } + public void setId(Object id) { this.id = id; } + } + + @XmlRootElement(name="bah") + public static class JaxbAnnotatedObject { + + private BigDecimal number; + + public JaxbAnnotatedObject() { } + + public JaxbAnnotatedObject(String number) { + this.number = new BigDecimal(number); + } + + @XmlElement + public void setNumber(BigDecimal number) { + this.number = number; + } + + @XmlTransient + public BigDecimal getNumber() { + return number; + } + + @XmlElement(name = "number") + public BigDecimal getNumberString() { + return number; + } + } + + public static class DualAnnotationObjectMapper extends ObjectMapper { + + public DualAnnotationObjectMapper() { + super(); + AnnotationIntrospector primary = new JaxbAnnotationIntrospector(); + AnnotationIntrospector secondary = new JacksonAnnotationIntrospector(); + + // make de/serializer use JAXB annotations first, then jackson ones + AnnotationIntrospector pair = new AnnotationIntrospector.Pair(primary, secondary); + setAnnotationIntrospector(pair); + } + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + public void testAutoDetectDisable() throws IOException + { + ObjectMapper mapper = new ObjectMapper(); + mapper.setAnnotationIntrospector(new JaxbAnnotationIntrospector()); + Jackson183Bean bean = new Jackson183Bean(); + Map<String,Object> result; + + // Ok: by default, should see 2 fields: + result = writeAndMap(mapper, bean); + assertEquals(2, result.size()); + assertEquals("a", result.get("a")); + assertEquals("b", result.get("b")); + + // But when disabling auto-detection, just one + mapper = new ObjectMapper(); + mapper.setAnnotationIntrospector(new JaxbAnnotationIntrospector()); + mapper.configure(SerializationConfig.Feature.AUTO_DETECT_GETTERS, false); + result = writeAndMap(mapper, bean); + assertEquals(1, result.size()); + assertNull(result.get("a")); + assertEquals("b", result.get("b")); + } + + // @since 1.5 + public void testIssue246() throws IOException + { + ObjectMapper mapper = new ObjectMapper(); + mapper.setAnnotationIntrospector(new JaxbAnnotationIntrospector()); + Identified id = new Identified(); + id.id = "123"; + assertEquals("{\"id\":\"123\"}", mapper.writeValueAsString(id)); + } + + // [JACKSON-556] + public void testJaxbAnnotatedObject() throws Exception + { + JaxbAnnotatedObject original = new JaxbAnnotatedObject("123"); + ObjectMapper mapper = new DualAnnotationObjectMapper(); + String json = mapper.writeValueAsString(original); + assertFalse("numberString field in JSON", json.contains("numberString")); // kinda hack-y :) + JaxbAnnotatedObject result = mapper.readValue(json, JaxbAnnotatedObject.class); + assertEquals(new BigDecimal("123"), result.number); + } + + /* + public void testJaxbAnnotatedObjectXML() throws Exception + { + JAXBContext ctxt = JAXBContext.newInstance(JaxbAnnotatedObject.class); + JaxbAnnotatedObject original = new JaxbAnnotatedObject("123"); + StringWriter sw = new StringWriter(); + ctxt.createMarshaller().marshal(original, sw); + String xml = sw.toString(); + JaxbAnnotatedObject result = (JaxbAnnotatedObject) ctxt.createUnmarshaller().unmarshal(new StringReader(xml)); + assertEquals(new BigDecimal("123"), result.number); + } + */ +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/jaxb/TestJaxbFieldAccess.java b/1.9.10/src/test/org/codehaus/jackson/jaxb/TestJaxbFieldAccess.java new file mode 100644 index 0000000..5f0f503 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/jaxb/TestJaxbFieldAccess.java
@@ -0,0 +1,49 @@ +package org.codehaus.jackson.jaxb; + +import java.io.IOException; + +import javax.xml.bind.annotation.*; + +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.xc.JaxbAnnotationIntrospector; + +public class TestJaxbFieldAccess + extends org.codehaus.jackson.map.BaseMapTest +{ + /* + /********************************************************** + /* Helper beans + /********************************************************** + */ + + @XmlAccessorType(XmlAccessType.FIELD) + static class Fields { + protected int x; + + public Fields() { } + Fields(int x) { this.x = x; } + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + // Verify serialization wrt [JACKSON-202] + public void testFieldSerialization() throws IOException + { + ObjectMapper mapper = new ObjectMapper(); + mapper.setAnnotationIntrospector(new JaxbAnnotationIntrospector()); + assertEquals("{\"x\":3}", serializeAsString(mapper, new Fields(3))); + } + + // Verify deserialization wrt [JACKSON-202] + public void testFieldDeserialization() throws IOException + { + ObjectMapper mapper = new ObjectMapper(); + mapper.setAnnotationIntrospector(new JaxbAnnotationIntrospector()); + Fields result = mapper.readValue("{ \"x\":3 }", Fields.class); + assertEquals(3, result.x); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/jaxb/TestJaxbNullProperties.java b/1.9.10/src/test/org/codehaus/jackson/jaxb/TestJaxbNullProperties.java new file mode 100644 index 0000000..cd8eefb --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/jaxb/TestJaxbNullProperties.java
@@ -0,0 +1,40 @@ +package org.codehaus.jackson.jaxb; + +import org.codehaus.jackson.map.ObjectMapper; +import org.codehaus.jackson.map.annotate.JsonSerialize; + +/** + * Unit tests to ensure that handling of writing of null properties (or not) + * works when using JAXB annotation introspector. + * Mostly to test out [JACKSON-309]. + */ +public class TestJaxbNullProperties + extends BaseJaxbTest +{ + /* + /********************************************************** + /* Helper beans + /********************************************************** + */ + + public static class Bean + { + public String empty; + + public String x = "y"; + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + // Testing [JACKSON-309] + public void testNullProps() throws Exception + { + ObjectMapper mapper = getJaxbMapper(); + mapper.setSerializationInclusion(JsonSerialize.Inclusion.NON_NULL); + assertEquals("{\"x\":\"y\"}", mapper.writeValueAsString(new Bean())); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/jaxb/TestJaxbPolymorphic.java b/1.9.10/src/test/org/codehaus/jackson/jaxb/TestJaxbPolymorphic.java new file mode 100644 index 0000000..6708a21 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/jaxb/TestJaxbPolymorphic.java
@@ -0,0 +1,189 @@ +package org.codehaus.jackson.jaxb; + +import java.util.*; +import javax.xml.bind.annotation.*; + +import org.codehaus.jackson.map.ObjectMapper; + +/** + * Tests for handling of type-related JAXB annotations + * + * @since 1.5 + * + * @author Tatu Saloranta + * @author Ryan Heaton + */ +public class TestJaxbPolymorphic + extends BaseJaxbTest +{ + /* + /********************************************************** + /* Helper beans + /********************************************************** + */ + + static class Bean + { + @XmlElements({ + @XmlElement(type=Buffalo.class, name="beefalot"), + @XmlElement(type=Whale.class, name="whale") + }) + public Animal animal; + + @XmlElementRefs({ + @XmlElementRef(type=Emu.class), + @XmlElementRef(type=Cow.class) + }) + public Animal other; + + public Bean() { } + public Bean(Animal a) { animal = a; } + } + + static class ArrayBean + { + @XmlElements({ + @XmlElement(type=Buffalo.class, name="b"), + @XmlElement(type=Whale.class, name="w") + }) + public Animal[] animals; + + @XmlElementRefs({ + @XmlElementRef(type=Emu.class), + @XmlElementRef(type=Cow.class) + }) + public Animal[] otherAnimals; + + public ArrayBean() { } + public ArrayBean(Animal... a) { + animals = a; + } + } + + static abstract class Animal { + public String nickname; + + protected Animal(String n) { nickname = n; } + } + + static class Buffalo extends Animal { + public String hairColor; + + public Buffalo() { this(null, null); } + public Buffalo(String name, String hc) { + super(name); + hairColor = hc; + } + } + + static class Whale extends Animal { + public int weightInTons; + public Whale() { this(null, 0); } + public Whale(String n, int w) { + super(n); + weightInTons = w; + } + } + + @XmlRootElement + static class Emu extends Animal { + public String featherColor; + public Emu() { this(null, null); } + public Emu(String n, String w) { + super(n); + featherColor = w; + } + } + + @XmlRootElement (name="moo") + static class Cow extends Animal { + public int weightInPounds; + public Cow() { this(null, 0); } + public Cow(String n, int w) { + super(n); + weightInPounds = w; + } + } + + /* + /********************************************************** + /* Test methods + /********************************************************** + */ + + /** + * First a simple test with non-collection field + */ + @SuppressWarnings("unchecked") + public void testSinglePolymorphic() throws Exception + { + ObjectMapper mapper = getJaxbMapper(); + Bean input = new Bean(new Buffalo("Billy", "brown")); + String str = mapper.writeValueAsString(input); + // First: let's verify output looks like what we expect: + Map<String,Object> map = mapper.readValue(str, Map.class); + assertEquals(2, map.size()); + Map<String,Object> map2 = (Map<String,Object>) map.get("animal"); + assertNotNull(map2); + // second level, should have type info as WRAPPER_OBJECT + assertEquals(1, map2.size()); + assertTrue(map2.containsKey("beefalot")); + Map<String,Object> map3 = (Map<String,Object>) map2.get("beefalot"); + assertEquals(2, map3.size()); + // good enough, let's deserialize + + Bean result = mapper.readValue(str, Bean.class); + Animal a = result.animal; + assertNotNull(a); + assertEquals(Buffalo.class, a.getClass()); + assertEquals("Billy", a.nickname); + assertEquals("brown", ((Buffalo) a).hairColor); + } + + public void testPolymorphicArray() throws Exception + { + ObjectMapper mapper = getJaxbMapper(); + Animal a1 = new Buffalo("Bill", "grey"); + Animal a2 = new Whale("moe", 3000); + ArrayBean input = new ArrayBean(a1, null, a2); + String str = mapper.writeValueAsString(input); + ArrayBean result = mapper.readValue(str, ArrayBean.class); + assertEquals(3, result.animals.length); + a1 = result.animals[0]; + assertNull(result.animals[1]); + a2 = result.animals[2]; + assertNotNull(a1); + assertNotNull(a2); + assertEquals(Buffalo.class, a1.getClass()); + assertEquals(Whale.class, a2.getClass()); + assertEquals("Bill", a1.nickname); + assertEquals("grey", ((Buffalo) a1).hairColor); + + assertEquals("moe", a2.nickname); + assertEquals(3000, ((Whale)a2).weightInTons); + } + + public void testPolymorphicArrayElementRef() throws Exception + { + ObjectMapper mapper = getJaxbMapper(); + Animal a1 = new Emu("Bill", "grey"); + Animal a2 = new Cow("moe", 3000); + ArrayBean input = new ArrayBean(); + input.otherAnimals = new Animal[]{a1, null, a2}; + String str = mapper.writeValueAsString(input); + ArrayBean result = mapper.readValue(str, ArrayBean.class); + assertEquals(3, result.otherAnimals.length); + a1 = result.otherAnimals[0]; + assertNull(result.otherAnimals[1]); + a2 = result.otherAnimals[2]; + assertNotNull(a1); + assertNotNull(a2); + assertEquals(Emu.class, a1.getClass()); + assertEquals(Cow.class, a2.getClass()); + assertEquals("Bill", a1.nickname); + assertEquals("grey", ((Emu) a1).featherColor); + + assertEquals("moe", a2.nickname); + assertEquals(3000, ((Cow)a2).weightInPounds); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/jaxb/TestJaxbPolymorphicLists.java b/1.9.10/src/test/org/codehaus/jackson/jaxb/TestJaxbPolymorphicLists.java new file mode 100644 index 0000000..d334d1a --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/jaxb/TestJaxbPolymorphicLists.java
@@ -0,0 +1,130 @@ +package org.codehaus.jackson.jaxb; + +import java.util.*; + +import javax.xml.bind.annotation.*; + +import org.codehaus.jackson.jaxb.TestJaxbPolymorphic.Animal; +import org.codehaus.jackson.jaxb.TestJaxbPolymorphic.Buffalo; +import org.codehaus.jackson.jaxb.TestJaxbPolymorphic.Cow; +import org.codehaus.jackson.jaxb.TestJaxbPolymorphic.Emu; +import org.codehaus.jackson.jaxb.TestJaxbPolymorphic.Whale; +import org.codehaus.jackson.map.ObjectMapper; + +/** + * Tests for handling of type-related JAXB annotations with collection (List) + * types. + * + * @since 1.5 + */ +public class TestJaxbPolymorphicLists + extends BaseJaxbTest +{ + /* + /********************************************************** + /* Helper beans + /********************************************************** + */ + + static class ListBean + { + @XmlElements({ + @XmlElement(type=Buffalo.class, name="beefalot"), + @XmlElement(type=Whale.class, name="whale") + }) + public List<Animal> animals; + + @XmlElementRefs({ + @XmlElementRef(type=Emu.class), + @XmlElementRef(type=Cow.class) + }) + public List<Animal> otherAnimals; + + public ListBean() { } + public ListBean(Animal... a) { + animals = new ArrayList<Animal>(); + for (Animal an : a) { + animals.add(an); + } + } + } + + static class Leopard extends Animal { + public Leopard() { super("Lez"); } + } + + static class ShortListHolder { + @XmlElement(name="id", type=Short.class) + public List<Short> ids; + } + + /* + /********************************************************** + /* Tests + /********************************************************** + */ + + /** + * And then a test for collection types + */ + public void testPolymorphicList() throws Exception + { + ObjectMapper mapper = getJaxbMapper(); + ListBean input = new ListBean(new Whale("bluey", 150), + new Buffalo("Bob", "black") + ); + String str = mapper.writeValueAsString(input); + // Let's assume it's ok, and try deserialize right away: + ListBean result = mapper.readValue(str, ListBean.class); + assertEquals(2, result.animals.size()); + Animal a1 = result.animals.get(0); + assertNotNull(a1); + assertEquals(Whale.class, a1.getClass()); + assertEquals("bluey", a1.nickname); + assertEquals(150, ((Whale)a1).weightInTons); + Animal a2 = result.animals.get(1); + assertNotNull(a2); + assertEquals(Buffalo.class, a2.getClass()); + assertEquals("Bob", a2.nickname); + assertEquals("black", ((Buffalo) a2).hairColor); + } + + /** + * And then a test for collection types using element ref(s) + */ + public void testPolymorphicListElementRef() throws Exception + { + ObjectMapper mapper = getJaxbMapper(); + ListBean input = new ListBean(); + input.otherAnimals = Arrays.asList( + new Cow("bluey", 150), + new Emu("Bob", "black") + ); + String str = mapper.writeValueAsString(input); + // Let's assume it's ok, and try deserialize right away: + ListBean result = mapper.readValue(str, ListBean.class); + assertEquals(2, result.otherAnimals.size()); + Animal a1 = result.otherAnimals.get(0); + assertNotNull(a1); + assertEquals(Cow.class, a1.getClass()); + assertEquals("bluey", a1.nickname); + assertEquals(150, ((Cow)a1).weightInPounds); + Animal a2 = result.otherAnimals.get(1); + assertNotNull(a2); + assertEquals(Emu.class, a2.getClass()); + assertEquals("Bob", a2.nickname); + assertEquals("black", ((Emu) a2).featherColor); + } + + // [JACKSON-348] + public void testShortList() throws Exception + { + ShortListHolder holder = getJaxbMapper().readValue("{\"id\":[1,2,3]}", + ShortListHolder.class); + assertNotNull(holder.ids); + assertEquals(3, holder.ids.size()); + assertSame(Short.valueOf((short)1), holder.ids.get(0)); + assertSame(Short.valueOf((short)2), holder.ids.get(1)); + assertSame(Short.valueOf((short)3), holder.ids.get(2)); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/jaxb/TestJaxbPolymorphicMaps.java b/1.9.10/src/test/org/codehaus/jackson/jaxb/TestJaxbPolymorphicMaps.java new file mode 100644 index 0000000..e4e70f9 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/jaxb/TestJaxbPolymorphicMaps.java
@@ -0,0 +1,98 @@ +package org.codehaus.jackson.jaxb; + +import java.util.*; + +import javax.xml.bind.annotation.*; + +import org.codehaus.jackson.jaxb.TestJaxbPolymorphic.Animal; +import org.codehaus.jackson.jaxb.TestJaxbPolymorphic.Buffalo; +import org.codehaus.jackson.jaxb.TestJaxbPolymorphic.Cow; +import org.codehaus.jackson.jaxb.TestJaxbPolymorphic.Emu; +import org.codehaus.jackson.jaxb.TestJaxbPolymorphic.Whale; +import org.codehaus.jackson.map.ObjectMapper; + +/** + * Tests for handling of type-related JAXB annotations + * + * @since 1.5 + */ +public class TestJaxbPolymorphicMaps + extends BaseJaxbTest +{ + /* + /********************************************************** + /* Helper beans + /********************************************************** + */ + + static class MapBean + { + @XmlElements({ + @XmlElement(type=Buffalo.class, name="beefalot"), + @XmlElement(type=Whale.class, name="whale") + }) + public Map<Integer,Animal> animals; + + @XmlElementRefs({ + @XmlElementRef(type=Emu.class), + @XmlElementRef(type=Cow.class) + }) + public Map<Integer,Animal> otherAnimals; + + public MapBean() { + animals = new HashMap<Integer,Animal>(); + otherAnimals = new HashMap<Integer,Animal>(); + } + + public void add(Integer key, Animal value) { animals.put(key, value); } + public void addOther(Integer key, Animal value) { otherAnimals.put(key, value); } + } + + /* + /********************************************************** + /* Tests + /********************************************************** + */ + + public void testPolymorphicMap() throws Exception + { + ObjectMapper mapper = getJaxbMapper(); + Animal a = new Whale("Jaska", 3000); + Animal b = new Whale("Arska", 2000); + Animal c = new Whale("Pena", 1500); + MapBean input = new MapBean(); + input.add(1, a); + input.add(2, b); + input.add(3, c); + String str = mapper.writeValueAsString(input); + + MapBean result = mapper.readValue(str, MapBean.class); + Map<Integer,Animal> map = result.animals; + assertEquals(3, map.size()); + assertEquals("Jaska", ((Whale) map.get(Integer.valueOf(1))).nickname); + assertEquals("Arska", ((Whale) map.get(Integer.valueOf(2))).nickname); + assertEquals("Pena", ((Whale) map.get(Integer.valueOf(3))).nickname); + } + + /* + public void testPolymorphicMapElementRefs() throws Exception + { + ObjectMapper mapper = getJaxbMapper(); + Animal a = new Cow("Jaska", 3000); + Animal b = new Cow("Arska", 2000); + Animal c = new Cow("Pena", 1500); + MapBean input = new MapBean(); + input.addOther(1, a); + input.addOther(2, b); + input.addOther(3, c); + String str = mapper.writeValueAsString(input); + + MapBean result = mapper.readValue(str, MapBean.class); + Map<Integer,Animal> map = result.otherAnimals; + assertEquals(3, map.size()); + assertEquals("Jaska", ((Cow) map.get(Integer.valueOf(1))).nickname); + assertEquals("Arska", ((Cow) map.get(Integer.valueOf(2))).nickname); + assertEquals("Pena", ((Cow) map.get(Integer.valueOf(3))).nickname); + } + */ +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/jaxb/TestJaxbTypeCoercion.java b/1.9.10/src/test/org/codehaus/jackson/jaxb/TestJaxbTypeCoercion.java new file mode 100644 index 0000000..4d0b239 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/jaxb/TestJaxbTypeCoercion.java
@@ -0,0 +1,47 @@ +package org.codehaus.jackson.jaxb; + +import javax.xml.bind.annotation.XmlElement; + +import org.codehaus.jackson.map.ObjectMapper; + +public class TestJaxbTypeCoercion extends BaseJaxbTest +{ + /* + /********************************************************** + /* Helper beans + /********************************************************** + */ + + /** + * Unit test related to [JACKSON-416] + */ + static class Jackson416Bean + { + @XmlElement(type=Jackson416Base.class) + public Jackson416Base value = new Jackson416Sub(); + } + + static class Jackson416Base + { + public String foo = "foo"; + } + + static class Jackson416Sub extends Jackson416Base + { + public String bar = "bar"; + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + public void testIssue416() throws Exception + { + ObjectMapper mapper = getJaxbAndJacksonMapper(); + Jackson416Bean bean = new Jackson416Bean(); + String json = mapper.writeValueAsString(bean); + assertEquals("{\"value\":{\"foo\":\"foo\"}}", json); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/jaxb/TestJaxbTypes.java b/1.9.10/src/test/org/codehaus/jackson/jaxb/TestJaxbTypes.java new file mode 100644 index 0000000..d67f4d8 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/jaxb/TestJaxbTypes.java
@@ -0,0 +1,235 @@ +package org.codehaus.jackson.jaxb; + +import java.util.*; + +import javax.xml.bind.annotation.*; + +import org.codehaus.jackson.annotate.*; +import org.codehaus.jackson.map.*; + +/** + * Tests for handling of type-related JAXB annotations + */ +public class TestJaxbTypes + extends BaseJaxbTest +{ + /* + /********************************************************** + /* Helper beans + /********************************************************** + */ + + static class AbstractWrapper { + @XmlElement(type=BeanImpl.class) + public AbstractBean wrapped; + + public AbstractWrapper() { this(null); } + public AbstractWrapper(AbstractBean bean) { wrapped = bean; } + } + + interface AbstractBean { } + + static class BeanImpl + implements AbstractBean + { + public int a; + protected String b; + + public BeanImpl() { this(0, null); } + public BeanImpl(int a, String b) { + this.a = a; + this.b = b; + } + + public String getB() { return b; } + public void setB(String b) { this.b = b; } + } + + static class ListBean { + /* Note: here we rely on implicit linking between the field + * and accessors. + */ + @XmlElement(type=BeanImpl.class) + private List<AbstractBean> beans; + + public ListBean() { } + public ListBean(AbstractBean ... beans) { + this.beans = Arrays.asList(beans); + } + public ListBean(List<AbstractBean> beans) { + this.beans = beans; + } + + public List<AbstractBean> getBeans() { return beans; } + public void setBeans(List<AbstractBean> b) { beans = b; } + + public int size() { return beans.size(); } + public BeanImpl get(int index) { return (BeanImpl) beans.get(index); } + } + + /* And then mix'n match, to try end-to-end + */ + static class ComboBean + { + private AbstractBean bean; + + public ListBean beans; + + public ComboBean() { } + public ComboBean(AbstractBean bean, ListBean beans) + { + this.bean = bean; + this.beans = beans; + } + + @XmlElement(type=BeanImpl.class) + public AbstractBean getBean() { return bean; } + public void setBean(AbstractBean bean) { this.bean = bean; } + } + + /** + * Unit test for [JACKSON-250] + */ + @JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include= JsonTypeInfo.As.PROPERTY) + @JsonTypeName("Name") + @XmlType + static class P2 + { + String id; + public P2(String id) { this.id = id; } + public P2() { } + + @XmlID + @XmlAttribute(name="id") + public String getId() { return id; } + + public void setId(String id) { this.id = id; } + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + public void testXmlElementTypeDeser() throws Exception + { + ObjectMapper mapper = getJaxbMapper(); + AbstractWrapper wrapper = mapper.readValue("{\"wrapped\":{\"a\":13,\"b\":\"...\"}}", AbstractWrapper.class); + assertNotNull(wrapper); + BeanImpl bean = (BeanImpl) wrapper.wrapped; + assertEquals(13, bean.a); + assertEquals("...", bean.b); + } + + public void testXmlElementTypeSer() throws Exception + { + ObjectMapper mapper = getJaxbMapper(); + AbstractWrapper wrapper = new AbstractWrapper(new BeanImpl(-3, "c")); + assertEquals("{\"wrapped\":{\"a\":-3,\"b\":\"c\"}}", + mapper.writeValueAsString(wrapper)); + } + + public void testXmlElementListTypeDeser() throws Exception + { + ObjectMapper mapper = getJaxbMapper(); + ListBean listBean = mapper.readValue + ("{\"beans\": [{\"a\":1,\"b\":\"a\"}, {\"a\":7,\"b\":\"b\" }]}", + ListBean.class); + assertNotNull(listBean); + List<AbstractBean> beans = listBean.beans; + assertNotNull(beans); + assertEquals(2, beans.size()); + assertNotNull(beans.get(0)); + assertNotNull(beans.get(1)); + + BeanImpl bean = (BeanImpl) beans.get(0); + assertEquals(1, bean.a); + assertEquals("a", bean.b); + + bean = (BeanImpl) beans.get(1); + assertEquals(7, bean.a); + assertEquals("b", bean.b); + } + + public void testXmlElementListArrayDeser() throws Exception + { + ObjectMapper mapper = getJaxbMapper(); + ListBean[] listBeans = mapper.readValue + ("[{\"beans\": [{\"a\":1,\"b\":\"a\"}, {\"a\":7,\"b\":\"b\" }]}]", + ListBean[].class); + assertNotNull(listBeans); + assertEquals(1, listBeans.length); + List<AbstractBean> beans = listBeans[0].beans; + assertNotNull(beans); + assertEquals(2, beans.size()); + BeanImpl bean = (BeanImpl) beans.get(0); + assertEquals(1, bean.a); + assertEquals("a", bean.b); + bean = (BeanImpl) beans.get(1); + assertEquals(7, bean.a); + assertEquals("b", bean.b); + } + + public void testXmlElementListTypeSer() throws Exception + { + ObjectMapper mapper = getJaxbMapper(); + ListBean bean = new ListBean(); + List<AbstractBean> beans = new ArrayList<AbstractBean>(); + beans.add(new BeanImpl(1, "a")); + beans.add(new BeanImpl(2, "b")); + bean.beans = beans; + + assertEquals("{\"beans\":[{\"a\":1,\"b\":\"a\"},{\"a\":2,\"b\":\"b\"}]}", + mapper.writeValueAsString(bean)); + } + + public void testRoundTrip() throws Exception + { + ComboBean input = new ComboBean(new BeanImpl(3, "abc"), + new ListBean(new BeanImpl(1, "a"), + new BeanImpl(2, "b"), + new BeanImpl(3, "c"))); + ObjectMapper mapper = getJaxbMapper(); + String str = mapper.writeValueAsString(input); + + ComboBean result = mapper.readValue(str, ComboBean.class); + + assertEquals(3, ((BeanImpl)result.bean).a); + assertEquals("abc", ((BeanImpl)result.bean).b); + + assertEquals(3, result.beans.size()); + assertEquals(1, (result.beans.get(0)).a); + assertEquals("a", (result.beans.get(0)).b); + assertEquals(2, (result.beans.get(1)).a); + assertEquals("b", (result.beans.get(1)).b); + assertEquals(3, (result.beans.get(2)).a); + assertEquals("c", (result.beans.get(2)).b); + } + + public void testListWithDefaultTyping() throws Exception + { + Object input = new ListBean(new BeanImpl(1, "a")); + ObjectMapper mapper = getJaxbMapper(); + mapper.enableDefaultTyping(); + String str = mapper.writeValueAsString(input); + + ListBean listBean = mapper.readValue(str, ListBean.class); + assertNotNull(listBean); + List<AbstractBean> beans = listBean.beans; + assertNotNull(beans); + assertEquals(1, beans.size()); + assertNotNull(beans.get(0)); + BeanImpl bean = (BeanImpl) beans.get(0); + assertEquals(1, bean.a); + assertEquals("a", bean.b); + } + + public void testIssue250() throws Exception + { + ObjectMapper mapper = getJaxbAndJacksonMapper(); + P2 bean = new P2("myId"); + String str = mapper.writeValueAsString(bean); + assertEquals("{\"@type\":\"Name\",\"id\":\"myId\"}", str); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/jaxb/TestPropertyOrdering.java b/1.9.10/src/test/org/codehaus/jackson/jaxb/TestPropertyOrdering.java new file mode 100644 index 0000000..29f5995 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/jaxb/TestPropertyOrdering.java
@@ -0,0 +1,88 @@ +package org.codehaus.jackson.jaxb; + +import javax.xml.bind.annotation.*; + +import org.codehaus.jackson.map.ObjectMapper; + +public class TestPropertyOrdering + extends BaseJaxbTest +{ + /* + /********************************************************** + /* Helper beans + /********************************************************** + */ + + @XmlType(propOrder = {"cparty", "contacts"}) + @XmlAccessorOrder(XmlAccessOrder.ALPHABETICAL) + public class BeanFor268 + { + private String cpartyDto = "dto"; + private int[] contacts = new int[] { 1, 2, 3 }; + + @XmlElement(name="cparty") + public String getCpartyDto() { return cpartyDto; } + public void setCpartyDto(String cpartyDto) { this.cpartyDto = cpartyDto; } + + @XmlElement(name="contact") + @XmlElementWrapper(name="contacts") + public int[] getContacts() { return contacts; } + public void setContacts(int[] contacts) { this.contacts = contacts; } + } + + /* Also, considering that JAXB actually seems to expect original + * names for property ordering, let's see that alternative + * annotation also works + * (see [JACKSON-268] for more details) + */ + @XmlType(propOrder = {"cpartyDto", "contacts"}) + @XmlAccessorOrder(XmlAccessOrder.ALPHABETICAL) + public class BeanWithImplicitNames + { + private String cpartyDto = "dto"; + private int[] contacts = new int[] { 1, 2, 3 }; + + @XmlElement(name="cparty") + public String getCpartyDto() { return cpartyDto; } + public void setCpartyDto(String cpartyDto) { this.cpartyDto = cpartyDto; } + + @XmlElement(name="contact") + @XmlElementWrapper(name="contacts") + public int[] getContacts() { return contacts; } + public void setContacts(int[] contacts) { this.contacts = contacts; } + } + + @XmlType(propOrder={"b", "a", "c"}) + public static class AlphaBean2 + { + public int c = 3; + public int a = 1; + public int b = 2; + } + + /* + /********************************************************** + /* Tests + /********************************************************** + */ + + public void testSerializationExplicitOrdering() throws Exception + { + ObjectMapper mapper = getJaxbMapper(); + assertEquals("{\"b\":2,\"a\":1,\"c\":3}", serializeAsString(mapper, new AlphaBean2())); + } + + // Trying to reproduce [JACKSON-268] + public void testOrderingWithRename() throws Exception + { + ObjectMapper mapper = getJaxbMapper(); + assertEquals("{\"cparty\":\"dto\",\"contacts\":[1,2,3]}", mapper.writeValueAsString(new BeanFor268())); + } + + public void testOrderingWithOriginalPropName() throws Exception + { + ObjectMapper mapper = getJaxbMapper(); + assertEquals("{\"cparty\":\"dto\",\"contacts\":[1,2,3]}", + mapper.writeValueAsString(new BeanWithImplicitNames())); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/jaxb/TestPropertyVisibility.java b/1.9.10/src/test/org/codehaus/jackson/jaxb/TestPropertyVisibility.java new file mode 100644 index 0000000..3ca51f2 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/jaxb/TestPropertyVisibility.java
@@ -0,0 +1,97 @@ +package org.codehaus.jackson.jaxb; + +import java.io.IOException; + +import javax.xml.bind.annotation.*; + +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.xc.JaxbAnnotationIntrospector; + +/** + * Those JAXB support unit tests that fail, mostly because our JAXB + * introspector is not all that good... But fixing that is easiest + * done once we rewrite the method introspector (can't do it with + * current version 1.8) + */ +public class TestPropertyVisibility + extends BaseJaxbTest +{ + /* + /********************************************************** + /* Helper beans + /********************************************************** + */ + + @XmlAccessorType(XmlAccessType.NONE) + protected static class Bean354 + { + protected String name = "foo"; + + @XmlElement + protected String getName() { return name; } + + public void setName(String s) { name = s; } + } + + // Note: full example would be "Content"; but let's use simpler demonstration here, easier to debug + @XmlAccessorType(XmlAccessType.PROPERTY) + static class Jackson539Bean + { + protected int type; + + @XmlTransient + public String getType() { + throw new UnsupportedOperationException(); + } + + public void setType(String type) { + throw new UnsupportedOperationException(); + } + + @XmlAttribute(name = "type") + public int getRawType() { + return type; + } + + public void setRawType(int type) { + this.type = type; + } + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + // Verify serialization wrt [JACKSON-354] + // + // NOTE: fails currently because we use Bean Introspector which only sees public methods -- need to rewrite + public void testJackson354Serialization() throws IOException + { + ObjectMapper mapper = new ObjectMapper(); + mapper.setAnnotationIntrospector(new JaxbAnnotationIntrospector()); + assertEquals("{\"name\":\"foo\"}", mapper.writeValueAsString(new Bean354())); + } + + // For [JACKSON-539] + public void testJacksonSerialization() + throws Exception + { + /* Earlier + Content content = new Content(); + content.setRawType("application/json"); + String json = mapper.writeValueAsString(content); + Content content2 = mapper.readValue(json, Content.class); // deserialize + assertNotNull(content2); + */ + + Jackson539Bean input = new Jackson539Bean(); + input.type = 123; + ObjectMapper mapper = getJaxbMapper(); + String json = mapper.writeValueAsString(input); + Jackson539Bean result = mapper.readValue(json, Jackson539Bean.class); + assertNotNull(result); + assertEquals(123, result.type); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/jaxb/TestRootName.java b/1.9.10/src/test/org/codehaus/jackson/jaxb/TestRootName.java new file mode 100644 index 0000000..cf17da2 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/jaxb/TestRootName.java
@@ -0,0 +1,34 @@ +package org.codehaus.jackson.jaxb; + +import javax.xml.bind.annotation.XmlRootElement; + +import org.codehaus.jackson.map.ObjectMapper; +import org.codehaus.jackson.map.SerializationConfig; + +public class TestRootName extends BaseJaxbTest +{ + /* + /********************************************************** + /* Helper beans + /********************************************************** + */ + + @XmlRootElement(name="rooty") + static class MyType + { + public int value = 37; + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + public void testRootName() throws Exception + { + ObjectMapper mapper = getJaxbMapper(); + mapper.configure(SerializationConfig.Feature.WRAP_ROOT_VALUE, true); + assertEquals("{\"rooty\":{\"value\":37}}", mapper.writeValueAsString(new MyType())); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/jaxb/TestSchemaGeneration.java b/1.9.10/src/test/org/codehaus/jackson/jaxb/TestSchemaGeneration.java new file mode 100644 index 0000000..76d297a --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/jaxb/TestSchemaGeneration.java
@@ -0,0 +1,72 @@ +package org.codehaus.jackson.jaxb; + +import javax.xml.bind.annotation.*; + +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.map.ObjectMapper; +import org.codehaus.jackson.node.ObjectNode; +import org.codehaus.jackson.schema.JsonSchema; + +/** + * Test(s) to see that JAXB annotations-based information is properly + * accessible and used by JSON Schema generation + * + * @author tatu + */ +public class TestSchemaGeneration extends BaseJaxbTest +{ + /* + /********************************************************** + /* Helper beans + /********************************************************** + */ + + @XmlAccessorType(XmlAccessType.FIELD) + protected static class Person { + public String firstName; + public String lastName; + + @XmlElement(type=Address.class) + public IAddress address; + } + + protected interface IAddress { + public String getCity(); + public void setCity(String city); + } + + protected static class Address implements IAddress { + private String city; + private String state; + + @Override + public String getCity() { return city; } + @Override + public void setCity(String city) { this.city = city; } + public String getState() { return state; } + public void setState(String state) { this.state = state; } + } + + /* + /********************************************************** + /* Tests + /********************************************************** + */ + + /** + * Test for [JACKSON-415] + * + * @since 1.7 + */ + public void testWithJaxb() throws Exception + { + ObjectMapper mapper = getJaxbMapper(); + JsonSchema jsonSchema = mapper.generateJsonSchema(Address.class); + ObjectNode root = jsonSchema.getSchemaNode(); + // should find two properties ("city", "state"), not just one... + JsonNode itemsNode = root.findValue("properties"); + assertNotNull("Missing 'state' field", itemsNode.get("state")); + assertNotNull("Missing 'city' field", itemsNode.get("city")); + assertEquals(2, itemsNode.size()); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/jaxb/TestXmlAnyElementWithElementRef.java b/1.9.10/src/test/org/codehaus/jackson/jaxb/TestXmlAnyElementWithElementRef.java new file mode 100644 index 0000000..5406161 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/jaxb/TestXmlAnyElementWithElementRef.java
@@ -0,0 +1,65 @@ +package org.codehaus.jackson.jaxb; + +import java.util.*; + +import javax.xml.bind.annotation.*; + +import org.codehaus.jackson.map.ObjectMapper; + +/** + * @since 1.6 + */ +public class TestXmlAnyElementWithElementRef + extends BaseJaxbTest +{ + static class Bean { + @XmlAnyElement(lax=true) + @XmlElementRefs({ + @XmlElementRef(name="a", type=Name.class), + @XmlElementRef(name="b", type=Count.class) + }) + public List<Object> others; + + public Bean() { } + public Bean(Object ob) { + others = new ArrayList<Object>(); + others.add(ob); + } + } + + static class Name { + public String name; + } + + static class Count { + public int count; + } + + /* + /********************************************************** + /* Test methods + /********************************************************** + */ + + // [JACKSON-254]: verify that things do work + public void testXmlAnyElementWithElementRef() throws Exception + { + ObjectMapper mapper = getJaxbMapper(); + + Count count = new Count(); + count.count = 8; + Bean value = new Bean(count); + + // typed handling should be triggered by annotation on property, so + String json = mapper.writeValueAsString(value); + assertEquals("{\"others\":[{\"b\":{\"count\":8}}]}", json); + + Bean result = mapper.readValue(json, Bean.class); + assertNotNull(result); + assertEquals(1, result.others.size()); + Object resultOb = result.others.get(0); + assertSame(Count.class, resultOb.getClass()); + assertEquals(8, ((Count) resultOb).count); + } + +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/jaxb/package-info.java b/1.9.10/src/test/org/codehaus/jackson/jaxb/package-info.java new file mode 100644 index 0000000..f07265d --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/jaxb/package-info.java
@@ -0,0 +1,11 @@ +/** + * Package info can be used to add "package annotations", so here we are... + */ +@javax.xml.bind.annotation.adapters.XmlJavaTypeAdapters({ + @javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter( + type = javax.xml.namespace.QName.class, + value = org.codehaus.jackson.jaxb.TestJaxbAnnotationIntrospector.QNameAdapter.class + ) +}) +package org.codehaus.jackson.jaxb; +
diff --git a/1.9.10/src/test/org/codehaus/jackson/jaxrs/TestCanSerialize.java b/1.9.10/src/test/org/codehaus/jackson/jaxrs/TestCanSerialize.java new file mode 100644 index 0000000..9e55064 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/jaxrs/TestCanSerialize.java
@@ -0,0 +1,45 @@ +package org.codehaus.jackson.jaxrs; + +import java.io.*; +import java.util.*; + +import org.codehaus.jackson.map.ObjectMapper; +import org.codehaus.jackson.annotate.JsonTypeInfo; + +/** + * Unit test to check [JACKSON-540] + */ +public class TestCanSerialize extends main.BaseTest +{ + static class Simple { + protected List<String> list; + + public List<String> getList( ) { return list; } + public void setList(List<String> l) { list = l; } + } + + public void testCanSerialize() throws IOException + { + ObjectMapper mapper = new ObjectMapper(); + mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.WRAPPER_ARRAY); + + // construct test object + List<String> l = new ArrayList<String>(); + l.add("foo"); + l.add("bar"); + + Simple s = new Simple(); + s.setList(l); + + // this is fine: + boolean can = mapper.canSerialize(Simple.class); + assertTrue(can); + + // but with problem of [JACKSON-540], we get nasty surprise here... + String json = mapper.writeValueAsString(s); + + Simple result = mapper.readValue(json, Simple.class); + assertNotNull(result.list); + assertEquals(2, result.list.size()); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/jaxrs/TestJsonView.java b/1.9.10/src/test/org/codehaus/jackson/jaxrs/TestJsonView.java new file mode 100644 index 0000000..a0717ae --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/jaxrs/TestJsonView.java
@@ -0,0 +1,57 @@ +package org.codehaus.jackson.jaxrs; + +import java.io.ByteArrayOutputStream; +import java.lang.annotation.Annotation; + +import javax.ws.rs.core.MediaType; + +import org.codehaus.jackson.map.annotate.JsonView; + +public class TestJsonView extends main.BaseTest +{ + /* + /********************************************************** + /* Helper types + /********************************************************** + */ + + static class MyView1 { } + static class MyView2 { } + + static class Bean { + @JsonView(MyView1.class) + public int value1 = 1; + + @JsonView(MyView2.class) + public int value2 = 2; + } + + + /* + /********************************************************** + /* Test methods + /********************************************************** + */ + + // [JACKSON-578] + public void testViews() throws Exception + { + JacksonJsonProvider prov = new JacksonJsonProvider(); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + Bean bean = new Bean(); + Annotation ann = new JsonView() { + @Override + public Class<?>[] value() { return new Class[] { MyView1.class }; } + + @Override + public Class<? extends Annotation> annotationType() { + return JsonView.class; + } + }; + prov.writeTo(bean, bean.getClass(), bean.getClass(), new Annotation[] { ann }, + MediaType.APPLICATION_JSON_TYPE, null, out); + assertEquals("{\"value1\":1}", out.toString("UTF-8")); + } + + +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/jaxrs/TestJsonpWrapping.java b/1.9.10/src/test/org/codehaus/jackson/jaxrs/TestJsonpWrapping.java new file mode 100644 index 0000000..849ff54 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/jaxrs/TestJsonpWrapping.java
@@ -0,0 +1,27 @@ +package org.codehaus.jackson.jaxrs; + +import java.io.*; +import java.lang.annotation.Annotation; + +import javax.ws.rs.core.MediaType; + +public class TestJsonpWrapping + extends main.BaseTest +{ + public void testSimple() throws Exception + { + JacksonJsonProvider prov = new JacksonJsonProvider(); + Object bean = new Integer[] { 1, 2, 3 }; + + // First: no JSONP wrapping: + ByteArrayOutputStream out = new ByteArrayOutputStream(); + prov.writeTo(bean, bean.getClass(), bean.getClass(), new Annotation[0], MediaType.APPLICATION_JSON_TYPE, null, out); + assertEquals("[1,2,3]", out.toString("UTF-8")); + + // then with wrapping: + prov.setJSONPFunctionName("addAll"); + out = new ByteArrayOutputStream(); + prov.writeTo(bean, bean.getClass(), bean.getClass(), new Annotation[0], MediaType.APPLICATION_JSON_TYPE, null, out); + assertEquals("addAll([1,2,3])", out.toString("UTF-8")); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/jaxrs/TestLoading.java b/1.9.10/src/test/org/codehaus/jackson/jaxrs/TestLoading.java new file mode 100644 index 0000000..95f0eb6 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/jaxrs/TestLoading.java
@@ -0,0 +1,44 @@ +package org.codehaus.jackson.jaxrs; + +import org.codehaus.jackson.map.ObjectMapper; + +/** + * Trivially simple test to ensure that JAX-RS piece can be loaded + * in. + */ +public class TestLoading extends main.BaseTest +{ + final static class Bean { + public int x = 3; + } + + /** + * Test for ensuring loading works ok, without needing XC module + * (which means JUnit setup has to be ensure those classes + * are not in...) + */ + public void testLoading() throws Exception + { + JacksonJsonProvider prov = new JacksonJsonProvider(); + // alas, can not map 'real' MediaType, due to some deps within jax-rs api impl + ObjectMapper m = prov.locateMapper(Bean.class, null); + assertNotNull(m); + } + + public void testEnsureXcMissing() throws Exception + { + /* 01-Sep-2010, tatus: Skip if not running from Ant/cli: + */ + if (runsFromAnt()) { + JacksonJaxbJsonProvider prov = new JacksonJaxbJsonProvider(); + try { + // should fail here... + prov.locateMapper(Bean.class, null); + fail("Expected exception due to missing 'xc' module"); + } catch (NoClassDefFoundError e) { + // as per [JACKSON-243], JVM messages differ here, should still have class name tho: + verifyException(e, "JaxbAnnotationIntrospector"); + } + } + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/jaxrs/TestRootType.java b/1.9.10/src/test/org/codehaus/jackson/jaxrs/TestRootType.java new file mode 100644 index 0000000..1a6130a --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/jaxrs/TestRootType.java
@@ -0,0 +1,38 @@ +package org.codehaus.jackson.jaxrs; + +import java.io.ByteArrayOutputStream; +import java.lang.annotation.Annotation; +import java.util.ArrayList; +import java.util.List; + +import javax.ws.rs.core.MediaType; + +import org.codehaus.jackson.annotate.*; +import org.codehaus.jackson.annotate.JsonTypeInfo.As; +import org.codehaus.jackson.annotate.JsonTypeInfo.Id; +import org.codehaus.jackson.type.TypeReference; + +public class TestRootType + extends main.BaseTest +{ + @JsonTypeInfo(use=Id.NAME, include=As.WRAPPER_OBJECT, property="type") + @JsonTypeName("bean") + static class Bean { + public int a = 3; + } + + public void testRootType() throws Exception + { + JacksonJsonProvider prov = new JacksonJsonProvider(); + TypeReference<?> ref = new TypeReference<List<Bean>>(){}; + + Bean bean = new Bean(); + ArrayList<Bean> list = new ArrayList<Bean>(); + list.add(bean); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + prov.writeTo(list, List.class, ref.getType(), new Annotation[0], MediaType.APPLICATION_JSON_TYPE, null, out); + + String json = out.toString("UTF-8"); + assertEquals("[{\"bean\":{\"a\":3}}]", json); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/jaxrs/TestUntouchables.java b/1.9.10/src/test/org/codehaus/jackson/jaxrs/TestUntouchables.java new file mode 100644 index 0000000..a310ad9 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/jaxrs/TestUntouchables.java
@@ -0,0 +1,62 @@ +package org.codehaus.jackson.jaxrs; + +import java.util.*; + +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.StreamingOutput; + +/** + * Unit tests for verifying that certain JDK base types will be + * ignored by default Jackson JAX-RS conversion provider. + * + * @since 1.5 + */ +public class TestUntouchables + extends main.BaseTest +{ + /** + * Test type added for [JACKSON-460]... just to ensure that "isJsonType" + * remains overridable. + */ + public static class MyJacksonJsonProvider extends JacksonJsonProvider { + // ensure isJsonType remains "protected" � this is a compile-time check. + // Some users of JacksonJsonProvider override this method; + // changing to "private" would regress them. + @Override + protected boolean isJsonType(MediaType mediaType) { return super.isJsonType(mediaType); } + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + public void testDefaultUntouchables() throws Exception + { + JacksonJsonProvider prov = new JacksonJsonProvider(); + // By default, no reason to exclude, say, this test class... + assertTrue(prov.isReadable(getClass(), getClass(), null, null)); + assertTrue(prov.isWriteable(getClass(), getClass(), null, null)); + + // but some types should be ignored (set of ignorable may change over time tho!) + assertFalse(prov.isReadable(String.class, getClass(), null, null)); + assertFalse(prov.isWriteable(StreamingOutput.class, StreamingOutput.class, null, null)); + } + + public void testCustomUntouchables() throws Exception + { + JacksonJsonProvider prov = new JacksonJsonProvider(); + // can mark this as ignorable... + prov.addUntouchable(getClass()); + // and then it shouldn't be processable + assertFalse(prov.isReadable(getClass(), getClass(), null, null)); + assertFalse(prov.isWriteable(getClass(), getClass(), null, null)); + + // Same for interfaces, like: + prov.addUntouchable(Collection.class); + assertFalse(prov.isReadable(ArrayList.class, ArrayList.class, null, null)); + assertFalse(prov.isWriteable(HashSet.class, HashSet.class, null, null)); + } +} + \ No newline at end of file
diff --git a/1.9.10/src/test/org/codehaus/jackson/main/TestArrayParsing.java b/1.9.10/src/test/org/codehaus/jackson/main/TestArrayParsing.java new file mode 100644 index 0000000..3c85124 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/main/TestArrayParsing.java
@@ -0,0 +1,73 @@ +package org.codehaus.jackson.main; + +import org.codehaus.jackson.*; + +/** + * Set of additional unit for verifying array parsing, specifically + * edge cases. + */ +public class TestArrayParsing + extends main.BaseTest +{ + public void testValidEmpty() + throws Exception + { + final String DOC = "[ \n ]"; + + JsonParser jp = createParserUsingStream(DOC, "UTF-8"); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + assertNull(jp.nextToken()); + jp.close(); + } + + public void testInvalidEmptyMissingClose() + throws Exception + { + final String DOC = "[ "; + + JsonParser jp = createParserUsingStream(DOC, "UTF-8"); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + + try { + jp.nextToken(); + fail("Expected a parsing error for missing array close marker"); + } catch (JsonParseException jex) { + verifyException(jex, "expected close marker for ARRAY"); + } + } + + public void testInvalidMissingFieldName() + throws Exception + { + final String DOC = "[ : 3 ] "; + + JsonParser jp = createParserUsingStream(DOC, "UTF-8"); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + + try { + jp.nextToken(); + fail("Expected a parsing error for odd character"); + } catch (JsonParseException jex) { + verifyException(jex, "Unexpected character"); + } + } + + public void testInvalidExtraComma() + throws Exception + { + final String DOC = "[ 24, ] "; + + JsonParser jp = createParserUsingStream(DOC, "UTF-8"); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(24, jp.getIntValue()); + + try { + jp.nextToken(); + fail("Expected a parsing error for missing array close marker"); + } catch (JsonParseException jex) { + verifyException(jex, "expected a value"); + } + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/main/TestCharEscaping.java b/1.9.10/src/test/org/codehaus/jackson/main/TestCharEscaping.java new file mode 100644 index 0000000..63e7d74 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/main/TestCharEscaping.java
@@ -0,0 +1,145 @@ +package org.codehaus.jackson.main; + +import java.io.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.io.CharacterEscapes; + +/** + * Set of basic unit tests for verifying that the basic parser + * functionality works as expected. + */ +public class TestCharEscaping + extends main.BaseTest +{ + // for [JACKSON-627] + private final static CharacterEscapes ESC_627 = new CharacterEscapes() { + final int[] ascii = CharacterEscapes.standardAsciiEscapesForJSON(); + { + ascii['<'] = CharacterEscapes.ESCAPE_STANDARD; + ascii['>'] = CharacterEscapes.ESCAPE_STANDARD; + } + + @Override + public int[] getEscapeCodesForAscii() { + return ascii; + } + + @Override + public SerializableString getEscapeSequence(int ch) { + throw new UnsupportedOperationException("Not implemented for test"); + } + }; + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + public void testMissingEscaping() + throws Exception + { + // Invalid: control chars, including lf, must be escaped + final String DOC = "[" + +"\"Linefeed: \n.\"" + +"]"; + JsonParser jp = createParserUsingReader(DOC); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + try { + // This may or may not trigger exception + JsonToken t = jp.nextToken(); + assertToken(JsonToken.VALUE_STRING, t); + // and if not, should get it here: + jp.getText(); + fail("Expected an exception for un-escaped linefeed in string value"); + } catch (JsonParseException jex) { + verifyException(jex, "has to be escaped"); + } + } + + public void testSimpleEscaping() + throws Exception + { + String DOC = "[" + +"\"LF=\\n\"" + +"]"; + + JsonParser jp = createParserUsingReader(DOC); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + assertEquals("LF=\n", jp.getText()); + jp.close(); + + + /* Note: must split Strings, so that javac won't try to handle + * escape and inline null char + */ + DOC = "[\"NULL:\\u0000!\"]"; + + jp = createParserUsingReader(DOC); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + assertEquals("NULL:\0!", jp.getText()); + + // Then just a single char escaping + jp = createParserUsingReader("[\"\\u0123\"]"); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + assertEquals("\u0123", jp.getText()); + + // And then double sequence + jp = createParserUsingReader("[\"\\u0041\\u0043\"]"); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + assertEquals("AC", jp.getText()); + } + + public void testInvalid() + throws Exception + { + // 2-char sequences not allowed: + String DOC = "[\"\\u41=A\"]"; + JsonParser jp = createParserUsingReader(DOC); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + try { + jp.nextToken(); + jp.getText(); + fail("Expected an exception for unclosed ARRAY"); + } catch (JsonParseException jpe) { + verifyException(jpe, "for character escape"); + } + } + + /** + * Test to verify that decoder does not allow 8-digit escapes + * (non-BMP characters must be escaped using two 4-digit sequences) + */ + public void test8DigitSequence() + throws Exception + { + String DOC = "[\"\\u00411234\"]"; + JsonParser jp = createParserUsingReader(DOC); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + assertEquals("A1234", jp.getText()); + } + + // for [JACKSON-627] + public void testWriteLongCustomEscapes() throws Exception + { + JsonFactory jf = new JsonFactory(); + jf.setCharacterEscapes(ESC_627); // must set to trigger bug + StringBuilder longString = new StringBuilder(); + while (longString.length() < 2000) { + longString.append("\u65e5\u672c\u8a9e"); + } + + StringWriter writer = new StringWriter(); + // must call #createJsonGenerator(Writer), #createJsonGenerator(OutputStream) doesn't trigger bug + JsonGenerator jgen = jf.createJsonGenerator(writer); + jgen.setHighestNonEscapedChar(127); // must set to trigger bug + jgen.writeString(longString.toString()); + } + +} +
diff --git a/1.9.10/src/test/org/codehaus/jackson/main/TestComments.java b/1.9.10/src/test/org/codehaus/jackson/main/TestComments.java new file mode 100644 index 0000000..425f8c2 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/main/TestComments.java
@@ -0,0 +1,114 @@ +package org.codehaus.jackson.main; + +import java.io.*; + +import org.codehaus.jackson.*; + +/** + * Unit tests for verifying that support for (non-standard) comments + * works as expected. + */ +public class TestComments extends main.BaseTest +{ + final static String DOC_WITH_SLASHSTAR_COMMENT = + "[ /* comment:\n ends here */ 1 /* one more ok to have \"unquoted\" */ ]" + ; + + final static String DOC_WITH_SLASHSLASH_COMMENT = + "[ // comment...\n 1 \r // one more, not array: [] \n ]" + ; + + /* + /********************************************************** + /* Test method wrappers + /********************************************************** + */ + + /** + * Unit test for verifying that by default comments are not + * recognized. + */ + public void testDefaultSettings() + throws Exception + { + JsonFactory jf = new JsonFactory(); + assertFalse(jf.isEnabled(JsonParser.Feature.ALLOW_COMMENTS)); + JsonParser jp = jf.createJsonParser(new StringReader("[ 1 ]")); + assertFalse(jp.isEnabled(JsonParser.Feature.ALLOW_COMMENTS)); + } + + public void testCommentsDisabled() + throws Exception + { + _testDisabled(DOC_WITH_SLASHSTAR_COMMENT, false); + _testDisabled(DOC_WITH_SLASHSLASH_COMMENT, false); + _testDisabled(DOC_WITH_SLASHSTAR_COMMENT, true); + _testDisabled(DOC_WITH_SLASHSLASH_COMMENT, true); + } + + public void testCommentsEnabled() + throws Exception + { + _testEnabled(DOC_WITH_SLASHSTAR_COMMENT, false); + _testEnabled(DOC_WITH_SLASHSLASH_COMMENT, false); + _testEnabled(DOC_WITH_SLASHSTAR_COMMENT, true); + _testEnabled(DOC_WITH_SLASHSLASH_COMMENT, true); + } + + // for [JACKSON-779] + public void testCommentsWithUTF8() throws Exception + { + final String JSON = "/* \u00a9 2099 Yoyodyne Inc. */\n [ \"bar? \u00a9\" ]\n"; + _testWithUTF8Chars(JSON, false); + _testWithUTF8Chars(JSON, true); + } + + /* + /********************************************************** + /* Helper methods + /********************************************************** + */ + + private void _testWithUTF8Chars(String doc, boolean useStream) throws IOException + { + // should basically just stream through + JsonParser jp = _createParser(doc, useStream, true); + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + assertNull(jp.nextToken()); + jp.close(); + } + + private void _testDisabled(String doc, boolean useStream) throws IOException + { + JsonParser jp = _createParser(doc, useStream, false); + try { + jp.nextToken(); + fail("Expected exception for unrecognized comment"); + } catch (JsonParseException je) { + // Should have something denoting that user may want to enable 'ALLOW_COMMENTS' + verifyException(je, "ALLOW_COMMENTS"); + } + } + + private void _testEnabled(String doc, boolean useStream) + throws IOException + { + JsonParser jp = _createParser(doc, useStream, true); + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(1, jp.getIntValue()); + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + } + + private JsonParser _createParser(String doc, boolean useStream, boolean enabled) + throws IOException + { + JsonFactory jf = new JsonFactory(); + jf.configure(JsonParser.Feature.ALLOW_COMMENTS, enabled); + JsonParser jp = useStream ? + jf.createJsonParser(doc.getBytes("UTF-8")) + : jf.createJsonParser(doc); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + return jp; + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/main/TestGeneratorArray.java b/1.9.10/src/test/org/codehaus/jackson/main/TestGeneratorArray.java new file mode 100644 index 0000000..4fe4263 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/main/TestGeneratorArray.java
@@ -0,0 +1,109 @@ +package org.codehaus.jackson.main; + +import org.codehaus.jackson.*; + +import java.io.*; + +/** + * Set of basic unit tests for verifying that the Array write methods + * of {@link JsonGenerator} work as expected. + */ +public class TestGeneratorArray + extends main.BaseTest +{ + public void testEmptyArrayWrite() + throws Exception + { + StringWriter sw = new StringWriter(); + JsonGenerator gen = new JsonFactory().createJsonGenerator(sw); + + JsonStreamContext ctxt = gen.getOutputContext(); + assertTrue(ctxt.inRoot()); + assertFalse(ctxt.inArray()); + assertFalse(ctxt.inObject()); + assertEquals(0, ctxt.getEntryCount()); + assertEquals(0, ctxt.getCurrentIndex()); + + gen.writeStartArray(); + + ctxt = gen.getOutputContext(); + assertFalse(ctxt.inRoot()); + assertTrue(ctxt.inArray()); + assertFalse(ctxt.inObject()); + assertEquals(0, ctxt.getEntryCount()); + assertEquals(0, ctxt.getCurrentIndex()); + + gen.writeEndArray(); + + ctxt = gen.getOutputContext(); + assertTrue("Should be in root, was "+ctxt.getTypeDesc(), ctxt.inRoot()); + assertFalse(ctxt.inArray()); + assertFalse(ctxt.inObject()); + assertEquals(1, ctxt.getEntryCount()); + // Index won't yet move + assertEquals(0, ctxt.getCurrentIndex()); + + gen.close(); + String docStr = sw.toString(); + JsonParser jp = createParserUsingReader(docStr); + assertEquals(JsonToken.START_ARRAY, jp.nextToken()); + assertEquals(JsonToken.END_ARRAY, jp.nextToken()); + jp.close(); + + // Ok, then array with nested empty array + sw = new StringWriter(); + gen = new JsonFactory().createJsonGenerator(sw); + gen.writeStartArray(); + gen.writeStartArray(); + gen.writeEndArray(); + gen.writeEndArray(); + gen.close(); + docStr = sw.toString(); + jp = createParserUsingReader(docStr); + assertEquals(JsonToken.START_ARRAY, jp.nextToken()); + assertEquals(JsonToken.START_ARRAY, jp.nextToken()); + assertEquals(JsonToken.END_ARRAY, jp.nextToken()); + assertEquals(JsonToken.END_ARRAY, jp.nextToken()); + assertEquals(null, jp.nextToken()); + jp.close(); + } + + public void testInvalidArrayWrite() + throws Exception + { + StringWriter sw = new StringWriter(); + JsonGenerator gen = new JsonFactory().createJsonGenerator(sw); + gen.writeStartArray(); + // Mismatch: + try { + gen.writeEndObject(); + fail("Expected an exception for mismatched array/object write"); + } catch (JsonGenerationException e) { + verifyException(e, "Current context not an object"); + } + } + + public void testSimpleArrayWrite() + throws Exception + { + StringWriter sw = new StringWriter(); + JsonGenerator gen = new JsonFactory().createJsonGenerator(sw); + gen.writeStartArray(); + gen.writeNumber(13); + gen.writeBoolean(true); + gen.writeString("foobar"); + gen.writeEndArray(); + gen.close(); + String docStr = sw.toString(); + JsonParser jp = createParserUsingReader(docStr); + assertEquals(JsonToken.START_ARRAY, jp.nextToken()); + assertEquals(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(13, jp.getIntValue()); + assertEquals(JsonToken.VALUE_TRUE, jp.nextToken()); + assertEquals(JsonToken.VALUE_STRING, jp.nextToken()); + assertEquals("foobar", jp.getText()); + assertEquals(JsonToken.END_ARRAY, jp.nextToken()); + assertEquals(null, jp.nextToken()); + jp.close(); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/main/TestGeneratorClosing.java b/1.9.10/src/test/org/codehaus/jackson/main/TestGeneratorClosing.java new file mode 100644 index 0000000..91ea426 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/main/TestGeneratorClosing.java
@@ -0,0 +1,235 @@ +package org.codehaus.jackson.main; + +import main.BaseTest; + +import org.codehaus.jackson.*; + +import java.io.*; + +/** + * Set of basic unit tests that verify aspect of closing a + * {@link JsonGenerator} instance. This includes both closing + * of physical resources (target), and logical content + * (json content tree) + *<p> + * Specifically, features + * <code>JsonGenerator.Feature#AUTO_CLOSE_TARGET</code> + * and + * <code>JsonGenerator.Feature.AUTO_CLOSE_JSON_CONTENT</code> + * are tested. + */ +public class TestGeneratorClosing + extends BaseTest +{ + /* + /********************************************************** + /* Helper classes + /********************************************************** + */ + + final static class MyWriter extends StringWriter + { + boolean mIsClosed = false; + + public MyWriter() { } + + @Override + public void close() throws IOException { + mIsClosed = true; + super.close(); + } + public boolean isClosed() { return mIsClosed; } + } + + final static class MyStream extends ByteArrayOutputStream + { + boolean mIsClosed = false; + + public MyStream() { } + + @Override + public void close() throws IOException { + mIsClosed = true; + super.close(); + } + public boolean isClosed() { return mIsClosed; } + } + + static class MyBytes extends ByteArrayOutputStream + { + public int flushed = 0; + + @Override + public void flush() throws IOException + { + ++flushed; + super.flush(); + } + } + + static class MyChars extends StringWriter + { + public int flushed = 0; + + @Override + public void flush() + { + ++flushed; + super.flush(); + } + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + /** + * This unit test checks the default behaviour; with no auto-close, no + * automatic closing should occur, nor explicit one unless specific + * forcing method is used. + */ + public void testNoAutoCloseGenerator() + throws Exception + { + JsonFactory f = new JsonFactory(); + + // Check the default settings + assertTrue(f.isEnabled(JsonGenerator.Feature.AUTO_CLOSE_TARGET)); + // then change + f.disable(JsonGenerator.Feature.AUTO_CLOSE_TARGET); + assertFalse(f.isEnabled(JsonGenerator.Feature.AUTO_CLOSE_TARGET)); + MyWriter output = new MyWriter(); + JsonGenerator jg = f.createJsonGenerator(output); + + // shouldn't be closed to begin with... + assertFalse(output.isClosed()); + jg.writeNumber(39); + // regular close won't close it either: + jg.close(); + assertFalse(output.isClosed()); + } + + public void testCloseGenerator() + throws Exception + { + JsonFactory f = new JsonFactory(); + f.enable(JsonGenerator.Feature.AUTO_CLOSE_TARGET); + MyWriter output = new MyWriter(); + JsonGenerator jg = f.createJsonGenerator(output); + + // shouldn't be closed to begin with... + assertFalse(output.isClosed()); + jg.writeNumber(39); + // but close() should now close the writer + jg.close(); + assertTrue(output.isClosed()); + } + + public void testNoAutoCloseOutputStream() + throws Exception + { + JsonFactory f = new JsonFactory(); + f.disable(JsonGenerator.Feature.AUTO_CLOSE_TARGET); + MyStream output = new MyStream(); + JsonGenerator jg = f.createJsonGenerator(output, JsonEncoding.UTF8); + + assertFalse(output.isClosed()); + jg.writeNumber(39); + jg.close(); + assertFalse(output.isClosed()); + } + + public void testAutoCloseArraysAndObjects() + throws Exception + { + JsonFactory f = new JsonFactory(); + // let's verify default setting, first: + assertTrue(f.isEnabled(JsonGenerator.Feature.AUTO_CLOSE_JSON_CONTENT)); + StringWriter sw = new StringWriter(); + + // First, test arrays: + JsonGenerator jg = f.createJsonGenerator(sw); + jg.writeStartArray(); + jg.close(); + assertEquals("[]", sw.toString()); + + // Then objects + sw = new StringWriter(); + jg = f.createJsonGenerator(sw); + jg.writeStartObject(); + jg.close(); + assertEquals("{}", sw.toString()); + } + + public void testNoAutoCloseArraysAndObjects() + throws Exception + { + JsonFactory f = new JsonFactory(); + f.disable(JsonGenerator.Feature.AUTO_CLOSE_JSON_CONTENT); + StringWriter sw = new StringWriter(); + JsonGenerator jg = f.createJsonGenerator(sw); + jg.writeStartArray(); + jg.close(); + // shouldn't close + assertEquals("[", sw.toString()); + + // Then objects + sw = new StringWriter(); + jg = f.createJsonGenerator(sw); + jg.writeStartObject(); + jg.close(); + assertEquals("{", sw.toString()); + } + + // [JACKSON-401] + public void testAutoFlushOrNot() throws Exception + { + JsonFactory f = new JsonFactory(); + assertTrue(f.isEnabled(JsonGenerator.Feature.FLUSH_PASSED_TO_STREAM)); + MyChars sw = new MyChars(); + JsonGenerator jg = f.createJsonGenerator(sw); + jg.writeStartArray(); + jg.writeEndArray(); + assertEquals(0, sw.flushed); + jg.flush(); + assertEquals(1, sw.flushed); + jg.close(); + + // ditto with stream + MyBytes bytes = new MyBytes(); + jg = f.createJsonGenerator(bytes, JsonEncoding.UTF8); + jg.writeStartArray(); + jg.writeEndArray(); + assertEquals(0, bytes.flushed); + jg.flush(); + assertEquals(1, bytes.flushed); + assertEquals(2, bytes.toByteArray().length); + jg.close(); + + // then disable and we should not see flushing again... + f.disable(JsonGenerator.Feature.FLUSH_PASSED_TO_STREAM); + // first with a Writer + sw = new MyChars(); + jg = f.createJsonGenerator(sw); + jg.writeStartArray(); + jg.writeEndArray(); + assertEquals(0, sw.flushed); + jg.flush(); + assertEquals(0, sw.flushed); + jg.close(); + assertEquals("[]", sw.toString()); + + // and then with OutputStream + bytes = new MyBytes(); + jg = f.createJsonGenerator(bytes, JsonEncoding.UTF8); + jg.writeStartArray(); + jg.writeEndArray(); + assertEquals(0, bytes.flushed); + jg.flush(); + assertEquals(0, bytes.flushed); + jg.close(); + assertEquals(2, bytes.toByteArray().length); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/main/TestGeneratorCopy.java b/1.9.10/src/test/org/codehaus/jackson/main/TestGeneratorCopy.java new file mode 100644 index 0000000..a556694 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/main/TestGeneratorCopy.java
@@ -0,0 +1,82 @@ +package org.codehaus.jackson.main; + +import main.BaseTest; + +import org.codehaus.jackson.*; + +import java.io.*; + +/** + * Set of basic unit tests for verifying that copy-through methods + * of {@link JsonGenerator} work as expected. + */ +public class TestGeneratorCopy + extends BaseTest +{ + public void testCopyRootTokens() + throws IOException + { + JsonFactory jf = new JsonFactory(); + final String DOC = "\"text\\non two lines\" true false 2.0"; + JsonParser jp = jf.createJsonParser(new StringReader(DOC)); + StringWriter sw = new StringWriter(); + JsonGenerator gen = jf.createJsonGenerator(sw); + + JsonToken t; + + while ((t = jp.nextToken()) != null) { + gen.copyCurrentEvent(jp); + // should not change parser state: + assertToken(t, jp.getCurrentToken()); + } + jp.close(); + gen.close(); + + assertEquals("\"text\\non two lines\" true false 2.0", sw.toString()); + } + + public void testCopyArrayTokens() + throws IOException + { + JsonFactory jf = new JsonFactory(); + final String DOC = "123 [ 1, null, [ false ] ]"; + JsonParser jp = jf.createJsonParser(new StringReader(DOC)); + StringWriter sw = new StringWriter(); + JsonGenerator gen = jf.createJsonGenerator(sw); + + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + gen.copyCurrentEvent(jp); + // should not change parser state: + assertToken(JsonToken.VALUE_NUMBER_INT, jp.getCurrentToken()); + assertEquals(123, jp.getIntValue()); + + // And then let's copy the array + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + gen.copyCurrentStructure(jp); + // which will advance parser to matching close Array + assertToken(JsonToken.END_ARRAY, jp.getCurrentToken()); + jp.close(); + gen.close(); + + assertEquals("123 [1,null,[false]]", sw.toString()); + } + + public void testCopyObjectTokens() + throws IOException + { + JsonFactory jf = new JsonFactory(); + final String DOC = "{ \"a\":1, \"b\":[{ \"c\" : null }] }"; + JsonParser jp = jf.createJsonParser(new StringReader(DOC)); + StringWriter sw = new StringWriter(); + JsonGenerator gen = jf.createJsonGenerator(sw); + + assertToken(JsonToken.START_OBJECT, jp.nextToken()); + gen.copyCurrentStructure(jp); + // which will advance parser to matching end Object + assertToken(JsonToken.END_OBJECT, jp.getCurrentToken()); + jp.close(); + gen.close(); + + assertEquals("{\"a\":1,\"b\":[{\"c\":null}]}", sw.toString()); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/main/TestGeneratorMisc.java b/1.9.10/src/test/org/codehaus/jackson/main/TestGeneratorMisc.java new file mode 100644 index 0000000..bb9e484 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/main/TestGeneratorMisc.java
@@ -0,0 +1,341 @@ +package org.codehaus.jackson.main; + +import java.io.*; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.concurrent.atomic.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.MappingJsonFactory; + +/** + * Set of basic unit tests for verifying basic generator + * features. + */ +public class TestGeneratorMisc + extends main.BaseTest +{ + final static class Pojo + { + public int getX() { return 4; } + } + + /* + /********************************************************** + /* Tests for closing, status + /********************************************************** + */ + + public void testIsClosed() + throws IOException + { + JsonFactory jf = new JsonFactory(); + for (int i = 0; i < 2; ++i) { + boolean stream = ((i & 1) == 0); + JsonGenerator jg = stream ? + jf.createJsonGenerator(new StringWriter()) + : jf.createJsonGenerator(new ByteArrayOutputStream(), JsonEncoding.UTF8) + ; + assertFalse(jg.isClosed()); + jg.writeStartArray(); + jg.writeNumber(-1); + jg.writeEndArray(); + assertFalse(jg.isClosed()); + jg.close(); + assertTrue(jg.isClosed()); + jg.close(); + assertTrue(jg.isClosed()); + } + } + + /* + /********************************************************** + /* Tests for data binding integration + /********************************************************** + */ + + public void testPojoWriting() + throws IOException + { + JsonFactory jf = new MappingJsonFactory(); + StringWriter sw = new StringWriter(); + JsonGenerator gen = jf.createJsonGenerator(sw); + gen.writeObject(new Pojo()); + gen.close(); + // trimming needed if main-level object has leading space + String act = sw.toString().trim(); + assertEquals("{\"x\":4}", act); + } + + public void testPojoWritingFailing() + throws IOException + { + // regular factory can't do it, without a call to setCodec() + JsonFactory jf = new JsonFactory(); + try { + StringWriter sw = new StringWriter(); + JsonGenerator gen = jf.createJsonGenerator(sw); + gen.writeObject(new Pojo()); + gen.close(); + fail("Expected an exception: got sw '"+sw.toString()+"'"); + } catch (IllegalStateException e) { + verifyException(e, "No ObjectCodec defined"); + } + } + + // Also, "very simple" objects are supported even without Codec: + public void testSimpleWriteObject() throws IOException + { + // note: NOT mapping factory, for this test + JsonFactory jf = new JsonFactory(); + StringWriter sw = new StringWriter(); + JsonGenerator gen = jf.createJsonGenerator(sw); + gen.writeStartArray(); + + // simple wrappers first + gen.writeObject(Integer.valueOf(1)); + gen.writeObject(Short.valueOf((short)-2)); + gen.writeObject(Long.valueOf(3)); + gen.writeObject(Byte.valueOf((byte)-4)); + gen.writeObject(Double.valueOf(0.25)); + gen.writeObject(Float.valueOf(-0.125f)); + gen.writeObject(Boolean.TRUE); + gen.close(); + String act = sw.toString().trim(); + assertEquals("[1,-2,3,-4,0.25,-0.125,true]", act); + + // then other basic types + sw = new StringWriter(); + gen = jf.createJsonGenerator(sw); + gen.writeStartArray(); + gen.writeObject(BigInteger.valueOf(1234)); + gen.writeObject(new BigDecimal(0.5)); + gen.writeEndArray(); + gen.close(); + act = sw.toString().trim(); + assertEquals("[1234,0.5]", act); + + // then Atomic types + sw = new StringWriter(); + gen = jf.createJsonGenerator(sw); + gen.writeStartArray(); + gen.writeObject(new AtomicBoolean(false)); + gen.writeObject(new AtomicInteger(13)); + gen.writeObject(new AtomicLong(-127L)); + gen.writeEndArray(); + gen.close(); + act = sw.toString().trim(); + assertEquals("[false,13,-127]", act); + } + + /* + /********************************************************** + /* Tests for raw output + /********************************************************** + */ + + public void testRaw() throws IOException + { + JsonFactory jf = new JsonFactory(); + StringWriter sw = new StringWriter(); + JsonGenerator gen = jf.createJsonGenerator(sw); + gen.writeStartArray(); + gen.writeRaw("-123, true"); + gen.writeRaw(", \"x\" "); + gen.writeEndArray(); + gen.close(); + + + JsonParser jp = createParserUsingReader(sw.toString()); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(-123, jp.getIntValue()); + assertToken(JsonToken.VALUE_TRUE, jp.nextToken()); + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + assertEquals("x", jp.getText()); + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + jp.close(); + } + + public void testRawValue() throws IOException + { + JsonFactory jf = new JsonFactory(); + StringWriter sw = new StringWriter(); + JsonGenerator gen = jf.createJsonGenerator(sw); + gen.writeStartArray(); + gen.writeRawValue("7"); + gen.writeRawValue("[ null ]"); + gen.writeRawValue("false"); + gen.writeEndArray(); + gen.close(); + + JsonParser jp = createParserUsingReader(sw.toString()); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(7, jp.getIntValue()); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + assertToken(JsonToken.VALUE_NULL, jp.nextToken()); + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + assertToken(JsonToken.VALUE_FALSE, jp.nextToken()); + + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + jp.close(); + } + + /* + /********************************************************** + /* Tests for binary data + /********************************************************** + */ + + /** + * This is really inadequate test, all in all, but should serve + * as some kind of sanity check. Reader-side should more thoroughly + * test things, as it does need writers to construct the data first. + */ + public void testBinaryWrite() throws Exception + { + _testBinaryWrite(false); + _testBinaryWrite(true); + } + + private void _testBinaryWrite(boolean useCharBased) throws Exception + { + /* The usual sample input string, from Thomas Hobbes's "Leviathan" + * (via Wikipedia) + */ + final String INPUT = "Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure."; + final byte[] INPUT_BYTES = INPUT.getBytes("US-ASCII"); + // as per MIME variant, result minus lfs = + final String OUTPUT = + "TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlz" ++"IHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGljaCBpcyBhIGx1c3Qgb2Yg" ++"dGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGlu" ++"dWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRo" ++"ZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4=" + ; + + /* Let's only test the standard base64 variant; but write + * values in root, array and object contexts. + */ + Base64Variant b64v = Base64Variants.getDefaultVariant(); + JsonFactory jf = new JsonFactory(); + + for (int i = 0; i < 3; ++i) { + JsonGenerator gen; + ByteArrayOutputStream bout = new ByteArrayOutputStream(200); + if (useCharBased) { + gen = jf.createJsonGenerator(new OutputStreamWriter(bout, "UTF-8")); + } else { + gen = jf.createJsonGenerator(bout, JsonEncoding.UTF8); + } + + switch (i) { + case 0: // root + gen.writeBinary(b64v, INPUT_BYTES, 0, INPUT_BYTES.length); + break; + case 1: // array + gen.writeStartArray(); + gen.writeBinary(b64v, INPUT_BYTES, 0, INPUT_BYTES.length); + gen.writeEndArray(); + break; + default: // object + gen.writeStartObject(); + gen.writeFieldName("field"); + gen.writeBinary(b64v, INPUT_BYTES, 0, INPUT_BYTES.length); + gen.writeEndObject(); + break; + } + gen.close(); + + JsonParser jp = jf.createJsonParser(new ByteArrayInputStream(bout.toByteArray())); + + // Need to skip other events before binary data: + switch (i) { + case 0: + break; + case 1: + assertEquals(JsonToken.START_ARRAY, jp.nextToken()); + break; + default: + assertEquals(JsonToken.START_OBJECT, jp.nextToken()); + assertEquals(JsonToken.FIELD_NAME, jp.nextToken()); + break; + } + assertEquals(JsonToken.VALUE_STRING, jp.nextToken()); + String actualValue = jp.getText(); + jp.close(); + assertEquals(OUTPUT, actualValue); + } + } + + /* + /********************************************************** + /* Tests for object writing + /********************************************************** + */ + + /** + * Unit test that tries to trigger buffer-boundary conditions + */ + public void testLongerObjects() throws Exception + { + JsonFactory jf = new JsonFactory(); + for (int i = 0; i < 2; ++i) { + boolean useChars = (i == 0); + JsonGenerator jgen; + ByteArrayOutputStream bout = new ByteArrayOutputStream(200); + if (useChars) { + jgen = jf.createJsonGenerator(new OutputStreamWriter(bout, "UTF-8")); + } else { + jgen = jf.createJsonGenerator(bout, JsonEncoding.UTF8); + } + + jgen.writeStartObject(); + + for (int rounds = 0; rounds < 1500; ++rounds) { + for (int letter = 'a'; letter <= 'z'; ++letter) { + for (int index = 0; index < 20; ++index) { + String name; + if (letter > 'f') { + name = "X"+letter+index; + } else if (letter > 'p') { + name = ""+letter+index; + } else { + name = "__"+index+letter; + } + jgen.writeFieldName(name); + jgen.writeNumber(index-1); + } + jgen.writeRaw('\n'); + } + } + jgen.writeEndObject(); + jgen.close(); + + byte[] json = bout.toByteArray(); + JsonParser jp = jf.createJsonParser(json); + assertToken(JsonToken.START_OBJECT, jp.nextToken()); + for (int rounds = 0; rounds < 1500; ++rounds) { + for (int letter = 'a'; letter <= 'z'; ++letter) { + for (int index = 0; index < 20; ++index) { + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + String name; + if (letter > 'f') { + name = "X"+letter+index; + } else if (letter > 'p') { + name = ""+letter+index; + } else { + name = "__"+index+letter; + } + assertEquals(name, jp.getCurrentName()); + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(index-1, jp.getIntValue()); + } + } + } + assertToken(JsonToken.END_OBJECT, jp.nextToken()); + } + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/main/TestGeneratorObject.java b/1.9.10/src/test/org/codehaus/jackson/main/TestGeneratorObject.java new file mode 100644 index 0000000..966be73 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/main/TestGeneratorObject.java
@@ -0,0 +1,209 @@ +package org.codehaus.jackson.main; + +import main.BaseTest; + +import org.codehaus.jackson.*; + +import java.io.*; +import java.math.BigDecimal; + +/** + * Set of basic unit tests for verifying that the Object write methods + * of {@link JsonGenerator} work as expected. + */ +public class TestGeneratorObject + extends BaseTest +{ + public void testEmptyObjectWrite() + throws Exception + { + StringWriter sw = new StringWriter(); + JsonGenerator gen = new JsonFactory().createJsonGenerator(sw); + + JsonStreamContext ctxt = gen.getOutputContext(); + assertTrue(ctxt.inRoot()); + assertFalse(ctxt.inArray()); + assertFalse(ctxt.inObject()); + assertEquals(0, ctxt.getEntryCount()); + assertEquals(0, ctxt.getCurrentIndex()); + + gen.writeStartObject(); + + ctxt = gen.getOutputContext(); + assertFalse(ctxt.inRoot()); + assertFalse(ctxt.inArray()); + assertTrue(ctxt.inObject()); + assertEquals(0, ctxt.getEntryCount()); + assertEquals(0, ctxt.getCurrentIndex()); + + gen.writeEndObject(); + + ctxt = gen.getOutputContext(); + assertTrue(ctxt.inRoot()); + assertFalse(ctxt.inArray()); + assertFalse(ctxt.inObject()); + assertEquals(1, ctxt.getEntryCount()); + // Index won't yet move + assertEquals(0, ctxt.getCurrentIndex()); + + gen.close(); + + String docStr = sw.toString(); + JsonParser jp = createParserUsingReader(docStr); + assertEquals(JsonToken.START_OBJECT, jp.nextToken()); + assertEquals(JsonToken.END_OBJECT, jp.nextToken()); + assertEquals(null, jp.nextToken()); + } + + public void testInvalidObjectWrite() + throws Exception + { + StringWriter sw = new StringWriter(); + JsonGenerator gen = new JsonFactory().createJsonGenerator(sw); + gen.writeStartObject(); + // Mismatch: + try { + gen.writeEndArray(); + fail("Expected an exception for mismatched array/object write"); + } catch (JsonGenerationException e) { + verifyException(e, "Current context not an array"); + } + } + + public void testSimpleObjectWrite() + throws Exception + { + StringWriter sw = new StringWriter(); + JsonGenerator gen = new JsonFactory().createJsonGenerator(sw); + gen.writeStartObject(); + gen.writeFieldName("first"); + gen.writeNumber(-901); + gen.writeFieldName("sec"); + gen.writeBoolean(false); + gen.writeFieldName("3rd!"); // json field names are just strings, not ids with restrictions + gen.writeString("yee-haw"); + gen.writeEndObject(); + gen.close(); + String docStr = sw.toString(); + JsonParser jp = createParserUsingReader(docStr); + assertEquals(JsonToken.START_OBJECT, jp.nextToken()); + assertEquals(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals("first", jp.getText()); + assertEquals(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(-901, jp.getIntValue()); + assertEquals(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals("sec", jp.getText()); + assertEquals(JsonToken.VALUE_FALSE, jp.nextToken()); + assertEquals(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals("3rd!", jp.getText()); + assertEquals(JsonToken.VALUE_STRING, jp.nextToken()); + assertEquals("yee-haw", jp.getText()); + assertEquals(JsonToken.END_OBJECT, jp.nextToken()); + assertEquals(null, jp.nextToken()); + jp.close(); + } + + /** + * Methods to test functionality added for [JACKSON-26] + */ + public void testConvenienceMethods() + throws Exception + { + StringWriter sw = new StringWriter(); + JsonGenerator gen = new JsonFactory().createJsonGenerator(sw); + gen.writeStartObject(); + + final BigDecimal dec = new BigDecimal("0.1"); + final String TEXT = "\"some\nString!\""; + + gen.writeNullField("null"); + gen.writeBooleanField("bt", true); + gen.writeBooleanField("bf", false); + gen.writeNumberField("int", -1289); + gen.writeNumberField("dec", dec); + + gen.writeObjectFieldStart("ob"); + gen.writeStringField("str", TEXT); + gen.writeEndObject(); + + gen.writeArrayFieldStart("arr"); + gen.writeEndArray(); + + gen.writeEndObject(); + gen.close(); + + String docStr = sw.toString(); + JsonParser jp = createParserUsingReader(docStr); + assertEquals(JsonToken.START_OBJECT, jp.nextToken()); + + assertEquals(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals("null", jp.getText()); + assertEquals(JsonToken.VALUE_NULL, jp.nextToken()); + assertEquals(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals("bt", jp.getText()); + assertEquals(JsonToken.VALUE_TRUE, jp.nextToken()); + assertEquals(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals("bf", jp.getText()); + assertEquals(JsonToken.VALUE_FALSE, jp.nextToken()); + assertEquals(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals("int", jp.getText()); + assertEquals(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals("dec", jp.getText()); + assertEquals(JsonToken.VALUE_NUMBER_FLOAT, jp.nextToken()); + + assertEquals(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals("ob", jp.getText()); + assertEquals(JsonToken.START_OBJECT, jp.nextToken()); + assertEquals(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals("str", jp.getText()); + assertEquals(JsonToken.VALUE_STRING, jp.nextToken()); + assertEquals(TEXT, getAndVerifyText(jp)); + assertEquals(JsonToken.END_OBJECT, jp.nextToken()); + + assertEquals(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals("arr", jp.getText()); + assertEquals(JsonToken.START_ARRAY, jp.nextToken()); + assertEquals(JsonToken.END_ARRAY, jp.nextToken()); + + assertEquals(JsonToken.END_OBJECT, jp.nextToken()); + assertEquals(null, jp.nextToken()); + jp.close(); + } + + /** + * Tests to cover [JACKSON-164] + */ + public void testConvenienceMethodsWithNulls() + throws Exception + { + StringWriter sw = new StringWriter(); + JsonGenerator gen = new JsonFactory().createJsonGenerator(sw); + gen.writeStartObject(); + + gen.writeStringField("str", null); + gen.writeNumberField("num", null); + gen.writeObjectField("obj", null); + + gen.writeEndObject(); + gen.close(); + + String docStr = sw.toString(); + JsonParser jp = createParserUsingReader(docStr); + assertEquals(JsonToken.START_OBJECT, jp.nextToken()); + + assertEquals(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals("str", jp.getCurrentName()); + assertEquals(JsonToken.VALUE_NULL, jp.nextToken()); + + assertEquals(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals("num", jp.getCurrentName()); + assertEquals(JsonToken.VALUE_NULL, jp.nextToken()); + + assertEquals(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals("obj", jp.getCurrentName()); + assertEquals(JsonToken.VALUE_NULL, jp.nextToken()); + + assertEquals(JsonToken.END_OBJECT, jp.nextToken()); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/main/TestGeneratorWithSerializedString.java b/1.9.10/src/test/org/codehaus/jackson/main/TestGeneratorWithSerializedString.java new file mode 100644 index 0000000..c96f9fd --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/main/TestGeneratorWithSerializedString.java
@@ -0,0 +1,95 @@ +package org.codehaus.jackson.main; + +import java.io.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.io.SerializedString; + +public class TestGeneratorWithSerializedString + extends main.BaseTest +{ + final static String NAME_WITH_QUOTES = "\"name\""; + final static String NAME_WITH_LATIN1 = "P\u00f6ll\u00f6"; + + private final SerializedString quotedName = new SerializedString(NAME_WITH_QUOTES); + private final SerializedString latin1Name = new SerializedString(NAME_WITH_LATIN1); + + public void testSimple() throws Exception + { + JsonFactory jf = new JsonFactory(); + + // First using char-backed generator + StringWriter sw = new StringWriter(); + JsonGenerator jgen = jf.createJsonGenerator(sw); + _writeSimple(jgen); + jgen.close(); + String json = sw.toString(); + _verifySimple(jf.createJsonParser(json)); + + // then using UTF-8 + ByteArrayOutputStream out = new ByteArrayOutputStream(); + jgen = jf.createJsonGenerator(out, JsonEncoding.UTF8); + _writeSimple(jgen); + jgen.close(); + byte[] jsonB = out.toByteArray(); + _verifySimple(jf.createJsonParser(jsonB)); + } + + /* + /********************************************************** + /* Helper methods + /********************************************************** + */ + + private void _writeSimple(JsonGenerator jgen) throws Exception + { + // Let's just write array of 2 objects + jgen.writeStartArray(); + + jgen.writeStartObject(); + jgen.writeFieldName(quotedName); + jgen.writeString("a"); + jgen.writeFieldName(latin1Name); + jgen.writeString("b"); + jgen.writeEndObject(); + + jgen.writeStartObject(); + jgen.writeFieldName(latin1Name); + jgen.writeString("c"); + jgen.writeFieldName(quotedName); + jgen.writeString("d"); + jgen.writeEndObject(); + + jgen.writeEndArray(); + } + + private void _verifySimple(JsonParser jp) throws Exception + { + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + + assertToken(JsonToken.START_OBJECT, jp.nextToken()); + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals(NAME_WITH_QUOTES, jp.getText()); + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + assertEquals("a", jp.getText()); + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals(NAME_WITH_LATIN1, jp.getText()); + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + assertEquals("b", jp.getText()); + assertToken(JsonToken.END_OBJECT, jp.nextToken()); + + assertToken(JsonToken.START_OBJECT, jp.nextToken()); + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals(NAME_WITH_LATIN1, jp.getText()); + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + assertEquals("c", jp.getText()); + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals(NAME_WITH_QUOTES, jp.getText()); + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + assertEquals("d", jp.getText()); + assertToken(JsonToken.END_OBJECT, jp.nextToken()); + + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + assertNull(jp.nextToken()); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/main/TestJsonFactory.java b/1.9.10/src/test/org/codehaus/jackson/main/TestJsonFactory.java new file mode 100644 index 0000000..8975ab1 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/main/TestJsonFactory.java
@@ -0,0 +1,83 @@ +package org.codehaus.jackson.main; + +import java.io.*; + +import org.codehaus.jackson.*; + +public class TestJsonFactory + extends main.BaseTest +{ + public void testGeneratorFeatures() throws Exception + { + JsonFactory f = new JsonFactory(); + assertNull(f.getCodec()); + + f.configure(JsonGenerator.Feature.QUOTE_FIELD_NAMES, true); + assertTrue(f.isEnabled(JsonGenerator.Feature.QUOTE_FIELD_NAMES)); + f.configure(JsonGenerator.Feature.QUOTE_FIELD_NAMES, false); + assertFalse(f.isEnabled(JsonGenerator.Feature.QUOTE_FIELD_NAMES)); + } + + public void testParserFeatures() throws Exception + { + JsonFactory f = new JsonFactory(); + assertNull(f.getCodec()); + + f.configure(JsonParser.Feature.INTERN_FIELD_NAMES, true); + assertTrue(f.isEnabled(JsonParser.Feature.INTERN_FIELD_NAMES)); + f.configure(JsonParser.Feature.INTERN_FIELD_NAMES, false); + assertFalse(f.isEnabled(JsonParser.Feature.INTERN_FIELD_NAMES)); + } + + @SuppressWarnings("deprecation") + public void testDeprecatedFeatures() throws Exception + { + JsonFactory f = new JsonFactory(); + f.enableParserFeature(JsonParser.Feature.ALLOW_COMMENTS); + assertTrue(f.isParserFeatureEnabled(JsonParser.Feature.ALLOW_COMMENTS)); + f.disableParserFeature(JsonParser.Feature.ALLOW_COMMENTS); + assertFalse(f.isParserFeatureEnabled(JsonParser.Feature.ALLOW_COMMENTS)); + f.setParserFeature(JsonParser.Feature.ALLOW_COMMENTS, true); + assertTrue(f.isParserFeatureEnabled(JsonParser.Feature.ALLOW_COMMENTS)); + + f.enableGeneratorFeature(JsonGenerator.Feature.QUOTE_FIELD_NAMES); + assertTrue(f.isGeneratorFeatureEnabled(JsonGenerator.Feature.QUOTE_FIELD_NAMES)); + f.disableGeneratorFeature(JsonGenerator.Feature.QUOTE_FIELD_NAMES); + assertFalse(f.isGeneratorFeatureEnabled(JsonGenerator.Feature.QUOTE_FIELD_NAMES)); + f.setGeneratorFeature(JsonGenerator.Feature.QUOTE_FIELD_NAMES, true); + assertTrue(f.isGeneratorFeatureEnabled(JsonGenerator.Feature.QUOTE_FIELD_NAMES)); + + } + + public void testJsonWithFiles() throws Exception + { + File file = File.createTempFile("jackson-test", null); + file.deleteOnExit(); + + JsonFactory f = new JsonFactory(); + + // First: create file via generator.. and use an odd encoding + JsonGenerator jg = f.createJsonGenerator(file, JsonEncoding.UTF16_LE); + jg.writeStartObject(); + jg.writeRaw(" "); + jg.writeEndObject(); + jg.close(); + + // Ok: first read file directly + JsonParser jp = f.createJsonParser(file); + assertToken(JsonToken.START_OBJECT, jp.nextToken()); + assertToken(JsonToken.END_OBJECT, jp.nextToken()); + assertNull(jp.nextToken()); + jp.close(); + + // Then via URL: + jp = f.createJsonParser(file.toURI().toURL()); + assertToken(JsonToken.START_OBJECT, jp.nextToken()); + assertToken(JsonToken.END_OBJECT, jp.nextToken()); + assertNull(jp.nextToken()); + jp.close(); + + // ok, delete once we are done + file.delete(); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/main/TestJsonGenerator.java b/1.9.10/src/test/org/codehaus/jackson/main/TestJsonGenerator.java new file mode 100644 index 0000000..e2e24e4 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/main/TestJsonGenerator.java
@@ -0,0 +1,228 @@ +package org.codehaus.jackson.main; + +import org.codehaus.jackson.*; + +import java.io.*; + +/** + * Set of basic unit tests for verifying that the basic generator + * functionality works as expected. + */ +public class TestJsonGenerator + extends main.BaseTest +{ + // // // First, tests for primitive (non-structured) values + + public void testStringWrite() + throws Exception + { + JsonFactory jf = new JsonFactory(); + String[] inputStrings = new String[] { "", "X", "1234567890" }; + for (int useReader = 0; useReader < 2; ++useReader) { + for (int writeString = 0; writeString < 2; ++writeString) { + for (int strIx = 0; strIx < inputStrings.length; ++strIx) { + String input = inputStrings[strIx]; + JsonGenerator gen; + ByteArrayOutputStream bout = new ByteArrayOutputStream(); + if (useReader != 0) { + gen = jf.createJsonGenerator(new OutputStreamWriter(bout, "UTF-8")); + } else { + gen = jf.createJsonGenerator(bout, JsonEncoding.UTF8); + } + if (writeString > 0) { + gen.writeString(input); + } else { + int len = input.length(); + char[] buffer = new char[len + 20]; + // Let's use non-zero base offset too... + input.getChars(0, len, buffer, strIx); + gen.writeString(buffer, strIx, len); + } + gen.flush(); + gen.close(); + JsonParser jp = jf.createJsonParser(new ByteArrayInputStream(bout.toByteArray())); + + JsonToken t = jp.nextToken(); + assertNotNull("Document \""+bout.toString("UTF-8")+"\" yielded no tokens", t); + assertEquals(JsonToken.VALUE_STRING, t); + assertEquals(input, jp.getText()); + assertEquals(null, jp.nextToken()); + jp.close(); + } + } + } + } + + public void testIntWrite() + throws Exception + { + doTestIntWrite(false); + doTestIntWrite(true); + } + + public void testLongWrite() + throws Exception + { + doTestLongWrite(false); + doTestLongWrite(true); + } + + public void testBooleanWrite() + throws Exception + { + for (int i = 0; i < 4; ++i) { + boolean state = (i & 1) == 0; + boolean pad = (i & 2) == 0; + StringWriter sw = new StringWriter(); + JsonGenerator gen = new JsonFactory().createJsonGenerator(sw); + gen.writeBoolean(state); + if (pad) { + gen.writeRaw(" "); + } + gen.close(); + String docStr = sw.toString(); + JsonParser jp = createParserUsingReader(docStr); + JsonToken t = jp.nextToken(); + String exp = Boolean.valueOf(state).toString(); + if (!exp.equals(jp.getText())) { + fail("Expected '"+exp+"', got '"+jp.getText()); + } + assertEquals(state ? JsonToken.VALUE_TRUE : JsonToken.VALUE_FALSE, t); + assertEquals(null, jp.nextToken()); + jp.close(); + } + } + + public void testNullWrite() + throws Exception + { + for (int i = 0; i < 2; ++i) { + boolean pad = (i & 1) == 0; + StringWriter sw = new StringWriter(); + JsonGenerator gen = new JsonFactory().createJsonGenerator(sw); + gen.writeNull(); + if (pad) { + gen.writeRaw(" "); + } + gen.close(); + String docStr = sw.toString(); + JsonParser jp = createParserUsingReader(docStr); + JsonToken t = jp.nextToken(); + String exp = "null"; + if (!exp.equals(jp.getText())) { + fail("Expected '"+exp+"', got '"+jp.getText()); + } + assertEquals(JsonToken.VALUE_NULL, t); + assertEquals(null, jp.nextToken()); + jp.close(); + } + } + + // // Then root-level output testing + + public void testRootIntsWrite() + throws Exception + { + StringWriter sw = new StringWriter(); + JsonGenerator gen = new JsonFactory().createJsonGenerator(sw); + gen.writeNumber(1); + gen.writeNumber(2); + gen.writeNumber(-13); + gen.close(); + + String docStr = sw.toString(); + + JsonParser jp = createParserUsingReader(docStr); + assertEquals(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(1, jp.getIntValue()); + assertEquals(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(2, jp.getIntValue()); + assertEquals(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(-13, jp.getIntValue()); + jp.close(); + } + + // Convenience methods + + public void testFieldValueWrites() + throws Exception + { + StringWriter sw = new StringWriter(); + JsonGenerator gen = new JsonFactory().createJsonGenerator(sw); + gen.writeStartObject(); + gen.writeNumberField("long", 3L); + gen.writeNumberField("double", 0.25); + gen.writeNumberField("float", -0.25f); + gen.writeEndObject(); + gen.close(); + + assertEquals("{\"long\":3,\"double\":0.25,\"float\":-0.25}", sw.toString().trim()); + } + + /* + /********************************************************** + /* Internal methods + /********************************************************** + */ + + private void doTestIntWrite(boolean pad) + throws Exception + { + int[] VALUES = new int[] { + 0, 1, -9, 32, -32, 57, 13240, -9999, Integer.MAX_VALUE, Integer.MAX_VALUE + }; + for (int i = 0; i < VALUES.length; ++i) { + int VALUE = VALUES[i]; + StringWriter sw = new StringWriter(); + JsonGenerator gen = new JsonFactory().createJsonGenerator(sw); + gen.writeNumber(VALUE); + if (pad) { + gen.writeRaw(" "); + } + gen.close(); + String docStr = sw.toString(); + JsonParser jp = createParserUsingReader(docStr); + JsonToken t = jp.nextToken(); + assertNotNull("Document \""+docStr+"\" yielded no tokens", t); + // Number are always available as lexical representation too + String exp = ""+VALUE; + if (!exp.equals(jp.getText())) { + fail("Expected '"+exp+"', got '"+jp.getText()); + } + assertEquals(JsonToken.VALUE_NUMBER_INT, t); + assertEquals(VALUE, jp.getIntValue()); + assertEquals(null, jp.nextToken()); + jp.close(); + } + } + + private void doTestLongWrite(boolean pad) + throws Exception + { + long[] VALUES = new long[] { + 0L, 1L, -1L, -12005002294L, Long.MIN_VALUE, Long.MAX_VALUE + }; + for (int i = 0; i < VALUES.length; ++i) { + long VALUE = VALUES[i]; + StringWriter sw = new StringWriter(); + JsonGenerator gen = new JsonFactory().createJsonGenerator(sw); + gen.writeNumber(VALUE); + if (pad) { + gen.writeRaw(" "); + } + gen.close(); + String docStr = sw.toString(); + JsonParser jp = createParserUsingReader(docStr); + JsonToken t = jp.nextToken(); + assertNotNull("Document \""+docStr+"\" yielded no tokens", t); + String exp = ""+VALUE; + if (!exp.equals(jp.getText())) { + fail("Expected '"+exp+"', got '"+jp.getText()); + } + assertEquals(JsonToken.VALUE_NUMBER_INT, t); + assertEquals(VALUE, jp.getLongValue()); + assertEquals(null, jp.nextToken()); + jp.close(); + } + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/main/TestJsonGeneratorFeatures.java b/1.9.10/src/test/org/codehaus/jackson/main/TestJsonGeneratorFeatures.java new file mode 100644 index 0000000..f00eb97 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/main/TestJsonGeneratorFeatures.java
@@ -0,0 +1,146 @@ +package org.codehaus.jackson.main; + +import java.io.*; +import java.math.BigDecimal; +import java.math.BigInteger; + +import org.codehaus.jackson.*; + +/** + * Set of basic unit tests for verifying that the basic generator + * functionality works as expected. + */ +public class TestJsonGeneratorFeatures + extends main.BaseTest +{ + public void testConfigDefaults() throws IOException + { + JsonFactory jf = new JsonFactory(); + JsonGenerator jg = jf.createJsonGenerator(new StringWriter()); + assertFalse(jg.isEnabled(JsonGenerator.Feature.WRITE_NUMBERS_AS_STRINGS)); + } + + public void testFieldNameQuoting() throws IOException + { + JsonFactory jf = new JsonFactory(); + // by default, quoting should be enabled + _testFieldNameQuoting(jf, true); + // can disable it + jf.disable(JsonGenerator.Feature.QUOTE_FIELD_NAMES); + _testFieldNameQuoting(jf, false); + // and (re)enable: + jf.enable(JsonGenerator.Feature.QUOTE_FIELD_NAMES); + _testFieldNameQuoting(jf, true); + } + + public void testNonNumericQuoting() + throws IOException + { + JsonFactory jf = new JsonFactory(); + // by default, quoting should be enabled + _testNonNumericQuoting(jf, true); + // can disable it + jf.disable(JsonGenerator.Feature.QUOTE_NON_NUMERIC_NUMBERS); + _testNonNumericQuoting(jf, false); + // and (re)enable: + jf.enable(JsonGenerator.Feature.QUOTE_NON_NUMERIC_NUMBERS); + _testNonNumericQuoting(jf, true); + } + + /** + * Testing for [JACKSON-176], ability to force serializing numbers + * as JSON Strings. + */ + public void testNumbersAsJSONStrings() throws IOException + { + JsonFactory jf = new JsonFactory(); + // by default should output numbers as-is: + assertEquals("[1,2,1.25,2.25,3001,0.5,-1]", _writeNumbers(jf)); + + // but if overridden, quotes as Strings + jf.configure(JsonGenerator.Feature.WRITE_NUMBERS_AS_STRINGS, true); + assertEquals("[\"1\",\"2\",\"1.25\",\"2.25\",\"3001\",\"0.5\",\"-1\"]", + _writeNumbers(jf)); + } + + private String _writeNumbers(JsonFactory jf) throws IOException + { + StringWriter sw = new StringWriter(); + JsonGenerator jg = jf.createJsonGenerator(sw); + + jg.writeStartArray(); + jg.writeNumber(1); + jg.writeNumber(2L); + jg.writeNumber(1.25); + jg.writeNumber(2.25f); + jg.writeNumber(BigInteger.valueOf(3001)); + jg.writeNumber(BigDecimal.valueOf(0.5)); + jg.writeNumber("-1"); + jg.writeEndArray(); + jg.close(); + + return sw.toString(); + } + + + @SuppressWarnings("deprecation") + public void testDeprecated() throws IOException + { + JsonFactory jf = new JsonFactory(); + JsonGenerator jg = jf.createJsonGenerator(new StringWriter()); + + jg.enableFeature(JsonGenerator.Feature.QUOTE_FIELD_NAMES); + assertTrue(jg.isFeatureEnabled(JsonGenerator.Feature.QUOTE_FIELD_NAMES)); + jg.disableFeature(JsonGenerator.Feature.QUOTE_FIELD_NAMES); + assertFalse(jg.isFeatureEnabled(JsonGenerator.Feature.QUOTE_FIELD_NAMES)); + jg.setFeature(JsonGenerator.Feature.QUOTE_FIELD_NAMES, true); + assertTrue(jg.isFeatureEnabled(JsonGenerator.Feature.QUOTE_FIELD_NAMES)); + } + + /* + /////////////////////////////////////////////////////////// + // Helper methods + /////////////////////////////////////////////////////////// + */ + + private void _testFieldNameQuoting(JsonFactory jf, boolean quoted) + throws IOException + { + StringWriter sw = new StringWriter(); + JsonGenerator jg = jf.createJsonGenerator(sw); + jg.writeStartObject(); + jg.writeFieldName("foo"); + jg.writeNumber(1); + jg.writeEndObject(); + jg.close(); + + String result = sw.toString(); + if (quoted) { + assertEquals("{\"foo\":1}", result); + } else { + assertEquals("{foo:1}", result); + } + } + private void _testNonNumericQuoting(JsonFactory jf, boolean quoted) + throws IOException + { + StringWriter sw = new StringWriter(); + JsonGenerator jg = jf.createJsonGenerator(sw); + jg.writeStartObject(); + jg.writeFieldName("double"); + jg.writeNumber(Double.NaN); + jg.writeEndObject(); + jg.writeStartObject(); + jg.writeFieldName("float"); + jg.writeNumber(Float.NaN); + jg.writeEndObject(); + jg.close(); + + String result = sw.toString(); + if (quoted) { + assertEquals("{\"double\":\"NaN\"} {\"float\":\"NaN\"}", result); + } else { + assertEquals("{\"double\":NaN} {\"float\":NaN}", result); + } + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/main/TestJsonParserSymbols.java b/1.9.10/src/test/org/codehaus/jackson/main/TestJsonParserSymbols.java new file mode 100644 index 0000000..07ab829 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/main/TestJsonParserSymbols.java
@@ -0,0 +1,109 @@ +package org.codehaus.jackson.main; + +import java.io.IOException; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.impl.*; + +/** + * Unit tests for verifying that {@link JsonParser} instances properly + * merge back symbols to the root symbol table + */ +public class TestJsonParserSymbols + extends main.BaseTest +{ + final static String JSON = "{ \"a\" : 3, \"aaa\" : 4, \"_a\" : 0 }"; + + public void testByteSymbolsWithClose() throws Exception + { + _testWithClose(true); + } + + public void testByteSymbolsWithEOF() throws Exception + { + MyJsonFactory f = new MyJsonFactory(); + JsonParser jp = _getParser(f, JSON, true); + while (jp.nextToken() != null) { + // shouldn't update before hitting end + assertEquals(0, f.byteSymbolCount()); + } + // but now should have it after hitting EOF + assertEquals(3, f.byteSymbolCount()); + jp.close(); + assertEquals(3, f.byteSymbolCount()); + } + + public void testCharSymbolsWithClose() throws Exception + { + _testWithClose(false); + } + + public void testCharSymbolsWithEOF() throws Exception + { + MyJsonFactory f = new MyJsonFactory(); + JsonParser jp = _getParser(f, JSON, false); + while (jp.nextToken() != null) { + // shouldn't update before hitting end + assertEquals(0, f.charSymbolCount()); + } + // but now should have it + assertEquals(3, f.charSymbolCount()); + jp.close(); + assertEquals(3, f.charSymbolCount()); + } + + /* + //////////////////////////////////// + // Helper methods + //////////////////////////////////// + */ + + private void _testWithClose(boolean useBytes) throws IOException + { + MyJsonFactory f = new MyJsonFactory(); + JsonParser jp = _getParser(f, JSON, useBytes); + // Let's check 2 names + assertToken(JsonToken.START_OBJECT, jp.nextToken()); + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + + // shouldn't update before close or EOF: + assertEquals(0, useBytes ? f.byteSymbolCount() : f.charSymbolCount()); + jp.close(); + // but should after close + assertEquals(2, useBytes ? f.byteSymbolCount() : f.charSymbolCount()); + } + + private JsonParser _getParser(MyJsonFactory f, String doc, boolean useBytes) throws IOException + { + JsonParser jp; + if (useBytes) { + jp = f.createJsonParser(doc.getBytes("UTF-8")); + assertEquals(Utf8StreamParser.class, jp.getClass()); + assertEquals(0, f.byteSymbolCount()); + } else { + jp = f.createJsonParser(doc); + assertEquals(ReaderBasedParser.class, jp.getClass()); + assertEquals(0, f.charSymbolCount()); + } + return jp; + } + + /* + //////////////////////////////////// + // Helper classes + //////////////////////////////////// + */ + + /** + * To peek into state of "root" symbol tables (parent of all symbol + * tables for parsers constructed by this factory) we need to + * add some methods. + */ + final static class MyJsonFactory extends JsonFactory + { + public int byteSymbolCount() { return _rootByteSymbols.size(); } + public int charSymbolCount() { return _rootCharSymbols.size(); } + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/main/TestNumberParsing.java b/1.9.10/src/test/org/codehaus/jackson/main/TestNumberParsing.java new file mode 100644 index 0000000..0f3b76c --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/main/TestNumberParsing.java
@@ -0,0 +1,83 @@ +package org.codehaus.jackson.main; + +import org.codehaus.jackson.io.NumberInput; + +/** + * Set of basic unit tests for verifying that the low-level number + * handling methods work as expected. + */ +public class TestNumberParsing + extends main.BaseTest +{ + public void testIntParsing() throws Exception + { + char[] testChars = "123456789".toCharArray(); + + assertEquals(3, NumberInput.parseInt(testChars, 2, 1)); + assertEquals(123, NumberInput.parseInt(testChars, 0, 3)); + assertEquals(2345, NumberInput.parseInt(testChars, 1, 4)); + assertEquals(9, NumberInput.parseInt(testChars, 8, 1)); + assertEquals(456789, NumberInput.parseInt(testChars, 3, 6)); + assertEquals(23456, NumberInput.parseInt(testChars, 1, 5)); + assertEquals(123456789, NumberInput.parseInt(testChars, 0, 9)); + + testChars = "32".toCharArray(); + assertEquals(32, NumberInput.parseInt(testChars, 0, 2)); + testChars = "189".toCharArray(); + assertEquals(189, NumberInput.parseInt(testChars, 0, 3)); + + testChars = "10".toCharArray(); + assertEquals(10, NumberInput.parseInt(testChars, 0, 2)); + assertEquals(0, NumberInput.parseInt(testChars, 1, 1)); + } + + public void testIntParsingWithStrings() throws Exception + { + assertEquals(3, NumberInput.parseInt("3")); + assertEquals(0, NumberInput.parseInt("0")); + assertEquals(-3, NumberInput.parseInt("-3")); + assertEquals(27, NumberInput.parseInt("27")); + assertEquals(-31, NumberInput.parseInt("-31")); + assertEquals(271, NumberInput.parseInt("271")); + assertEquals(-131, NumberInput.parseInt("-131")); + assertEquals(2709, NumberInput.parseInt("2709")); + assertEquals(-9999, NumberInput.parseInt("-9999")); + assertEquals(Integer.MIN_VALUE, NumberInput.parseInt(""+Integer.MIN_VALUE)); + assertEquals(Integer.MAX_VALUE, NumberInput.parseInt(""+Integer.MAX_VALUE)); + } + + public void testLongParsing() throws Exception + { + char[] testChars = "123456789012345678".toCharArray(); + + assertEquals(123456789012345678L, NumberInput.parseLong(testChars, 0, testChars.length)); + } + + // Unit test for [JACKSON-491] + public void testLongBoundsChecks() throws Exception + { + String minLong = String.valueOf(Long.MIN_VALUE).substring(1); + String maxLong = String.valueOf(Long.MAX_VALUE); + final String VALUE_491 = "1323372036854775807"; // is within range (JACKSON-491) + final String OVERFLOW = "9999999999999999999"; // and this one is clearly out + + assertTrue(NumberInput.inLongRange(minLong, true)); + assertTrue(NumberInput.inLongRange(maxLong, false)); + assertTrue(NumberInput.inLongRange(VALUE_491, true)); + assertTrue(NumberInput.inLongRange(VALUE_491, false)); + assertFalse(NumberInput.inLongRange(OVERFLOW, false)); + assertFalse(NumberInput.inLongRange(OVERFLOW, true)); + + char[] cbuf = minLong.toCharArray(); + assertTrue(NumberInput.inLongRange(cbuf, 0, cbuf.length, true)); + cbuf = maxLong.toCharArray(); + assertTrue(NumberInput.inLongRange(cbuf, 0, cbuf.length, false)); + cbuf = VALUE_491.toCharArray(); + assertTrue(NumberInput.inLongRange(cbuf, 0, cbuf.length, true)); + assertTrue(NumberInput.inLongRange(cbuf, 0, cbuf.length, false)); + cbuf = OVERFLOW.toCharArray(); + assertFalse(NumberInput.inLongRange(cbuf, 0, cbuf.length, true)); + assertFalse(NumberInput.inLongRange(cbuf, 0, cbuf.length, false)); + } + +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/main/TestNumericValues.java b/1.9.10/src/test/org/codehaus/jackson/main/TestNumericValues.java new file mode 100644 index 0000000..85a5541 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/main/TestNumericValues.java
@@ -0,0 +1,375 @@ +package org.codehaus.jackson.main; + +import java.math.BigDecimal; +import java.math.BigInteger; + +import org.codehaus.jackson.*; + +/** + * Set of basic unit tests for verifying that the basic parser + * functionality works as expected. + */ +public class TestNumericValues + extends main.BaseTest +{ + public void testSimpleInt() + throws Exception + { + int EXP_I = 1234; + + JsonParser jp = createParserUsingReader("[ "+EXP_I+" ]"); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(JsonParser.NumberType.INT, jp.getNumberType()); + assertEquals(""+EXP_I, jp.getText()); + + assertEquals(EXP_I, jp.getIntValue()); + assertEquals((long) EXP_I, jp.getLongValue()); + assertEquals((double) EXP_I, jp.getDoubleValue()); + assertEquals(BigDecimal.valueOf((long) EXP_I), jp.getDecimalValue()); + } + + public void testIntRange() + throws Exception + { + // let's test with readers and streams, separate code paths: + for (int i = 0; i < 2; ++i) { + String input = "[ "+Integer.MAX_VALUE+","+Integer.MIN_VALUE+" ]"; + JsonParser jp; + if (i == 0) { + jp = createParserUsingReader(input); + } else { + jp = this.createParserUsingStream(input, "UTF-8"); + } + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(JsonParser.NumberType.INT, jp.getNumberType()); + assertEquals(Integer.MAX_VALUE, jp.getIntValue()); + + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(JsonParser.NumberType.INT, jp.getNumberType()); + assertEquals(Integer.MIN_VALUE, jp.getIntValue()); + } + } + + public void testInvalidIntAccess() + throws Exception + { + JsonParser jp = createParserUsingReader("[ \"abc\" ]"); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + try { + jp.getIntValue(); + fail("Expected error trying to call getIntValue on non-numeric value"); + } catch (JsonParseException e) { + verifyException(e, "can not use numeric value accessors"); + } + } + + public void testSimpleLong() + throws Exception + { + long EXP_L = 12345678907L; + + JsonParser jp = createParserUsingReader("[ "+EXP_L+" ]"); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + // beyond int, should be long + assertEquals(JsonParser.NumberType.LONG, jp.getNumberType()); + assertEquals(""+EXP_L, jp.getText()); + + assertEquals(EXP_L, jp.getLongValue()); + // Should get an exception if trying to convert to int + try { + jp.getIntValue(); + } catch (JsonParseException jpe) { + verifyException(jpe, "out of range"); + } + assertEquals((double) EXP_L, jp.getDoubleValue()); + assertEquals(BigDecimal.valueOf((long) EXP_L), jp.getDecimalValue()); + } + + public void testLongRange() + throws Exception + { + for (int i = 0; i < 2; ++i) { + long belowMinInt = -1L + Integer.MIN_VALUE; + long aboveMaxInt = 1L + Integer.MAX_VALUE; + String input = "[ "+Long.MAX_VALUE+","+Long.MIN_VALUE+","+aboveMaxInt+", "+belowMinInt+" ]"; + JsonParser jp; + if (i == 0) { + jp = createParserUsingReader(input); + } else { + jp = this.createParserUsingStream(input, "UTF-8"); + } + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(JsonParser.NumberType.LONG, jp.getNumberType()); + assertEquals(Long.MAX_VALUE, jp.getLongValue()); + + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(JsonParser.NumberType.LONG, jp.getNumberType()); + assertEquals(Long.MIN_VALUE, jp.getLongValue()); + + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(JsonParser.NumberType.LONG, jp.getNumberType()); + assertEquals(aboveMaxInt, jp.getLongValue()); + + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(JsonParser.NumberType.LONG, jp.getNumberType()); + assertEquals(belowMinInt, jp.getLongValue()); + + + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + jp.close(); + } + } + + public void testBigDecimalRange() + throws Exception + { + for (int i = 0; i < 2; ++i) { + // let's test first values outside of Long range + BigInteger small = new BigDecimal(Long.MIN_VALUE).toBigInteger(); + small = small.subtract(BigInteger.ONE); + BigInteger big = new BigDecimal(Long.MAX_VALUE).toBigInteger(); + big = big.add(BigInteger.ONE); + String input = "[ "+small+" , "+big+"]"; + JsonParser jp; + if (i == 0) { + jp = createParserUsingReader(input); + } else { + jp = this.createParserUsingStream(input, "UTF-8"); + } + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(JsonParser.NumberType.BIG_INTEGER, jp.getNumberType()); + assertEquals(small, jp.getBigIntegerValue()); + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(JsonParser.NumberType.BIG_INTEGER, jp.getNumberType()); + assertEquals(big, jp.getBigIntegerValue()); + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + jp.close(); + } +} + + public void testSimpleDouble() + throws Exception + { + final String[] INPUTS = new String[] { + "1234.00", "2.1101567E-16", "1.0e5", "2.5e+5", "9e4", "-12e-3", "0.25" + }; + for (int input = 0; input < 2; ++input) { + for (int i = 0; i < INPUTS.length; ++i) { + + /* Testing double is more difficult, given the rounding + * errors and such. But let's try anyways. + */ + String STR = INPUTS[i]; + double EXP_D = Double.parseDouble(STR); + String DOC = "["+STR+"]"; + + JsonParser jp; + + if (input == 0) { + jp = createParserUsingStream(DOC, "UTF-8"); + } else { + jp = createParserUsingReader(DOC); + } + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + assertToken(JsonToken.VALUE_NUMBER_FLOAT, jp.nextToken()); + assertEquals(STR, jp.getText()); + assertEquals(EXP_D, jp.getDoubleValue()); + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + jp.close(); + } + } + } + + public void testNumbers() + throws Exception + { + final String DOC = "[ -13, 8100200300, 13.5, 0.00010, -2.033 ]"; + + for (int input = 0; input < 2; ++input) { + JsonParser jp; + + if (input == 0) { + jp = createParserUsingStream(DOC, "UTF-8"); + } else { + jp = createParserUsingReader(DOC); + } + + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(-13, jp.getIntValue()); + assertEquals(-13L, jp.getLongValue()); + assertEquals(-13., jp.getDoubleValue()); + assertEquals("-13", jp.getText()); + + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(8100200300L, jp.getLongValue()); + // Should get exception for overflow: + try { + /*int x =*/ jp.getIntValue(); + fail("Expected an exception for overflow"); + } catch (Exception e) { + verifyException(e, "out of range"); + } + assertEquals(8100200300., jp.getDoubleValue()); + assertEquals("8100200300", jp.getText()); + + assertToken(JsonToken.VALUE_NUMBER_FLOAT, jp.nextToken()); + assertEquals(13, jp.getIntValue()); + assertEquals(13L, jp.getLongValue()); + assertEquals(13.5, jp.getDoubleValue()); + assertEquals("13.5", jp.getText()); + + assertToken(JsonToken.VALUE_NUMBER_FLOAT, jp.nextToken()); + assertEquals(0, jp.getIntValue()); + assertEquals(0L, jp.getLongValue()); + assertEquals(0.00010, jp.getDoubleValue()); + assertEquals("0.00010", jp.getText()); + + assertToken(JsonToken.VALUE_NUMBER_FLOAT, jp.nextToken()); + assertEquals(-2, jp.getIntValue()); + assertEquals(-2L, jp.getLongValue()); + assertEquals(-2.033, jp.getDoubleValue()); + assertEquals("-2.033", jp.getText()); + + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + } + } + + public void testLongOverflow() throws Exception + { + BigInteger below = BigInteger.valueOf(Long.MIN_VALUE); + below = below.subtract(BigInteger.ONE); + BigInteger above = BigInteger.valueOf(Long.MAX_VALUE); + above = above.add(BigInteger.ONE); + + String DOC_BELOW = below.toString() + " "; + String DOC_ABOVE = below.toString() + " "; + for (int input = 0; input < 2; ++input) { + JsonParser jp; + + if (input == 0) { + jp = createParserUsingStream(DOC_BELOW, "UTF-8"); + } else { + jp = createParserUsingReader(DOC_BELOW); + } + jp.nextToken(); + try { + long x = jp.getLongValue(); + fail("Expected an exception for underflow (input "+jp.getText()+"): instead, got long value: "+x); + } catch (JsonParseException e) { + verifyException(e, "out of range of long"); + } + jp.close(); + + if (input == 0) { + jp = createParserUsingStream(DOC_ABOVE, "UTF-8"); + } else { + jp = createParserUsingReader(DOC_ABOVE); + } + jp.nextToken(); + try { + long x = jp.getLongValue(); + fail("Expected an exception for underflow (input "+jp.getText()+"): instead, got long value: "+x); + } catch (JsonParseException e) { + verifyException(e, "out of range of long"); + } + jp.close(); + + } + } + + /** + * Method that tries to test that number parsing works in cases where + * input is split between buffer boundaries. + */ + public void testParsingOfLongerSequences() + throws Exception + { + double[] values = new double[] { 0.01, -10.5, 2.1e9, 4.0e-8 }; + StringBuilder sb = new StringBuilder(); + + for (int i = 0; i < values.length; ++i) { + if (i > 0) { + sb.append(','); + } + sb.append(values[i]); + } + String segment = sb.toString(); + + int COUNT = 1000; + sb = new StringBuilder(COUNT * segment.length() + 20); + sb.append("["); + for (int i = 0; i < COUNT; ++i) { + if (i > 0) { + sb.append(','); + } + sb.append(segment); + sb.append('\n'); + // let's add somewhat arbitray number of spaces + int x = (i & 3); + if (i > 300) { + x += i % 5; + } + while (--x > 0) { + sb.append(' '); + } + } + sb.append("]"); + String DOC = sb.toString(); + + for (int input = 0; input < 2; ++input) { + JsonParser jp; + + if (input == 0) { + jp = createParserUsingStream(DOC, "UTF-8"); + } else { + jp = createParserUsingReader(DOC); + } + + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + for (int i = 0; i < COUNT; ++i) { + for (double d : values) { + assertToken(JsonToken.VALUE_NUMBER_FLOAT, jp.nextToken()); + assertEquals(d, jp.getDoubleValue()); + } + } + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + } + } + + /* + /********************************************************** + /* New tests for 1.3 features + /********************************************************** + */ + + public void testSimpleBoolean() + throws Exception + { + JsonParser jp = createParserUsingReader("[ true ]"); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + assertToken(JsonToken.VALUE_TRUE, jp.nextToken()); + assertEquals(true, jp.getBooleanValue()); + } + + public void testInvalidBooleanAccess() + throws Exception + { + JsonParser jp = createParserUsingReader("[ \"abc\" ]"); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + try { + jp.getBooleanValue(); + fail("Expected error trying to call getBooleanValue on non-boolean value"); + } catch (JsonParseException e) { + verifyException(e, "not of boolean type"); + } + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/main/TestParserClosing.java b/1.9.10/src/test/org/codehaus/jackson/main/TestParserClosing.java new file mode 100644 index 0000000..4830c9f --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/main/TestParserClosing.java
@@ -0,0 +1,167 @@ +package org.codehaus.jackson.main; + +import main.BaseTest; +import static org.junit.Assert.*; + +import org.codehaus.jackson.*; + +import java.io.*; + +/** + * Set of basic unit tests that verify that the closing (or not) of + * the underlying source occurs as expected and specified + * by documentation. + */ +public class TestParserClosing + extends BaseTest +{ + /** + * This unit test checks the default behaviour; with no auto-close, no + * automatic closing should occur, nor explicit one unless specific + * forcing method is used. + */ + public void testNoAutoCloseReader() + throws Exception + { + final String DOC = "[ 1 ]"; + + JsonFactory f = new JsonFactory(); + + // Check the default settings + assertTrue(f.isEnabled(JsonParser.Feature.AUTO_CLOSE_SOURCE)); + // then change + f.disable(JsonParser.Feature.AUTO_CLOSE_SOURCE); + assertFalse(f.isEnabled(JsonParser.Feature.AUTO_CLOSE_SOURCE)); + MyReader input = new MyReader(DOC); + JsonParser jp = f.createJsonParser(input); + + // shouldn't be closed to begin with... + assertFalse(input.isClosed()); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + assertNull(jp.nextToken()); + // normally would be closed now + assertFalse(input.isClosed()); + // regular close won't close it either: + jp.close(); + assertFalse(input.isClosed()); + + } + + public void testAutoCloseReader() throws Exception + { + final String DOC = "[ 1 ]"; + + JsonFactory f = new JsonFactory(); + f.enable(JsonParser.Feature.AUTO_CLOSE_SOURCE); + assertTrue(f.isEnabled(JsonParser.Feature.AUTO_CLOSE_SOURCE)); + MyReader input = new MyReader(DOC); + JsonParser jp = f.createJsonParser(input); + assertFalse(input.isClosed()); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + // but can close half-way through + jp.close(); + assertTrue(input.isClosed()); + + // And then let's test implicit close at the end too: + input = new MyReader(DOC); + jp = f.createJsonParser(input); + assertFalse(input.isClosed()); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + assertNull(jp.nextToken()); + assertTrue(input.isClosed()); + } + + public void testNoAutoCloseInputStream() + throws Exception + { + final String DOC = "[ 1 ]"; + JsonFactory f = new JsonFactory(); + + f.disable(JsonParser.Feature.AUTO_CLOSE_SOURCE); + MyStream input = new MyStream(DOC.getBytes("UTF-8")); + JsonParser jp = f.createJsonParser(input); + + // shouldn't be closed to begin with... + assertFalse(input.isClosed()); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + assertNull(jp.nextToken()); + // normally would be closed now + assertFalse(input.isClosed()); + // regular close won't close it either: + jp.close(); + assertFalse(input.isClosed()); + } + + // [JACKSON-287] + public void testReleaseContentBytes() throws Exception + { + byte[] input = "[1]foobar".getBytes("UTF-8"); + JsonParser jp = new JsonFactory().createJsonParser(input); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + // theoretically could have only read subset; but current impl is more greedy + assertEquals(6, jp.releaseBuffered(out)); + assertArrayEquals("foobar".getBytes("UTF-8"), out.toByteArray()); + } + + public void testReleaseContentChars() throws Exception + { + JsonParser jp = new JsonFactory().createJsonParser("[true]xyz"); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + assertToken(JsonToken.VALUE_TRUE, jp.nextToken()); + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + StringWriter sw = new StringWriter(); + // theoretically could have only read subset; but current impl is more greedy + assertEquals(3, jp.releaseBuffered(sw)); + assertEquals("xyz", sw.toString()); + } + + /* + /********************************************************** + /* Helper classes + /********************************************************** + */ + + final static class MyReader extends StringReader + { + boolean mIsClosed = false; + + public MyReader(String contents) { + super(contents); + } + + @Override + public void close() { + mIsClosed = true; + super.close(); + } + + public boolean isClosed() { return mIsClosed; } + } + + final static class MyStream extends ByteArrayInputStream + { + boolean mIsClosed = false; + + public MyStream(byte[] data) { + super(data); + } + + @Override + public void close() throws IOException { + mIsClosed = true; + super.close(); + } + + public boolean isClosed() { return mIsClosed; } + } + +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/main/TestParserFeatures.java b/1.9.10/src/test/org/codehaus/jackson/main/TestParserFeatures.java new file mode 100644 index 0000000..2bca736 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/main/TestParserFeatures.java
@@ -0,0 +1,102 @@ +package org.codehaus.jackson.main; + +import org.codehaus.jackson.*; + +/** + * Unit tests for verifying that additional <code>JsonParser.Feature</code> + * settings work as expected. + */ +public class TestParserFeatures + extends main.BaseTest +{ + public void testDefaultSettings() + { + JsonFactory f = new JsonFactory(); + assertTrue(f.isEnabled(JsonParser.Feature.AUTO_CLOSE_SOURCE)); + assertFalse(f.isEnabled(JsonParser.Feature.ALLOW_COMMENTS)); + assertFalse(f.isEnabled(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES)); + assertFalse(f.isEnabled(JsonParser.Feature.ALLOW_SINGLE_QUOTES)); + assertFalse(f.isEnabled(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS)); + } + + public void testQuotesRequired() throws Exception + { + _testQuotesRequired(false); + _testQuotesRequired(true); + } + + + // // Tests for [JACKSON-208], unquoted tabs: + + public void testTabsDefault() throws Exception + { + _testTabsDefault(false); + _testTabsDefault(true); + } + + public void testTabsEnabled() throws Exception + { + _testTabsEnabled(false); + _testTabsEnabled(true); + } + + /* + /**************************************************************** + /* Secondary test methods + /**************************************************************** + */ + + private void _testQuotesRequired(boolean useStream) throws Exception + { + final String JSON = "{ test : 3 }"; + final String EXP_ERROR_FRAGMENT = "was expecting double-quote to start"; + JsonFactory f = new JsonFactory(); + JsonParser jp = useStream ? + createParserUsingStream(f, JSON, "UTF-8") + : createParserUsingReader(f, JSON) + ; + + assertToken(JsonToken.START_OBJECT, jp.nextToken()); + try { + jp.nextToken(); + } catch (JsonParseException je) { + verifyException(je, EXP_ERROR_FRAGMENT); + } + } + + // // // Tests for [JACKSON-208] + + private void _testTabsDefault(boolean useStream) throws Exception + { + JsonFactory f = new JsonFactory(); + // First, let's see that by default unquoted tabs are illegal + String JSON = "[\"tab:\t\"]"; + JsonParser jp = useStream ? createParserUsingStream(f, JSON, "UTF-8") : createParserUsingReader(f, JSON); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + try { + jp.nextToken(); + jp.getText(); + fail("Expected exception"); + } catch (JsonParseException e) { + verifyException(e, "Illegal unquoted character"); + } + } + + private void _testTabsEnabled(boolean useStream) throws Exception + { + JsonFactory f = new JsonFactory(); + f.configure(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true); + + String FIELD = "a\tb"; + String VALUE = "\t"; + String JSON = "{ "+quote(FIELD)+" : "+quote(VALUE)+"}"; + JsonParser jp = useStream ? createParserUsingStream(f, JSON, "UTF-8") : createParserUsingReader(f, JSON); + + assertToken(JsonToken.START_OBJECT, jp.nextToken()); + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals(FIELD, jp.getText()); + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + assertEquals(VALUE, jp.getText()); + assertToken(JsonToken.END_OBJECT, jp.nextToken()); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/main/TestParserLinefeeds.java b/1.9.10/src/test/org/codehaus/jackson/main/TestParserLinefeeds.java new file mode 100644 index 0000000..e85fb52 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/main/TestParserLinefeeds.java
@@ -0,0 +1,70 @@ +package org.codehaus.jackson.main; + +import main.BaseTest; + +import org.codehaus.jackson.*; + +import java.io.IOException; + +/** + * Set of basic unit tests for verifying that the basic parser + * functionality works as expected. + */ +public class TestParserLinefeeds + extends BaseTest +{ + public void testCR() throws Exception + { + _testLinefeeds("\r", true); + _testLinefeeds("\r", false); + } + + public void testLF() throws Exception + { + _testLinefeeds("\n", true); + _testLinefeeds("\n", false); + } + + public void testCRLF() throws Exception + { + _testLinefeeds("\r\n", true); + _testLinefeeds("\r\n", false); + } + + /* + /********************************************************** + /* Helper methods + /********************************************************** + */ + + private void _testLinefeeds(String lf, boolean useStream) + throws IOException + { + String DOC = "[1,@2,@-178@]"; + DOC = DOC.replaceAll("@", lf); + + JsonParser jp = useStream ? + createParserUsingStream(DOC, "UTF-8") + : createParserUsingReader(DOC); + + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + assertEquals(1, jp.getCurrentLocation().getLineNr()); + + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(1, jp.getIntValue()); + assertEquals(1, jp.getCurrentLocation().getLineNr()); + + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(2, jp.getIntValue()); + assertEquals(2, jp.getCurrentLocation().getLineNr()); + + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(-178, jp.getIntValue()); + assertEquals(3, jp.getCurrentLocation().getLineNr()); + + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + assertEquals(4, jp.getCurrentLocation().getLineNr()); + + jp.close(); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/main/TestParserWithObjects.java b/1.9.10/src/test/org/codehaus/jackson/main/TestParserWithObjects.java new file mode 100644 index 0000000..121ddc2 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/main/TestParserWithObjects.java
@@ -0,0 +1,274 @@ +package org.codehaus.jackson.main; + +import java.io.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.MappingJsonFactory; + +/** + * Unit tests for verifying that object mapping functionality can + * be accessed using JsonParser. + */ +public class TestParserWithObjects + extends main.BaseTest +{ + final static class Pojo + { + int _x; + + public void setX(int x) { _x = x; } + } + + /* + /********************************************************** + /* Test for simple traversal with data mapping + /********************************************************** + */ + + public void testNextValue() throws IOException + { + // Let's test both byte-backed and Reader-based one + _testNextValueBasic(false); + _testNextValueBasic(true); + } + + // [JACKSON-395] + public void testNextValueNested() throws IOException + { + // Let's test both byte-backed and Reader-based one + _testNextValueNested(false); + _testNextValueNested(true); + } + + public void testPojoReading() throws IOException + { + JsonFactory jf = new MappingJsonFactory(); + final String JSON = "{ \"x\" : 9 }"; + JsonParser jp = jf.createJsonParser(new StringReader(JSON)); + + // let's try first by advancing: + assertToken(JsonToken.START_OBJECT, jp.nextToken()); + Pojo p = jp.readValueAs(Pojo.class); + assertEquals(9, p._x); + jp.close(); + + // and without + jp = jf.createJsonParser(new StringReader(JSON)); + p = jp.readValueAs(Pojo.class); + assertEquals(9, p._x); + jp.close(); + } + + public void testReadingArrayAsTree() throws IOException + { + JsonFactory jf = new MappingJsonFactory(); + final String JSON = "[ 1, 2, false ]"; + + for (int i = 0; i < 2; ++i) { + JsonParser jp = jf.createJsonParser(new StringReader(JSON)); + // whether to try advancing first or not? Try both + if (i == 0) { + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + } + JsonNode root = jp.readValueAsTree(); + jp.close(); + assertTrue(root.isArray()); + assertEquals(3, root.size()); + assertEquals(1, root.get(0).getIntValue()); + assertEquals(2, root.get(1).getIntValue()); + assertFalse(root.get(2).getBooleanValue()); + } + } + + public void testIsClosed() + throws IOException + { + for (int i = 0; i < 4; ++i) { + String JSON = "[ 1, 2, 3 ]"; + boolean stream = ((i & 1) == 0); + JsonParser jp = stream ? + createParserUsingStream(JSON, "UTF-8") + : createParserUsingReader(JSON); + boolean partial = ((i & 2) == 0); + + assertFalse(jp.isClosed()); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertFalse(jp.isClosed()); + + if (partial) { + jp.close(); + assertTrue(jp.isClosed()); + } else { + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + assertNull(jp.nextToken()); + assertTrue(jp.isClosed()); + } + } + } + + /* + /********************************************************** + /* Tests for data binding + /********************************************************** + */ + + /** + * Test similar to above, but instead reads a sequence of values + */ + public void testIncrementalPojoReading() + throws IOException + { + JsonFactory jf = new MappingJsonFactory(); + final String JSON = "[ 1, true, null, \"abc\" ]"; + JsonParser jp = jf.createJsonParser(new StringReader(JSON)); + + // let's advance past array start to prevent full binding + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(Integer.valueOf(1), jp.readValueAs(Integer.class)); + assertEquals(Boolean.TRUE, jp.readValueAs(Boolean.class)); + /* note: null can be returned both when there is no more + * data in current scope, AND when Json null literal is + * bound! + */ + assertNull(jp.readValueAs(Object.class)); + // but we can verify that it was Json null by: + assertEquals(JsonToken.VALUE_NULL, jp.getLastClearedToken()); + + assertEquals("abc", jp.readValueAs(String.class)); + + // this null is for actually hitting the END_ARRAY + assertNull(jp.readValueAs(Object.class)); + assertEquals(JsonToken.END_ARRAY, jp.getLastClearedToken()); + + // afrer which there should be nothing to advance to: + assertNull(jp.nextToken()); + + jp.close(); + } + + public void testPojoReadingFailing() + throws IOException + { + // regular factory can't do it, without a call to setCodec() + JsonFactory jf = new JsonFactory(); + try { + final String JSON = "{ \"x\" : 9 }"; + JsonParser jp = jf.createJsonParser(new StringReader(JSON)); + Pojo p = jp.readValueAs(Pojo.class); + fail("Expected an exception: got "+p); + } catch (IllegalStateException e) { + verifyException(e, "No ObjectCodec defined"); + } + } + + /* + /********************************************************** + /* Supporting methods + /********************************************************** + */ + + private void _testNextValueBasic(boolean useStream) throws IOException + { + // first array, no change to default + JsonParser jp = _getParser("[ 1, 2, 3, 4 ]", useStream); + assertToken(JsonToken.START_ARRAY, jp.nextValue()); + for (int i = 1; i <= 4; ++i) { + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextValue()); + assertEquals(i, jp.getIntValue()); + } + assertToken(JsonToken.END_ARRAY, jp.nextValue()); + assertNull(jp.nextValue()); + jp.close(); + + // then Object, is different + jp = _getParser("{ \"3\" :3, \"4\": 4, \"5\" : 5 }", useStream); + assertToken(JsonToken.START_OBJECT, jp.nextValue()); + for (int i = 3; i <= 5; ++i) { + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextValue()); + assertEquals(String.valueOf(i), jp.getCurrentName()); + assertEquals(i, jp.getIntValue()); + } + assertToken(JsonToken.END_OBJECT, jp.nextValue()); + assertNull(jp.nextValue()); + jp.close(); + + // and then mixed... + jp = _getParser("[ true, [ ], { \"a\" : 3 } ]", useStream); + + assertToken(JsonToken.START_ARRAY, jp.nextValue()); + assertToken(JsonToken.VALUE_TRUE, jp.nextValue()); + assertToken(JsonToken.START_ARRAY, jp.nextValue()); + assertToken(JsonToken.END_ARRAY, jp.nextValue()); + + assertToken(JsonToken.START_OBJECT, jp.nextValue()); + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextValue()); + assertEquals("a", jp.getCurrentName()); + assertToken(JsonToken.END_OBJECT, jp.nextValue()); + assertToken(JsonToken.END_ARRAY, jp.nextValue()); + + assertNull(jp.nextValue()); + jp.close(); + } + + // [JACKSON-395] + private void _testNextValueNested(boolean useStream) throws IOException + { + // first array, no change to default + JsonParser jp; + + // then object with sub-objects... + jp = _getParser("{\"a\": { \"b\" : true, \"c\": false }, \"d\": 3 }", useStream); + + assertToken(JsonToken.START_OBJECT, jp.nextValue()); + assertNull(jp.getCurrentName()); + assertToken(JsonToken.START_OBJECT, jp.nextValue()); + assertEquals("a", jp.getCurrentName()); + assertToken(JsonToken.VALUE_TRUE, jp.nextValue()); + assertEquals("b", jp.getCurrentName()); + assertToken(JsonToken.VALUE_FALSE, jp.nextValue()); + assertEquals("c", jp.getCurrentName()); + assertToken(JsonToken.END_OBJECT, jp.nextValue()); + // ideally we should match closing marker with field, too: + assertEquals("a", jp.getCurrentName()); + + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextValue()); + assertEquals("d", jp.getCurrentName()); + assertToken(JsonToken.END_OBJECT, jp.nextValue()); + assertNull(jp.getCurrentName()); + assertNull(jp.nextValue()); + jp.close(); + + // and arrays + jp = _getParser("{\"a\": [ false ] }", useStream); + + assertToken(JsonToken.START_OBJECT, jp.nextValue()); + assertNull(jp.getCurrentName()); + assertToken(JsonToken.START_ARRAY, jp.nextValue()); + assertEquals("a", jp.getCurrentName()); + assertToken(JsonToken.VALUE_FALSE, jp.nextValue()); + assertNull(jp.getCurrentName()); + assertToken(JsonToken.END_ARRAY, jp.nextValue()); + // ideally we should match closing marker with field, too: + assertEquals("a", jp.getCurrentName()); + assertToken(JsonToken.END_OBJECT, jp.nextValue()); + assertNull(jp.getCurrentName()); + assertNull(jp.nextValue()); + jp.close(); + } + + private JsonParser _getParser(String doc, boolean useStream) + throws IOException + { + JsonFactory jf = new JsonFactory(); + if (useStream) { + return jf.createJsonParser(doc.getBytes("UTF-8")); + } + return jf.createJsonParser(new StringReader(doc)); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/main/TestPrettyPrinter.java b/1.9.10/src/test/org/codehaus/jackson/main/TestPrettyPrinter.java new file mode 100644 index 0000000..db12ec5 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/main/TestPrettyPrinter.java
@@ -0,0 +1,98 @@ +package org.codehaus.jackson.main; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.util.MinimalPrettyPrinter; + +import java.io.*; + +/** + * Set of basic unit tests for verifying that indenting + * option of generator works correctly + */ +public class TestPrettyPrinter + extends main.BaseTest +{ + public void testSimpleDocWithDefault() throws Exception + { + StringWriter sw = new StringWriter(); + JsonGenerator gen = new JsonFactory().createJsonGenerator(sw); + gen.useDefaultPrettyPrinter(); + _verifyPrettyPrinter(gen, sw); + } + + public void testSimpleDocWithMinimal() throws Exception + { + StringWriter sw = new StringWriter(); + JsonGenerator gen = new JsonFactory().createJsonGenerator(sw); + // first with standard minimal + gen.setPrettyPrinter(new MinimalPrettyPrinter()); + String docStr = _verifyPrettyPrinter(gen, sw); + // which should have no linefeeds, tabs + assertEquals(-1, docStr.indexOf('\n')); + assertEquals(-1, docStr.indexOf('\t')); + + // And then with slightly customized variant + gen = new JsonFactory().createJsonGenerator(sw); + gen.setPrettyPrinter(new MinimalPrettyPrinter() { + @Override + // use TAB between array values + public void beforeArrayValues(JsonGenerator jg) throws IOException, JsonGenerationException + { + jg.writeRaw("\t"); + } + }); + docStr = _verifyPrettyPrinter(gen, sw); + assertEquals(-1, docStr.indexOf('\n')); + assertTrue(docStr.indexOf('\t') >= 0); + } + + private String _verifyPrettyPrinter(JsonGenerator gen, StringWriter sw) throws Exception + { + gen.writeStartArray(); + gen.writeNumber(3); + gen.writeString("abc"); + + gen.writeStartArray(); + gen.writeBoolean(true); + gen.writeEndArray(); + + gen.writeStartObject(); + gen.writeFieldName("f"); + gen.writeNull(); + gen.writeFieldName("f2"); + gen.writeNull(); + gen.writeEndObject(); + + gen.writeEndArray(); + gen.close(); + + String docStr = sw.toString(); + JsonParser jp = createParserUsingReader(docStr); + + assertEquals(JsonToken.START_ARRAY, jp.nextToken()); + + assertEquals(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(3, jp.getIntValue()); + assertEquals(JsonToken.VALUE_STRING, jp.nextToken()); + assertEquals("abc", jp.getText()); + + assertEquals(JsonToken.START_ARRAY, jp.nextToken()); + assertEquals(JsonToken.VALUE_TRUE, jp.nextToken()); + assertEquals(JsonToken.END_ARRAY, jp.nextToken()); + + assertEquals(JsonToken.START_OBJECT, jp.nextToken()); + assertEquals(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals("f", jp.getText()); + assertEquals(JsonToken.VALUE_NULL, jp.nextToken()); + assertEquals(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals("f2", jp.getText()); + assertEquals(JsonToken.VALUE_NULL, jp.nextToken()); + assertEquals(JsonToken.END_OBJECT, jp.nextToken()); + + assertEquals(JsonToken.END_ARRAY, jp.nextToken()); + + jp.close(); + + return docStr; + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/main/TestRawStringWriting.java b/1.9.10/src/test/org/codehaus/jackson/main/TestRawStringWriting.java new file mode 100644 index 0000000..1d0afa1 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/main/TestRawStringWriting.java
@@ -0,0 +1,132 @@ +package org.codehaus.jackson.main; + +import java.io.*; +import java.util.*; + +import static org.junit.Assert.*; + +import org.codehaus.jackson.*; + +/** + * @since 1.7 + */ +public class TestRawStringWriting extends main.BaseTest +{ + /** + * Unit test for "JsonGenerator.writeRawUTF8String()" + */ + public void testUtf8RawStrings() throws Exception + { + // Let's create set of Strings to output; no ctrl chars as we do raw + List<byte[]> strings = generateStrings(new Random(28), 750000, false); + ByteArrayOutputStream out = new ByteArrayOutputStream(16000); + JsonFactory jf = new JsonFactory(); + JsonGenerator jgen = jf.createJsonGenerator(out, JsonEncoding.UTF8); + jgen.writeStartArray(); + for (byte[] str : strings) { + jgen.writeRawUTF8String(str, 0, str.length); + } + jgen.writeEndArray(); + jgen.close(); + byte[] json = out.toByteArray(); + + // Ok: let's verify that stuff was written out ok + JsonParser jp = jf.createJsonParser(json); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + for (byte[] inputBytes : strings) { + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + String string = jp.getText(); + byte[] outputBytes = string.getBytes("UTF-8"); + assertEquals(inputBytes.length, outputBytes.length); + assertArrayEquals(inputBytes, outputBytes); + } + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + } + + /** + * Unit test for "JsonGenerator.writeUTF8String()", which needs + * to handle escaping properly + */ + public void testUtf8StringsWithEscaping() throws Exception + { + // Let's create set of Strings to output; do include control chars too: + List<byte[]> strings = generateStrings(new Random(28), 720000, true); + ByteArrayOutputStream out = new ByteArrayOutputStream(16000); + JsonFactory jf = new JsonFactory(); + JsonGenerator jgen = jf.createJsonGenerator(out, JsonEncoding.UTF8); + jgen.writeStartArray(); + + for (byte[] str : strings) { + jgen.writeUTF8String(str, 0, str.length); + jgen.writeRaw('\n'); + } + jgen.writeEndArray(); + jgen.close(); + byte[] json = out.toByteArray(); + + // Ok: let's verify that stuff was written out ok + JsonParser jp = jf.createJsonParser(json); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + for (byte[] inputBytes : strings) { + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + String string = jp.getText(); + + byte[] outputBytes = string.getBytes("UTF-8"); + assertEquals(inputBytes.length, outputBytes.length); + assertArrayEquals(inputBytes, outputBytes); + } + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + } + + /* + /********************************************************** + /* Helper methods + /********************************************************** + */ + + private List<byte[]> generateStrings(Random rnd, int totalLength, boolean includeCtrlChars) + throws IOException + { + ArrayList<byte[]> strings = new ArrayList<byte[]>(); + do { + int len = 2; + int bits = rnd.nextInt(13); + while (--bits >= 0) { + len += len; + } + len = 1 + ((len + len) / 3); + String str = generateString(rnd, len, includeCtrlChars); + byte[] bytes = str.getBytes("UTF-8"); + strings.add(bytes); + totalLength -= bytes.length; + } while (totalLength > 0); + return strings; + } + + private String generateString(Random rnd, int length, boolean includeCtrlChars) + { + StringBuilder sb = new StringBuilder(length); + do { + int i; + switch (rnd.nextInt(3)) { + case 0: // 3 byte one + i = 2048 + rnd.nextInt(16383); + break; + case 1: // 2 byte + i = 128 + rnd.nextInt(1024); + break; + default: // ASCII + i = rnd.nextInt(192); + if (!includeCtrlChars) { + i += 32; + // but also need to avoid backslash, double-quote + if (i == '\\' || i == '"') { + i = '@'; // just arbitrary choice + } + } + } + sb.append((char) i); + } while (sb.length() < length); + return sb.toString(); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/main/TestScopeMatching.java b/1.9.10/src/test/org/codehaus/jackson/main/TestScopeMatching.java new file mode 100644 index 0000000..1082cce --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/main/TestScopeMatching.java
@@ -0,0 +1,135 @@ +package org.codehaus.jackson.main; + +import main.BaseTest; + +import org.codehaus.jackson.*; + +/** + * Set of basic unit tests for verifying that Array/Object scopes + * are properly matched. + */ +public class TestScopeMatching + extends BaseTest +{ + public void testUnclosedArray() + throws Exception + { + JsonParser jp = createParserUsingReader("[ 1, 2"); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + + try { + jp.nextToken(); + fail("Expected an exception for unclosed ARRAY"); + } catch (JsonParseException jpe) { + verifyException(jpe, "expected close marker for ARRAY"); + } + } + + public void testUnclosedObject() + throws Exception + { + JsonParser jp = createParserUsingReader("{ \"key\" : 3 "); + assertToken(JsonToken.START_OBJECT, jp.nextToken()); + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + + try { + jp.nextToken(); + fail("Expected an exception for unclosed OBJECT"); + } catch (JsonParseException jpe) { + verifyException(jpe, "expected close marker for OBJECT"); + } + } + + public void testEOFInName() + throws Exception + { + final String JSON = "{ \"abcd"; + for (int i = 0; i < 2; ++i) { + JsonParser jp = (i == 0) ? createParserUsingReader(JSON) + : createParserUsingStream(JSON, "UTF-8"); + assertToken(JsonToken.START_OBJECT, jp.nextToken()); + try { + jp.nextToken(); + fail("Expected an exception for EOF"); + } catch (JsonParseException jpe) { + verifyException(jpe, "Unexpected end-of-input"); + } + } + } + + public void testWeirdToken() + throws Exception + { + final String JSON = "[ nil ]"; + for (int i = 0; i < 2; ++i) { + JsonParser jp = (i == 0) ? createParserUsingReader(JSON) + : createParserUsingStream(JSON, "UTF-8"); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + try { + jp.nextToken(); + fail("Expected an exception for weird token"); + } catch (JsonParseException jpe) { + verifyException(jpe, "Unrecognized token"); + } + } + } + + public void testMismatchArrayToObject() + throws Exception + { + final String JSON = "[ 1, 2 }"; + for (int i = 0; i < 2; ++i) { + JsonParser jp = (i == 0) ? createParserUsingReader(JSON) + : createParserUsingStream(JSON, "UTF-8"); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + try { + jp.nextToken(); + fail("Expected an exception for incorrectly closed ARRAY"); + } catch (JsonParseException jpe) { + verifyException(jpe, "Unexpected close marker '}': expected ']'"); + } + } + } + + public void testMismatchObjectToArray() + throws Exception + { + final String JSON = "{ ]"; + for (int i = 0; i < 2; ++i) { + JsonParser jp = (i == 0) ? createParserUsingReader(JSON) + : createParserUsingStream(JSON, "UTF-8"); + assertToken(JsonToken.START_OBJECT, jp.nextToken()); + + try { + jp.nextToken(); + fail("Expected an exception for incorrectly closed OBJECT"); + } catch (JsonParseException jpe) { + verifyException(jpe, "Unexpected close marker ']': expected '}'"); + } + } + } + + public void testMisssingColon() + throws Exception + { + final String JSON = "{ \"a\" \"b\" }"; + for (int i = 0; i < 2; ++i) { + JsonParser jp = (i == 0) ? createParserUsingReader(JSON) + : createParserUsingStream(JSON, "UTF-8"); + assertToken(JsonToken.START_OBJECT, jp.nextToken()); + try { + // can be either here, or with next one... + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + jp.nextToken(); + fail("Expected an exception for missing semicolon"); + } catch (JsonParseException jpe) { + verifyException(jpe, "was expecting a colon"); + } + } + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/main/TestStringGeneration.java b/1.9.10/src/test/org/codehaus/jackson/main/TestStringGeneration.java new file mode 100644 index 0000000..ba83082 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/main/TestStringGeneration.java
@@ -0,0 +1,225 @@ +package org.codehaus.jackson.main; + +import java.io.*; + +import main.BaseTest; + +import org.codehaus.jackson.*; + +import java.util.Random; + +/** + * Set of basic unit tests for verifying that the string + * generation, including character escaping, works as expected. + */ +public class TestStringGeneration + extends BaseTest +{ + final static String[] SAMPLES = new String[] { + "\"test\"", + "\n", "\\n", "\r\n", "a\\b", "tab:\nok?", + "a\tb\tc\n\fdef\t \tg\"\"\"h\"\\ijklmn\b", + "\"\"\"", "\\r)'\"", + "Longer text & other stuff:\twith some\r\n\r\n random linefeeds etc added in to cause some \"special\" handling \\\\ to occur...\n" + }; + + public void testBasicEscaping() + throws Exception + { + doTestBasicEscaping(false); + doTestBasicEscaping(true); + } + + public void testLongerRandomSingleChunk() + throws Exception + { + /* Let's first generate 100k of pseudo-random characters, favoring + * 7-bit ascii range + */ + for (int round = 0; round < 80; ++round) { + String content = generateRandom(75000+round); + doTestLongerRandom(content, false); + doTestLongerRandom(content, true); + } + } + + public void testLongerRandomMultiChunk() + throws Exception + { + /* Let's first generate 100k of pseudo-random characters, favoring + * 7-bit ascii range + */ + for (int round = 0; round < 70; ++round) { + String content = generateRandom(73000+round); + doTestLongerRandomMulti(content, false, round); + doTestLongerRandomMulti(content, true, round); + } + } + + /* + /********************************************************** + /* Internal methods + /********************************************************** + */ + + private String generateRandom(int len) + { + StringBuilder sb = new StringBuilder(len+1000); // pad for surrogates + Random r = new Random(len); + for (int i = 0; i < len; ++i) { + if (r.nextBoolean()) { // non-ascii + int value = r.nextInt() & 0xFFFF; + // Otherwise easy, except that need to ensure that + // surrogates are properly paired: and, also + // their values do not exceed 0x10FFFF + if (value >= 0xD800 && value <= 0xDFFF) { + // Let's discard first value, then, and produce valid pair + int fullValue = (r.nextInt() & 0xFFFFF); + sb.append((char) (0xD800 + (fullValue >> 10))); + value = 0xDC00 + (fullValue & 0x3FF); + } + sb.append((char) value); + } else { // ascii + sb.append((char) (r.nextInt() & 0x7F)); + } + } + return sb.toString(); + } + + private void doTestBasicEscaping(boolean charArray) + throws Exception + { + for (int i = 0; i < SAMPLES.length; ++i) { + String VALUE = SAMPLES[i]; + StringWriter sw = new StringWriter(); + JsonGenerator gen = new JsonFactory().createJsonGenerator(sw); + gen.writeStartArray(); + if (charArray) { + char[] buf = new char[VALUE.length() + i]; + VALUE.getChars(0, VALUE.length(), buf, i); + gen.writeString(buf, i, VALUE.length()); + } else { + gen.writeString(VALUE); + } + gen.writeEndArray(); + gen.close(); + String docStr = sw.toString(); + JsonParser jp = createParserUsingReader(docStr); + assertEquals(JsonToken.START_ARRAY, jp.nextToken()); + JsonToken t = jp.nextToken(); + assertEquals(JsonToken.VALUE_STRING, t); + assertEquals(VALUE, jp.getText()); + assertEquals(JsonToken.END_ARRAY, jp.nextToken()); + assertEquals(null, jp.nextToken()); + jp.close(); + } + } + + private void doTestLongerRandom(String text, boolean charArray) + throws Exception + { + ByteArrayOutputStream bow = new ByteArrayOutputStream(text.length()); + JsonGenerator gen = new JsonFactory().createJsonGenerator(bow, JsonEncoding.UTF8); + + gen.writeStartArray(); + if (charArray) { + char[] buf = new char[text.length()]; + text.getChars(0, text.length(), buf, 0); + gen.writeString(buf, 0, text.length()); + } else { + gen.writeString(text); + } + gen.writeEndArray(); + gen.close(); + byte[] docData = bow.toByteArray(); + JsonParser jp = new JsonFactory().createJsonParser(new ByteArrayInputStream(docData)); + assertEquals(JsonToken.START_ARRAY, jp.nextToken()); + JsonToken t = jp.nextToken(); + assertEquals(JsonToken.VALUE_STRING, t); + String act = jp.getText(); + if (!text.equals(act)) { + if (text.length() != act.length()) { + fail("Expected string length "+text.length()+", actual "+act.length()); + } + int i = 0; + for (int len = text.length(); i < len; ++i) { + if (text.charAt(i) != act.charAt(i)) { + break; + } + } + fail("Strings differ at position #"+i+" (len "+text.length()+"): expected char 0x"+Integer.toHexString(text.charAt(i))+", actual 0x"+Integer.toHexString(act.charAt(i))); + } + assertEquals(JsonToken.END_ARRAY, jp.nextToken()); + assertEquals(null, jp.nextToken()); + jp.close(); + } + + private void doTestLongerRandomMulti(String text, boolean charArray, int round) + throws Exception + { + ByteArrayOutputStream bow = new ByteArrayOutputStream(text.length()); + JsonGenerator gen = new JsonFactory().createJsonGenerator(bow, JsonEncoding.UTF8); + gen.writeStartArray(); + + gen.writeString(text); + gen.writeEndArray(); + gen.close(); + + gen = new JsonFactory().createJsonGenerator(bow, JsonEncoding.UTF8); + gen.writeStartArray(); + gen.writeStartArray(); + + Random rnd = new Random(text.length()); + int offset = 0; + + while (offset < text.length()) { + int shift = 1 + ((rnd.nextInt() & 0xFFFFF) % 12); // 1 - 12 + int len = (1 << shift) + shift; // up to 4k + if ((offset + len) >= text.length()) { + len = text.length() - offset; + } else { + // Need to avoid splitting surrogates though + char c = text.charAt(offset+len-1); + if (c >= 0xD800 && c < 0xDC00) { + ++len; + } + } + if (charArray) { + char[] buf = new char[len]; + text.getChars(offset, offset+len, buf, 0); + gen.writeString(buf, 0, len); + } else { + gen.writeString(text.substring(offset, offset+len)); + } + offset += len; + } + + gen.writeEndArray(); + gen.close(); + byte[] docData = bow.toByteArray(); + JsonParser jp = new JsonFactory().createJsonParser(new ByteArrayInputStream(docData)); + assertEquals(JsonToken.START_ARRAY, jp.nextToken()); + + offset = 0; + while (jp.nextToken() == JsonToken.VALUE_STRING) { + // Let's verify, piece by piece + String act = jp.getText(); + String exp = text.substring(offset, offset+act.length()); + if (act.length() != exp.length()) { + fail("String segment ["+offset+" - "+(offset+act.length())+"[ differs; exp length "+exp+", actual "+act); + } + if (!act.equals(exp)) { + int i = 0; + while (act.charAt(i) == exp.charAt(i)) { + ++i; + } + fail("String segment ["+offset+" - "+(offset+act.length())+"[ different at offset #"+i + +"; exp char 0x"+Integer.toHexString(exp.charAt(i)) + +", actual 0x"+Integer.toHexString(act.charAt(i))); + } + offset += act.length(); + } + assertEquals(JsonToken.END_ARRAY, jp.getCurrentToken()); + jp.close(); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/main/TestUnicode.java b/1.9.10/src/test/org/codehaus/jackson/main/TestUnicode.java new file mode 100644 index 0000000..c10813f --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/main/TestUnicode.java
@@ -0,0 +1,38 @@ +package org.codehaus.jackson.main; + +import java.io.IOException; + +import org.codehaus.jackson.*; + +public class TestUnicode extends main.BaseTest +{ + public void testSurrogates() throws Exception + { + JsonFactory f = new JsonFactory(); + _testSurrogates(f, true); + _testSurrogates(f, false); + } + + /* + /********************************************************** + /* Helper methods + /********************************************************** + */ + + private void _testSurrogates(JsonFactory f, boolean checkText) throws IOException + { + byte[] json = "{\"text\":\"\uD83D\uDE03\"}".getBytes("UTF-8"); + // first + JsonParser jp = f.createJsonParser(json); + assertToken(JsonToken.START_OBJECT, jp.nextToken()); + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + if (checkText) { + assertEquals("text", jp.getText()); + } + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + if (checkText) { + assertEquals("\uD83D\uDE03", jp.getText()); + } + assertToken(JsonToken.END_OBJECT, jp.nextToken()); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/main/TestValueConversions.java b/1.9.10/src/test/org/codehaus/jackson/main/TestValueConversions.java new file mode 100644 index 0000000..e30e747 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/main/TestValueConversions.java
@@ -0,0 +1,189 @@ +package org.codehaus.jackson.main; + +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.JsonToken; + +/** + * @since 1.6 + */ +public class TestValueConversions + extends main.BaseTest +{ + public void testAsInt() throws Exception + { + final String input = "[ 1, -3, 4.98, true, false, null, \"-17\", \"foo\" ]"; + for (int i = 0; i < 2; ++i) { + JsonParser jp; + if (i == 0) { + jp = createParserUsingReader(input); + } else { + jp = this.createParserUsingStream(input, "UTF-8"); + } + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + assertEquals(0, jp.getValueAsLong()); + assertEquals(9, jp.getValueAsLong(9)); + + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(1, jp.getValueAsLong()); + assertEquals(1, jp.getValueAsLong(-99)); + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(-3, jp.getValueAsLong()); + assertToken(JsonToken.VALUE_NUMBER_FLOAT, jp.nextToken()); + assertEquals(4, jp.getValueAsLong()); + assertEquals(4, jp.getValueAsLong(99)); + assertToken(JsonToken.VALUE_TRUE, jp.nextToken()); + assertEquals(1, jp.getValueAsLong()); + assertToken(JsonToken.VALUE_FALSE, jp.nextToken()); + assertEquals(0, jp.getValueAsLong()); + assertToken(JsonToken.VALUE_NULL, jp.nextToken()); + assertEquals(0, jp.getValueAsLong()); + assertEquals(0, jp.getValueAsLong(27)); + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + assertEquals(-17, jp.getValueAsLong()); + assertEquals(-17, jp.getValueAsLong(3)); + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + assertEquals(0, jp.getValueAsLong()); + assertEquals(9, jp.getValueAsLong(9)); + + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + assertEquals(0, jp.getValueAsLong()); + assertEquals(9, jp.getValueAsLong(9)); + + jp.close(); + } + } + + /** + * @since 1.7 + */ + public void testAsBoolean() throws Exception + { + final String input = "[ true, false, null, 1, 0, \"true\", \"false\", \"foo\" ]"; + for (int i = 0; i < 2; ++i) { + JsonParser jp; + if (i == 0) { + jp = createParserUsingReader(input); + } else { + jp = this.createParserUsingStream(input, "UTF-8"); + } + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + assertEquals(false, jp.getValueAsBoolean()); + assertEquals(true, jp.getValueAsBoolean(true)); + + assertToken(JsonToken.VALUE_TRUE, jp.nextToken()); + assertEquals(true, jp.getValueAsBoolean()); + assertToken(JsonToken.VALUE_FALSE, jp.nextToken()); + assertEquals(false, jp.getValueAsBoolean()); + assertToken(JsonToken.VALUE_NULL, jp.nextToken()); + assertEquals(false, jp.getValueAsBoolean()); + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(1, jp.getIntValue()); + assertEquals(true, jp.getValueAsBoolean()); + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(0, jp.getIntValue()); + assertEquals(false, jp.getValueAsBoolean()); + + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + assertEquals(true, jp.getValueAsBoolean()); + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + assertEquals(false, jp.getValueAsBoolean()); + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + assertEquals(false, jp.getValueAsBoolean()); + + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + assertEquals(false, jp.getValueAsBoolean()); + assertEquals(true, jp.getValueAsBoolean(true)); + + jp.close(); + } + } + + public void testAsLong() throws Exception + { + final String input = "[ 1, -3, 4.98, true, false, null, \"-17\", \"foo\" ]"; + for (int i = 0; i < 2; ++i) { + JsonParser jp; + if (i == 0) { + jp = createParserUsingReader(input); + } else { + jp = this.createParserUsingStream(input, "UTF-8"); + } + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + assertEquals(0L, jp.getValueAsLong()); + assertEquals(9L, jp.getValueAsLong(9L)); + + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(1L, jp.getValueAsLong()); + assertEquals(1L, jp.getValueAsLong(-99L)); + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(-3L, jp.getValueAsLong()); + assertToken(JsonToken.VALUE_NUMBER_FLOAT, jp.nextToken()); + assertEquals(4L, jp.getValueAsLong()); + assertEquals(4L, jp.getValueAsLong(99L)); + assertToken(JsonToken.VALUE_TRUE, jp.nextToken()); + assertEquals(1L, jp.getValueAsLong()); + assertToken(JsonToken.VALUE_FALSE, jp.nextToken()); + assertEquals(0L, jp.getValueAsLong()); + assertToken(JsonToken.VALUE_NULL, jp.nextToken()); + assertEquals(0L, jp.getValueAsLong()); + assertEquals(0L, jp.getValueAsLong(27L)); + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + assertEquals(-17L, jp.getValueAsLong()); + assertEquals(-17L, jp.getValueAsLong(3L)); + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + assertEquals(0L, jp.getValueAsLong()); + assertEquals(9L, jp.getValueAsLong(9L)); + + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + assertEquals(0L, jp.getValueAsLong()); + assertEquals(9L, jp.getValueAsLong(9L)); + + jp.close(); + } + } + + public void testAsDouble() throws Exception + { + final String input = "[ 1, -3, 4.98, true, false, null, \"-17.25\", \"foo\" ]"; + for (int i = 0; i < 2; ++i) { + JsonParser jp; + if (i == 0) { + jp = createParserUsingReader(input); + } else { + jp = this.createParserUsingStream(input, "UTF-8"); + } + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + assertEquals(0.0, jp.getValueAsDouble()); + assertEquals(9.0, jp.getValueAsDouble(9.0)); + + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(1., jp.getValueAsDouble()); + assertEquals(1., jp.getValueAsDouble(-99.0)); + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(-3., jp.getValueAsDouble()); + assertToken(JsonToken.VALUE_NUMBER_FLOAT, jp.nextToken()); + assertEquals(4.98, jp.getValueAsDouble()); + assertEquals(4.98, jp.getValueAsDouble(12.5)); + assertToken(JsonToken.VALUE_TRUE, jp.nextToken()); + assertEquals(1.0, jp.getValueAsDouble()); + assertToken(JsonToken.VALUE_FALSE, jp.nextToken()); + assertEquals(0.0, jp.getValueAsDouble()); + assertToken(JsonToken.VALUE_NULL, jp.nextToken()); + assertEquals(0.0, jp.getValueAsDouble()); + assertEquals(0.0, jp.getValueAsDouble(27.8)); + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + assertEquals(-17.25, jp.getValueAsDouble()); + assertEquals(-17.25, jp.getValueAsDouble(1.9)); + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + assertEquals(0.0, jp.getValueAsDouble()); + assertEquals(1.25, jp.getValueAsDouble(1.25)); + + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + assertEquals(0.0, jp.getValueAsDouble()); + assertEquals(7.5, jp.getValueAsDouble(7.5)); + + jp.close(); + } + } + +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/main/TestWithTonsaSymbols.java b/1.9.10/src/test/org/codehaus/jackson/main/TestWithTonsaSymbols.java new file mode 100644 index 0000000..67f955a --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/main/TestWithTonsaSymbols.java
@@ -0,0 +1,112 @@ +package org.codehaus.jackson.main; + +import main.BaseTest; + +import org.codehaus.jackson.*; + +import java.io.*; + +/** + * Some unit tests to try to exercise part of parser code that + * deals with symbol (table) management. + */ +public class TestWithTonsaSymbols + extends BaseTest +{ + final static String FIELD_BASENAME = "f"; + + /** + * How many fields to generate? Since maximum symbol table + * size is defined as 6000 (above which table gets cleared, + * assuming the name vocabulary is unbounded), let's do something + * just slightly below it. + */ + final static int FIELD_COUNT = 5000; + + public void testStreamReaderParser() throws Exception + { + _testWith(true); + } + + public void testReaderParser() throws Exception + { + _testWith(false); + } + + /* + ////////////////////////////////////////////////////// + // Helper methods + ////////////////////////////////////////////////////// + */ + + private void _testWith(boolean useStream) + throws Exception + { + JsonFactory jf = new JsonFactory(); + String doc = buildDoc(FIELD_COUNT); + + /* And let's do this multiple times: just so that symbol table + * state is different between runs. + */ + for (int x = 0; x < 3; ++x) { + JsonParser jp = useStream ? + jf.createJsonParser(new ByteArrayInputStream(doc.getBytes("UTF-8"))) + : jf.createJsonParser(new StringReader(doc)); + assertToken(JsonToken.START_OBJECT, jp.nextToken()); + for (int i = 0; i < FIELD_COUNT; ++i) { + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals(fieldNameFor(i), jp.getCurrentName()); + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(i, jp.getIntValue()); + } + assertToken(JsonToken.END_OBJECT, jp.nextToken()); + jp.close(); + } + } + + private void fieldNameFor(StringBuilder sb, int index) + { + /* let's do something like "f1.1" to exercise different + * field names (important for byte-based codec) + * Other name shuffling done mostly just for fun... :) + */ + sb.append(FIELD_BASENAME); + sb.append(index); + if (index > 50) { + sb.append('.'); + if (index > 200) { + sb.append(index); + if (index > 4000) { // and some even longer symbols... + sb.append(".").append(index); + } + } else { + sb.append(index >> 3); // divide by 8 + } + } + } + + private String fieldNameFor(int index) + { + StringBuilder sb = new StringBuilder(16); + fieldNameFor(sb, index); + return sb.toString(); + } + + private String buildDoc(int len) + { + StringBuilder sb = new StringBuilder(len * 12); + sb.append('{'); + for (int i = 0; i < len; ++i) { + if (i > 0) { + sb.append(','); + } + sb.append('"'); + fieldNameFor(sb, i); + sb.append('"'); + sb.append(':'); + sb.append(i); + } + sb.append('}'); + return sb.toString(); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/BaseMapTest.java b/1.9.10/src/test/org/codehaus/jackson/map/BaseMapTest.java new file mode 100644 index 0000000..24a32a1 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/BaseMapTest.java
@@ -0,0 +1,211 @@ +package org.codehaus.jackson.map; + +import java.io.*; +import java.util.*; + +import static org.junit.Assert.*; + +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.annotate.JsonCreator; +import org.codehaus.jackson.annotate.JsonValue; + +import main.BaseTest; + +public abstract class BaseMapTest + extends BaseTest +{ + private final static Object SINGLETON_OBJECT = new Object(); + + /* + /********************************************************** + /* Shared helper classes + /********************************************************** + */ + + /** + * Simple wrapper around boolean types, usually to test value + * conversions or wrapping + */ + protected static class BooleanWrapper { + public Boolean b; + + @JsonCreator + public BooleanWrapper(Boolean value) { b = value; } + + @JsonValue public Boolean value() { return b; } + } + + protected static class IntWrapper { + public int i; + + public IntWrapper() { } + public IntWrapper(int value) { i = value; } + } + + /** + * Simple wrapper around String type, usually to test value + * conversions or wrapping + */ + protected static class StringWrapper { + public String str; + + public StringWrapper() { } + public StringWrapper(String value) { + str = value; + } + } + + protected static class ObjectWrapper { + private final Object object; + protected ObjectWrapper(final Object object) { + this.object = object; + } + public Object getObject() { return object; } + @JsonCreator + static ObjectWrapper jsonValue(final Object object) { + return new ObjectWrapper(object); + } + } + + protected static class ListWrapper<T> + { + public List<T> list; + + public ListWrapper(T... values) { + list = new ArrayList<T>(); + for (T value : values) { + list.add(value); + } + } + } + + protected static class MapWrapper<K,V> + { + public Map<K,V> map; + + public MapWrapper(Map<K,V> m) { + map = m; + } + } + + protected static class ArrayWrapper<T> + { + public T[] array; + + public ArrayWrapper(T[] v) { + array = v; + } + } + + /** + * Enumeration type with sub-classes per value. + */ + protected enum EnumWithSubClass { + A { @Override public void foobar() { } } + ,B { @Override public void foobar() { } } + ; + + public abstract void foobar(); + } + + protected BaseMapTest() { super(); } + + /* + /********************************************************** + /* Additional assert methods + /********************************************************** + */ + + protected void assertEquals(int[] exp, int[] act) + { + assertArrayEquals(exp, act); + } + + /** + * Helper method for verifying 3 basic cookie cutter cases; + * identity comparison (true), and against null (false), + * or object of different type (false) + */ + protected void assertStandardEquals(Object o) + { + assertTrue(o.equals(o)); + assertFalse(o.equals(null)); + assertFalse(o.equals(SINGLETON_OBJECT)); + // just for fun, let's also call hash code... + o.hashCode(); + } + + protected void assertNodeNumbersForNonNumeric(JsonNode n) + { + assertEquals(0, n.asInt()); + assertEquals(-42, n.asInt(-42)); + assertEquals(0, n.asLong()); + assertEquals(12345678901L, n.asLong(12345678901L)); + assertEquals(0.0, n.asDouble()); + assertEquals(-19.25, n.asDouble(-19.25)); + } + + protected void assertNodeNumbers(JsonNode n, int expInt, double expDouble) + { + assertEquals(expInt, n.asInt()); + assertEquals(expInt, n.asInt(-42)); + assertEquals((long) expInt, n.asLong()); + assertEquals((long) expInt, n.asLong(19L)); + assertEquals(expDouble, n.asDouble()); + assertEquals(expDouble, n.asDouble(-19.25)); + } + + /* + /********************************************************** + /* Helper methods + /********************************************************** + */ + + @SuppressWarnings("unchecked") + protected Map<String,Object> writeAndMap(ObjectMapper m, Object value) + throws IOException + { + String str = m.writeValueAsString(value); + return (Map<String,Object>) m.readValue(str, Map.class); + } + + protected Map<String,Object> writeAndMap(Object value) + throws IOException + { + return writeAndMap(new ObjectMapper(), value); + } + + protected <T> T readAndMapFromString(ObjectMapper m, String input, Class<T> cls) + throws IOException + { + return (T) m.readValue("\""+input+"\"", cls); + } + + protected String serializeAsString(ObjectMapper m, Object value) + throws IOException + { + return m.writeValueAsString(value); + } + + protected String serializeAsString(Object value) + throws IOException + { + return serializeAsString(new ObjectMapper(), value); + } + + protected String asJSONObjectValueString(Object... args) + throws IOException + { + return asJSONObjectValueString(new ObjectMapper(), args); + } + + protected String asJSONObjectValueString(ObjectMapper m, Object... args) + throws IOException + { + LinkedHashMap<Object,Object> map = new LinkedHashMap<Object,Object>(); + for (int i = 0, len = args.length; i < len; i += 2) { + map.put(args[i], args[i+1]); + } + return m.writeValueAsString(map); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/BrokenStringReader.java b/1.9.10/src/test/org/codehaus/jackson/map/BrokenStringReader.java new file mode 100644 index 0000000..f8687da --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/BrokenStringReader.java
@@ -0,0 +1,26 @@ +package org.codehaus.jackson.map; + +import java.io.*; + +public class BrokenStringReader + extends FilterReader +{ + final String _message; + + public BrokenStringReader(String content, String msg) + { + super(new StringReader(content)); + _message = msg; + } + + @Override + public int read(char[] cbuf, int off, int len) + throws IOException + { + int i = super.read(cbuf, off, len); + if (i < 0) { + throw new IOException(_message); + } + return i; + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/BrokenStringWriter.java b/1.9.10/src/test/org/codehaus/jackson/map/BrokenStringWriter.java new file mode 100644 index 0000000..354c92b --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/BrokenStringWriter.java
@@ -0,0 +1,32 @@ +package org.codehaus.jackson.map; + +import java.io.*; + +public class BrokenStringWriter + extends FilterWriter +{ + final String _message; + + public BrokenStringWriter(String msg) { + super(new StringWriter()); + _message = msg; + } + + @Override + public void write(char[] cbuf, int off, int len) throws IOException + { + throw new IOException(_message); + } + + @Override + public void write(int c) throws IOException + { + throw new IOException(_message); + } + + @Override + public void write(String str, int off, int len) throws IOException + { + throw new IOException(_message); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/TestFormatSchema.java b/1.9.10/src/test/org/codehaus/jackson/map/TestFormatSchema.java new file mode 100644 index 0000000..d5f88b9 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/TestFormatSchema.java
@@ -0,0 +1,227 @@ +package org.codehaus.jackson.map; + +import java.io.*; +import java.math.BigDecimal; +import java.math.BigInteger; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.impl.*; +import org.codehaus.jackson.io.IOContext; + +/** + * Basic tests to ensure that {@link FormatSchema} instances are properly + * passed to {@link JsonGenerator} and {@link JsonParser} instances if + * mapper, reader or writer is configured with one. + * + * @since 1.8 + */ +public class TestFormatSchema extends BaseMapTest +{ + /* + /********************************************************************** + /* Helper classes + /********************************************************************** + */ + + static class MySchema implements FormatSchema { + @Override + public String getSchemaType() { return "test"; } + } + + static class FactoryWithSchema extends JsonFactory + { + @Override + protected JsonParser _createJsonParser(Reader r, IOContext ctxt) + throws IOException, JsonParseException + { + return new ParserWithSchema(ctxt, _parserFeatures, r); + } + + @Override + protected JsonGenerator _createJsonGenerator(Writer out, IOContext ctxt) throws IOException + { + return new GeneratorWithSchema(_generatorFeatures, _objectCodec); + } + } + + // Ugly, but easiest way to get schema back is to throw exception... + @SuppressWarnings("serial") + static class SchemaException extends RuntimeException + { + public final FormatSchema _schema; + + public SchemaException(FormatSchema s) { + _schema = s; + } + } + + @SuppressWarnings("deprecation") + static class ParserWithSchema extends ReaderBasedParserBase + { + public ParserWithSchema(IOContext ioCtxt, int features, Reader r) + { + super(ioCtxt, features, r); + } + + @Override + public void setSchema(FormatSchema schema) { + throw new SchemaException(schema); + } + + @Override + protected void _finishString() throws IOException, JsonParseException { } + + @Override + public byte[] getBinaryValue(Base64Variant b64variant) { + return null; + } + + @Override + public String getText() throws IOException, JsonParseException { + return null; + } + + @Override + public char[] getTextCharacters() throws IOException { + return null; + } + + @Override + public int getTextLength() throws IOException, JsonParseException { + return 0; + } + + @Override + public int getTextOffset() throws IOException, JsonParseException { + return 0; + } + + @Override + public JsonToken nextToken() throws IOException, JsonParseException { + return null; + } + + @Override + public ObjectCodec getCodec() { + return null; + } + + @Override + public void setCodec(ObjectCodec c) { } + } + + static class GeneratorWithSchema extends JsonGeneratorBase + { + public GeneratorWithSchema(int features, ObjectCodec codec) + { + super(features, codec); + } + + @Override + public void setSchema(FormatSchema schema) { + throw new SchemaException(schema); + } + + @Override + protected void _releaseBuffers() { } + + @Override + protected void _verifyValueWrite(String typeMsg) throws IOException { } + + @Override + public void flush() throws IOException { } + + @Override + public void writeBinary(Base64Variant b64variant, byte[] data, + int offset, int len) throws IOException { } + + @Override + public void writeBoolean(boolean state) throws IOException { } + + @Override + public void writeFieldName(String name) throws IOException { } + + @Override + public void writeNull() throws IOException, JsonGenerationException { } + + @Override + public void writeNumber(int v) throws IOException { } + + @Override + public void writeNumber(long v) throws IOException { } + + @Override + public void writeNumber(BigInteger v) throws IOException { } + + @Override + public void writeNumber(double d) throws IOException { } + + @Override + public void writeNumber(float f) throws IOException { } + + @Override + public void writeNumber(BigDecimal dec) throws IOException { } + + @Override + public void writeNumber(String encodedValue) throws IOException { } + + @Override + public void writeRaw(String text) throws IOException { } + + @Override + public void writeRaw(String text, int offset, int len) { } + + @Override + public void writeRaw(char[] text, int offset, int len) { } + + @Override + public void writeRaw(char c) throws IOException { } + + @Override + public void writeRawUTF8String(byte[] text, int offset, int length) { } + + @Override + public void writeString(String text) throws IOException { } + + @Override + public void writeString(char[] text, int offset, int len) { } + + @Override + public void writeUTF8String(byte[] text, int offset, int length) { } + } + + /* + /********************************************************************** + /* Unit tests + /********************************************************************** + */ + + public void testFormatForParsers() throws Exception + { + ObjectMapper mapper = new ObjectMapper(new FactoryWithSchema()); + MySchema s = new MySchema(); + StringReader r = new StringReader("{}"); + // bit ugly, but can't think of cleaner simple way to check this... + try { + mapper.reader(s).withType(Object.class).readValue(r); + fail("Excpected exception"); + } catch (SchemaException e) { + assertSame(s, e._schema); + } + } + + public void testFormatForGenerators() throws Exception + { + ObjectMapper mapper = new ObjectMapper(new FactoryWithSchema()); + MySchema s = new MySchema(); + StringWriter sw = new StringWriter(); + // bit ugly, but can't think of cleaner simple way to check this... + try { + mapper.writer(s).writeValue(sw, "Foobar"); + fail("Excpected exception"); + } catch (SchemaException e) { + assertSame(s, e._schema); + } + } + +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/TestFromJavaType.java b/1.9.10/src/test/org/codehaus/jackson/map/TestFromJavaType.java new file mode 100644 index 0000000..b5977bb --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/TestFromJavaType.java
@@ -0,0 +1,117 @@ +package org.codehaus.jackson.map; + +import java.math.BigDecimal; +import java.util.*; + +import org.codehaus.jackson.*; + +/** + * This unit test suite tries verify simplest aspects of + * "Native" java type mapper; basically that is can properly serialize + * core JDK objects to JSON. + * + * @author Tatu Saloranta + */ +public class TestFromJavaType + extends BaseMapTest +{ + public void testFromArray() + throws Exception + { + ArrayList<Object> doc = new ArrayList<Object>(); + doc.add("Elem1"); + doc.add(Integer.valueOf(3)); + Map<String,Object> struct = new LinkedHashMap<String, Object>(); + struct.put("first", Boolean.TRUE); + struct.put("Second", new ArrayList<Object>()); + doc.add(struct); + doc.add(Boolean.FALSE); + + ObjectMapper mapper = new ObjectMapper(); + JsonFactory f = new JsonFactory(); + + // loop more than once, just to ensure caching works ok (during second round) + for (int i = 0; i < 3; ++i) { + String str = mapper.writeValueAsString(doc); + + JsonParser jp = f.createJsonParser(str); + assertEquals(JsonToken.START_ARRAY, jp.nextToken()); + + assertEquals(JsonToken.VALUE_STRING, jp.nextToken()); + assertEquals("Elem1", getAndVerifyText(jp)); + + assertEquals(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(3, jp.getIntValue()); + + assertEquals(JsonToken.START_OBJECT, jp.nextToken()); + assertEquals(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals("first", getAndVerifyText(jp)); + + assertEquals(JsonToken.VALUE_TRUE, jp.nextToken()); + assertEquals(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals("Second", getAndVerifyText(jp)); + + if (jp.nextToken() != JsonToken.START_ARRAY) { + fail("Expected START_ARRAY: JSON == '"+str+"'"); + } + assertEquals(JsonToken.END_ARRAY, jp.nextToken()); + assertEquals(JsonToken.END_OBJECT, jp.nextToken()); + + assertEquals(JsonToken.VALUE_FALSE, jp.nextToken()); + + assertEquals(JsonToken.END_ARRAY, jp.nextToken()); + assertNull(jp.nextToken()); + } + } + + public void testFromMap() + throws Exception + { + LinkedHashMap<String,Object> doc = new LinkedHashMap<String,Object>(); + JsonFactory f = new JsonFactory(); + + doc.put("a1", "\"text\""); + doc.put("int", Integer.valueOf(137)); + doc.put("foo bar", Long.valueOf(1234567890L)); + + ObjectMapper mapper = new ObjectMapper(); + for (int i = 0; i < 3; ++i) { + String str = mapper.writeValueAsString(doc); + JsonParser jp = f.createJsonParser(str); + + assertEquals(JsonToken.START_OBJECT, jp.nextToken()); + + assertEquals(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals("a1", getAndVerifyText(jp)); + assertEquals(JsonToken.VALUE_STRING, jp.nextToken()); + assertEquals("\"text\"", getAndVerifyText(jp)); + + assertEquals(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals("int", getAndVerifyText(jp)); + assertEquals(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(137, jp.getIntValue()); + + assertEquals(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals("foo bar", getAndVerifyText(jp)); + assertEquals(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(1234567890L, jp.getLongValue()); + + assertEquals(JsonToken.END_OBJECT, jp.nextToken()); + + assertNull(jp.nextToken()); + } + } + + /** + * Unit test to catch bug [JACKSON-8]. + */ + public void testBigDecimal() + throws Exception + { + Map<String, Object> map = new HashMap<String, Object>(); + String PI_STR = "3.14159265"; + map.put("pi", new BigDecimal(PI_STR)); + String str = new ObjectMapper().writeValueAsString(map); + assertEquals("{\"pi\":3.14159265}", str); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/TestHandlerInstantiation.java b/1.9.10/src/test/org/codehaus/jackson/map/TestHandlerInstantiation.java new file mode 100644 index 0000000..32cb31c --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/TestHandlerInstantiation.java
@@ -0,0 +1,261 @@ +package org.codehaus.jackson.map; + +import java.io.IOException; +import java.util.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.annotate.JsonTypeInfo; +import org.codehaus.jackson.annotate.JsonTypeInfo.As; +import org.codehaus.jackson.annotate.JsonTypeInfo.Id; +import org.codehaus.jackson.map.introspect.Annotated; +import org.codehaus.jackson.map.jsontype.TypeIdResolver; +import org.codehaus.jackson.map.jsontype.TypeResolverBuilder; +import org.codehaus.jackson.map.type.TypeFactory; + +import org.codehaus.jackson.map.annotate.JsonDeserialize; +import org.codehaus.jackson.map.annotate.JsonSerialize; +import org.codehaus.jackson.map.annotate.JsonTypeIdResolver; +import org.codehaus.jackson.type.JavaType; + +public class TestHandlerInstantiation extends BaseMapTest +{ + /* + /********************************************************************** + /* Helper classes, beans + /********************************************************************** + */ + + @JsonDeserialize(using=MyBeanDeserializer.class) + @JsonSerialize(using=MyBeanSerializer.class) + static class MyBean + { + public String value; + + public MyBean() { this(null); } + public MyBean(String s) { value = s; } + } + + @SuppressWarnings("serial") + @JsonDeserialize(keyUsing=MyKeyDeserializer.class) + static class MyMap extends HashMap<String,String> { } + + @JsonTypeInfo(use=Id.CUSTOM, include=As.WRAPPER_ARRAY) + @JsonTypeIdResolver(CustomIdResolver.class) + static class TypeIdBean { + public int x; + + public TypeIdBean() { } + public TypeIdBean(int x) { this.x = x; } + } + + static class TypeIdBeanWrapper { + public TypeIdBean bean; + + public TypeIdBeanWrapper() { this(null); } + public TypeIdBeanWrapper(TypeIdBean b) { bean = b; } + } + + /* + /********************************************************************** + /* Helper classes, serializers/deserializers/resolvers + /********************************************************************** + */ + + static class MyBeanDeserializer extends JsonDeserializer<MyBean> + { + public String _prefix = ""; + + public MyBeanDeserializer(String p) { + _prefix = p; + } + + @Override + public MyBean deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + return new MyBean(_prefix+jp.getText()); + } + } + + static class MyKeyDeserializer extends KeyDeserializer + { + public MyKeyDeserializer() { } + + @Override + public Object deserializeKey(String key, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + return "KEY"; + } + } + + static class MyBeanSerializer extends JsonSerializer<MyBean> + { + public String _prefix = ""; + + public MyBeanSerializer(String p) { + _prefix = p; + } + + @Override + public void serialize(MyBean value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonProcessingException + { + jgen.writeString(_prefix + value.value); + } + } + + // copied from "TestCustomTypeIdResolver" + static class CustomIdResolver implements TypeIdResolver + { + static List<JavaType> initTypes; + + final String _id; + + public CustomIdResolver(String idForBean) { + _id = idForBean; + } + + @Override + public Id getMechanism() { + return Id.CUSTOM; + } + + @Override + public String idFromValue(Object value) + { + if (value.getClass() == TypeIdBean.class) { + return _id; + } + return "unknown"; + } + + @Override + public String idFromValueAndType(Object value, Class<?> type) { + return idFromValue(value); + } + + @Override + public void init(JavaType baseType) { + if (initTypes != null) { + initTypes.add(baseType); + } + } + + @Override + public JavaType typeFromId(String id) + { + if (id.equals(_id)) { + return TypeFactory.defaultInstance().constructType(TypeIdBean.class); + } + return null; + } + } + + /* + /********************************************************************** + /* Helper classes, handler instantiator + /********************************************************************** + */ + + static class MyInstantiator extends HandlerInstantiator + { + private final String _prefix; + + public MyInstantiator(String p) { + _prefix = p; + } + + @Override + public JsonDeserializer<?> deserializerInstance(DeserializationConfig config, Annotated annotated, + Class<? extends JsonDeserializer<?>> deserClass) + { + if (deserClass == MyBeanDeserializer.class) { + return new MyBeanDeserializer(_prefix); + } + return null; + } + + @Override + public KeyDeserializer keyDeserializerInstance(DeserializationConfig config, + Annotated annotated, Class<? extends KeyDeserializer> keyDeserClass) + { + if (keyDeserClass == MyKeyDeserializer.class) { + return new MyKeyDeserializer(); + } + return null; + + } + + @Override + public JsonSerializer<?> serializerInstance(SerializationConfig config, + Annotated annotated, Class<? extends JsonSerializer<?>> serClass) + { + if (serClass == MyBeanSerializer.class) { + return new MyBeanSerializer(_prefix); + } + return null; + } + + @Override + public TypeIdResolver typeIdResolverInstance(MapperConfig<?> config, + Annotated annotated, Class<? extends TypeIdResolver> resolverClass) + { + if (resolverClass == CustomIdResolver.class) { + return new CustomIdResolver("!!!"); + } + return null; + } + + @Override + public TypeResolverBuilder<?> typeResolverBuilderInstance(MapperConfig<?> config, Annotated annotated, + Class<? extends TypeResolverBuilder<?>> builderClass) + { + return null; + } + } + + /* + /********************************************************************** + /* Unit tests + /********************************************************************** + */ + + public void testDeserializer() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.setHandlerInstantiator(new MyInstantiator("abc:")); + MyBean result = mapper.readValue(quote("123"), MyBean.class); + assertEquals("abc:123", result.value); + } + + public void testKeyDeserializer() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.setHandlerInstantiator(new MyInstantiator("abc:")); + MyMap map = mapper.readValue("{\"a\":\"b\"}", MyMap.class); + // easiest to test by just serializing... + assertEquals("{\"KEY\":\"b\"}", mapper.writeValueAsString(map)); + } + + public void testSerializer() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.setHandlerInstantiator(new MyInstantiator("xyz:")); + assertEquals(quote("xyz:456"), mapper.writeValueAsString(new MyBean("456"))); + } + + public void testTypeIdResolver() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.setHandlerInstantiator(new MyInstantiator("foobar")); + String json = mapper.writeValueAsString(new TypeIdBeanWrapper(new TypeIdBean(123))); + // should now use our custom id scheme: + assertEquals("{\"bean\":[\"!!!\",{\"x\":123}]}", json); + // and bring it back too: + TypeIdBeanWrapper result = mapper.readValue(json, TypeIdBeanWrapper.class); + TypeIdBean bean = result.bean; + assertEquals(123, bean.x); + } + +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/TestNamingStrategy.java b/1.9.10/src/test/org/codehaus/jackson/map/TestNamingStrategy.java new file mode 100644 index 0000000..50ca254 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/TestNamingStrategy.java
@@ -0,0 +1,229 @@ +package org.codehaus.jackson.map; + +import java.util.*; + +import org.codehaus.jackson.annotate.JsonPropertyOrder; +import org.codehaus.jackson.map.annotate.JsonDeserialize; +import org.codehaus.jackson.map.introspect.AnnotatedField; +import org.codehaus.jackson.map.introspect.AnnotatedMethod; + +/** + * Unit tests to verify functioning of {@link PropertyNamingStrategy} which + * was added in Jackson 1.8, as per [JACKSON-178]. + * + * @since 1.8 + */ +public class TestNamingStrategy extends BaseMapTest +{ + /* + /********************************************************************** + /* Helper classes + /********************************************************************** + */ + + static class PrefixStrategy extends PropertyNamingStrategy + { + @Override + public String nameForField(MapperConfig<?> config, + AnnotatedField field, String defaultName) + { + return "Field-"+defaultName; + } + + @Override + public String nameForGetterMethod(MapperConfig<?> config, + AnnotatedMethod method, String defaultName) + { + return "Get-"+defaultName; + } + + @Override + public String nameForSetterMethod(MapperConfig<?> config, + AnnotatedMethod method, String defaultName) + { + return "Set-"+defaultName; + } + } + + static class CStyleStrategy extends PropertyNamingStrategy + { + @Override + public String nameForField(MapperConfig<?> config, AnnotatedField field, String defaultName) + { + return convert(defaultName); + } + + @Override + public String nameForGetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) + { + return convert(defaultName); + } + + @Override + public String nameForSetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) + { + return convert(defaultName); + } + + private String convert(String input) + { + // easy: replace capital letters with underscore, lower-cases equivalent + StringBuilder result = new StringBuilder(); + for (int i = 0, len = input.length(); i < len; ++i) { + char c = input.charAt(i); + if (Character.isUpperCase(c)) { + result.append('_'); + c = Character.toLowerCase(c); + } + result.append(c); + } + return result.toString(); + } + } + + static class GetterBean { + public int getKey() { return 123; } + } + + static class SetterBean { + protected int value; + + public void setKey(int v) { + value = v; + } + } + + static class FieldBean { + public int key; + + public FieldBean() { this(0); } + public FieldBean(int v) { key = v; } + } + + @JsonPropertyOrder({"first_name", "last_name"}) + static class PersonBean { + public String firstName; + public String lastName; + public int age; + + public PersonBean() { this(null, null, 0); } + public PersonBean(String f, String l, int a) + { + firstName = f; + lastName = l; + age = a; + } + } + + static class Value { + public int intValue; + + public Value() { this(0); } + public Value(int v) { intValue = v; } + } + + static class SetterlessWithValue + { + protected ArrayList<Value> values = new ArrayList<Value>(); + + public List<Value> getValueList() { return values; } + + public SetterlessWithValue add(int v) { + values.add(new Value(v)); + return this; + } + } + + // [JACKSON-687] + static class LcStrategy extends PropertyNamingStrategy.PropertyNamingStrategyBase + { + @Override + public String translate(String propertyName) { + return propertyName.toLowerCase(); + } + } + + static class RenamedCollectionBean + { + @JsonDeserialize + private List<String> THEvalues = Collections.emptyList(); + + // intentionally odd name, to be renamed by naming strategy + public List<String> getTheVALUEs() { return THEvalues; } + } + + /* + /********************************************************************** + /* Test methods + /********************************************************************** + */ + + public void testSimpleGetters() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.setPropertyNamingStrategy(new PrefixStrategy()); + assertEquals("{\"Get-key\":123}", mapper.writeValueAsString(new GetterBean())); + } + + public void testSimpleSetters() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.setPropertyNamingStrategy(new PrefixStrategy()); + SetterBean bean = mapper.readValue("{\"Set-key\":13}", SetterBean.class); + assertEquals(13, bean.value); + } + + public void testSimpleFields() throws Exception + { + // First serialize + ObjectMapper mapper = new ObjectMapper(); + mapper.setPropertyNamingStrategy(new PrefixStrategy()); + String json = mapper.writeValueAsString(new FieldBean(999)); + assertEquals("{\"Field-key\":999}", json); + + // then deserialize + FieldBean result = mapper.readValue(json, FieldBean.class); + assertEquals(999, result.key); + } + + public void testCStyleNaming() throws Exception + { + // First serialize + ObjectMapper mapper = new ObjectMapper(); + mapper.setPropertyNamingStrategy(new CStyleStrategy()); + String json = mapper.writeValueAsString(new PersonBean("Joe", "Sixpack", 42)); + assertEquals("{\"first_name\":\"Joe\",\"last_name\":\"Sixpack\",\"age\":42}", json); + + // then deserialize + PersonBean result = mapper.readValue(json, PersonBean.class); + assertEquals("Joe", result.firstName); + assertEquals("Sixpack", result.lastName); + assertEquals(42, result.age); + } + + public void testWithGetterAsSetter() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.setPropertyNamingStrategy(new CStyleStrategy()); + SetterlessWithValue input = new SetterlessWithValue().add(3); + String json = mapper.writeValueAsString(input); + assertEquals("{\"value_list\":[{\"int_value\":3}]}", json); + + SetterlessWithValue result = mapper.readValue(json, SetterlessWithValue.class); + assertNotNull(result.values); + assertEquals(1, result.values.size()); + assertEquals(3, result.values.get(0).intValue); + } + + // For [JACKSON-687] + public void testJson() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.setPropertyNamingStrategy(new LcStrategy()); +// mapper.disable(DeserializationConfig.Feature.USE_GETTERS_AS_SETTERS); + RenamedCollectionBean foo = mapper.readValue("{\"thevalues\":[\"a\"]}", RenamedCollectionBean.class); + assertNotNull(foo.getTheVALUEs()); + assertEquals(1, foo.getTheVALUEs().size()); + assertEquals("a", foo.getTheVALUEs().get(0)); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/TestObjectMapper.java b/1.9.10/src/test/org/codehaus/jackson/map/TestObjectMapper.java new file mode 100644 index 0000000..2cf4fc3 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/TestObjectMapper.java
@@ -0,0 +1,80 @@ +package org.codehaus.jackson.map; + +import java.io.*; + +import org.codehaus.jackson.JsonFactory; +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.map.type.TypeFactory; +import org.codehaus.jackson.node.*; + +public class TestObjectMapper extends BaseMapTest +{ + public void testProps() + { + ObjectMapper m = new ObjectMapper(); + // should have default factory + assertNotNull(m.getNodeFactory()); + JsonNodeFactory nf = JsonNodeFactory.instance; + m.setNodeFactory(nf); + assertSame(nf, m.getNodeFactory()); + } + + public void testSupport() + { + ObjectMapper m = new ObjectMapper(); + assertTrue(m.canSerialize(String.class)); + + assertTrue(m.canDeserialize(TypeFactory.defaultInstance().constructType(String.class))); + } + + public void testTreeRead() throws Exception + { + ObjectMapper m = new ObjectMapper(); + String JSON = "{ }"; + JsonNode n = m.readTree(JSON); + assertTrue(n instanceof ObjectNode); + + n = m.readTree(new StringReader(JSON)); + assertTrue(n instanceof ObjectNode); + + n = m.readTree(new ByteArrayInputStream(JSON.getBytes("UTF-8"))); + assertTrue(n instanceof ObjectNode); + } + + // Test to ensure that we can check property ordering defaults... + public void testConfigForPropertySorting() throws Exception + { + ObjectMapper m = new ObjectMapper(); + + // sort-alphabetically is disabled by default: + assertFalse(m.isEnabled(SerializationConfig.Feature.SORT_PROPERTIES_ALPHABETICALLY)); + SerializationConfig sc = m.copySerializationConfig(); + assertFalse(sc.isEnabled(SerializationConfig.Feature.SORT_PROPERTIES_ALPHABETICALLY)); + assertFalse(sc.shouldSortPropertiesAlphabetically()); + DeserializationConfig dc = m.copyDeserializationConfig(); + assertFalse(dc.shouldSortPropertiesAlphabetically()); + + // but when enabled, should be visible: + m.enable(SerializationConfig.Feature.SORT_PROPERTIES_ALPHABETICALLY); + sc = m.copySerializationConfig(); + assertTrue(sc.isEnabled(SerializationConfig.Feature.SORT_PROPERTIES_ALPHABETICALLY)); + assertTrue(sc.shouldSortPropertiesAlphabetically()); + dc = m.copyDeserializationConfig(); + // and not just via SerializationConfig, but also via DeserializationConfig + assertTrue(dc.shouldSortPropertiesAlphabetically()); + } + + + public void testJsonFactoryLinkage() + { + // first, implicit factory, giving implicit linkage + ObjectMapper m = new ObjectMapper(); + assertSame(m, m.getJsonFactory().getCodec()); + + // and then explicit factory, which should also be implicitly linked + JsonFactory f = new JsonFactory(); + m = new ObjectMapper(f); + assertSame(f, m.getJsonFactory()); + assertSame(m, f.getCodec()); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/TestObjectMapperBeanDeserializer.java b/1.9.10/src/test/org/codehaus/jackson/map/TestObjectMapperBeanDeserializer.java new file mode 100644 index 0000000..a0fc68c --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/TestObjectMapperBeanDeserializer.java
@@ -0,0 +1,280 @@ +package org.codehaus.jackson.map; + +import main.BaseTest; + +import java.io.*; +import java.net.URL; +import java.util.*; + +import org.codehaus.jackson.*; + +/** + * Unit tests for verifying deserialization of Beans. + */ +public class TestObjectMapperBeanDeserializer + extends BaseTest +{ + /* + ///////////////////////////////////////////////// + // Helper classes + ///////////////////////////////////////////////// + */ + + @SuppressWarnings("deprecation") + final static class CtorValueBean + implements JsonSerializable // so we can output as simple String + { + final String _desc; + + public CtorValueBean(String d) { _desc = d; } + public CtorValueBean(int value) { _desc = String.valueOf(value); } + public CtorValueBean(long value) { _desc = String.valueOf(value); } + + @Override + public void serialize(JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + jgen.writeString(_desc); + } + + @Override public String toString() { return _desc; } + + @Override public boolean equals(Object o) { + if (!(o instanceof CtorValueBean)) return false; + CtorValueBean other = (CtorValueBean) o; + return _desc.equals(other._desc); + } + } + + final static class FactoryValueBean + { + final String _desc; + + protected FactoryValueBean(String desc, int dummy) { _desc = desc; } + + public static FactoryValueBean valueOf(String v) { return new FactoryValueBean(v, 0); } + public static FactoryValueBean valueOf(int v) { return new FactoryValueBean(String.valueOf(v), 0); } + public static FactoryValueBean valueOf(long v) { return new FactoryValueBean(String.valueOf(v), 0); } + + @Override public String toString() { return _desc; } + } + + /** + * Simple test bean + */ + public final static class TestBean + { + int _x; + long _y; + String _desc; + URL _url; + Collection<?> _misc; + + // Explicit constructor + public TestBean(int x, long y, String desc, URL url, Collection<?> misc) + { + _x = x; + _y = y; + _desc = desc; + _url = url; + _misc = misc; + } + + // plus default one that is needed for deserialization + public TestBean() { } + + public String getDesc() { return _desc; } + public int getX() { return _x; } + public long getY() { return _y; } + public URL getURL() { return _url; } + public Collection<?> getMisc() { return _misc; } + + public void setDesc(String value) { _desc = value; } + public void setX(int value) { _x = value; } + public void setY(long value) { _y = value; } + public void setURL(URL value) { _url = value; } + public void setMisc(Collection<?> value) { _misc = value; } + + @Override + public boolean equals(Object o) + { + if (o == null || o.getClass() != getClass()) return false; + TestBean other = (TestBean) o; + return (other._x == _x) + && (other._y == _y) + && (other._desc.equals(_desc)) + && (other._url.equals(_url)) + && (other._misc.equals(_misc)) + ; + } + + @Override + public String toString() + { + StringBuilder sb = new StringBuilder(); + sb.append("[TestBean "); + sb.append("x=").append(_x); + sb.append(" y=").append(_y); + sb.append(" desc=").append(_desc); + sb.append(" url=").append(_url); + sb.append(" misc=").append(_misc); + sb.append("]"); + return sb.toString(); + } + } + + /** + * Another test bean, this one containing a typed list. Needed to ensure + * that generics type information is properly accessed via mutator methods. + * Note: List elements must be something other than what 'untyped' mapper + * would produce from serialization. + */ + public final static class BeanWithList + { + List<CtorValueBean> _beans; + + public BeanWithList() { } + public BeanWithList(List<CtorValueBean> beans) { _beans = beans; } + + public List<CtorValueBean> getBeans() { return _beans; } + + public void setBeans(List<CtorValueBean> beans) { + _beans = beans; + } + + @Override + public int hashCode() { return (_beans == null) ? -1 : _beans.size(); } + + @Override + public boolean equals(Object o) { + if (!(o instanceof BeanWithList)) return false; + BeanWithList other = BeanWithList.class.cast(o); + return _beans.equals(other._beans); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("[Bean, list "); + if (_beans == null) { + sb.append("NULL"); + } else { + sb.append('(').append(_beans.size()).append('/'); + sb.append(_beans.getClass().getName()).append(") "); + boolean type = false; + for (CtorValueBean bean : _beans) { + if (!type) { + sb.append("(").append(bean.getClass().getSimpleName()).append(")"); + type = true; + } + sb.append(bean); + sb.append(' '); + } + } + sb.append(']'); + return sb.toString(); + } + } + + /* + ///////////////////////////////////////////////// + // Deserialization from simple types (String, int) + ///////////////////////////////////////////////// + */ + + public void testFromStringCtor() throws Exception + { + CtorValueBean result = new ObjectMapper().readValue("\"abc\"", CtorValueBean.class); + assertEquals("abc", result.toString()); + } + + public void testFromIntCtor() throws Exception + { + CtorValueBean result = new ObjectMapper().readValue("13", CtorValueBean.class); + assertEquals("13", result.toString()); + } + + public void testFromLongCtor() throws Exception + { + // Must use something that is forced as Long... + long value = 12345678901244L; + CtorValueBean result = new ObjectMapper().readValue(""+value, CtorValueBean.class); + assertEquals(""+value, result.toString()); + } + + public void testFromStringFactory() throws Exception + { + FactoryValueBean result = new ObjectMapper().readValue("\"abc\"", FactoryValueBean.class); + assertEquals("abc", result.toString()); + } + + public void testFromIntFactory() throws Exception + { + FactoryValueBean result = new ObjectMapper().readValue("13", FactoryValueBean.class); + assertEquals("13", result.toString()); + } + + public void testFromLongFactory() throws Exception + { + // Must use something that is forced as Long... + long value = 12345678901244L; + FactoryValueBean result = new ObjectMapper().readValue(""+value, FactoryValueBean.class); + assertEquals(""+value, result.toString()); + } + + /* + ///////////////////////////////////////////////// + // Deserialization from Json Object + ///////////////////////////////////////////////// + */ + + public void testSimpleBean() throws Exception + { + ArrayList<Object> misc = new ArrayList<Object>(); + misc.add("xyz"); + misc.add(42); + misc.add(null); + misc.add(Boolean.TRUE); + TestBean bean = new TestBean(13, -900L, "\"test\"", new URL("http://foobar.com"), misc); + + // Hmmh. We probably should use serializer too... easier + StringWriter sw = new StringWriter(); + ObjectMapper mapper = new ObjectMapper(); + mapper.writeValue(sw, bean); + + TestBean result = new ObjectMapper().readValue(sw.toString(), TestBean.class); + assertEquals(bean, result); + } + + public void testListBean() throws Exception + { + final int COUNT = 13; + ArrayList<CtorValueBean> beans = new ArrayList<CtorValueBean>(); + for (int i = 0; i < COUNT; ++i) { + beans.add(new CtorValueBean(i)); + } + BeanWithList bean = new BeanWithList(beans); + + StringWriter sw = new StringWriter(); + ObjectMapper mapper = new ObjectMapper(); + mapper.writeValue(sw, bean); + + BeanWithList result = new ObjectMapper().readValue(sw.toString(), BeanWithList.class); + assertEquals(bean, result); + } + + /** + * Also, let's verify that unknown fields cause an exception with default + * settings. + */ + public void testUnknownFields() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + try { + TestBean bean = mapper.readValue("{ \"foobar\" : 3 }", TestBean.class); + fail("Expected an exception, got bean: "+bean); + } catch (JsonMappingException jse) { + ; + } + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/TestObjectMapperBeanSerializer.java b/1.9.10/src/test/org/codehaus/jackson/map/TestObjectMapperBeanSerializer.java new file mode 100644 index 0000000..6ebbea2 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/TestObjectMapperBeanSerializer.java
@@ -0,0 +1,233 @@ +package org.codehaus.jackson.map; + +import main.BaseTest; + +import java.io.*; +import java.net.*; +import java.math.BigDecimal; +import java.math.BigInteger; + +import org.codehaus.jackson.*; + +/** + * This unit test suite tries to verify that the "Native" java type + * mapper can properly serialize Java core objects to JSON. + * + * @author Scott Dixon + */ +public class TestObjectMapperBeanSerializer + extends BaseTest +{ + /** + * Sanity test to ensure the pieces all work when put together. + */ + public void testComplexObject() + throws Exception + { + FixtureObject aTestObj = new FixtureObject(); + ObjectMapper aMapper = new ObjectMapper(); + StringWriter aWriter = new StringWriter(); + JsonGenerator aGen = new JsonFactory().createJsonGenerator(aWriter); + aMapper.writeValue(aGen, aTestObj); + aGen.close(); + + JsonParser jp = new JsonFactory().createJsonParser(new StringReader(aWriter.toString())); + + assertEquals(JsonToken.START_OBJECT, jp.nextToken()); + + while (jp.nextToken() != JsonToken.END_OBJECT) { + assertEquals(JsonToken.FIELD_NAME, jp.getCurrentToken()); + String name = jp.getCurrentName(); + JsonToken t = jp.nextToken(); + + if (name.equals("uri")) { + assertToken(JsonToken.VALUE_STRING, t); + assertEquals(FixtureObject.VALUE_URSTR, getAndVerifyText(jp)); + } else if (name.equals("url")) { + assertToken(JsonToken.VALUE_STRING, t); + assertEquals(FixtureObject.VALUE_URSTR, getAndVerifyText(jp)); + } else if (name.equals("testNull")) { + assertToken(JsonToken.VALUE_NULL, t); + } else if (name.equals("testString")) { + assertToken(JsonToken.VALUE_STRING, t); + assertEquals(FixtureObject.VALUE_STRING, getAndVerifyText(jp)); + } else if (name.equals("testBoolean")) { + assertToken(JsonToken.VALUE_TRUE, t); + } else if (name.equals("testEnum")) { + assertToken(JsonToken.VALUE_STRING, t); + assertEquals(FixtureObject.VALUE_ENUM.toString(),getAndVerifyText(jp)); + } else if (name.equals("testInteger")) { + assertToken(JsonToken.VALUE_NUMBER_INT, t); + assertEquals(jp.getIntValue(),FixtureObject.VALUE_INT); + } else if (name.equals("testLong")) { + assertToken(JsonToken.VALUE_NUMBER_INT, t); + assertEquals(jp.getLongValue(),FixtureObject.VALUE_LONG); + } else if (name.equals("testBigInteger")) { + assertToken(JsonToken.VALUE_NUMBER_INT, t); + assertEquals(jp.getLongValue(),FixtureObject.VALUE_BIGINT.longValue()); + } else if (name.equals("testBigDecimal")) { + assertToken(JsonToken.VALUE_NUMBER_FLOAT, t); + assertEquals(jp.getText(), FixtureObject.VALUE_BIGDEC.toString()); + } else if (name.equals("testCharacter")) { + assertToken(JsonToken.VALUE_STRING, t); + assertEquals(String.valueOf(FixtureObject.VALUE_CHAR), getAndVerifyText(jp)); + } else if (name.equals("testShort")) { + assertToken(JsonToken.VALUE_NUMBER_INT, t); + assertEquals(jp.getIntValue(),FixtureObject.VALUE_SHORT); + } else if (name.equals("testByte")) { + assertToken(JsonToken.VALUE_NUMBER_INT, t); + assertEquals(jp.getIntValue(),FixtureObject.VALUE_BYTE); + } else if (name.equals("testFloat")) { + assertToken(JsonToken.VALUE_NUMBER_FLOAT, t); + assertEquals(jp.getDecimalValue().floatValue(),FixtureObject.VALUE_FLOAT); + } else if (name.equals("testDouble")) { + assertToken(JsonToken.VALUE_NUMBER_FLOAT, t); + assertEquals(jp.getDoubleValue(),FixtureObject.VALUE_DBL); + } else if (name.equals("testStringBuffer")) { + assertToken(JsonToken.VALUE_STRING, t); + assertEquals(FixtureObject.VALUE_STRING, getAndVerifyText(jp)); + } else if (name.equals("testError")) { + // More complicated... + assertToken(JsonToken.START_OBJECT, t); + + //getTestError->Exception::getCause + + while (jp.nextToken() == JsonToken.FIELD_NAME) { + name = jp.getCurrentName(); + if (name.equals("cause")) { + assertEquals(JsonToken.VALUE_NULL, jp.nextToken()); + } else if (name.equals("message")) { + assertEquals(JsonToken.VALUE_STRING, jp.nextToken()); + assertEquals(FixtureObject.VALUE_ERRTXT, getAndVerifyText(jp)); + } else if (name.equals("localizedMessage")) { + assertEquals(JsonToken.VALUE_STRING, jp.nextToken()); + } else if (name.equals("stackTrace")) { + assertEquals(JsonToken.START_ARRAY,jp.nextToken()); + int i = 0; + while(jp.nextToken() != JsonToken.END_ARRAY) { + if(i >= 100000) { + assertTrue("Probably run away loop in test. StackTrack Array was not properly closed.",false); + } + } + } else { + fail("Unexpected field name '"+name+"'"); + } + } + //CLOSE OF THE EXCEPTION + assertEquals(JsonToken.END_OBJECT, jp.getCurrentToken()); + } else { + fail("Unexpected field, name '"+name+"'"); + } + } + + //END OF TOKEN PARSING + assertNull(jp.nextToken()); + } + + private static enum EFixtureEnum + { + THIS_IS_AN_ENUM_VALUE_0, + THIS_IS_AN_ENUM_VALUE_1, + THIS_IS_AN_ENUM_VALUE_2, + THIS_IS_AN_ENUM_VALUE_3, + } + + @SuppressWarnings("unused") + private static class FixtureObjectBase + { + public static final String VALUE_STRING = "foobar"; + public static final EFixtureEnum VALUE_ENUM = EFixtureEnum.THIS_IS_AN_ENUM_VALUE_2; + public static final int VALUE_INT = Integer.MIN_VALUE; + public static final long VALUE_LONG = Long.MIN_VALUE; + public static final BigInteger VALUE_BIGINT = new BigInteger((new Long(Long.MAX_VALUE)).toString()); + public static final BigDecimal VALUE_BIGDEC = new BigDecimal((new Double(Double.MAX_VALUE)).toString()); + // this is not necessarily a good char to check + public static final char VALUE_CHAR = Character.MAX_VALUE; + public static final short VALUE_SHORT = Short.MAX_VALUE; + public static final byte VALUE_BYTE = Byte.MAX_VALUE; + public static final float VALUE_FLOAT = Float.MAX_VALUE; + public static final double VALUE_DBL = Double.MAX_VALUE; + public static final String VALUE_ERRTXT = "This is the message text for the test error."; + + public static final String VALUE_URSTR = "http://jackson.codehaus.org/hi?var1=foo%20bar"; + + public URL getURL() throws IOException + { + return new URL(VALUE_URSTR); + } + + public URI getURI() throws IOException + { + try { + return new URI(VALUE_URSTR); + } catch (Exception e) { + throw new IllegalArgumentException(e); + } + } + public String getTestNull() + { + return null; + } + public String getTestString() + { + return VALUE_STRING; + } + public boolean getTestBoolean() + { + return true; + } + public EFixtureEnum getTestEnum() + { + return VALUE_ENUM; + } + public int getTestInteger() + { + return VALUE_INT; + } + public long getTestLong() + { + return VALUE_LONG; + } + public BigInteger getTestBigInteger() + { + return VALUE_BIGINT; + } + public BigDecimal getTestBigDecimal() + { + return VALUE_BIGDEC; + } + public char getTestCharacter() + { + return VALUE_CHAR; + } + public short getTestShort() + { + return VALUE_SHORT; + } + public byte getTestByte() + { + return VALUE_BYTE; + } + public float getTestFloat() + { + return VALUE_FLOAT; + } + public double getTestDouble() + { + return VALUE_DBL; + } + public StringBuffer getTestStringBuffer() + { + return new StringBuffer(VALUE_STRING); + } + } + + @SuppressWarnings("unused") + private static class FixtureObject extends FixtureObjectBase + { + public Exception getTestError() + { + return new Exception(VALUE_ERRTXT); + } + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/TestReadValues.java b/1.9.10/src/test/org/codehaus/jackson/map/TestReadValues.java new file mode 100644 index 0000000..ee97a8c --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/TestReadValues.java
@@ -0,0 +1,163 @@ +package org.codehaus.jackson.map; + +import java.util.*; + +import org.codehaus.jackson.*; + +public class TestReadValues extends BaseMapTest +{ + /* + /********************************************************** + /* Helper types + /********************************************************** + */ + + static class Bean { + public int a; + } + + /* + /********************************************************** + /* Unit tests; root-level value sequences via Mapper + /********************************************************** + */ + + public void testRootBeans() throws Exception + { + final String JSON = "{\"a\":3}{\"a\":27} "; + ObjectMapper mapper = new ObjectMapper(); + Iterator<Bean> it = mapper.reader(Bean.class).readValues(JSON); + + assertTrue(it.hasNext()); + Bean b = it.next(); + assertEquals(3, b.a); + assertTrue(it.hasNext()); + b = it.next(); + assertEquals(27, b.a); + assertFalse(it.hasNext()); + } + + public void testRootMaps() throws Exception + { + final String JSON = "{\"a\":3}{\"a\":27} "; + ObjectMapper mapper = new ObjectMapper(); + Iterator<Map<?,?>> it = mapper.reader(Map.class).readValues(JSON); + + assertTrue(it.hasNext()); + Map<?,?> map = it.next(); + assertEquals(1, map.size()); + assertEquals(Integer.valueOf(3), map.get("a")); + assertTrue(it.hasNext()); + map = it.next(); + assertEquals(1, map.size()); + assertEquals(Integer.valueOf(27), map.get("a")); + assertFalse(it.hasNext()); + } + + public void testRootArrays() throws Exception + { + final String JSON = "[1][3]"; + ObjectMapper mapper = new ObjectMapper(); + Iterator<int[]> it = mapper.reader(int[].class).readValues(JSON); + + assertTrue(it.hasNext()); + int[] array = it.next(); + assertEquals(1, array.length); + assertEquals(1, array[0]); + assertTrue(it.hasNext()); + array = it.next(); + assertEquals(1, array.length); + assertEquals(3, array[0]); + assertFalse(it.hasNext()); + } + + /* + /********************************************************** + /* Unit tests; root-level value sequences via JsonParser + /********************************************************** + */ + + public void testRootBeansWithParser() throws Exception + { + final String JSON = "{\"a\":3}{\"a\":27} "; + ObjectMapper mapper = new ObjectMapper(); + JsonParser jp = mapper.getJsonFactory().createJsonParser(JSON); + + Iterator<Bean> it = jp.readValuesAs(Bean.class); + + assertTrue(it.hasNext()); + Bean b = it.next(); + assertEquals(3, b.a); + assertTrue(it.hasNext()); + b = it.next(); + assertEquals(27, b.a); + assertFalse(it.hasNext()); + } + + /* + /********************************************************** + /* Unit tests; non-root arrays + /********************************************************** + */ + + public void testNonRootBeans() throws Exception + { + final String JSON = "{\"leaf\":[{\"a\":3},{\"a\":27}]}"; + ObjectMapper mapper = new ObjectMapper(); + JsonParser jp = mapper.getJsonFactory().createJsonParser(JSON); + assertToken(JsonToken.START_OBJECT, jp.nextToken()); + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + + Iterator<Bean> it = mapper.reader(Bean.class).readValues(jp); + + assertTrue(it.hasNext()); + Bean b = it.next(); + assertEquals(3, b.a); + assertTrue(it.hasNext()); + b = it.next(); + assertEquals(27, b.a); + assertFalse(it.hasNext()); + jp.close(); + } + + public void testNonRootMaps() throws Exception + { + final String JSON = "[{\"a\":3},{\"a\":27}]"; + ObjectMapper mapper = new ObjectMapper(); + JsonParser jp = mapper.getJsonFactory().createJsonParser(JSON); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + Iterator<Map<?,?>> it = mapper.reader(Map.class).readValues(jp); + + assertTrue(it.hasNext()); + Map<?,?> map = it.next(); + assertEquals(1, map.size()); + assertEquals(Integer.valueOf(3), map.get("a")); + assertTrue(it.hasNext()); + map = it.next(); + assertEquals(1, map.size()); + assertEquals(Integer.valueOf(27), map.get("a")); + assertFalse(it.hasNext()); + jp.close(); + } + + public void testNonRootArrays() throws Exception + { + final String JSON = "[[1],[3]]"; + ObjectMapper mapper = new ObjectMapper(); + JsonParser jp = mapper.getJsonFactory().createJsonParser(JSON); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + Iterator<int[]> it = mapper.readValues(jp, int[].class); + + assertTrue(it.hasNext()); + int[] array = it.next(); + assertEquals(1, array.length); + assertEquals(1, array[0]); + assertTrue(it.hasNext()); + array = it.next(); + assertEquals(1, array.length); + assertEquals(3, array[0]); + assertFalse(it.hasNext()); + jp.close(); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/TestRootName.java b/1.9.10/src/test/org/codehaus/jackson/map/TestRootName.java new file mode 100644 index 0000000..2c8ac18 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/TestRootName.java
@@ -0,0 +1,55 @@ +package org.codehaus.jackson.map; + +import org.codehaus.jackson.map.annotate.JsonRootName; + +public class TestRootName extends BaseMapTest +{ + /* + /********************************************************** + /* Helper types + /********************************************************** + */ + + @JsonRootName("rudy") + static class Bean { + public int a = 3; + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + public void testRootViaMapper() throws Exception + { + ObjectMapper mapper = rootMapper(); + String json = mapper.writeValueAsString(new Bean()); + assertEquals("{\"rudy\":{\"a\":3}}", json); + Bean bean = mapper.readValue(json, Bean.class); + assertNotNull(bean); + } + + public void testRootViaWriterAndReader() throws Exception + { + ObjectMapper mapper = rootMapper(); + String json = mapper.writer().writeValueAsString(new Bean()); + assertEquals("{\"rudy\":{\"a\":3}}", json); + Bean bean = mapper.reader(Bean.class).readValue(json); + assertNotNull(bean); + } + + /* + /********************************************************** + /* Helper methods + /********************************************************** + */ + + private ObjectMapper rootMapper() + { + ObjectMapper mapper = new ObjectMapper(); + mapper.configure(SerializationConfig.Feature.WRAP_ROOT_VALUE, true); + mapper.configure(DeserializationConfig.Feature.UNWRAP_ROOT_VALUE, true); + return mapper; + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/TestStdDateFormat.java b/1.9.10/src/test/org/codehaus/jackson/map/TestStdDateFormat.java new file mode 100644 index 0000000..54b53d8 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/TestStdDateFormat.java
@@ -0,0 +1,26 @@ +package org.codehaus.jackson.map; + +import java.util.*; + +import org.codehaus.jackson.map.util.StdDateFormat; + +public class TestStdDateFormat + extends BaseMapTest +{ + public void testFactories() { + assertNotNull(StdDateFormat.getBlueprintISO8601Format()); + assertNotNull(StdDateFormat.getBlueprintRFC1123Format()); + TimeZone tz = TimeZone.getTimeZone("GMT"); + assertNotNull(StdDateFormat.getISO8601Format(tz)); + assertNotNull(StdDateFormat.getRFC1123Format(tz)); + } + + public void testInvalid() { + StdDateFormat std = new StdDateFormat(); + try { + std.parse("foobar"); + } catch (java.text.ParseException e) { + verifyException(e, "Can not parse"); + } + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/TestStdNamingStrategies.java b/1.9.10/src/test/org/codehaus/jackson/map/TestStdNamingStrategies.java new file mode 100644 index 0000000..35047e3 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/TestStdNamingStrategies.java
@@ -0,0 +1,228 @@ +package org.codehaus.jackson.map; + +import static org.codehaus.jackson.map.PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES; + +import java.util.Arrays; +import java.util.List; + +import org.codehaus.jackson.annotate.JsonPropertyOrder; +import org.codehaus.jackson.map.TestNamingStrategy.PersonBean; +import org.junit.Test; + +/** + * Unit tests to verify functioning of + * {@link PropertyNamingStrategy#CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES} + * inside the context of an ObjectMapper. + * CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES was added in Jackson 1.9, + * as per [JACKSON-598]. + * + * @since 1.9 + */ +public class TestStdNamingStrategies extends BaseMapTest +{ + /* + /********************************************************** + /* Helper types + /********************************************************** + */ + + @JsonPropertyOrder({"www", "some_url", "some_uris"}) + static class Acronyms + { + public String WWW; + public String someURL; + public String someURIs; + + public Acronyms() {this(null, null, null);} + public Acronyms(String WWW, String someURL, String someURIs) + { + this.WWW = WWW; + this.someURL = someURL; + this.someURIs = someURIs; + } + } + + @JsonPropertyOrder({"from_user", "user", "from$user", "from7user", "_"}) + static class UnchangedNames + { + public String from_user; + public String _user; + public String from$user; + public String from7user; + public String _; + + public UnchangedNames() {this(null, null, null, null, null);} + public UnchangedNames(String from_user, String _user, String from$user, String from7user, String _) + { + this.from_user = from_user; + this._user = _user; + this.from$user = from$user; + this.from7user = from7user; + this._ = _; + } + } + + @JsonPropertyOrder({"results", "user", "__", "$_user"}) + static class OtherNonStandardNames + { + public String Results; + public String _User; + public String ___; + public String $User; + + public OtherNonStandardNames() {this(null, null, null, null);} + public OtherNonStandardNames(String Results, String _User, String ___, String $User) + { + this.Results = Results; + this._User = _User; + this.___ = ___; + this.$User = $User; + } + } + + /* + /********************************************************** + /* Set up + /********************************************************** + */ + + public static List<Object[]> NAME_TRANSLATIONS = Arrays.asList(new Object[][] { + {null, null}, + {"", ""}, + {"a", "a"}, + {"abc", "abc"}, + {"1", "1"}, + {"123", "123"}, + {"1a", "1a"}, + {"a1", "a1"}, + {"$", "$"}, + {"$a", "$a"}, + {"a$", "a$"}, + {"$_a", "$_a"}, + {"a_$", "a_$"}, + {"a$a", "a$a"}, + {"$A", "$_a"}, + {"$_A", "$_a"}, + {"_", "_"}, + {"__", "_"}, + {"___", "__"}, + {"A", "a"}, + {"A1", "a1"}, + {"1A", "1_a"}, + {"_a", "a"}, + {"_A", "a"}, + {"a_a", "a_a"}, + {"a_A", "a_a"}, + {"A_A", "a_a"}, + {"A_a", "a_a"}, + {"WWW", "www"}, + {"someURI", "some_uri"}, + {"someURIs", "some_uris"}, + {"Results", "results"}, + {"_Results", "results"}, + {"_results", "results"}, + {"__results", "_results"}, + {"__Results", "_results"}, + {"___results", "__results"}, + {"___Results", "__results"}, + {"userName", "user_name"}, + {"user_name", "user_name"}, + {"user__name", "user__name"}, + {"UserName", "user_name"}, + {"User_Name", "user_name"}, + {"User__Name", "user__name"}, + {"_user_name", "user_name"}, + {"_UserName", "user_name"}, + {"_User_Name", "user_name"}, + {"UGLY_NAME", "ugly_name"}, + {"_Bars", "bars" } + }); + + private ObjectMapper mapper; + + @Override + public void setUp() throws Exception + { + super.setUp(); + mapper = new ObjectMapper(); + mapper.setPropertyNamingStrategy(CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES); + } + + /* + /********************************************************** + /* Test methods for CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES + /********************************************************** + */ + + /** + * Unit test to verify translations of + * {@link PropertyNamingStrategy#CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES} + * outside the context of an ObjectMapper. + * CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES was added in Jackson 1.9, + * as per [JACKSON-598]. + */ + @Test + public void testLowerCaseStrategyStandAlone() + { + for (Object[] pair : NAME_TRANSLATIONS) { + String translatedJavaName = PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES.nameForField(null, null, + (String) pair[0]); + assertEquals((String) pair[1], translatedJavaName); + } + } + + public void testLowerCaseTranslations() throws Exception + { + // First serialize + String json = mapper.writeValueAsString(new PersonBean("Joe", "Sixpack", 42)); + assertEquals("{\"first_name\":\"Joe\",\"last_name\":\"Sixpack\",\"age\":42}", json); + + // then deserialize + PersonBean result = mapper.readValue(json, PersonBean.class); + assertEquals("Joe", result.firstName); + assertEquals("Sixpack", result.lastName); + assertEquals(42, result.age); + } + + public void testLowerCaseAcronymsTranslations() throws Exception + { + // First serialize + String json = mapper.writeValueAsString(new Acronyms("world wide web", "http://jackson.codehaus.org", "/path1/,/path2/")); + assertEquals("{\"www\":\"world wide web\",\"some_url\":\"http://jackson.codehaus.org\",\"some_uris\":\"/path1/,/path2/\"}", json); + + // then deserialize + Acronyms result = mapper.readValue(json, Acronyms.class); + assertEquals("world wide web", result.WWW); + assertEquals("http://jackson.codehaus.org", result.someURL); + assertEquals("/path1/,/path2/", result.someURIs); + } + + public void testLowerCaseOtherNonStandardNamesTranslations() throws Exception + { + // First serialize + String json = mapper.writeValueAsString(new OtherNonStandardNames("Results", "_User", "___", "$User")); + assertEquals("{\"results\":\"Results\",\"user\":\"_User\",\"__\":\"___\",\"$_user\":\"$User\"}", json); + + // then deserialize + OtherNonStandardNames result = mapper.readValue(json, OtherNonStandardNames.class); + assertEquals("Results", result.Results); + assertEquals("_User", result._User); + assertEquals("___", result.___); + assertEquals("$User", result.$User); + } + + public void testLowerCaseUnchangedNames() throws Exception + { + // First serialize + String json = mapper.writeValueAsString(new UnchangedNames("from_user", "_user", "from$user", "from7user", "_")); + assertEquals("{\"from_user\":\"from_user\",\"user\":\"_user\",\"from$user\":\"from$user\",\"from7user\":\"from7user\",\"_\":\"_\"}", json); + + // then deserialize + UnchangedNames result = mapper.readValue(json, UnchangedNames.class); + assertEquals("from_user", result.from_user); + assertEquals("_user", result._user); + assertEquals("from$user", result.from$user); + assertEquals("from7user", result.from7user); + assertEquals("_", result._); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/TestToJavaType.java b/1.9.10/src/test/org/codehaus/jackson/map/TestToJavaType.java new file mode 100644 index 0000000..d4f8aa1 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/TestToJavaType.java
@@ -0,0 +1,71 @@ +package org.codehaus.jackson.map; + +import java.io.*; +import java.util.*; + +import org.codehaus.jackson.*; + +/** + * Unit tests for verifying "old" data binding from Json to JDK objects; + * one that only uses core JDK types; wrappers, Maps and Lists. + */ +public class TestToJavaType + extends main.BaseTest +{ + @SuppressWarnings("unchecked") + public void testSampleDoc() + throws Exception + { + final String JSON = SAMPLE_DOC_JSON_SPEC; + + JsonFactory jf = new JsonFactory(); + + /* To get "untyped" Mapping (to Maps, Lists, instead of beans etc), + * we'll specify plain old Object.class as the target. + */ + Object root = new ObjectMapper().readValue(jf.createJsonParser(new StringReader(JSON)), Object.class); + + assertType(root, Map.class); + Map<?,?> rootMap = (Map<?,?>) root; + assertEquals(1, rootMap.size()); + Map.Entry<?,?> rootEntry = rootMap.entrySet().iterator().next(); + assertEquals("Image", rootEntry.getKey()); + Object image = rootEntry.getValue(); + assertType(image, Map.class); + Map<?,?> imageMap = (Map<?,?>) image; + assertEquals(5, imageMap.size()); + + Object value = imageMap.get("Width"); + assertType(value, Integer.class); + assertEquals(Integer.valueOf(SAMPLE_SPEC_VALUE_WIDTH), value); + + value = imageMap.get("Height"); + assertType(value, Integer.class); + assertEquals(Integer.valueOf(SAMPLE_SPEC_VALUE_HEIGHT), value); + + assertEquals(SAMPLE_SPEC_VALUE_TITLE, imageMap.get("Title")); + + // Another Object, "thumbnail" + value = imageMap.get("Thumbnail"); + assertType(value, Map.class); + Map<?,?> tnMap = (Map<?,?>) value; + assertEquals(3, tnMap.size()); + + assertEquals(Integer.valueOf(SAMPLE_SPEC_VALUE_TN_HEIGHT), tnMap.get("Height")); + // for some reason, width is textual, not numeric... + assertEquals(SAMPLE_SPEC_VALUE_TN_WIDTH, tnMap.get("Width")); + assertEquals(SAMPLE_SPEC_VALUE_TN_URL, tnMap.get("Url")); + + // And then number list, "IDs" + value = imageMap.get("IDs"); + assertType(value, List.class); + List<Object> ids = (List<Object>) value; + assertEquals(4, ids.size()); + assertEquals(Integer.valueOf(SAMPLE_SPEC_VALUE_TN_ID1), ids.get(0)); + assertEquals(Integer.valueOf(SAMPLE_SPEC_VALUE_TN_ID2), ids.get(1)); + assertEquals(Integer.valueOf(SAMPLE_SPEC_VALUE_TN_ID3), ids.get(2)); + assertEquals(Integer.valueOf(SAMPLE_SPEC_VALUE_TN_ID4), ids.get(3)); + + // and that's all folks! + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/TestUpdateValue.java b/1.9.10/src/test/org/codehaus/jackson/map/TestUpdateValue.java new file mode 100644 index 0000000..da9e57f --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/TestUpdateValue.java
@@ -0,0 +1,115 @@ +package org.codehaus.jackson.map; + +import java.util.*; + +import static org.junit.Assert.assertArrayEquals; + +public class TestUpdateValue extends BaseMapTest +{ + /* + /******************************************************** + /* Helper types + /******************************************************** + */ + + static class Bean { + public String a = "a"; + public String b = "b"; + + public int[] c = new int[] { 1, 2, 3 }; + + public Bean child = null; + } + + static class XYBean { + public int x, y; + } + + /* + /******************************************************** + /* Unit tests + /******************************************************** + */ + + public void testBeanUpdate() throws Exception + { + ObjectMapper m = new ObjectMapper(); + Bean bean = new Bean(); + assertEquals("b", bean.b); + assertEquals(3, bean.c.length); + assertNull(bean.child); + + Object ob = m.readerForUpdating(bean).readValue("{ \"b\":\"x\", \"c\":[4,5], \"child\":{ \"a\":\"y\"} }"); + assertSame(ob, bean); + + assertEquals("a", bean.a); + assertEquals("x", bean.b); + assertArrayEquals(new int[] { 4, 5 }, bean.c); + + Bean child = bean.child; + assertNotNull(child); + assertEquals("y", child.a); + assertEquals("b", child.b); + assertArrayEquals(new int[] { 1, 2, 3 }, child.c); + assertNull(child.child); + } + + public void testListUpdate() throws Exception + { + ObjectMapper m = new ObjectMapper(); + List<String> strs = new ArrayList<String>(); + strs.add("a"); + // for lists, we will be appending entries + Object ob = m.readerForUpdating(strs).readValue("[ \"b\", \"c\", \"d\" ]"); + assertSame(strs, ob); + assertEquals(4, strs.size()); + assertEquals("a", strs.get(0)); + assertEquals("b", strs.get(1)); + assertEquals("c", strs.get(2)); + assertEquals("d", strs.get(3)); + } + + public void testMapUpdate() throws Exception + { + ObjectMapper m = new ObjectMapper(); + Map<String,String> strs = new HashMap<String,String>(); + strs.put("a", "a"); + strs.put("b", "b"); + // for maps, we will be adding and/or overwriting entries + Object ob = m.readerForUpdating(strs).readValue("{ \"c\" : \"c\", \"a\" : \"z\" }"); + assertSame(strs, ob); + assertEquals(3, strs.size()); + assertEquals("z", strs.get("a")); + assertEquals("b", strs.get("b")); + assertEquals("c", strs.get("c")); + } + + // Test for [JACKSON-717] -- ensure 'readValues' also does update + public void testUpdateSequence() throws Exception + { + ObjectMapper m = new ObjectMapper(); + XYBean toUpdate = new XYBean(); + Iterator<XYBean> it = m.readerForUpdating(toUpdate).readValues( + "{\"x\":1,\"y\":2}\n{\"x\":16}{\"y\":37}"); + + assertTrue(it.hasNext()); + XYBean value = it.next(); + assertSame(toUpdate, value); + assertEquals(1, value.x); + assertEquals(2, value.y); + + assertTrue(it.hasNext()); + value = it.next(); + assertSame(toUpdate, value); + assertEquals(16, value.x); + assertEquals(2, value.y); // unchanged + + assertTrue(it.hasNext()); + value = it.next(); + assertSame(toUpdate, value); + assertEquals(16, value.x); // unchanged + assertEquals(37, value.y); + + assertFalse(it.hasNext()); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/access/TestSerAnyGetter.java b/1.9.10/src/test/org/codehaus/jackson/map/access/TestSerAnyGetter.java new file mode 100644 index 0000000..2e8be43 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/access/TestSerAnyGetter.java
@@ -0,0 +1,75 @@ +package org.codehaus.jackson.map.access; + +import java.util.*; + +import org.codehaus.jackson.annotate.JsonAnyGetter; +import org.codehaus.jackson.annotate.JsonAnySetter; +import org.codehaus.jackson.map.*; + +/** + * Separate tests located in different package than code being + * exercised; needed to trigger some access-related failures. + */ +public class TestSerAnyGetter + extends BaseMapTest +{ + /* + /********************************************************** + /* Helper bean classes + /********************************************************** + */ + + static class DynaBean { + public int id; + + protected HashMap<String,String> other = new HashMap<String,String>(); + + @JsonAnyGetter + public Map<String,String> any() { + return other; + } + + @JsonAnySetter + public void set(String name, String value) { + other.put(name, value); + } + } + + private static class PrivateThing + { + @SuppressWarnings("unused") + @JsonAnyGetter + public Map<?,?> getProperties() + { + HashMap<String,String> map = new HashMap<String,String>(); + map.put("a", "A"); + return map; + } + } + + /* + /********************************************************** + /* Test cases + /********************************************************** + */ + + public void testDynaBean() throws Exception + { + ObjectMapper m = new ObjectMapper(); + DynaBean b = new DynaBean(); + b.id = 123; + b.set("name", "Billy"); + assertEquals("{\"id\":123,\"name\":\"Billy\"}", m.writeValueAsString(b)); + + DynaBean result = m.readValue("{\"id\":2,\"name\":\"Joe\"}", DynaBean.class); + assertEquals(2, result.id); + assertEquals("Joe", result.other.get("name")); + } + + public void testPrivate() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + String json = mapper.writeValueAsString(new PrivateThing()); + assertEquals("{\"a\":\"A\"}", json); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/contextual/TestContextualDeserialization.java b/1.9.10/src/test/org/codehaus/jackson/map/contextual/TestContextualDeserialization.java new file mode 100644 index 0000000..9cc2d0f --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/contextual/TestContextualDeserialization.java
@@ -0,0 +1,297 @@ +package org.codehaus.jackson.map.contextual; + +import java.io.IOException; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.util.*; + +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.Version; +import org.codehaus.jackson.annotate.JacksonAnnotation; +import org.codehaus.jackson.annotate.JsonCreator; +import org.codehaus.jackson.annotate.JsonProperty; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.JsonDeserialize; +import org.codehaus.jackson.map.module.SimpleModule; + +/** + * Test cases to verify that it is possible to define deserializers + * that can use contextual information (like field/method + * annotations) for configuration. + * + * @since 1.7 + */ +public class TestContextualDeserialization extends BaseMapTest +{ + /* + /********************************************************** + /* Helper classes + /********************************************************** + */ + + /* NOTE: important; MUST be considered a 'Jackson' annotation to be seen + * (or recognized otherwise via AnnotationIntrospect.isHandled()) + */ + @Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.TYPE}) + @Retention(RetentionPolicy.RUNTIME) + @JacksonAnnotation + public @interface Name { + public String value(); + } + + static class ContextualType { + protected String value; + + public ContextualType(String v) { value = v; } + } + + static class ContextualBean + { + @Name("NameA") + public ContextualType a; + @Name("NameB") + public ContextualType b; + } + + static class ContextualCtorBean + { + protected String a, b; + + @JsonCreator + public ContextualCtorBean( + @Name("CtorA") @JsonProperty("a") ContextualType a, + @Name("CtorB") @JsonProperty("b") ContextualType b) + { + this.a = a.value; + this.b = b.value; + } + } + + @Name("Class") + static class ContextualClassBean + { + public ContextualType a; + + @Name("NameB") + public ContextualType b; + } + + static class AnnotatedContextualClassBean + { + @Name("xyz") + @JsonDeserialize(using=AnnotatedContextualDeserializer.class) + public ContextualType value; + } + + static class ContextualArrayBean + { + @Name("array") + public ContextualType[] beans; + } + + static class ContextualListBean + { + @Name("list") + public List<ContextualType> beans; + } + + static class ContextualMapBean + { + @Name("map") + public Map<String, ContextualType> beans; + } + + static class MyContextualDeserializer + extends JsonDeserializer<ContextualType> + implements ContextualDeserializer<ContextualType> + { + protected final String _fieldName; + + public MyContextualDeserializer() { this(""); } + public MyContextualDeserializer(String fieldName) { + _fieldName = fieldName; + } + + @Override + public ContextualType deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException + { + return new ContextualType(""+_fieldName+"="+jp.getText()); + } + + @Override + public JsonDeserializer<ContextualType> createContextual(DeserializationConfig config, + BeanProperty property) + throws JsonMappingException + { + return new MyContextualDeserializer(property.getName()); + } + } + + /** + * Alternative that uses annotation for choosing name to use + */ + static class AnnotatedContextualDeserializer + extends JsonDeserializer<ContextualType> + implements ContextualDeserializer<ContextualType> + { + protected final String _fieldName; + + public AnnotatedContextualDeserializer() { this(""); } + public AnnotatedContextualDeserializer(String fieldName) { + _fieldName = fieldName; + } + + @Override + public ContextualType deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException + { + return new ContextualType(""+_fieldName+"="+jp.getText()); + } + + @Override + public JsonDeserializer<ContextualType> createContextual(DeserializationConfig config, + BeanProperty property) + throws JsonMappingException + { + Name ann = property.getAnnotation(Name.class); + if (ann == null) { + ann = property.getContextAnnotation(Name.class); + } + String propertyName = (ann == null) ? "UNKNOWN" : ann.value(); + return new MyContextualDeserializer(propertyName); + } + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + public void testSimple() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + SimpleModule module = new SimpleModule("test", Version.unknownVersion()); + module.addDeserializer(ContextualType.class, new MyContextualDeserializer()); + mapper.registerModule(module); + ContextualBean bean = mapper.readValue("{\"a\":\"1\",\"b\":\"2\"}", ContextualBean.class); + assertEquals("a=1", bean.a.value); + assertEquals("b=2", bean.b.value); + + // try again, to ensure caching etc works + bean = mapper.readValue("{\"a\":\"3\",\"b\":\"4\"}", ContextualBean.class); + assertEquals("a=3", bean.a.value); + assertEquals("b=4", bean.b.value); + } + + public void testSimpleWithAnnotations() throws Exception + { + ObjectMapper mapper = _mapperWithAnnotatedContextual(); + ContextualBean bean = mapper.readValue("{\"a\":\"1\",\"b\":\"2\"}", ContextualBean.class); + assertEquals("NameA=1", bean.a.value); + assertEquals("NameB=2", bean.b.value); + + // try again, to ensure caching etc works + bean = mapper.readValue("{\"a\":\"x\",\"b\":\"y\"}", ContextualBean.class); + assertEquals("NameA=x", bean.a.value); + assertEquals("NameB=y", bean.b.value); + } + + public void testSimpleWithClassAnnotations() throws Exception + { + ObjectMapper mapper = _mapperWithAnnotatedContextual(); + ContextualClassBean bean = mapper.readValue("{\"a\":\"1\",\"b\":\"2\"}", ContextualClassBean.class); + assertEquals("Class=1", bean.a.value); + assertEquals("NameB=2", bean.b.value); + // and again + bean = mapper.readValue("{\"a\":\"123\",\"b\":\"345\"}", ContextualClassBean.class); + assertEquals("Class=123", bean.a.value); + assertEquals("NameB=345", bean.b.value); + } + + public void testAnnotatedCtor() throws Exception + { + ObjectMapper mapper = _mapperWithAnnotatedContextual(); + ContextualCtorBean bean = mapper.readValue("{\"a\":\"foo\",\"b\":\"bar\"}", ContextualCtorBean.class); + assertEquals("CtorA=foo", bean.a); + assertEquals("CtorB=bar", bean.b); + + bean = mapper.readValue("{\"a\":\"1\",\"b\":\"0\"}", ContextualCtorBean.class); + assertEquals("CtorA=1", bean.a); + assertEquals("CtorB=0", bean.b); + } + + public void testAnnotatedArray() throws Exception + { + ObjectMapper mapper = _mapperWithAnnotatedContextual(); + ContextualArrayBean bean = mapper.readValue("{\"beans\":[\"x\"]}", ContextualArrayBean.class); + assertEquals(1, bean.beans.length); + assertEquals("array=x", bean.beans[0].value); + + bean = mapper.readValue("{\"beans\":[\"a\",\"b\"]}", ContextualArrayBean.class); + assertEquals(2, bean.beans.length); + assertEquals("array=a", bean.beans[0].value); + assertEquals("array=b", bean.beans[1].value); + } + + public void testAnnotatedList() throws Exception + { + ObjectMapper mapper = _mapperWithAnnotatedContextual(); + ContextualListBean bean = mapper.readValue("{\"beans\":[\"x\"]}", ContextualListBean.class); + assertEquals(1, bean.beans.size()); + assertEquals("list=x", bean.beans.get(0).value); + + bean = mapper.readValue("{\"beans\":[\"x\",\"y\",\"z\"]}", ContextualListBean.class); + assertEquals(3, bean.beans.size()); + assertEquals("list=x", bean.beans.get(0).value); + assertEquals("list=y", bean.beans.get(1).value); + assertEquals("list=z", bean.beans.get(2).value); + } + + public void testAnnotatedMap() throws Exception + { + ObjectMapper mapper = _mapperWithAnnotatedContextual(); + ContextualMapBean bean = mapper.readValue("{\"beans\":{\"a\":\"b\"}}", ContextualMapBean.class); + assertEquals(1, bean.beans.size()); + Map.Entry<String,ContextualType> entry = bean.beans.entrySet().iterator().next(); + assertEquals("a", entry.getKey()); + assertEquals("map=b", entry.getValue().value); + + bean = mapper.readValue("{\"beans\":{\"x\":\"y\",\"1\":\"2\"}}", ContextualMapBean.class); + assertEquals(2, bean.beans.size()); + Iterator<Map.Entry<String,ContextualType>> it = bean.beans.entrySet().iterator(); + entry = it.next(); + assertEquals("x", entry.getKey()); + assertEquals("map=y", entry.getValue().value); + entry = it.next(); + assertEquals("1", entry.getKey()); + assertEquals("map=2", entry.getValue().value); + } + + // ensure that direct associations also work + public void testAnnotatedContextual() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + AnnotatedContextualClassBean bean = mapper.readValue( + "{\"value\":\"a\"}", + AnnotatedContextualClassBean.class); + assertNotNull(bean); + assertEquals("xyz=a", bean.value.value); + } + + /* + /********************************************************** + /* Helper methods + /********************************************************** + */ + + private ObjectMapper _mapperWithAnnotatedContextual() + { + ObjectMapper mapper = new ObjectMapper(); + SimpleModule module = new SimpleModule("test", Version.unknownVersion()); + module.addDeserializer(ContextualType.class, new AnnotatedContextualDeserializer()); + mapper.registerModule(module); + return mapper; + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/contextual/TestContextualKeyTypes.java b/1.9.10/src/test/org/codehaus/jackson/map/contextual/TestContextualKeyTypes.java new file mode 100644 index 0000000..0bff444 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/contextual/TestContextualKeyTypes.java
@@ -0,0 +1,123 @@ +package org.codehaus.jackson.map.contextual; + +import java.io.IOException; +import java.util.*; + +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.Version; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.module.SimpleModule; +import org.codehaus.jackson.map.type.TypeFactory; + +/** + * Tests to ensure that we can do contextual key serializers and + * deserializers as well as value ser/deser. + * + * @since 1.8 + */ +public class TestContextualKeyTypes extends BaseMapTest +{ + /* + /********************************************************** + /* Helper classes + /********************************************************** + */ + + static class ContextualKeySerializer + extends JsonSerializer<String> + implements ContextualSerializer<String> + { + protected final String _prefix; + + public ContextualKeySerializer() { this(""); } + public ContextualKeySerializer(String p) { + _prefix = p; + } + + @Override + public void serialize(String value, JsonGenerator jgen, SerializerProvider provider) throws IOException + { + if (_prefix != null) { + value = _prefix + value; + } + jgen.writeFieldName(value); + } + + @Override + public JsonSerializer<String> createContextual(SerializationConfig config, BeanProperty property) + throws JsonMappingException + { + return new ContextualKeySerializer(_prefix+":"); + } + } + + static class ContextualDeser + extends KeyDeserializer + implements ContextualKeyDeserializer + { + protected final String _prefix; + + protected ContextualDeser(String p) { + _prefix = p; + } + + @Override + public Object deserializeKey(String key, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + return _prefix + ":" + key; + } + + @Override + public KeyDeserializer createContextual(DeserializationConfig config, + BeanProperty property) throws JsonMappingException + { + return new ContextualDeser((property == null) ? "ROOT" : property.getName()); + } + } + + static class MapBean { + public Map<String, Integer> map; + } + + /* + /********************************************************** + /* Unit tests, serialization + /********************************************************** + */ + + public void testSimpleKeySer() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + SimpleModule module = new SimpleModule("test", Version.unknownVersion()); + module.addKeySerializer(String.class, new ContextualKeySerializer("prefix")); + mapper.registerModule(module); + Map<String,Object> input = new HashMap<String,Object>(); + input.put("a", Integer.valueOf(3)); + String json = mapper.writerWithType(TypeFactory.defaultInstance().constructMapType(HashMap.class, String.class, Object.class)) + .writeValueAsString(input); + assertEquals("{\"prefix:a\":3}", json); + } + + /* + /********************************************************** + /* Unit tests, deserialization + /********************************************************** + */ + + public void testSimpleKeyDeser() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + SimpleModule module = new SimpleModule("test", Version.unknownVersion()); + module.addKeyDeserializer(String.class, new ContextualDeser("???")); + mapper.registerModule(module); + MapBean result = mapper.readValue("{\"map\":{\"a\":3}}", MapBean.class); + Map<String,Integer> map = result.map; + assertNotNull(map); + assertEquals(1, map.size()); + Map.Entry<String,Integer> entry = map.entrySet().iterator().next(); + assertEquals(Integer.valueOf(3), entry.getValue()); + assertEquals("map:a", entry.getKey()); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/contextual/TestContextualSerialization.java b/1.9.10/src/test/org/codehaus/jackson/map/contextual/TestContextualSerialization.java new file mode 100644 index 0000000..31dc710 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/contextual/TestContextualSerialization.java
@@ -0,0 +1,277 @@ +package org.codehaus.jackson.map.contextual; + +import java.io.IOException; +import java.lang.annotation.*; +import java.util.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.annotate.JacksonAnnotation; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.JsonSerialize; +import org.codehaus.jackson.map.module.SimpleModule; + +/** + * Test cases to verify that it is possible to define serializers + * that can use contextual information (like field/method + * annotations) for configuration. + * + * @since 1.7 + */ +public class TestContextualSerialization extends BaseMapTest +{ + /* + /********************************************************** + /* Helper classes + /********************************************************** + */ + + /* NOTE: important; MUST be considered a 'Jackson' annotation to be seen + * (or recognized otherwise via AnnotationIntrospect.isHandled()) + */ + @Target({ElementType.FIELD, ElementType.TYPE, ElementType.METHOD}) + @Retention(RetentionPolicy.RUNTIME) + @JacksonAnnotation + public @interface Prefix { + public String value(); + } + + static class ContextualBean + { + protected final String _value; + + public ContextualBean(String s) { _value = s; } + + @Prefix("see:") + public String getValue() { return _value; } + } + + // For [JACKSON-569] + static class AnnotatedContextualBean + { + @Prefix("prefix->") + @JsonSerialize(using=AnnotatedContextualSerializer.class) + protected final String value; + + public AnnotatedContextualBean(String s) { value = s; } + } + + + @Prefix("wrappedBean:") + static class ContextualBeanWrapper + { + @Prefix("wrapped:") + public ContextualBean wrapped; + + public ContextualBeanWrapper(String s) { + wrapped = new ContextualBean(s); + } + } + + static class ContextualArrayBean + { + @Prefix("array->") + public final String[] beans; + + public ContextualArrayBean(String... strings) { + beans = strings; + } + } + + static class ContextualListBean + { + @Prefix("list->") + public final List<String> beans = new ArrayList<String>(); + + public ContextualListBean(String... strings) { + for (String string : strings) { + beans.add(string); + } + } + } + + static class ContextualMapBean + { + @Prefix("map->") + public final Map<String, String> beans = new HashMap<String, String>(); + } + + /** + * Another bean that has class annotations that should be visible for + * contextualizer, too + */ + @Prefix("Voila->") + static class BeanWithClassConfig + { + public String value; + + public BeanWithClassConfig(String v) { value = v; } + } + + /** + * Annotation-based contextual serializer that simply prepends piece of text. + */ + static class AnnotatedContextualSerializer + extends JsonSerializer<String> + implements ContextualSerializer<String> + { + protected final String _prefix; + + public AnnotatedContextualSerializer() { this(""); } + public AnnotatedContextualSerializer(String p) { + _prefix = p; + } + + @Override + public void serialize(String value, JsonGenerator jgen, SerializerProvider provider) throws IOException + { + jgen.writeString(_prefix + value); + } + + @Override + public JsonSerializer<String> createContextual(SerializationConfig config, BeanProperty property) + throws JsonMappingException + { + String prefix = "UNKNOWN"; + Prefix ann = property.getAnnotation(Prefix.class); + if (ann == null) { + ann = property.getContextAnnotation(Prefix.class); + } + if (ann != null) { + prefix = ann.value(); + } + return new AnnotatedContextualSerializer(prefix); + } + } + + static class ContextualAndResolvable + extends JsonSerializer<String> + implements ContextualSerializer<String>, ResolvableSerializer + { + protected boolean isContextual; + protected boolean isResolved; + + public ContextualAndResolvable() { this(false); } + + public ContextualAndResolvable(boolean contextual) + { + isContextual = contextual; + isResolved = false; + } + + @Override + public void serialize(String value, JsonGenerator jgen, SerializerProvider provider) throws IOException + { + jgen.writeString("contextual="+isContextual+",resolved="+isResolved); + } + + @Override + public JsonSerializer<String> createContextual(SerializationConfig config, BeanProperty property) + throws JsonMappingException + { + return new ContextualAndResolvable(true); + } + + @Override + public void resolve(SerializerProvider provider) { + isResolved = true; + } + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + /** + * Test to verify that contextual serializer can make use of property + * (method, field) annotations. + */ + public void testMethodAnnotations() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + SimpleModule module = new SimpleModule("test", Version.unknownVersion()); + module.addSerializer(String.class, new AnnotatedContextualSerializer()); + mapper.registerModule(module); + assertEquals("{\"value\":\"see:foobar\"}", mapper.writeValueAsString(new ContextualBean("foobar"))); + } + + /** + * Test to verify that contextual serializer can also use annotations + * for enclosing class. + */ + public void testClassAnnotations() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + SimpleModule module = new SimpleModule("test", Version.unknownVersion()); + module.addSerializer(String.class, new AnnotatedContextualSerializer()); + mapper.registerModule(module); + assertEquals("{\"value\":\"Voila->xyz\"}", mapper.writeValueAsString(new BeanWithClassConfig("xyz"))); + } + + public void testWrappedBean() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + SimpleModule module = new SimpleModule("test", Version.unknownVersion()); + module.addSerializer(String.class, new AnnotatedContextualSerializer()); + mapper.registerModule(module); + assertEquals("{\"wrapped\":{\"value\":\"see:xyz\"}}", mapper.writeValueAsString(new ContextualBeanWrapper("xyz"))); + } + + /** + * Serializer should get passed property context even if contained in an array. + */ + public void testMethodAnnotationInArray() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + SimpleModule module = new SimpleModule("test", Version.unknownVersion()); + module.addSerializer(String.class, new AnnotatedContextualSerializer()); + mapper.registerModule(module); + ContextualArrayBean beans = new ContextualArrayBean("123"); + assertEquals("{\"beans\":[\"array->123\"]}", mapper.writeValueAsString(beans)); + } + + /** + * Serializer should get passed property context even if contained in a Collection. + */ + public void testMethodAnnotationInList() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + SimpleModule module = new SimpleModule("test", Version.unknownVersion()); + module.addSerializer(String.class, new AnnotatedContextualSerializer()); + mapper.registerModule(module); + ContextualListBean beans = new ContextualListBean("abc"); + assertEquals("{\"beans\":[\"list->abc\"]}", mapper.writeValueAsString(beans)); + } + + /** + * Serializer should get passed property context even if contained in a Collection. + */ + public void testMethodAnnotationInMap() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + SimpleModule module = new SimpleModule("test", Version.unknownVersion()); + module.addSerializer(String.class, new AnnotatedContextualSerializer()); + mapper.registerModule(module); + ContextualMapBean map = new ContextualMapBean(); + map.beans.put("first", "In Map"); + assertEquals("{\"beans\":{\"first\":\"map->In Map\"}}", mapper.writeValueAsString(map)); + } + + public void testContextualViaAnnotation() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + AnnotatedContextualBean bean = new AnnotatedContextualBean("abc"); + assertEquals("{\"value\":\"prefix->abc\"}", mapper.writeValueAsString(bean)); + } + + // [JACKSON-647]: is resolve() called for contextual instances? + public void testResolveOnContextual() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + SimpleModule module = new SimpleModule("test", Version.unknownVersion()); + module.addSerializer(String.class, new ContextualAndResolvable()); + mapper.registerModule(module); + assertEquals(quote("contextual=true,resolved=true"), mapper.writeValueAsString("abc")); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/convert/TestArrayConversions.java b/1.9.10/src/test/org/codehaus/jackson/map/convert/TestArrayConversions.java new file mode 100644 index 0000000..c13effe --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/convert/TestArrayConversions.java
@@ -0,0 +1,215 @@ +package org.codehaus.jackson.map.convert; + +import java.math.*; +import java.util.*; +import java.lang.reflect.Array; + +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.type.TypeReference; + +public class TestArrayConversions + extends org.codehaus.jackson.map.BaseMapTest +{ + final static String OVERFLOW_MSG_BYTE = "out of range of Java byte"; + final static String OVERFLOW_MSG = "overflow"; + + final ObjectMapper mapper = new ObjectMapper(); + + public void testNullXform() throws Exception + { + /* when given null, null should be returned without conversion + * (Java null has no type) + */ + assertNull(mapper.convertValue(null, Integer.class)); + assertNull(mapper.convertValue(null, String.class)); + assertNull(mapper.convertValue(null, byte[].class)); + } + + /** + * Tests to verify that primitive number arrays round-trip + * correctly, i.e. type -> type gives equal (although + * not necessarily same) output + */ + public void testArrayIdentityTransforms() throws Exception + { + // first integral types + // (note: byte[] is ok, even if it goes to base64 and back) + verifyByteArrayConversion(bytes(), byte[].class); + verifyShortArrayConversion(shorts(), short[].class); + verifyIntArrayConversion(ints(), int[].class); + verifyLongArrayConversion(longs(), long[].class); + // then primitive decimal types + verifyFloatArrayConversion(floats(), float[].class); + verifyDoubleArrayConversion(doubles(), float[].class); + } + + public void testByteArrayFrom() throws Exception + { + /* Note: byte arrays are tricky, since they are considered + * binary data primarily, not as array of numbers. Hence + * output will be base64 encoded... + */ + byte[] data = _convert("c3VyZS4=", byte[].class); + byte[] exp = "sure.".getBytes("Ascii"); + verifyIntegralArrays(exp, data, exp.length); + } + + public void testShortArrayToX() throws Exception + { + short[] data = shorts(); + verifyShortArrayConversion(data, byte[].class); + verifyShortArrayConversion(data, int[].class); + verifyShortArrayConversion(data, long[].class); + } + + public void testIntArrayToX() throws Exception + { + int[] data = ints(); + verifyIntArrayConversion(data, byte[].class); + verifyIntArrayConversion(data, short[].class); + verifyIntArrayConversion(data, long[].class); + + List<Number> expNums = _numberList(data, data.length); + // Alas, due to type erasure, need to use TypeRef, not just class + List<Integer> actNums = mapper.convertValue(data, new TypeReference<List<Integer>>() {}); + assertEquals(expNums, actNums); + } + + public void testLongArrayToX() throws Exception + { + long[] data = longs(); + verifyLongArrayConversion(data, byte[].class); + verifyLongArrayConversion(data, short[].class); + verifyLongArrayConversion(data, int[].class); + + List<Number> expNums = _numberList(data, data.length); + List<Long> actNums = mapper.convertValue(data, new TypeReference<List<Long>>() {}); + assertEquals(expNums, actNums); + } + + public void testOverflows() + { + // Byte overflow + try { + mapper.convertValue(new int[] { 1000 }, byte[].class); + } catch (IllegalArgumentException e) { + verifyException(e, OVERFLOW_MSG_BYTE); + } + // Short overflow + try { + mapper.convertValue(new int[] { -99999 }, short[].class); + } catch (IllegalArgumentException e) { + verifyException(e, OVERFLOW_MSG); + } + // Int overflow + try { + mapper.convertValue(new long[] { Long.MAX_VALUE }, int[].class); + } catch (IllegalArgumentException e) { + verifyException(e, OVERFLOW_MSG); + } + // Longs need help of BigInteger... + BigInteger biggie = BigInteger.valueOf(Long.MAX_VALUE); + biggie.add(BigInteger.ONE); + List<BigInteger> l = new ArrayList<BigInteger>(); + l.add(biggie); + try { + mapper.convertValue(l, int[].class); + } catch (IllegalArgumentException e) { + verifyException(e, OVERFLOW_MSG); + } + + } + + /* + ******************************************************** + * Helper methods + ******************************************************** + */ + + // note: all value need to be within byte range + + private byte[] bytes() { return new byte[] { 1, -1, 0, 98, 127 }; } + private short[] shorts() { return new short[] { 1, -1, 0, 98, 127 }; } + private int[] ints() { return new int[] { 1, -1, 0, 98, 127 }; } + private long[] longs() { return new long[] { 1, -1, 0, 98, 127 }; } + + // note: use values that are exact in binary + + private double[] doubles() { return new double[] { 0.0, 0.25, -0.125, 10.5, 9875.0 }; } + private float[] floats() { return new float[] { + 0.0f, 0.25f, -0.125f, 10.5f, 9875.0f }; + } + + private <T> void verifyByteArrayConversion(byte[] data, Class<T> arrayType) { + T result = _convert(data, arrayType); + verifyIntegralArrays(data, result, data.length); + } + private <T> void verifyShortArrayConversion(short[] data, Class<T> arrayType) { + T result = _convert(data, arrayType); + verifyIntegralArrays(data, result, data.length); + } + private <T> void verifyIntArrayConversion(int[] data, Class<T> arrayType) { + T result = _convert(data, arrayType); + verifyIntegralArrays(data, result, data.length); + } + private <T> void verifyLongArrayConversion(long[] data, Class<T> arrayType) { + T result = _convert(data, arrayType); + verifyIntegralArrays(data, result, data.length); + } + private <T> void verifyFloatArrayConversion(float[] data, Class<T> arrayType) { + T result = _convert(data, arrayType); + verifyDoubleArrays(data, result, data.length); + } + private <T> void verifyDoubleArrayConversion(double[] data, Class<T> arrayType) { + T result = _convert(data, arrayType); + verifyDoubleArrays(data, result, data.length); + } + + private <T> T _convert(Object input, Class<T> outputType) + { + // must be a primitive array, like "int[].class" + if (!outputType.isArray()) throw new IllegalArgumentException(); + if (!outputType.getComponentType().isPrimitive()) throw new IllegalArgumentException(); + T result = mapper.convertValue(input, outputType); + // sanity check first: + assertNotNull(result); + assertEquals(outputType, result.getClass()); + return result; + } + + private List<Number> _numberList(Object numberArray, int size) + { + ArrayList<Number> result = new ArrayList<Number>(size); + for (int i = 0; i < size; ++i) { + result.add((Number) Array.get(numberArray, i)); + } + return result; + } + + /** + * Helper method for checking that given collections contain integral Numbers + * that essentially contain same values in same order + */ + private void verifyIntegralArrays(Object inputArray, Object outputArray, int size) + { + for (int i = 0; i < size; ++i) { + Number n1 = (Number) Array.get(inputArray, i); + Number n2 = (Number) Array.get(outputArray, i); + double value1 = ((Number) n1).longValue(); + double value2 = ((Number) n2).longValue(); + assertEquals("Entry #"+i+"/"+size+" not equal", value1, value2); + } + } + + private void verifyDoubleArrays(Object inputArray, Object outputArray, int size) + { + for (int i = 0; i < size; ++i) { + Number n1 = (Number) Array.get(inputArray, i); + Number n2 = (Number) Array.get(outputArray, i); + double value1 = ((Number) n1).doubleValue(); + double value2 = ((Number) n2).doubleValue(); + assertEquals("Entry #"+i+"/"+size+" not equal", value1, value2); + } + } + +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/convert/TestBeanConversions.java b/1.9.10/src/test/org/codehaus/jackson/map/convert/TestBeanConversions.java new file mode 100644 index 0000000..8ce0623 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/convert/TestBeanConversions.java
@@ -0,0 +1,112 @@ +package org.codehaus.jackson.map.convert; + +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.map.*; + +public class TestBeanConversions + extends org.codehaus.jackson.map.BaseMapTest +{ + final ObjectMapper mapper = new ObjectMapper(); + + static class Point { + public int x, y; + + public int z = -13; + + public Point() { } + public Point(int a, int b, int c) + { + x = a; + y = b; + z = c; + } + } + + static class PointStrings { + public final String x, y; + + public PointStrings(String x, String y) { + this.x = x; + this.y = y; + } + } + + public static class BooleanBean { + public boolean boolProp; + } + + static class WrapperBean { + public BooleanBean x; + } + + static class ObjectWrapper + { + private Object data; + + public ObjectWrapper() { } + public ObjectWrapper(Object o) { data = o; } + + public Object getData() { return data; } + public void setData(Object data) { this.data = data; } + } + + /* + /********************************************************** + /* Test methods + /********************************************************** + */ + + public void testBeanConvert() + { + // should have no problems convert between compatible beans... + PointStrings input = new PointStrings("37", "-9"); + Point point = mapper.convertValue(input, Point.class); + assertEquals(37, point.x); + assertEquals(-9, point.y); + // z not included in input, will be whatever default constructor provides + assertEquals(-13, point.z); + } + + // For [JACKSON-371]; verify that we know property that caused issue... + // (note: not optimal place for test, but will have to do for now) + public void testErrorReporting() throws Exception + { + //String json = "{\"boolProp\":\"oops\"}"; + // First: unknown property + try { + mapper.readValue("{\"unknownProp\":true}", BooleanBean.class); + } catch (JsonProcessingException e) { + verifyException(e, "unknownProp"); + } + + // then bad conversion + try { + mapper.readValue("{\"boolProp\":\"foobar\"}", BooleanBean.class); + } catch (JsonProcessingException e) { + verifyException(e, "boolProp"); + } + } + + public void testIssue458() throws Exception + { + ObjectWrapper a = new ObjectWrapper("foo"); + ObjectWrapper b = new ObjectWrapper(a); + ObjectWrapper b2 = mapper.convertValue(b, ObjectWrapper.class); + ObjectWrapper a2 = mapper.convertValue(b2.getData(), ObjectWrapper.class); + assertEquals("foo", a2.getData()); + } + + // [JACKSON-710]: should work regardless of wrapping... + public void testWrapping() throws Exception + { + ObjectMapper wrappingMapper = new ObjectMapper(); + wrappingMapper.enable(DeserializationConfig.Feature.UNWRAP_ROOT_VALUE); + wrappingMapper.enable(SerializationConfig.Feature.WRAP_ROOT_VALUE); + Point input = new Point(1, 2, 3); + // conversion is ok, even if it's bogus one + Point output = wrappingMapper.convertValue(input, Point.class); + assertEquals(1, output.x); + assertEquals(2, output.y); + assertEquals(3, output.z); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/convert/TestMapConversions.java b/1.9.10/src/test/org/codehaus/jackson/map/convert/TestMapConversions.java new file mode 100644 index 0000000..764d0c2 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/convert/TestMapConversions.java
@@ -0,0 +1,62 @@ +package org.codehaus.jackson.map.convert; + +import java.util.*; + +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.type.TypeReference; + +public class TestMapConversions + extends org.codehaus.jackson.map.BaseMapTest +{ + final ObjectMapper mapper = new ObjectMapper(); + + enum AB { A, B; } + + static class Bean { + public Integer A; + public String B; + } + + /** + * Test that verifies that we can go between couple of types of Maps... + */ + public void testMapToMap() + { + Map<String,Integer> input = new LinkedHashMap<String,Integer>(); + input.put("A", Integer.valueOf(3)); + input.put("B", Integer.valueOf(-4)); + Map<AB,String> output = mapper.convertValue(input, + new TypeReference<Map<AB,String>>() { }); + assertEquals(2, output.size()); + assertEquals("3", output.get(AB.A)); + assertEquals("-4", output.get(AB.B)); + + // Let's try the other way too... and mix up types a bit + Map<String,Integer> roundtrip = mapper.convertValue(input, + new TypeReference<TreeMap<String,Integer>>() { }); + assertEquals(2, roundtrip.size()); + assertEquals(Integer.valueOf(3), roundtrip.get("A")); + assertEquals(Integer.valueOf(-4), roundtrip.get("B")); + } + + public void testMapToBean() + { + EnumMap<AB,String> map = new EnumMap<AB,String>(AB.class); + map.put(AB.A, " 17"); + map.put(AB.B, " -1"); + Bean bean = mapper.convertValue(map, Bean.class); + assertEquals(Integer.valueOf(17), bean.A); + assertEquals(" -1", bean.B); + } + + public void testBeanToMap() + { + Bean bean = new Bean(); + bean.A = 129; + bean.B = "13"; + EnumMap<AB,String> result = mapper.convertValue(bean, + new TypeReference<EnumMap<AB,String>>() { }); + assertEquals("129", result.get(AB.A)); + assertEquals("13", result.get(AB.B)); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/convert/TestStringConversions.java b/1.9.10/src/test/org/codehaus/jackson/map/convert/TestStringConversions.java new file mode 100644 index 0000000..cf00971 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/convert/TestStringConversions.java
@@ -0,0 +1,60 @@ +package org.codehaus.jackson.map.convert; + +import java.util.*; + +import static org.junit.Assert.*; + +import org.codehaus.jackson.map.*; + +public class TestStringConversions + extends org.codehaus.jackson.map.BaseMapTest +{ + final ObjectMapper mapper = new ObjectMapper(); + + public void testSimple() + { + assertEquals(Boolean.TRUE, mapper.convertValue("true", Boolean.class)); + assertEquals(Integer.valueOf(-3), mapper.convertValue(" -3 ", Integer.class)); + assertEquals(Long.valueOf(77), mapper.convertValue("77", Long.class)); + + int[] ints = { 1, 2, 3 }; + List<Integer> Ints = new ArrayList<Integer>(); + Ints.add(1); + Ints.add(2); + Ints.add(3); + + assertArrayEquals(ints, mapper.convertValue(Ints, int[].class)); + } + + public void testStringsToInts() + { + // let's verify our "neat trick" actually works... + assertArrayEquals(new int[] { 1, 2, 3, 4, -1, 0 }, + mapper.convertValue("1 2 3 4 -1 0".split("\\s+"), int[].class)); + } + + /** + * @since 1.6 + */ + public void testBytesToBase64AndBack() throws Exception + { + byte[] input = new byte[] { 1, 2, 3, 4, 5, 6, 7 }; + String encoded = mapper.convertValue(input, String.class); + assertNotNull(encoded); + byte[] result = mapper.convertValue(encoded, byte[].class); + assertArrayEquals(input, result); + } + + /** + * @since 1.7.3 + */ + public void testBytestoCharArray() throws Exception + { + byte[] input = new byte[] { 1, 2, 3, 4, 5, 6, 7 }; + // first, do baseline encoding + char[] expEncoded = mapper.convertValue(input, String.class).toCharArray(); + // then compare + char[] actEncoded = mapper.convertValue(input, char[].class); + assertArrayEquals(expEncoded, actEncoded); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/deser/TestAbstract.java b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestAbstract.java new file mode 100644 index 0000000..034c445 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestAbstract.java
@@ -0,0 +1,37 @@ +package org.codehaus.jackson.map.deser; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.*; + +/** + * Tests for checking handling of abstract types. + */ +public class TestAbstract + extends BaseMapTest +{ + static abstract class Abstract { + public int x; + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + /** + * Test to verify details of how trying to deserialize into + * abstract type should fail (if there is no way to determine + * actual type information for the concrete type to use) + */ + public void testAbstractFailure() throws Exception + { + ObjectMapper m = new ObjectMapper(); + try { + m.readValue("{ \"x\" : 3 }", Abstract.class); + fail("Should fail on trying to deserialize abstract type"); + } catch (JsonProcessingException e) { + verifyException(e, "can not construct"); + } + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/deser/TestAnnotationIgnore.java b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestAnnotationIgnore.java new file mode 100644 index 0000000..78a2079 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestAnnotationIgnore.java
@@ -0,0 +1,53 @@ +package org.codehaus.jackson.map.deser; + +import org.codehaus.jackson.annotate.*; +import org.codehaus.jackson.map.*; + +/** + * This unit test suite that tests use of {@link JsonIgnore} + * annotation with deserialization. + */ +public class TestAnnotationIgnore + extends BaseMapTest +{ + /* + /********************************************************** + /* Helper classes + /********************************************************** + */ + + /// Class for testing {@link JsonIgnore} annotations with setters + final static class SizeClassIgnore + { + int _x = 0; + int _y = 0; + + public void setX(int value) { _x = value; } + @JsonIgnore public void setY(int value) { _y = value; } + + /* Just igoring won't help a lot here; let's define a replacement + * so that we won't get an exception for "unknown field" + */ + @JsonProperty("y") void foobar(int value) { + ; // nop + } + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + public void testSimpleIgnore() throws Exception + { + ObjectMapper m = new ObjectMapper(); + SizeClassIgnore result = m.readValue + ("{ \"x\":1, \"y\" : 2 }", + SizeClassIgnore.class); + // x should be set, y not + assertEquals(1, result._x); + assertEquals(0, result._y); + } + +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/deser/TestAnnotationUsing.java b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestAnnotationUsing.java new file mode 100644 index 0000000..3ec5d1f --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestAnnotationUsing.java
@@ -0,0 +1,229 @@ +package org.codehaus.jackson.map.deser; + +import java.io.*; +import java.util.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.JsonDeserialize; +import org.codehaus.jackson.map.deser.std.StdDeserializer; + +/** + * Unit test suite that tests "usingXxx" properties of + * {@link JsonDeserialize} annotation. + */ +public class TestAnnotationUsing + extends BaseMapTest +{ + /* + /********************************************************************** + /* Annotated Bean classes + /********************************************************************** + */ + + /** + * Class for testing {@link JsonDeserializer} annotation + * for class itself. + */ + @JsonDeserialize(using=ValueDeserializer.class) + final static class ValueClass { + int _a; + + /* we'll test it by not having default no-arg ctor, and leaving + * out single-int-arg ctor (because deserializer would use that too) + */ + public ValueClass(int a, int b) { + _a = a; + } + } + + /** + * Class for testing {@link JsonDeserializer} annotation + * for a method + */ + final static class MethodBean { + int[] _ints; + + /* Note: could be made to work otherwise, except that + * to trigger failure (in absence of annotation) Json + * is of type VALUE_NUMBER_INT, not an Array: array would + * work by default, but scalar not + */ + @JsonDeserialize(using=IntsDeserializer.class) + public void setInts(int[] i) { + _ints = i; + } + } + + static class ArrayBean { + @JsonDeserialize(contentUsing=ValueDeserializer.class) + public Object[] values; + } + + + static class ListBean { + @JsonDeserialize(contentUsing=ValueDeserializer.class) + public List<Object> values; + } + + static class MapBean { + @JsonDeserialize(contentUsing=ValueDeserializer.class) + public Map<String,Object> values; + } + + static class MapKeyBean { + @JsonDeserialize(keyUsing=MapKeyDeserializer.class) + public Map<Object,Object> values; + } + + @SuppressWarnings("serial") + @JsonDeserialize(keyUsing=MapKeyDeserializer.class, contentUsing=ValueDeserializer.class) + static class MapKeyMap extends HashMap<Object,Object> { } + + /* + /********************************************************************** + /* Deserializers + /********************************************************************** + */ + + static class ValueDeserializer extends StdDeserializer<ValueClass> + { + public ValueDeserializer() { super(ValueClass.class); } + @Override + public ValueClass deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + int i = jp.getIntValue(); + return new ValueClass(i, i); + } + } + + private final static class IntsDeserializer extends StdDeserializer<int[]> + { + public IntsDeserializer() { super(int[].class); } + @Override + public int[] deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + return new int[] { jp.getIntValue() }; + } + } + + private final static class MapKeyDeserializer extends KeyDeserializer + { + @Override + public Object deserializeKey(String key, DeserializationContext ctxt) + { + return new String[] { key }; + } + } + + /* + /********************************************************************** + /* Tests: specifying deserializer of value itself + /********************************************************************** + */ + + // Unit test to verify that {@link JsonDeserialize#using} annotation works + // when applied to a class + public void testClassDeserializer() throws Exception + { + ObjectMapper m = new ObjectMapper(); + ValueClass result = m.readValue(" 123 ", ValueClass.class); + assertEquals(123, result._a); + } + + // Unit test to verify that {@link JsonDeserialize#using} annotation works + // when applied to a Method + public void testMethodDeserializer() throws Exception + { + ObjectMapper m = new ObjectMapper(); + // note: since it's part of method, must parse from Object struct + MethodBean result = m.readValue(" { \"ints\" : 3 } ", MethodBean.class); + assertNotNull(result); + int[] ints = result._ints; + assertNotNull(ints); + assertEquals(1, ints.length); + assertEquals(3, ints[0]); + } + + /* + /********************************************************************** + /* Tests: specifying deserializer for keys and/or contents + /********************************************************************** + */ + + public void testArrayContentUsing() throws Exception + { + ObjectMapper m = new ObjectMapper(); + ArrayBean result = m.readValue(" { \"values\" : [ 1, 2, 3 ] } ", ArrayBean.class); + assertNotNull(result); + Object[] obs = result.values; + assertNotNull(obs); + assertEquals(3, obs.length); + assertEquals(ValueClass.class, obs[0].getClass()); + assertEquals(1, ((ValueClass) obs[0])._a); + assertEquals(ValueClass.class, obs[1].getClass()); + assertEquals(2, ((ValueClass) obs[1])._a); + assertEquals(ValueClass.class, obs[2].getClass()); + assertEquals(3, ((ValueClass) obs[2])._a); + } + + public void testListContentUsing() throws Exception + { + ObjectMapper m = new ObjectMapper(); + ListBean result = m.readValue(" { \"values\" : [ 1, 2, 3 ] } ", ListBean.class); + assertNotNull(result); + List<Object> obs = result.values; + assertNotNull(obs); + assertEquals(3, obs.size()); + assertEquals(ValueClass.class, obs.get(0).getClass()); + assertEquals(1, ((ValueClass) obs.get(0))._a); + assertEquals(ValueClass.class, obs.get(1).getClass()); + assertEquals(2, ((ValueClass) obs.get(1))._a); + assertEquals(ValueClass.class, obs.get(2).getClass()); + assertEquals(3, ((ValueClass) obs.get(2))._a); + } + + public void testMapContentUsing() throws Exception + { + ObjectMapper m = new ObjectMapper(); + MapBean result = m.readValue(" { \"values\" : { \"a\": 1, \"b\":2 } } ", MapBean.class); + assertNotNull(result); + Map<String,Object> map = result.values; + assertNotNull(map); + assertEquals(2, map.size()); + assertEquals(ValueClass.class, map.get("a").getClass()); + assertEquals(1, ((ValueClass) map.get("a"))._a); + assertEquals(ValueClass.class, map.get("b").getClass()); + assertEquals(2, ((ValueClass) map.get("b"))._a); + } + + public void testMapKeyUsing() throws Exception + { + ObjectMapper m = new ObjectMapper(); + MapKeyBean result = m.readValue(" { \"values\" : { \"a\": true } } ", MapKeyBean.class); + assertNotNull(result); + Map<Object,Object> map = result.values; + assertNotNull(map); + assertEquals(1, map.size()); + Map.Entry<Object,Object> en = map.entrySet().iterator().next(); + assertEquals(String[].class, en.getKey().getClass()); + assertEquals(Boolean.TRUE, en.getValue()); + } + + // @since 1.8 + public void testRootValueWithCustomKey() throws Exception + { + ObjectMapper m = new ObjectMapper(); + MapKeyMap result = m.readValue(" { \"a\": 13 } ", MapKeyMap.class); + assertNotNull(result); + assertNotNull(result); + assertEquals(1, result.size()); + Map.Entry<Object,Object> en = result.entrySet().iterator().next(); + assertEquals(ValueClass.class, en.getValue().getClass()); + assertEquals(13, ((ValueClass) en.getValue())._a); + assertEquals(String[].class, en.getKey().getClass()); + } + +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/deser/TestAnyProperties.java b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestAnyProperties.java new file mode 100644 index 0000000..af25db9 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestAnyProperties.java
@@ -0,0 +1,197 @@ +package org.codehaus.jackson.map.deser; + +import java.util.*; + +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.annotate.*; +import org.codehaus.jackson.map.*; + +/** + * Unit tests for verifying that {@link JsonAnySetter} annotation + * works as expected. + */ +public class TestAnyProperties + extends BaseMapTest +{ + /* + /********************************************************** + /* Annotated helper classes + /********************************************************** + */ + + static class MapImitator + { + HashMap<String,Object> _map; + + public MapImitator() { + _map = new HashMap<String,Object>(); + } + + @JsonAnySetter + void addEntry(String key, Object value) + { + _map.put(key, value); + } + } + + /** + * Let's also verify that it is possible to define different + * value: not often useful, but possible. + */ + static class MapImitatorWithValue + { + HashMap<String,int[]> _map; + + public MapImitatorWithValue() { + _map = new HashMap<String,int[]>(); + } + + @JsonAnySetter + void addEntry(String key, int[] value) + { + _map.put(key, value); + } + } + + // Bad; 2 "any setters" + static class Broken + { + @JsonAnySetter + void addEntry1(String key, Object value) { } + @JsonAnySetter + void addEntry2(String key, Object value) { } + } + + @JsonIgnoreProperties("dummy") + static class Ignored + { + HashMap<String,Object> map = new HashMap<String,Object>(); + + @JsonIgnore + public String bogus; + + @JsonAnySetter + void addEntry(String key, Object value) + { + map.put(key, value); + } + } + + static class Bean744 + { + protected Map<String,Object> additionalProperties; + + @JsonAnySetter + public void addAdditionalProperty(String key, Object value) { + if (additionalProperties == null) additionalProperties = new HashMap<String, Object>(); + additionalProperties.put(key,value); + } + + public void setAdditionalProperties(Map<String, Object> additionalProperties) { + this.additionalProperties = additionalProperties; + } + + @JsonAnyGetter + public Map<String,Object> getAdditionalProperties() { return additionalProperties; } + + @JsonIgnore + public String getName() { + return (String) additionalProperties.get("name"); + } + } + + public class Bean797Base + { + @JsonAnyGetter + public Map<String, JsonNode> getUndefinedProperties() { + throw new IllegalStateException("Should not call parent version!"); + } + } + + public class Bean797BaseImpl extends Bean797Base + { + @Override + public Map<String, JsonNode> getUndefinedProperties() { + return new HashMap<String, JsonNode>(); + } + } + + /* + /********************************************************** + /* Test methods + /********************************************************** + */ + + public void testSimpleMapImitation() throws Exception + { + ObjectMapper m = new ObjectMapper(); + MapImitator mapHolder = m.readValue + ("{ \"a\" : 3, \"b\" : true }", MapImitator.class); + Map<String,Object> result = mapHolder._map; + assertEquals(2, result.size()); + assertEquals(Integer.valueOf(3), result.get("a")); + assertEquals(Boolean.TRUE, result.get("b")); + } + + public void testSimpleTyped() throws Exception + { + ObjectMapper m = new ObjectMapper(); + MapImitatorWithValue mapHolder = m.readValue + ("{ \"a\" : [ 3, -1 ], \"b\" : [ ] }", MapImitatorWithValue.class); + Map<String,int[]> result = mapHolder._map; + assertEquals(2, result.size()); + assertEquals(new int[] { 3, -1 }, result.get("a")); + assertEquals(new int[0], result.get("b")); + } + + public void testBrokenWithDoubleAnnotations() throws Exception + { + ObjectMapper m = new ObjectMapper(); + try { + @SuppressWarnings("unused") + Broken b = m.readValue("{ \"a\" : 3 }", Broken.class); + fail("Should have gotten an exception"); + } catch (JsonMappingException e) { + verifyException(e, "Multiple 'any-setters'"); + } + } + + // [JACKSON-313] + public void testIgnored() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.configure(org.codehaus.jackson.map.DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, true); + Ignored bean = mapper.readValue("{\"name\":\"Bob\", \"bogus\": [ 1, 2, 3], \"dummy\" : 13 }", Ignored.class); + assertNull(bean.map.get("dummy")); + assertNull(bean.map.get("bogus")); + assertEquals("Bob", bean.map.get("name")); + assertEquals(1, bean.map.size()); + } + + public void testIgnored383() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.configure(org.codehaus.jackson.map.DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false); + Ignored bean = mapper.readValue("{\"name\":\"Bob\", \"bogus\": [ 1, 2, 3], \"dummy\" : 13 }", Ignored.class); + assertNull(bean.map.get("dummy")); + assertNull(bean.map.get("bogus")); + assertEquals("Bob", bean.map.get("name")); + assertEquals(1, bean.map.size()); + } + + public void testProblem744() throws Exception + { + ObjectMapper m = new ObjectMapper(); + Bean744 bean = m.readValue("{\"name\":\"Bob\"}", Bean744.class); + assertNotNull(bean.additionalProperties); + assertEquals(1, bean.additionalProperties.size()); + assertEquals("Bob", bean.additionalProperties.get("name")); + } + + public void testIssue797() throws Exception + { + final ObjectMapper mapper = new ObjectMapper(); + String json = mapper.writeValueAsString(new Bean797BaseImpl()); + assertEquals("{}", json); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/deser/TestArrayDeserialization.java b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestArrayDeserialization.java new file mode 100644 index 0000000..e7a2017 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestArrayDeserialization.java
@@ -0,0 +1,554 @@ +package org.codehaus.jackson.map.deser; + +import org.codehaus.jackson.map.BaseMapTest; +import org.codehaus.jackson.map.DeserializationConfig; +import org.codehaus.jackson.map.DeserializationContext; +import org.codehaus.jackson.map.ObjectMapper; + +import java.io.*; +import java.util.*; + +import static org.junit.Assert.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.module.SimpleModule; +import org.codehaus.jackson.type.TypeReference; + +/** + * This unit test suite tries to verify that the "Native" java type + * mapper can properly re-construct Java array objects from Json arrays. + */ +public class TestArrayDeserialization + extends BaseMapTest +{ + /* + /********************************************************** + /* Helper classes + /********************************************************** + */ + + public final static class Bean1 + { + int _x, _y; + List<Bean2> _beans; + + // Just for deserialization: + @SuppressWarnings("unused") + private Bean1() { } + + public Bean1(int x, int y, List<Bean2> beans) + { + _x = x; + _y = y; + _beans = beans; + } + + public int getX() { return _x; } + public int getY() { return _y; } + public List<Bean2> getBeans() { return _beans; } + + public void setX(int x) { _x = x; } + public void setY(int y) { _y = y; } + public void setBeans(List<Bean2> b) { _beans = b; } + + @Override public boolean equals(Object o) { + if (!(o instanceof Bean1)) return false; + Bean1 other = (Bean1) o; + return (_x == other._x) + && (_y == other._y) + && _beans.equals(other._beans) + ; + } + } + + /** + * Simple bean that just gets serialized as a String value. + * Deserialization from String value will be done via single-arg + * constructor. + */ + @SuppressWarnings("deprecation") + public final static class Bean2 + implements JsonSerializable // so we can output as simple String + { + final String _desc; + + public Bean2(String d) + { + _desc = d; + } + + @Override + public void serialize(JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + jgen.writeString(_desc); + } + + @Override public String toString() { return _desc; } + + @Override public boolean equals(Object o) { + if (!(o instanceof Bean2)) return false; + Bean2 other = (Bean2) o; + return _desc.equals(other._desc); + } + } + + static class ObjectWrapper { + public Object wrapped; + } + + static class ObjectArrayWrapper { + public Object[] wrapped; + } + + static class CustomNonDeserArrayDeserializer extends JsonDeserializer<NonDeserializable[]> + { + @Override + public NonDeserializable[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException + { + List<NonDeserializable> list = new ArrayList<NonDeserializable>(); + while (jp.nextToken() != JsonToken.END_ARRAY) { + list.add(new NonDeserializable(jp.getText(), false)); + } + return list.toArray(new NonDeserializable[list.size()]); + } + } + + static class NonDeserializable { + protected String value; + + public NonDeserializable(String v, boolean bogus) { + value = v; + } + } + + /* + /********************************************************** + /* Tests for "untyped" arrays, Object[] + /********************************************************** + */ + + public void testUntypedArray() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + + // to get "untyped" default map-to-map, pass Object[].class + String JSON = "[ 1, null, \"x\", true, 2.0 ]"; + + Object[] result = mapper.readValue(JSON, Object[].class); + assertNotNull(result); + + assertEquals(5, result.length); + + assertEquals(Integer.valueOf(1), result[0]); + assertNull(result[1]); + assertEquals("x", result[2]); + assertEquals(Boolean.TRUE, result[3]); + assertEquals(Double.valueOf(2.0), result[4]); + } + + public void testIntegerArray() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + final int LEN = 90000; + + // Let's construct array to get it big enough + + StringBuilder sb = new StringBuilder(); + sb.append('['); + for (int i = 0; i < LEN; ++i) { + if (i > 0) { + sb.append(','); + } + sb.append(i); + } + sb.append(']'); + + Integer[] result = mapper.readValue(sb.toString(), Integer[].class); + assertNotNull(result); + + assertEquals(LEN, result.length); + for (int i = 0; i < LEN; ++i) { + assertEquals(i, result[i].intValue()); + } + } + + // [JACKSON-620]: allow "" to mean 'null' for Maps + public void testFromEmptyString() throws Exception + { + ObjectMapper m = new ObjectMapper(); + m.configure(DeserializationConfig.Feature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true); + assertNull(m.readValue(quote(""), Object[].class)); + assertNull( m.readValue(quote(""), String[].class)); + assertNull( m.readValue(quote(""), int[].class)); + } + + /* + /********************************************************** + /* Arrays of arrays... + /********************************************************** + */ + + public void testUntypedArrayOfArrays() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + + // to get "untyped" default map-to-map, pass Object[].class + final String JSON = "[[[-0.027512,51.503221],[-0.008497,51.503221],[-0.008497,51.509744],[-0.027512,51.509744]]]"; + + Object result = mapper.readValue(JSON, Object.class); + assertEquals(ArrayList.class, result.getClass()); + assertNotNull(result); + + // Should be able to get it as an Object array as well + + Object[] array = mapper.readValue(JSON, Object[].class); + assertNotNull(array); + assertEquals(Object[].class, array.getClass()); + + // and as wrapped variants too + ObjectWrapper w = mapper.readValue("{\"wrapped\":"+JSON+"}", ObjectWrapper.class); + assertNotNull(w); + assertNotNull(w.wrapped); + assertEquals(ArrayList.class, w.wrapped.getClass()); + + ObjectArrayWrapper aw = mapper.readValue("{\"wrapped\":"+JSON+"}", ObjectArrayWrapper.class); + assertNotNull(aw); + assertNotNull(aw.wrapped); + } + + /* + /********************************************************** + /* Tests for String arrays, char[] + /********************************************************** + */ + + public void testStringArray() throws Exception + { + final String[] STRS = new String[] { + "a", "b", "abcd", "", "???", "\"quoted\"", "lf: \n", + }; + StringWriter sw = new StringWriter(); + JsonGenerator jg = new JsonFactory().createJsonGenerator(sw); + jg.writeStartArray(); + for (String str : STRS) { + jg.writeString(str); + } + jg.writeEndArray(); + jg.close(); + + ObjectMapper mapper = new ObjectMapper(); + String[] result = mapper.readValue(sw.toString(), String[].class); + assertNotNull(result); + + assertEquals(STRS.length, result.length); + for (int i = 0; i < STRS.length; ++i) { + assertEquals(STRS[i], result[i]); + } + } + + public void testCharArray() throws Exception + { + final String TEST_STR = "Let's just test it? Ok!"; + ObjectMapper mapper = new ObjectMapper(); + char[] result = mapper.readValue("\""+TEST_STR+"\"", char[].class); + assertEquals(TEST_STR, new String(result)); + + // And just for [JACKSON-289], let's verify that fluffy arrays work too + result = mapper.readValue("[\"a\",\"b\",\"c\"]", char[].class); + assertEquals("abc", new String(result)); + } + + /* + /********************************************************** + /* Tests for primitive arrays + /********************************************************** + */ + + public void testBooleanArray() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + boolean[] result = mapper.readValue("[ true, false, false ]", boolean[].class); + assertNotNull(result); + assertEquals(3, result.length); + assertTrue(result[0]); + assertFalse(result[1]); + assertFalse(result[2]); + } + + public void testByteArrayAsNumbers() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + final int LEN = 37000; + StringBuilder sb = new StringBuilder(); + sb.append('['); + for (int i = 0; i < LEN; ++i) { + if (i > 0) { + sb.append(','); + } + sb.append(i & 0x7F); + } + sb.append(']'); + byte[] result = mapper.readValue(sb.toString(), byte[].class); + assertNotNull(result); + assertEquals(LEN, result.length); + for (int i = 0; i < LEN; ++i) { + byte exp = (byte) (i & 0x7F); + assertEquals(exp, result[i]); + } + } + + public void testByteArrayAsBase64() throws Exception + { + /* Hmmh... let's use JsonGenerator here, to hopefully ensure we + * get proper base64 encoding. Plus, not always using that + * silly sample from Wikipedia. + */ + JsonFactory jf = new JsonFactory(); + StringWriter sw = new StringWriter(); + + int LEN = 9000; + byte[] TEST = new byte[LEN]; + for (int i = 0; i < LEN; ++i) { + TEST[i] = (byte) i; + } + + JsonGenerator jg = jf.createJsonGenerator(sw); + jg.writeBinary(TEST); + jg.close(); + String inputData = sw.toString(); + + ObjectMapper mapper = new ObjectMapper(); + byte[] result = mapper.readValue(inputData, byte[].class); + assertNotNull(result); + assertArrayEquals(TEST, result); + } + + /** + * And then bit more challenging case; let's try decoding + * multiple byte arrays from an array... + */ + public void testByteArraysAsBase64() throws Exception + { + JsonFactory jf = new JsonFactory(); + StringWriter sw = new StringWriter(1000); + + final int entryCount = 15; + + JsonGenerator jg = jf.createJsonGenerator(sw); + jg.writeStartArray(); + + byte[][] entries = new byte[entryCount][]; + for (int i = 0; i < entryCount; ++i) { + byte[] b = new byte[1000 - i * 20]; + for (int x = 0; x < b.length; ++x) { + b[x] = (byte) (i + x); + } + entries[i] = b; + jg.writeBinary(b); + } + jg.writeEndArray(); + jg.close(); + + String inputData = sw.toString(); + + ObjectMapper mapper = new ObjectMapper(); + byte[][] result = mapper.readValue(inputData, byte[][].class); + assertNotNull(result); + + assertEquals(entryCount, result.length); + for (int i = 0; i < entryCount; ++i) { + byte[] b = result[i]; + assertArrayEquals("Comparing entry #"+i+"/"+entryCount,entries[i], b); + } + } + + // [JACKSON-763] + public void testByteArraysWith763() throws Exception + { + String[] input = new String[] { "YQ==", "Yg==", "Yw==" }; + byte[][] data = new ObjectMapper().convertValue(input, byte[][].class); + assertEquals("a", new String(data[0], "US-ASCII")); + assertEquals("b", new String(data[1], "US-ASCII")); + assertEquals("c", new String(data[2], "US-ASCII")); + } + + public void testShortArray() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + final int LEN = 31001; // fits in signed 16-bit + StringBuilder sb = new StringBuilder(); + sb.append('['); + for (int i = 0; i < LEN; ++i) { + if (i > 0) { + sb.append(','); + } + sb.append(i); + } + sb.append(']'); + + short[] result = mapper.readValue(sb.toString(), short[].class); + assertNotNull(result); + + assertEquals(LEN, result.length); + for (int i = 0; i < LEN; ++i) { + short exp = (short) i; + assertEquals(exp, result[i]); + } + } + + public void testIntArray() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + final int LEN = 70000; + + // Let's construct array to get it big enough + + StringBuilder sb = new StringBuilder(); + sb.append('['); + for (int i = 0; i < LEN; ++i) { + if (i > 0) { + sb.append(','); + } + sb.append(-i); + } + sb.append(']'); + + int[] result = mapper.readValue(sb.toString(), int[].class); + assertNotNull(result); + + assertEquals(LEN, result.length); + for (int i = 0; i < LEN; ++i) { + assertEquals(-i, result[i]); + } + } + + public void testLongArray() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + final int LEN = 12300; + StringBuilder sb = new StringBuilder(); + sb.append('['); + for (int i = 0; i < LEN; ++i) { + if (i > 0) { + sb.append(','); + } + sb.append(i); + } + sb.append(']'); + + long[] result = mapper.readValue(sb.toString(), long[].class); + assertNotNull(result); + + assertEquals(LEN, result.length); + for (int i = 0; i < LEN; ++i) { + long exp = (long) i; + assertEquals(exp, result[i]); + } + } + + public void testDoubleArray() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + final int LEN = 7000; + StringBuilder sb = new StringBuilder(); + sb.append('['); + for (int i = 0; i < LEN; ++i) { + // not ideal, but has to do... + if (i > 0) { + sb.append(','); + } + sb.append(i).append('.').append(i % 10); + } + sb.append(']'); + + double[] result = mapper.readValue(sb.toString(), double[].class); + assertNotNull(result); + + assertEquals(LEN, result.length); + for (int i = 0; i < LEN; ++i) { + String expStr = String.valueOf(i) + "." + String.valueOf(i % 10); + String actStr = String.valueOf(result[i]); + if (!expStr.equals(actStr)) { + fail("Entry #"+i+"/"+LEN+"; exp '"+expStr+"', got '"+actStr+"'"); + } + } + } + + public void testFloatArray() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + final int LEN = 7000; + StringBuilder sb = new StringBuilder(); + sb.append('['); + for (int i = 0; i < LEN; ++i) { + if (i > 0) { + sb.append(','); + } + // not ideal, but has to do... + sb.append(i).append('.').append(i % 10); + } + sb.append(']'); + + float[] result = mapper.readValue(sb.toString(), float[].class); + assertNotNull(result); + + assertEquals(LEN, result.length); + for (int i = 0; i < LEN; ++i) { + String expStr = String.valueOf(i) + "." + String.valueOf(i % 10); + assertEquals(expStr, String.valueOf(result[i])); + } + } + + /* + /********************************************************** + /* Tests for Bean arrays + /********************************************************** + */ + + public void testBeanArray() + throws Exception + { + List<Bean1> src = new ArrayList<Bean1>(); + + List<Bean2> b2 = new ArrayList<Bean2>(); + b2.add(new Bean2("a")); + b2.add(new Bean2("foobar")); + src.add(new Bean1(1, 2, b2)); + + b2 = new ArrayList<Bean2>(); + b2.add(null); + src.add(new Bean1(4, 5, b2)); + + // Ok: let's assume bean serializer works ok.... + ObjectMapper mapper = new ObjectMapper(); + StringWriter sw = new StringWriter(); + + mapper.writeValue(sw, src); + + // And then test de-serializer + List<Bean1> result = mapper.readValue(sw.toString(), new TypeReference<List<Bean1>>() { }); + assertNotNull(result); + assertEquals(src, result); + } + + /* + /********************************************************** + /* And custom deserializers too + /********************************************************** + */ + + public void testCustomDeserializers() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + SimpleModule testModule = new SimpleModule("test", Version.unknownVersion()); + testModule.addDeserializer(NonDeserializable[].class, new CustomNonDeserArrayDeserializer()); + mapper.registerModule(testModule); + + NonDeserializable[] result = mapper.readValue("[\"a\"]", NonDeserializable[].class); + assertNotNull(result); + assertEquals(1, result.length); + assertEquals("a", result[0].value); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/deser/TestAutoDetect.java b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestAutoDetect.java new file mode 100644 index 0000000..2d49df2 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestAutoDetect.java
@@ -0,0 +1,49 @@ +package org.codehaus.jackson.map.deser; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.annotate.*; +import org.codehaus.jackson.map.*; + +public class TestAutoDetect + extends BaseMapTest +{ + /* + /******************************************************** + /* Helper beans + /******************************************************** + */ + + static class PrivateBean { + String a; + + private PrivateBean() { } + + private PrivateBean(String a) { this.a = a; } + } + + /* + /******************************************************** + /* Unit tests + /******************************************************** + */ + + public void testPrivateCtor() throws Exception + { + // first, default settings, with which construction works ok + ObjectMapper m = new ObjectMapper(); + PrivateBean bean = m.readValue("\"abc\"", PrivateBean.class); + assertEquals("abc", bean.a); + + // then by increasing visibility requirement: + m = new ObjectMapper(); + m.setVisibilityChecker(m.getVisibilityChecker().withCreatorVisibility + (JsonAutoDetect.Visibility.PUBLIC_ONLY)); + try { + m.readValue("\"abc\"", PrivateBean.class); + fail("Expected exception for missing constructor"); + } catch (JsonProcessingException e) { + verifyException(e, "no single-String constructor/factory"); + } + } + +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/deser/TestBasicAnnotations.java b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestBasicAnnotations.java new file mode 100644 index 0000000..9763f9e --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestBasicAnnotations.java
@@ -0,0 +1,161 @@ +package org.codehaus.jackson.map.deser; + +import java.io.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.annotate.*; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.deser.std.StdDeserializer; +import org.codehaus.jackson.map.annotate.JsonDeserialize; + +/** + * This unit test suite tests use of basic Annotations for + * bean deserialization; ones that indicate (non-constructor) + * method types, explicit deserializer annotations. + */ +public class TestBasicAnnotations + extends BaseMapTest +{ + /* + /********************************************************** + /* Annotated helper classes + /********************************************************** + */ + + /// Class for testing {@link JsonProperty} annotations + final static class SizeClassSetter + { + int _size; + int _length; + int _other; + + @JsonProperty public void size(int value) { _size = value; } + @JsonProperty("length") public void foobar(int value) { _length = value; } + + // note: need not be public if annotated + @JsonProperty protected void other(int value) { _other = value; } + + // finally: let's add a red herring that should be avoided... + public void errorOut(int value) { throw new Error(); } + } + + final static class SizeClassSetter2 + { + int _x; + + @JsonProperty public void setX(int value) { _x = value; } + + // another red herring, which shouldn't be included + public void setXandY(int x, int y) { throw new Error(); } + } + + /** + * One more, but this time checking for implied setter + * using @JsonDeserialize + */ + final static class SizeClassSetter3 + { + int _x; + + @JsonDeserialize public void x(int value) { _x = value; } + } + + + /// Classes for testing Setter discovery with inheritance + static class BaseBean + { + int _x = 0, _y = 0; + + public void setX(int value) { _x = value; } + @JsonProperty("y") void foobar(int value) { _y = value; } + } + + static class BeanSubClass extends BaseBean + { + int _z; + + public void setZ(int value) { _z = value; } + } + + static class BeanWithDeserialize { + @JsonDeserialize private int a; + } + + /* + /********************************************************** + /* Other helper classes + /********************************************************** + */ + + final static class IntsDeserializer extends StdDeserializer<int[]> + { + public IntsDeserializer() { super(int[].class); } + @Override + public int[] deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + return new int[] { jp.getIntValue() }; + } + } + + /* + /********************************************************** + /* Test methods + /********************************************************** + */ + + public void testSimpleSetter() throws Exception + { + ObjectMapper m = new ObjectMapper(); + SizeClassSetter result = m.readValue + ("{ \"other\":3, \"size\" : 2, \"length\" : -999 }", + SizeClassSetter.class); + + assertEquals(3, result._other); + assertEquals(2, result._size); + assertEquals(-999, result._length); + } + + // Test for checking [JACKSON-64] + public void testSimpleSetter2() throws Exception + { + ObjectMapper m = new ObjectMapper(); + SizeClassSetter2 result = m.readValue + ("{ \"x\": -3 }", + SizeClassSetter2.class); + assertEquals(-3, result._x); + } + + // Checking parts of [JACKSON-120] + public void testSimpleSetter3() throws Exception + { + ObjectMapper m = new ObjectMapper(); + SizeClassSetter3 result = m.readValue + ("{ \"x\": 128 }", + SizeClassSetter3.class); + assertEquals(128, result._x); + } + + /** + * Test for verifying that super-class setters are used as + * expected. + */ + public void testSetterInheritance() throws Exception + { + ObjectMapper m = new ObjectMapper(); + BeanSubClass result = m.readValue + ("{ \"x\":1, \"z\" : 3, \"y\" : 2 }", + BeanSubClass.class); + assertEquals(1, result._x); + assertEquals(2, result._y); + assertEquals(3, result._z); + } + + public void testImpliedProperty() throws Exception + { + ObjectMapper m = new ObjectMapper(); + BeanWithDeserialize bean = m.readValue("{\"a\":3}", BeanWithDeserialize.class); + assertNotNull(bean); + assertEquals(3, bean.a); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/deser/TestBeanDeserializer.java b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestBeanDeserializer.java new file mode 100644 index 0000000..fd5b11a --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestBeanDeserializer.java
@@ -0,0 +1,191 @@ +package org.codehaus.jackson.map.deser; + +import java.io.IOException; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.deser.BeanDeserializerModifier; +import org.codehaus.jackson.map.introspect.BasicBeanDescription; +import org.codehaus.jackson.map.module.SimpleModule; + +public class TestBeanDeserializer extends BaseMapTest +{ + /* + /********************************************************** + /* Helper types + /********************************************************** + */ + + static class Bean { + public String b = "b"; + public String a = "a"; + + public Bean() { } + public Bean(String a, String b) { + this.a = a; + this.b = b; + } + } + + static class ModuleImpl extends SimpleModule + { + protected BeanDeserializerModifier modifier; + + public ModuleImpl(BeanDeserializerModifier modifier) + { + super("test", Version.unknownVersion()); + this.modifier = modifier; + } + + @Override + public void setupModule(SetupContext context) + { + super.setupModule(context); + if (modifier != null) { + context.addBeanDeserializerModifier(modifier); + } + } + } + + static class RemovingModifier extends BeanDeserializerModifier + { + private final String _removedProperty; + + public RemovingModifier(String remove) { _removedProperty = remove; } + + @Override + public BeanDeserializerBuilder updateBuilder(DeserializationConfig config, + BasicBeanDescription beanDesc, BeanDeserializerBuilder builder) { + builder.addIgnorable(_removedProperty); + return builder; + } + } + + static class ReplacingModifier extends BeanDeserializerModifier + { + private final JsonDeserializer<?> _deserializer; + + public ReplacingModifier(JsonDeserializer<?> s) { _deserializer = s; } + + @Override + public JsonDeserializer<?> modifyDeserializer(DeserializationConfig config, BasicBeanDescription beanDesc, + JsonDeserializer<?> deserializer) { + return _deserializer; + } + } + + static class BogusBeanDeserializer extends JsonDeserializer<Object> + { + private final String a, b; + + public BogusBeanDeserializer(String a, String b) { + this.a = a; + this.b = b; + } + + @Override + public Object deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + return new Bean(a, b); + } + } + + static class Issue476Bean { + public Issue476Type value1, value2; + } + static class Issue476Type { + public String name, value; + } + static class Issue476Deserializer extends BeanDeserializer + implements ContextualDeserializer<Object> + { + protected static int propCount; + + public Issue476Deserializer(BeanDeserializer src) { + super(src); + } + + @Override + public JsonDeserializer<Object> createContextual(DeserializationConfig config, BeanProperty property) throws JsonMappingException { + propCount++; + return this; + } + } + public class Issue476DeserializerModifier extends BeanDeserializerModifier { + @Override + public JsonDeserializer<?> modifyDeserializer(DeserializationConfig config, BasicBeanDescription beanDesc, JsonDeserializer<?> deserializer) { + if (Issue476Type.class == beanDesc.getBeanClass()) { + return new Issue476Deserializer((BeanDeserializer)deserializer); + } + return super.modifyDeserializer(config, beanDesc, deserializer); + } + } + public class Issue476Module extends SimpleModule + { + public Issue476Module() { + super("Issue476Module", Version.unknownVersion()); + } + + @Override + public void setupModule(SetupContext context) { + context.addBeanDeserializerModifier(new Issue476DeserializerModifier()); + } + } + + /* + /******************************************************** + /* Unit tests + /******************************************************** + */ + + public void testPropertyRemoval() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.registerModule(new ModuleImpl(new RemovingModifier("a"))); + Bean bean = mapper.readValue("{\"b\":\"2\"}", Bean.class); + assertEquals("2", bean.b); + // and 'a' has its default value: + assertEquals("a", bean.a); + } + + public void testDeserializerReplacement() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.registerModule(new ModuleImpl(new ReplacingModifier(new BogusBeanDeserializer("foo", "bar")))); + Bean bean = mapper.readValue("{\"a\":\"xyz\"}", Bean.class); + // custom deserializer always produces instance like this: + assertEquals("foo", bean.a); + assertEquals("bar", bean.b); + } + + public void testIssue476() throws Exception + { + final String JSON = "{\"value1\" : {\"name\" : \"fruit\", \"value\" : \"apple\"}, \"value2\" : {\"name\" : \"color\", \"value\" : \"red\"}}"; + + ObjectMapper mapper = new ObjectMapper(); + mapper.registerModule(new Issue476Module()); + mapper.readValue(JSON, Issue476Bean.class); + + // there are 2 properties + assertEquals(2, Issue476Deserializer.propCount); + } + + public void testPOJOFromEmptyString() throws Exception + { + // first, verify default settings which do not accept empty String: + ObjectMapper mapper = new ObjectMapper(); + try { + mapper.readValue(quote(""), Bean.class); + fail("Should not accept Empty String for POJO"); + } catch (JsonProcessingException e) { + verifyException(e, "from JSON String"); + } + + // should be ok to enable dynamically: + mapper = new ObjectMapper(); + mapper.configure(DeserializationConfig.Feature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true); + Bean result = mapper.readValue(quote(""), Bean.class); + assertNull(result); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/deser/TestBlocking.java b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestBlocking.java new file mode 100644 index 0000000..c84c377 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestBlocking.java
@@ -0,0 +1,39 @@ +package org.codehaus.jackson.map.deser; + +import java.io.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.*; + +/** + * Unit test mostly written to cover issue [JACKSON-81]; unintended blocking + * after data binding. + */ +public class TestBlocking + extends BaseMapTest +{ + /** + * This is an indirect test that should trigger problems if (and only if) + * underlying parser is advanced beyond the only element array. + * Basically, although content is invalid, this should be encountered + * quite yet. + */ + public void testEagerAdvance() throws IOException + { + ObjectMapper mapper = new ObjectMapper(); + JsonParser jp = createParserUsingReader("[ 1 "); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + + // And then try to map just a single entry: shouldn't fail: + Integer I = mapper.readValue(jp, Integer.class); + assertEquals(Integer.valueOf(1), I); + + // and should fail only now: + try { + jp.nextToken(); + } catch (IOException ioe) { + verifyException(ioe, "Unexpected end-of-input: expected close marker for ARRAY"); + } + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/deser/TestCollectionDeserialization.java b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestCollectionDeserialization.java new file mode 100644 index 0000000..0fc0d23 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestCollectionDeserialization.java
@@ -0,0 +1,153 @@ +package org.codehaus.jackson.map.deser; + +import java.io.IOException; +import java.util.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.JsonDeserialize; +import org.codehaus.jackson.map.deser.std.StdDeserializer; +import org.codehaus.jackson.type.TypeReference; + +public class TestCollectionDeserialization + extends BaseMapTest +{ + enum Key { + KEY1, KEY2, WHATEVER; + } + + @SuppressWarnings("serial") + @JsonDeserialize(using=ListDeserializer.class) + static class CustomList extends LinkedList<String> { } + + static class ListDeserializer extends StdDeserializer<CustomList> + { + public ListDeserializer() { super(CustomList.class); } + + @Override + public CustomList deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException + { + CustomList result = new CustomList(); + result.add(jp.getText()); + return result; + } + } + + static class XBean { + public int x; + } + + /* + /********************************************************** + /* Test methods + /********************************************************** + */ + + public void testUntypedList() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + // to get "untyped" default List, pass Object.class + String JSON = "[ \"text!\", true, null, 23 ]"; + + /* Not a guaranteed cast theoretically, but will work: + * (since we know that Jackson will construct an ArrayList here...) + */ + Object value = mapper.readValue(JSON, Object.class); + assertNotNull(value); + assertTrue(value instanceof ArrayList<?>); + List<?> result = (List<?>) value; + + assertEquals(4, result.size()); + + assertEquals("text!", result.get(0)); + assertEquals(Boolean.TRUE, result.get(1)); + assertNull(result.get(2)); + assertEquals(Integer.valueOf(23), result.get(3)); + } + + public void testExactStringCollection() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + // to get typing, must use type reference + String JSON = "[ \"a\", \"b\" ]"; + List<String> result = mapper.readValue(JSON, new TypeReference<ArrayList<String>>() { }); + + assertNotNull(result); + assertEquals(ArrayList.class, result.getClass()); + assertEquals(2, result.size()); + + assertEquals("a", result.get(0)); + assertEquals("b", result.get(1)); + } + + public void testHashSet() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + String JSON = "[ \"KEY1\", \"KEY2\" ]"; + + EnumSet<Key> result = mapper.readValue(JSON, new TypeReference<EnumSet<Key>>() { }); + assertNotNull(result); + assertTrue(EnumSet.class.isAssignableFrom(result.getClass())); + assertEquals(2, result.size()); + + assertTrue(result.contains(Key.KEY1)); + assertTrue(result.contains(Key.KEY2)); + assertFalse(result.contains(Key.WHATEVER)); + } + + /** + * Test to verify that @JsonDeserialize.using works as expected + */ + public void testCustomDeserializer() throws IOException + { + ObjectMapper mapper = new ObjectMapper(); + CustomList result = mapper.readValue(quote("abc"), CustomList.class); + assertEquals(1, result.size()); + assertEquals("abc", result.get(0)); + } + + /* Testing [JACKSON-526], "implicit JSON array" for single-element arrays, + * mostly produced by Jettison, Badgerfish conversions (from XML) + */ + @SuppressWarnings("unchecked") + public void testImplicitArrays() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.configure(DeserializationConfig.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true); + + // first with simple scalar types (numbers), with collections + List<Integer> ints = mapper.readValue("4", List.class); + assertEquals(1, ints.size()); + assertEquals(Integer.valueOf(4), ints.get(0)); + List<String> strings = mapper.readValue(quote("abc"), new TypeReference<ArrayList<String>>() { }); + assertEquals(1, strings.size()); + assertEquals("abc", strings.get(0)); + // and arrays: + int[] intArray = mapper.readValue("-7", int[].class); + assertEquals(1, intArray.length); + assertEquals(-7, intArray[0]); + String[] stringArray = mapper.readValue(quote("xyz"), String[].class); + assertEquals(1, stringArray.length); + assertEquals("xyz", stringArray[0]); + + // and then with Beans: + List<XBean> xbeanList = mapper.readValue("{\"x\":4}", new TypeReference<List<XBean>>() { }); + assertEquals(1, xbeanList.size()); + assertEquals(XBean.class, xbeanList.get(0).getClass()); + + Object ob = mapper.readValue("{\"x\":29}", XBean[].class); + XBean[] xbeanArray = (XBean[]) ob; + assertEquals(1, xbeanArray.length); + assertEquals(XBean.class, xbeanArray[0].getClass()); + } + + // [JACKSON-620]: allow "" to mean 'null' for Maps + public void testFromEmptyString() throws Exception + { + ObjectMapper m = new ObjectMapper(); + m.configure(DeserializationConfig.Feature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true); + List<?> result = m.readValue(quote(""), List.class); + assertNull(result); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/deser/TestConcurrency.java b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestConcurrency.java new file mode 100644 index 0000000..5ed1c5f --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestConcurrency.java
@@ -0,0 +1,101 @@ +package org.codehaus.jackson.map.deser; + +import java.io.IOException; + +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.*; + +/** + * Testing for [JACKSON-237] (NPE due to race condition) + * + * @since 1.5 + */ +public class TestConcurrency extends BaseMapTest +{ + /* + /********************************************** + /* Helper beans + /********************************************** + */ + + @JsonDeserialize(using=BeanDeserializer.class) + static class Bean + { + public int value = 42; + } + + /* + /********************************************** + /* Helper classes + /********************************************** + */ + + /** + * Dummy deserializer used for verifying that partially handled (i.e. not yet + * resolved) deserializers are not allowed to be used. + */ + static class BeanDeserializer + extends JsonDeserializer<Bean> + implements ResolvableDeserializer + { + protected volatile boolean resolved = false; + + @Override + public Bean deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException + { + if (!resolved) { + throw new IOException("Deserializer not yet completely resolved"); + } + Bean b = new Bean(); + b.value = 13; + return b; + } + + @Override + public void resolve(DeserializationConfig config, DeserializerProvider provider) + throws JsonMappingException + { + try { + Thread.sleep(100L); + } catch (Exception e) { } + resolved = true; + } + } + + /* + /********************************************** + /* Unit tests + /********************************************** + */ + + public void testDeserializerResolution() throws Exception + { + /* Let's repeat couple of times, just to be sure; thread timing is not + * exact science; plus caching plays a role too + */ + final String JSON = "{\"value\":42}"; + + for (int i = 0; i < 5; ++i) { + final ObjectMapper mapper = new ObjectMapper(); + Runnable r = new Runnable() { + @Override + public void run() { + try { + /*Bean b =*/ mapper.readValue(JSON, Bean.class); + } catch (Exception e) { } + } + }; + Thread t = new Thread(r); + t.start(); + // then let it proceed + Thread.sleep(10L); + // and try the same... + Bean b = mapper.readValue(JSON, Bean.class); + // note: funny deserializer, mangles data.. :) + assertEquals(13, b.value); + t.join(); + } + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/deser/TestConfig.java b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestConfig.java new file mode 100644 index 0000000..e6ef9d5 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestConfig.java
@@ -0,0 +1,118 @@ +package org.codehaus.jackson.map.deser; + +import org.codehaus.jackson.map.BaseMapTest; + +import org.codehaus.jackson.annotate.*; +import org.codehaus.jackson.map.*; + +/** + * Unit tests for checking handling of DeserializationConfig. + */ +public class TestConfig + extends BaseMapTest +{ + @JsonAutoDetect(JsonMethod.NONE) + final static class Dummy { } + + final static class EmptyDummy { } + + static class AnnoBean { + int value = 3; + + @JsonProperty("y") + public void setX(int v) { value = v; } + } + + /* + /********************************************************** + /* Main tests + /********************************************************** + */ + + public void testDefaults() + { + ObjectMapper m = new ObjectMapper(); + DeserializationConfig cfg = m.getDeserializationConfig(); + + // Expected defaults: + assertTrue(cfg.isEnabled(DeserializationConfig.Feature.USE_ANNOTATIONS)); + assertTrue(cfg.isEnabled(DeserializationConfig.Feature.AUTO_DETECT_SETTERS)); + assertTrue(cfg.isEnabled(DeserializationConfig.Feature.AUTO_DETECT_CREATORS)); + assertTrue(cfg.isEnabled(DeserializationConfig.Feature.USE_GETTERS_AS_SETTERS)); + assertTrue(cfg.isEnabled(DeserializationConfig.Feature.CAN_OVERRIDE_ACCESS_MODIFIERS)); + + + assertFalse(cfg.isEnabled(DeserializationConfig.Feature.USE_BIG_DECIMAL_FOR_FLOATS)); + assertFalse(cfg.isEnabled(DeserializationConfig.Feature.USE_BIG_INTEGER_FOR_INTS)); + + assertTrue(cfg.isEnabled(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES)); + } + + public void testOverrideIntrospectors() + { + ObjectMapper m = new ObjectMapper(); + DeserializationConfig cfg = m.getDeserializationConfig(); + // and finally, ensure we could override introspectors + cfg = cfg.withClassIntrospector(null); // no way to verify tho + cfg = cfg.withAnnotationIntrospector(null); + assertNull(cfg.getAnnotationIntrospector()); + } + + @SuppressWarnings("deprecation") + public void testFromAnnotations() + { + ObjectMapper m = new ObjectMapper(); + DeserializationConfig cfg = m.getDeserializationConfig(); + + /* 08-Mar-2010, tatu: Due to change in the way visibility checks are done, + * following checks are not valid any more. + */ + + // First: without any annotations + cfg.fromAnnotations(EmptyDummy.class); + assertTrue(cfg.isEnabled(DeserializationConfig.Feature.AUTO_DETECT_SETTERS)); + assertTrue(cfg.isEnabled(DeserializationConfig.Feature.AUTO_DETECT_CREATORS)); + + /* Then configure using annotations from dummy object that + * does have annotations; only subset of features affected this way + */ + /* + cfg.fromAnnotations(Dummy.class); + assertFalse(cfg.isEnabled(DeserializationConfig.Feature.AUTO_DETECT_SETTERS)); + assertFalse(cfg.isEnabled(DeserializationConfig.Feature.AUTO_DETECT_CREATORS)); + */ + } + + public void testAnnotationsDisabled() throws Exception + { + // first: verify that annotation introspection is enabled by default + ObjectMapper m = new ObjectMapper(); + assertTrue(m.getDeserializationConfig().isEnabled(DeserializationConfig.Feature.USE_ANNOTATIONS)); + // with annotations, property is renamed + AnnoBean bean = m.readValue("{ \"y\" : 0 }", AnnoBean.class); + assertEquals(0, bean.value); + + m = new ObjectMapper(); + m.configure(DeserializationConfig.Feature.USE_ANNOTATIONS, false); + // without annotations, should default to default bean-based name... + bean = m.readValue("{ \"x\" : 0 }", AnnoBean.class); + assertEquals(0, bean.value); + } + + /** + * Test for verifying working of [JACKSON-191] + * + * @since 1.4 + */ + public void testProviderConfig() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + assertEquals(0, mapper.getDeserializerProvider().cachedDeserializersCount()); + // and then should get one constructed for: + AnnoBean bean = mapper.readValue("{ \"y\" : 3 }", AnnoBean.class); + assertNotNull(bean); + assertEquals(1, mapper.getDeserializerProvider().cachedDeserializersCount()); + mapper.getDeserializerProvider().flushCachedDeserializers(); + assertEquals(0, mapper.getDeserializerProvider().cachedDeserializersCount()); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/deser/TestConstructFromMap.java b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestConstructFromMap.java new file mode 100644 index 0000000..8a93295 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestConstructFromMap.java
@@ -0,0 +1,95 @@ +package org.codehaus.jackson.map.deser; + +import java.awt.Point; // just for convenience +import java.math.BigDecimal; +import java.util.*; + +import org.codehaus.jackson.annotate.*; +import org.codehaus.jackson.map.*; + +/** + * This unit test suite that tests use of {@link JsonCreator} + * with "delegate" constructors and factory methods: ones that + * take a deserializable type that is bound from JSON content. + * This is usually done to get two-phase data binding, often using + * {@link java.util.Map} as the intermediate form. + */ +public class TestConstructFromMap + extends BaseMapTest +{ + static class ConstructorFromMap + { + int _x; + String _y; + + @JsonCreator + ConstructorFromMap(Map<?,?> arg) + { + _x = ((Number) arg.get("x")).intValue(); + _y = (String) arg.get("y"); + } + } + + static class FactoryFromPoint + { + int _x, _y; + + private FactoryFromPoint(Point p) { + _x = p.x; + _y = p.y; + } + + @JsonCreator + static FactoryFromPoint createIt(Point p) + { + return new FactoryFromPoint(p); + } + } + + // Also: let's test BigDecimal-from-JSON-String factory + static class FactoryFromDecimalString + { + int _value; + + private FactoryFromDecimalString(BigDecimal d) { + _value = d.intValue(); + } + + @JsonCreator + static FactoryFromDecimalString whateverNameWontMatter(BigDecimal d) + { + return new FactoryFromDecimalString(d); + } + } + + /* + /********************************************************** + /* Test methods + /********************************************************** + */ + + public void testViaConstructor() throws Exception + { + ObjectMapper m = new ObjectMapper(); + ConstructorFromMap result = m.readValue + ("{ \"x\":1, \"y\" : \"abc\" }", ConstructorFromMap.class); + assertEquals(1, result._x); + assertEquals("abc", result._y); + } + + public void testViaFactory() throws Exception + { + ObjectMapper m = new ObjectMapper(); + FactoryFromPoint result = m.readValue("{ \"x\" : 3, \"y\" : 4 }", FactoryFromPoint.class); + assertEquals(3, result._x); + assertEquals(4, result._y); + } + + public void testViaFactoryUsingString() throws Exception + { + ObjectMapper m = new ObjectMapper(); + FactoryFromDecimalString result = m.readValue("\"12.57\"", FactoryFromDecimalString.class); + assertNotNull(result); + assertEquals(12, result._value); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/deser/TestCreatorNullValue.java b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestCreatorNullValue.java new file mode 100644 index 0000000..8239e41 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestCreatorNullValue.java
@@ -0,0 +1,82 @@ +package org.codehaus.jackson.map.deser; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.annotate.*; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.type.JavaType; + +// for [JACKSON-774] +@SuppressWarnings("rawtypes") +public class TestCreatorNullValue extends BaseMapTest +{ + private static class Container { + Contained<String> contained; + + @SuppressWarnings("unused") + @JsonCreator + public Container(@JsonProperty("contained") Contained<String> contained) { + this.contained = contained; + } + } + + private static interface Contained<T> {} + + private static class NullContained implements Contained<Object> {} + + private static final NullContained NULL_CONTAINED = new NullContained(); + + private static class ContainedDeserializer extends JsonDeserializer<Contained> { + @Override + public Contained deserialize(JsonParser jp, DeserializationContext ctxt) throws JsonProcessingException { + return null; + } + + @Override + public Contained getNullValue() { + return NULL_CONTAINED; + } + } + + private static class ContainerDeserializerResolver extends Deserializers.Base { + @Override + public JsonDeserializer<?> findBeanDeserializer(JavaType type, + DeserializationConfig config, DeserializerProvider provider, BeanDescription beanDesc, BeanProperty property) + throws JsonMappingException { + if (!Contained.class.isAssignableFrom(type.getRawClass())) { + return null; + } else { + return new ContainedDeserializer(); + } + } + } + + private static class TestModule extends Module { + @Override + public String getModuleName() { + return "ContainedModule"; + } + + @Override + public Version version() { + return Version.unknownVersion(); + } + + @Override + public void setupModule(SetupContext setupContext) { + setupContext.addDeserializers(new ContainerDeserializerResolver()); + } + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + public void testUsesDeserializersNullValue() throws Exception { + ObjectMapper mapper = new ObjectMapper(); + mapper.registerModule(new TestModule()); + Container container = mapper.readValue("{}", Container.class); + assertEquals(NULL_CONTAINED, container.contained); + } +} \ No newline at end of file
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/deser/TestCreators.java b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestCreators.java new file mode 100644 index 0000000..c6e04c3 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestCreators.java
@@ -0,0 +1,471 @@ +package org.codehaus.jackson.map.deser; + +import java.util.*; + +import org.codehaus.jackson.annotate.*; +import org.codehaus.jackson.map.*; + +/** + * Unit tests for verifying that it is possible to annotate + * various kinds of things with {@link JsonCreator} annotation. + */ +public class TestCreators + extends BaseMapTest +{ + /* + /********************************************************** + /* Annotated helper classes, simple + /********************************************************** + */ + + /** + * Simple(st) possible demonstration of using annotated + * constructors + */ + static class ConstructorBean { + int x; + + @JsonCreator protected ConstructorBean(@JsonProperty("x") int x) { + this.x = x; + } + } + + /** + * Another simple constructor, but with bit more unusual argument + * type + */ + static class BooleanConstructorBean { + Boolean b; + @JsonCreator protected BooleanConstructorBean(Boolean b) { + this.b = b; + } + } + + @SuppressWarnings("unused") + private static class BooleanConstructorBean2 { + boolean b; + @JsonCreator protected BooleanConstructorBean2(boolean b) { + this.b = b; + } + } + + static class DoubleConstructorBean { + Double d; // cup? + @JsonCreator protected DoubleConstructorBean(Double d) { + this.d = d; + } + } + + static class FactoryBean { + double d; // teehee + + private FactoryBean(double value, boolean dummy) { d = value; } + + @JsonCreator protected static FactoryBean createIt(@JsonProperty("f") double value) { + return new FactoryBean(value, true); + } + } + + static class LongFactoryBean { + long value; + + private LongFactoryBean(long v) { value = v; } + + @JsonCreator static protected LongFactoryBean valueOf(long v) { + return new LongFactoryBean(v); + } + } + + static class StringFactoryBean { + String value; + + private StringFactoryBean(String v, boolean dummy) { value = v; } + + @JsonCreator static protected StringFactoryBean valueOf(String v) { + return new StringFactoryBean(v, true); + } + } + + static class FactoryBeanMixIn { // static just to be able to use static methods + /** + * Note: signature (name and parameter types) must match; but + * only annotations will be used, not code or such. And use + * is by augmentation, so we only need to add things to add + * or override. + */ + static FactoryBean createIt(@JsonProperty("mixed") double xyz) { + return null; + } + } + + /** + * Simple demonstration of INVALID construtor annotation (only + * defining name for first arg) + */ + static class BrokenBean { + @JsonCreator protected BrokenBean(@JsonProperty("a") int a, + int b) { + } + } + + /** + * Bean that defines both creator and factory methor as + * creators. Constructors have priority; but it is possible + * to hide it using mix-in annotations. + */ + static class CreatorBean + { + String a; + int x; + + @JsonCreator + protected CreatorBean(@JsonProperty("a") String paramA, + @JsonProperty("x") int paramX) + { + a = "ctor:"+paramA; + x = 1+paramX; + } + + private CreatorBean(String a, int x, boolean dummy) { + this.a = a; + this.x = x; + } + + @JsonCreator + public static CreatorBean buildMeUpButterCup(@JsonProperty("a") String paramA, + @JsonProperty("x") int paramX) + { + return new CreatorBean("factory:"+paramA, paramX-1, false); + } + } + + /** + * Class for sole purpose of hosting mix-in annotations. + * Couple of things to note: (a) MUST be static class (non-static + * get implicit pseudo-arg, 'this'; + * (b) for factory methods, must have static to match (part of signature) + */ + abstract static class MixIn { + @JsonIgnore private MixIn(String a, int x) { } + } + + static class MultiBean { + Object value; + + @JsonCreator public MultiBean(int v) { value = v; } + @JsonCreator public MultiBean(double v) { value = v; } + @JsonCreator public MultiBean(String v) { value = v; } + @JsonCreator public MultiBean(boolean v) { value = v; } + } + + /* + /********************************************************** + /* Annotated helper classes, mixed (creator and props) + /********************************************************** + */ + + /** + * Test bean for ensuring that constructors can be mixed with setters + */ + static class ConstructorAndPropsBean + { + final int a, b; + boolean c; + + @JsonCreator protected ConstructorAndPropsBean(@JsonProperty("a") int a, + @JsonProperty("b") int b) + { + this.a = a; + this.b = b; + } + + public void setC(boolean value) { c = value; } + } + + /** + * Test bean for ensuring that factory methods can be mixed with setters + */ + static class FactoryAndPropsBean + { + boolean[] arg1; + int arg2, arg3; + + @JsonCreator protected FactoryAndPropsBean(@JsonProperty("a") boolean[] arg) + { + arg1 = arg; + } + + public void setB(int value) { arg2 = value; } + public void setC(int value) { arg3 = value; } + } + + static class DeferredConstructorAndPropsBean + { + final int[] createA; + String propA = "xyz"; + String propB; + + @JsonCreator + public DeferredConstructorAndPropsBean(@JsonProperty("createA") int[] a) + { + createA = a; + } + public void setPropA(String a) { propA = a; } + public void setPropB(String b) { propB = b; } + } + + static class DeferredFactoryAndPropsBean + { + String prop, ctor; + + @JsonCreator DeferredFactoryAndPropsBean(@JsonProperty("ctor") String str) + { + ctor = str; + } + + public void setProp(String str) { prop = str; } + } + + /* + ////////////////////////////////////////////// + // Annotated helper classes for Maps + ////////////////////////////////////////////// + */ + + @SuppressWarnings("serial") + static class MapWithCtor extends HashMap<Object,Object> + { + final int _number; + String _text = "initial"; + + MapWithCtor() { this(-1, "default"); } + + @JsonCreator + public MapWithCtor(@JsonProperty("number") int nr, + @JsonProperty("text") String t) + { + _number = nr; + _text = t; + } + } + + @SuppressWarnings("serial") + static class MapWithFactory extends TreeMap<Object,Object> + { + Boolean _b; + + private MapWithFactory(Boolean b) { + _b = b; + } + + @JsonCreator + static MapWithFactory createIt(@JsonProperty("b") Boolean b) + { + return new MapWithFactory(b); + } + } + + /* + ///////////////////////////////////////////////////// + // Test methods, valid cases, non-deferred, no-mixins + ///////////////////////////////////////////////////// + */ + + public void testSimpleConstructor() throws Exception + { + ObjectMapper m = new ObjectMapper(); + ConstructorBean bean = m.readValue("{ \"x\" : 42 }", ConstructorBean.class); + assertEquals(42, bean.x); + } + + public void testSimpleDoubleConstructor() throws Exception + { + ObjectMapper m = new ObjectMapper(); + Double exp = new Double("0.25"); + DoubleConstructorBean bean = m.readValue(exp.toString(), DoubleConstructorBean.class); + assertEquals(exp, bean.d); + } + + public void testSimpleBooleanConstructor() throws Exception + { + ObjectMapper m = new ObjectMapper(); + BooleanConstructorBean bean = m.readValue(" true ", BooleanConstructorBean.class); + assertEquals(Boolean.TRUE, bean.b); + + BooleanConstructorBean2 bean2 = m.readValue(" true ", BooleanConstructorBean2.class); + assertTrue(bean2.b); + } + + public void testSimpleFactory() throws Exception + { + ObjectMapper m = new ObjectMapper(); + FactoryBean bean = m.readValue("{ \"f\" : 0.25 }", FactoryBean.class); + assertEquals(0.25, bean.d); + } + + public void testLongFactory() throws Exception + { + ObjectMapper m = new ObjectMapper(); + long VALUE = 123456789000L; + LongFactoryBean bean = m.readValue(String.valueOf(VALUE), LongFactoryBean.class); + assertEquals(VALUE, bean.value); + } + + public void testStringFactory() throws Exception + { + ObjectMapper m = new ObjectMapper(); + String str = "abc"; + StringFactoryBean bean = m.readValue(quote(str), StringFactoryBean.class); + assertEquals(str, bean.value); + } + + public void testConstructorCreator() throws Exception + { + ObjectMapper m = new ObjectMapper(); + CreatorBean bean = m.readValue + ("{ \"a\" : \"xyz\", \"x\" : 12 }", CreatorBean.class); + assertEquals(13, bean.x); + assertEquals("ctor:xyz", bean.a); + } + + public void testConstructorAndProps() throws Exception + { + ObjectMapper m = new ObjectMapper(); + ConstructorAndPropsBean bean = m.readValue + ("{ \"a\" : \"1\", \"b\": 2, \"c\" : true }", ConstructorAndPropsBean.class); + assertEquals(1, bean.a); + assertEquals(2, bean.b); + assertEquals(true, bean.c); + } + + public void testFactoryAndProps() throws Exception + { + ObjectMapper m = new ObjectMapper(); + FactoryAndPropsBean bean = m.readValue + ("{ \"a\" : [ false, true, false ], \"b\": 2, \"c\" : -1 }", FactoryAndPropsBean.class); + assertEquals(2, bean.arg2); + assertEquals(-1, bean.arg3); + boolean[] arg1 = bean.arg1; + assertNotNull(arg1); + assertEquals(3, arg1.length); + assertFalse(arg1[0]); + assertTrue(arg1[1]); + assertFalse(arg1[2]); + } + + /** + * Test to verify that multiple creators may co-exist, iff + * they use different JSON type as input + */ + public void testMultipleCreators() throws Exception + { + ObjectMapper m = new ObjectMapper(); + MultiBean bean = m.readValue("123", MultiBean.class); + assertEquals(Integer.valueOf(123), bean.value); + bean = m.readValue(quote("abc"), MultiBean.class); + assertEquals("abc", bean.value); + bean = m.readValue("0.25", MultiBean.class); + assertEquals(Double.valueOf(0.25), bean.value); + } + + /* + /********************************************************** + /* Test methods, valid cases, deferred, no mixins + /********************************************************** + */ + + public void testDeferredConstructorAndProps() throws Exception + { + ObjectMapper m = new ObjectMapper(); + DeferredConstructorAndPropsBean bean = m.readValue + ("{ \"propB\" : \"...\", \"createA\" : [ 1 ], \"propA\" : null }", + DeferredConstructorAndPropsBean.class); + + assertEquals("...", bean.propB); + assertNull(bean.propA); + assertNotNull(bean.createA); + assertEquals(1, bean.createA.length); + assertEquals(1, bean.createA[0]); + } + + public void testDeferredFactoryAndProps() throws Exception + { + ObjectMapper m = new ObjectMapper(); + DeferredFactoryAndPropsBean bean = m.readValue + ("{ \"prop\" : \"1\", \"ctor\" : \"2\" }", DeferredFactoryAndPropsBean.class); + assertEquals("1", bean.prop); + assertEquals("2", bean.ctor); + } + + /* + ///////////////////////////////////////////////////// + // Test methods, valid cases, mixins + ///////////////////////////////////////////////////// + */ + + public void testFactoryCreatorWithMixin() throws Exception + { + ObjectMapper m = new ObjectMapper(); + m.getDeserializationConfig().addMixInAnnotations(CreatorBean.class, MixIn.class); + CreatorBean bean = m.readValue + ("{ \"a\" : \"xyz\", \"x\" : 12 }", CreatorBean.class); + assertEquals(11, bean.x); + assertEquals("factory:xyz", bean.a); + } + + public void testFactoryCreatorWithRenamingMixin() throws Exception + { + ObjectMapper m = new ObjectMapper(); + m.getDeserializationConfig().addMixInAnnotations(FactoryBean.class, FactoryBeanMixIn.class); + // override changes property name from "f" to "mixed" + FactoryBean bean = m.readValue("{ \"mixed\" : 20.5 }", FactoryBean.class); + assertEquals(20.5, bean.d); + } + + /* + ///////////////////////////////////////////////////// + // Test methods, valid cases, Map with creator + // (to test [JACKSON-153]) + ///////////////////////////////////////////////////// + */ + + public void testMapWithConstructor() throws Exception + { + MapWithCtor result = new ObjectMapper().readValue + ("{\"text\":\"abc\", \"entry\":true, \"number\":123, \"xy\":\"yx\"}", + MapWithCtor.class); + // regular Map entries: + assertEquals(Boolean.TRUE, result.get("entry")); + assertEquals("yx", result.get("xy")); + assertEquals(2, result.size()); + // then ones passed via constructor + assertEquals("abc", result._text); + assertEquals(123, result._number); + } + + public void testMapWithFactory() throws Exception + { + MapWithFactory result = new ObjectMapper().readValue + ("{\"x\":\"...\",\"b\":true }", + MapWithFactory.class); + assertEquals("...", result.get("x")); + assertEquals(1, result.size()); + assertEquals(Boolean.TRUE, result._b); + } + + /* + ////////////////////////////////////////////// + // Test methods, invalid/broken cases + ////////////////////////////////////////////// + */ + + public void testBrokenConstructor() throws Exception + { + ObjectMapper m = new ObjectMapper(); + try { + /*BrokenBean bean =*/ m.readValue("{ \"x\" : 42 }", BrokenBean.class); + } catch (JsonMappingException je) { + verifyException(je, "has no property name"); + } + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/deser/TestCreators2.java b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestCreators2.java new file mode 100644 index 0000000..9eda865 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestCreators2.java
@@ -0,0 +1,341 @@ + +package org.codehaus.jackson.map.deser; + +import java.io.IOException; +import java.util.List; +import java.util.Map; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.annotate.*; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.JsonDeserialize; + +public class TestCreators2 + extends BaseMapTest +{ + /* + /********************************************************** + /* Helper classes + /********************************************************** + */ + + static class HashTest + { + final byte[] bytes; + final String type; + + @JsonCreator + public HashTest(@JsonProperty("bytes") @JsonDeserialize(using = BytesDeserializer.class) final byte[] bytes, + @JsonProperty("type") final String type) + { + this.bytes = bytes; + this.type = type; + } + } + + static class BytesDeserializer extends JsonDeserializer<byte[]> + { + @Override + public byte[] deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { + String str = jp.getText(); + return str.getBytes("UTF-8"); + } + } + + static class Primitives + { + protected int x = 3; + protected double d = -0.5; + protected boolean b = true; + + @JsonCreator + public Primitives(@JsonProperty("x") int x, + @JsonProperty("d") double d, + @JsonProperty("b") boolean b) + { + this.x = x; + this.d = d; + this.b = b; + } + } + + protected static class Test431Container { + protected final List<Item431> items; + + @JsonCreator + public Test431Container(@JsonProperty("items") final List<Item431> i) { + items = i; + } +} + + @JsonIgnoreProperties(ignoreUnknown = true) + protected static class Item431 { + protected final String id; + + @JsonCreator + public Item431(@JsonProperty("id") String id) { + this.id = id; + } + } + + // Test class for verifying that creator-call failures are reported as checked exceptions + static class BeanFor438 { + @JsonCreator + public BeanFor438(@JsonProperty("name") String s) { + throw new IllegalArgumentException("I don't like that name!"); + } + } + + // For [JACKSON-465] + static class MapBean + { + protected Map<String,Long> map; + + @JsonCreator + public MapBean(Map<String, Long> map) { + this.map = map; + } + } + + // For [JACKSON-470]: should be appropriately detected, reported error about + static class BrokenCreatorBean + { + protected String bar; + + @JsonCreator + public BrokenCreatorBean(@JsonProperty("bar") String bar1, @JsonProperty("bar") String bar2) { + bar = ""+bar1+"/"+bar2; + } + } + + // For [JACKSON-541]: should not need @JsonCreator if Feature.AUTO_DETECT_CREATORS is on. + static class AutoDetectConstructorBean + { + protected final String foo; + protected final String bar; + + public AutoDetectConstructorBean(@JsonProperty("bar") String bar, @JsonProperty("foo") String foo){ + this.bar = bar; + this.foo = foo; + } + } + + static class BustedCtor { + @JsonCreator + BustedCtor(@JsonProperty("a") String value) { + throw new IllegalArgumentException("foobar"); + } + } + + // As per [JACKSON-575] + static class IgnoredCtor + { + @JsonIgnore + public IgnoredCtor(String arg) { + throw new RuntimeException("Should never use this constructor"); + } + + public IgnoredCtor() { } + } + + abstract static class AbstractBase { + @JsonCreator + public static AbstractBase create(Map<String,Object> props) + { + return new AbstractBaseImpl(props); + } + } + + static class AbstractBaseImpl extends AbstractBase + { + protected Map<String,Object> props; + + public AbstractBaseImpl(Map<String,Object> props) { + this.props = props; + } + } + + static class BooleanBean + { + protected Boolean value; + + public BooleanBean(Boolean v) { value = v; } + + @JsonCreator + protected static BooleanBean create(Boolean value) { + return new BooleanBean(value); + } + } + + static interface Issue700Set extends java.util.Set<Object> { } + + static class Issue700Bean + { + protected Issue700Set item; + + @JsonCreator + public Issue700Bean(@JsonProperty("item") String item) { } + + public String getItem() { return null; } + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + // for [JACKSON-547] + public void testExceptionFromConstructor() throws Exception + { + ObjectMapper m = new ObjectMapper(); + try { + m.readValue("{}", BustedCtor.class); + fail("Expected exception"); + } catch (JsonMappingException e) { + verifyException(e, ": foobar"); + // also: should have nested exception + Throwable t = e.getCause(); + assertNotNull(t); + assertEquals(IllegalArgumentException.class, t.getClass()); + assertEquals("foobar", t.getMessage()); + } + } + + public void testSimpleConstructor() throws Exception + { + ObjectMapper m = new ObjectMapper(); + HashTest test = m.readValue("{\"type\":\"custom\",\"bytes\":\"abc\" }", HashTest.class); + assertEquals("custom", test.type); + assertEquals("abc", new String(test.bytes, "UTF-8")); + } + + // Test for [JACKSON-372] + public void testMissingPrimitives() throws Exception + { + ObjectMapper m = new ObjectMapper(); + Primitives p = m.readValue("{}", Primitives.class); + assertFalse(p.b); + assertEquals(0, p.x); + assertEquals(0.0, p.d); + } + + public void testJackson431() throws Exception + { + ObjectMapper m = new ObjectMapper(); + final Test431Container foo = m.readValue( + "{\"items\":\n" + +"[{\"bar\": 0,\n" + +"\"id\": \"id123\",\n" + +"\"foo\": 1\n" + +"}]}", + Test431Container.class); + assertNotNull(foo); + } + + // [JACKSON-438]: Catch and rethrow exceptions that Creator methods throw + public void testJackson438() throws Exception + { + ObjectMapper m = new ObjectMapper(); + try { + m.readValue("{ \"name\":\"foobar\" }", BeanFor438.class); + fail("Should have failed"); + } catch (Exception e) { + if (!(e instanceof JsonMappingException)) { + fail("Should have received JsonMappingException, caught "+e.getClass().getName()); + } + verifyException(e, "don't like that name"); + // Ok: also, let's ensure root cause is directly linked, without other extra wrapping: + Throwable t = e.getCause(); + assertNotNull(t); + assertEquals(IllegalArgumentException.class, t.getClass()); + verifyException(e, "don't like that name"); + } + } + + @SuppressWarnings("unchecked") + public void testIssue465() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + final String JSON = "{\"A\":12}"; + + // first, test with regular Map, non empty + Map<String,Long> map = mapper.readValue(JSON, Map.class); + assertEquals(1, map.size()); + assertEquals(Integer.valueOf(12), map.get("A")); + + MapBean bean = mapper.readValue(JSON, MapBean.class); + assertEquals(1, bean.map.size()); + assertEquals(Long.valueOf(12L), bean.map.get("A")); + + // and then empty ones + final String EMPTY_JSON = "{}"; + + map = mapper.readValue(EMPTY_JSON, Map.class); + assertEquals(0, map.size()); + + bean = mapper.readValue(EMPTY_JSON, MapBean.class); + assertEquals(0, bean.map.size()); + } + + public void testCreatorWithDupNames() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + try { + mapper.readValue("{\"bar\":\"x\"}", BrokenCreatorBean.class); + fail("Should have caught duplicate creator parameters"); + } catch (JsonMappingException e) { + verifyException(e, "duplicate creator property \"bar\""); + } + } + + public void testCreatorMultipleArgumentWithoutAnnotation() throws Exception { + ObjectMapper mapper = new ObjectMapper(); + AutoDetectConstructorBean value = mapper.readValue("{\"bar\":\"bar\",\"foo\":\"foo\"}", AutoDetectConstructorBean.class); + assertEquals("bar", value.bar); + assertEquals("foo", value.foo); + } + + // for [JACKSON-575] + public void testIgnoredSingleArgCtor() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + try { + mapper.readValue(quote("abc"), IgnoredCtor.class); + fail("Should have caught missing constructor problem"); + } catch (JsonMappingException e) { + verifyException(e, "no single-String constructor/factory method"); + } + } + + public void testAbstractFactory() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + AbstractBase bean = mapper.readValue("{\"a\":3}", + AbstractBase.class); + assertNotNull(bean); + AbstractBaseImpl impl = (AbstractBaseImpl) bean; + assertEquals(1, impl.props.size()); + assertEquals(Integer.valueOf(3), impl.props.get("a")); + } + + public void testBooleanDelegate() throws Exception + { + ObjectMapper m = new ObjectMapper(); + // should obviously work with booleans... + BooleanBean bb = m.readValue("true", BooleanBean.class); + assertEquals(Boolean.TRUE, bb.value); + + // but also with value conversion from String + bb = m.readValue(quote("true"), BooleanBean.class); + assertEquals(Boolean.TRUE, bb.value); + } + + // [JACKSON-700] + public void testCreatorProperties() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + Issue700Bean value = mapper.readValue("{ \"item\" : \"foo\" }", Issue700Bean.class); + assertNotNull(value); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/deser/TestCustomFactory.java b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestCustomFactory.java new file mode 100644 index 0000000..b2ec171 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestCustomFactory.java
@@ -0,0 +1,152 @@ +package org.codehaus.jackson.map.deser; + +import java.io.*; +import java.util.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.JsonDeserialize; +import org.codehaus.jackson.map.deser.std.StdDeserializer; + +/** + * Test to check that customization using {@link CustomDeserializerFactory} + * works as expected. + */ +public class TestCustomFactory + extends BaseMapTest +{ + /* + /********************************************************** + /* Helper classes + /********************************************************** + */ + + static class DummyDeserializer<T> + extends StdDeserializer<T> + { + final T value; + + public DummyDeserializer(T v, Class<T> cls) { + super(cls); + value = v; + } + + @Override + public T deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + // need to skip, if structured... + jp.skipChildren(); + return value; + } + } + + static class TestBeans { + public List<TestBean> beans; + } + static class TestBean { + public CustomBean c; + public String d; + } + @JsonDeserialize(using=CustomBeanDeserializer.class) + static class CustomBean { + protected final int a, b; + public CustomBean(int a, int b) { + this.a = a; + this.b = b; + } + } + + static class CustomBeanDeserializer extends JsonDeserializer<CustomBean> + { + @Override + public CustomBean deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException + { + int a = 0, b = 0; + JsonToken t = jp.getCurrentToken(); + if (t == JsonToken.START_OBJECT) { + t = jp.nextToken(); + } else if (t != JsonToken.FIELD_NAME) { + throw new Error(); + } + while(t == JsonToken.FIELD_NAME) { + final String fieldName = jp.getCurrentName(); + t = jp.nextToken(); + if (t != JsonToken.VALUE_NUMBER_INT) { + throw new JsonParseException("expecting number got "+ t, jp.getCurrentLocation()); + } + if (fieldName.equals("a")) { + a = jp.getIntValue(); + } else if (fieldName.equals("b")) { + b = jp.getIntValue(); + } else { + throw new Error(); + } + t = jp.nextToken(); + } + return new CustomBean(a, b); + } + } + + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + @SuppressWarnings("deprecation") + public void testDateOverride() throws Exception + { + Date expResult = new Date(3L); + ObjectMapper mapper = new ObjectMapper(); + CustomDeserializerFactory sf = new CustomDeserializerFactory(); + sf.addSpecificMapping(Date.class, new DummyDeserializer<Date>(expResult, Date.class)); + mapper.setDeserializerProvider(new StdDeserializerProvider(sf)); + + Date result = mapper.readValue("123", Date.class); + assertEquals(expResult.getTime(), result.getTime()); + } + + public void testCustomBeanDeserializer() throws Exception + { + + final ObjectMapper map = new ObjectMapper(); + String json = "{\"beans\":[{\"c\":{\"a\":10,\"b\":20},\"d\":\"hello, tatu\"}]}"; + TestBeans beans = map.readValue(json, TestBeans.class); + + assertNotNull(beans); + List<TestBean> results = beans.beans; + assertNotNull(results); + assertEquals(1, results.size()); + TestBean bean = results.get(0); + assertEquals("hello, tatu", bean.d); + CustomBean c = bean.c; + assertNotNull(c); + assertEquals(10, c.a); + assertEquals(20, c.b); + + json = "{\"beans\":[{\"c\":{\"b\":3,\"a\":-4},\"d\":\"\"}," + +"{\"d\":\"abc\", \"c\":{\"b\":15}}]}"; + beans = map.readValue(json, TestBeans.class); + + assertNotNull(beans); + results = beans.beans; + assertNotNull(results); + assertEquals(2, results.size()); + + bean = results.get(0); + assertEquals("", bean.d); + c = bean.c; + assertNotNull(c); + assertEquals(-4, c.a); + assertEquals(3, c.b); + + bean = results.get(1); + assertEquals("abc", bean.d); + c = bean.c; + assertNotNull(c); + assertEquals(0, c.a); + assertEquals(15, c.b); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/deser/TestCyclicTypes.java b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestCyclicTypes.java new file mode 100644 index 0000000..c5ea6c7 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestCyclicTypes.java
@@ -0,0 +1,111 @@ +package org.codehaus.jackson.map.deser; + +import javax.xml.bind.annotation.*; + +import org.codehaus.jackson.map.BaseMapTest; + +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.xc.JaxbAnnotationIntrospector; + +/** + * Simple unit tests to verify that it is possible to handle + * potentially cyclic structures, as long as object graph itself + * is not cyclic. This is the case for directed hierarchies like + * trees and DAGs. + */ +public class TestCyclicTypes + extends BaseMapTest +{ + /* + /********************************************************** + /* Helper bean classes + /********************************************************** + */ + + static class Bean + { + Bean _next; + String _name; + + public Bean() { } + + public void setNext(Bean b) { _next = b; } + public void setName(String n) { _name = n; } + + } + + // Also another one to ensure JAXB annotation introspector has no problems + @XmlAccessorType(XmlAccessType.FIELD) + static class JaxbBean + { + @XmlElement(required = true) + protected int id; + + @XmlElement(required = false) + protected JaxbBean circular; + } + + static class LinkA { + public LinkB next; + } + + static class LinkB { + private LinkA a; + + public void setA(LinkA a) { this.a = a; } + public LinkA getA() { return a; } + } + + static class GenericLink<T> { + public GenericLink<T> next; + } + + static class StringLink extends GenericLink<String> { + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + public void testLinked() throws Exception + { + Bean first = new ObjectMapper().readValue + ("{\"name\":\"first\", \"next\": { " + +" \"name\":\"last\", \"next\" : null }}", + Bean.class); + + assertNotNull(first); + assertEquals("first", first._name); + Bean last = first._next; + assertNotNull(last); + assertEquals("last", last._name); + assertNull(last._next); + } + + public void testLinkedGeneric() throws Exception + { + StringLink link = new ObjectMapper().readValue + ("{\"next\":null}", StringLink.class); + assertNotNull(link); + assertNull(link.next); + } + + // Added to check for [JACKSON-171] + public void testWithJAXB() throws Exception + { + String jsonData = "{\"id\":1}"; + ObjectMapper mapper = new ObjectMapper(); + mapper.setAnnotationIntrospector(new JaxbAnnotationIntrospector()); + mapper.readValue(jsonData, JaxbBean.class); + } + + public void testCycleWith2Classes() throws Exception + { + LinkA a = new ObjectMapper().readValue("{\"next\":{\"a\":null}}", LinkA.class); + assertNotNull(a.next); + LinkB b = a.next; + assertNull(b.a); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/deser/TestDateDeserialization.java b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestDateDeserialization.java new file mode 100644 index 0000000..70af35e --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestDateDeserialization.java
@@ -0,0 +1,260 @@ +package org.codehaus.jackson.map.deser; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.*; + +import org.codehaus.jackson.map.*; + +public class TestDateDeserialization + extends BaseMapTest +{ + public void testDateUtil() throws Exception + { + long now = 123456789L; + java.util.Date value = new java.util.Date(now); + + // First from long + assertEquals(value, new ObjectMapper().readValue(""+now, java.util.Date.class)); + + String dateStr = serializeDateAsString(value); + java.util.Date result = new ObjectMapper().readValue("\""+dateStr+"\"", java.util.Date.class); + + assertEquals("Date: expect "+value+" ("+value.getTime()+"), got "+result+" ("+result.getTime()+")", value.getTime(), result.getTime()); + } + + /** + * @since 1.5.0 + */ + public void testDateUtilWithStringTimestamp() throws Exception + { + long now = 1321992375446L; + /* As of 1.5.0, should be ok to pass as JSON String, as long + * as it is plain timestamp (all numbers, 64-bit) + */ + String json = quote(String.valueOf(now)); + java.util.Date value = new ObjectMapper().readValue(json, java.util.Date.class); + assertEquals(now, value.getTime()); + } + + /** + * As of version 0.9.8, we'll try to cover RFC-1123 Strings too, + * automatically. + */ + public void testDateUtilRFC1123() throws Exception + { + DateFormat fmt = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz"); + // let's use an arbitrary value... + String inputStr = "Sat, 17 Jan 2009 06:13:58 +0000"; + java.util.Date inputDate = fmt.parse(inputStr); + assertEquals(inputDate, new ObjectMapper().readValue("\""+inputStr+"\"", java.util.Date.class)); + } + + /** + * ISO8601 is supported as well + */ + public void testDateUtilISO8601() throws Exception + { + /* let's use simple baseline value, arbitrary date in GMT, + * using the standard notation + */ + ObjectMapper mapper = new ObjectMapper(); + String inputStr = "1972-12-28T00:00:00.000+0000"; + Date inputDate = mapper.readValue("\""+inputStr+"\"", java.util.Date.class); + Calendar c = Calendar.getInstance(TimeZone.getTimeZone("GMT")); + c.setTime(inputDate); + assertEquals(1972, c.get(Calendar.YEAR)); + assertEquals(Calendar.DECEMBER, c.get(Calendar.MONTH)); + assertEquals(28, c.get(Calendar.DAY_OF_MONTH)); + + // And then the same, but using 'Z' as alias for +0000 (very common) + inputStr = "1972-12-28T00:00:00.000Z"; + inputDate = mapper.readValue(quote(inputStr), java.util.Date.class); + c.setTime(inputDate); + assertEquals(1972, c.get(Calendar.YEAR)); + assertEquals(Calendar.DECEMBER, c.get(Calendar.MONTH)); + assertEquals(28, c.get(Calendar.DAY_OF_MONTH)); + + // Same but using colon in timezone + inputStr = "1972-12-28T00:00:00.000+00:00"; + inputDate = mapper.readValue(quote(inputStr), java.util.Date.class); + c.setTime(inputDate); + assertEquals(1972, c.get(Calendar.YEAR)); + assertEquals(Calendar.DECEMBER, c.get(Calendar.MONTH)); + assertEquals(28, c.get(Calendar.DAY_OF_MONTH)); + + // Same but only passing hour difference as timezone + inputStr = "1972-12-28T00:00:00.000+00"; + inputDate = mapper.readValue(quote(inputStr), java.util.Date.class); + c.setTime(inputDate); + assertEquals(1972, c.get(Calendar.YEAR)); + assertEquals(Calendar.DECEMBER, c.get(Calendar.MONTH)); + assertEquals(28, c.get(Calendar.DAY_OF_MONTH)); + + inputStr = "1984-11-30T00:00:00.000Z"; + inputDate = mapper.readValue(quote(inputStr), java.util.Date.class); + c.setTime(inputDate); + assertEquals(1984, c.get(Calendar.YEAR)); + assertEquals(Calendar.NOVEMBER, c.get(Calendar.MONTH)); + assertEquals(30, c.get(Calendar.DAY_OF_MONTH)); + } + + public void testDateUtilISO8601NoTimezone() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + // Timezone itself is optional as well... + String inputStr = "1984-11-13T00:00:09"; + Date inputDate = mapper.readValue(quote(inputStr), java.util.Date.class); + Calendar c = Calendar.getInstance(TimeZone.getTimeZone("GMT")); + c.setTime(inputDate); + assertEquals(1984, c.get(Calendar.YEAR)); + assertEquals(Calendar.NOVEMBER, c.get(Calendar.MONTH)); + assertEquals(13, c.get(Calendar.DAY_OF_MONTH)); + assertEquals(0, c.get(Calendar.HOUR_OF_DAY)); + assertEquals(0, c.get(Calendar.MINUTE)); + assertEquals(9, c.get(Calendar.SECOND)); + assertEquals(0, c.get(Calendar.MILLISECOND)); + } + + public void testDateUtilISO8601JustDate() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + // Plain date (no time) + String inputStr = "1972-12-28"; + Date inputDate = mapper.readValue(quote(inputStr), java.util.Date.class); + Calendar c = Calendar.getInstance(TimeZone.getTimeZone("GMT")); + c.setTime(inputDate); + assertEquals(1972, c.get(Calendar.YEAR)); + assertEquals(Calendar.DECEMBER, c.get(Calendar.MONTH)); + assertEquals(28, c.get(Calendar.DAY_OF_MONTH)); + + } + + + @SuppressWarnings("deprecation") + public void testDateSql() throws Exception + { + java.sql.Date value = new java.sql.Date(0L); + value.setYear(99); // 1999 + value.setDate(19); + value.setMonth(Calendar.APRIL); + long now = value.getTime(); + + // First from long + ObjectMapper mapper = new ObjectMapper(); + assertEquals(value, mapper.readValue(String.valueOf(now), java.sql.Date.class)); + + // then from default java.sql.Date String serialization: + + java.sql.Date result = mapper.readValue(quote(value.toString()), java.sql.Date.class); + Calendar c = Calendar.getInstance(TimeZone.getTimeZone("GMT")); + c.setTimeInMillis(result.getTime()); + assertEquals(1999, c.get(Calendar.YEAR)); + assertEquals(Calendar.APRIL, c.get(Calendar.MONTH)); + assertEquals(19, c.get(Calendar.DAY_OF_MONTH)); + + /* [JACKSON-200]: looks like we better add support for regular date + * formats as well + */ + String expStr = "1981-07-13"; + result = mapper.readValue(quote(expStr), java.sql.Date.class); + c.setTimeInMillis(result.getTime()); + assertEquals(1981, c.get(Calendar.YEAR)); + assertEquals(Calendar.JULY, c.get(Calendar.MONTH)); + assertEquals(13, c.get(Calendar.DAY_OF_MONTH)); + + /* 20-Nov-2009, tatus: I'll be damned if I understand why string serialization + * is off-by-one, but day-of-month does seem to be one less. My guess is + * that something is funky with timezones (i.e. somewhere local TZ is + * being used), but just can't resolve it. Hence, need to comment this: + */ + //assertEquals(expStr, result.toString()); + } + + public void testCalendar() throws Exception + { + // not ideal, to use (ever-changing) current date, but... + java.util.Date now = new Date(); + java.util.Calendar value = Calendar.getInstance(); + value.setTime(now); + + // First from long + assertEquals(value, new ObjectMapper().readValue(""+now.getTime(), Calendar.class)); + + String dateStr = serializeDateAsString(now); + Calendar result = new ObjectMapper().readValue("\""+dateStr+"\"", Calendar.class); + + assertEquals(value, result); + } + + public void testCustom() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + DateFormat df = new SimpleDateFormat("yyyy-MM-dd'X'HH:mm:ss"); + df.setTimeZone(TimeZone.getTimeZone("PST")); + mapper.setDateFormat(df); + + String dateStr = "1972-12-28X15:45:00"; + java.util.Date exp = df.parse(dateStr); + java.util.Date result = mapper.readValue("\""+dateStr+"\"", java.util.Date.class); + assertEquals(exp, result); + } + + /** + * Test for [JACKSON-203]: make empty Strings deserialize as nulls by default, + * without need to turn on feature (which may be added in future) + */ + public void testDatesWithEmptyStrings() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + + assertNull(mapper.readValue(quote(""), java.util.Date.class)); + assertNull(mapper.readValue(quote(""), java.util.Calendar.class)); + assertNull(mapper.readValue(quote(""), java.sql.Date.class)); + } + + // for [JACKSON-334] + public void test8601DateTimeNoMilliSecs() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + // ok, Zebra, no milliseconds + for (String inputStr : new String[] { + "2010-06-28T23:34:22Z", + "2010-06-28T23:34:22+0000", + "2010-06-28T23:34:22+00", + }) { + Date inputDate = mapper.readValue(quote(inputStr), java.util.Date.class); + Calendar c = Calendar.getInstance(TimeZone.getTimeZone("GMT")); + c.setTime(inputDate); + assertEquals(2010, c.get(Calendar.YEAR)); + assertEquals(Calendar.JUNE, c.get(Calendar.MONTH)); + assertEquals(28, c.get(Calendar.DAY_OF_MONTH)); + assertEquals(23, c.get(Calendar.HOUR_OF_DAY)); + assertEquals(34, c.get(Calendar.MINUTE)); + assertEquals(22, c.get(Calendar.SECOND)); + assertEquals(0, c.get(Calendar.MILLISECOND)); + } + } + + public void testTimeZone() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + TimeZone result = mapper.readValue(quote("PST"), TimeZone.class); + assertEquals("PST", result.getID()); + } + + /* + /********************************************************** + /* Helper methods + /********************************************************** + */ + + String serializeDateAsString(java.util.Date value) + { + /* Then from String. This is bit tricky, since JDK does not really + * suggest a 'standard' format. So let's try using something... + */ + DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); + return df.format(value); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/deser/TestEnumDeserialization.java b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestEnumDeserialization.java new file mode 100644 index 0000000..e7162bc --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestEnumDeserialization.java
@@ -0,0 +1,251 @@ +package org.codehaus.jackson.map.deser; + +import java.util.EnumMap; +import java.util.EnumSet; +import java.util.concurrent.TimeUnit; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.annotate.JsonCreator; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.JsonDeserialize; +import org.codehaus.jackson.map.deser.std.StdDeserializer; +import org.codehaus.jackson.type.TypeReference; + +public class TestEnumDeserialization + extends BaseMapTest +{ + /* + /********************************************************** + /* Helper classes, enums + /********************************************************** + */ + + enum TestEnum { JACKSON, RULES, OK; } + + /** + * Alternative version that annotates which deserializer to use + */ + @JsonDeserialize(using=DummySerializer.class) + enum AnnotatedTestEnum { + JACKSON, RULES, OK; + } + + public static class DummySerializer extends StdDeserializer<Object> + { + public DummySerializer() { super(Object.class); } + @Override + public Object deserialize(JsonParser jp, DeserializationContext ctxt) + { + return AnnotatedTestEnum.OK; + } + } + + protected enum EnumWithCreator { + A, B; + + @JsonCreator + public static EnumWithCreator fromEnum(String str) { + if ("enumA".equals(str)) return A; + if ("enumB".equals(str)) return B; + return null; + } + } + + protected enum LowerCaseEnum { + A, B, C; + private LowerCaseEnum() { } + @Override + public String toString() { return name().toLowerCase(); } + } + + protected enum TestEnumFor834 + { + ENUM_A(1), ENUM_B(2), ENUM_C(3); + + private final int id; + + private TestEnumFor834(int id) { + this.id = id; + } + + @JsonCreator public static TestEnumFor834 fromId(int id) { + for (TestEnumFor834 e: values()) { + if (e.id == id) return e; + } + return null; + } + } + + /* + /********************************************************** + /* Tests + /********************************************************** + */ + + public void testSimple() throws Exception + { + // First "good" case with Strings + ObjectMapper mapper = new ObjectMapper(); + String JSON = "\"OK\" \"RULES\" null"; + // multiple main-level mappings, need explicit parser: + JsonParser jp = mapper.getJsonFactory().createJsonParser(JSON); + + assertEquals(TestEnum.OK, mapper.readValue(jp, TestEnum.class)); + assertEquals(TestEnum.RULES, mapper.readValue(jp, TestEnum.class)); + + /* should be ok; nulls are typeless; handled by mapper, not by + * deserializer + */ + assertNull(mapper.readValue(jp, TestEnum.class)); + + // and no more content beyond that... + assertFalse(jp.hasCurrentToken()); + + /* Then alternative with index (0 means first entry) + */ + assertEquals(TestEnum.JACKSON, mapper.readValue(" 0 ", TestEnum.class)); + + /* Then error case: unrecognized value + */ + try { + /*Object result =*/ mapper.readValue("\"NO-SUCH-VALUE\"", TestEnum.class); + fail("Expected an exception for bogus enum value..."); + } catch (JsonMappingException jex) { + verifyException(jex, "value not one of declared"); + } + } + + /** + * Enums are considered complex if they have code (and hence sub-classes)... an + * example is TimeUnit + */ + public void testComplexEnum() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + String json = mapper.writeValueAsString(TimeUnit.HOURS); + assertEquals(quote("HOURS"), json); + TimeUnit result = mapper.readValue(json, TimeUnit.class); + assertSame(TimeUnit.HOURS, result); + } + + /** + * Testing to see that annotation override works + */ + public void testAnnotated() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + AnnotatedTestEnum e = mapper.readValue("\"JACKSON\"", AnnotatedTestEnum.class); + /* dummy deser always returns value OK, independent of input; + * only works if annotation is used + */ + assertEquals(AnnotatedTestEnum.OK, e); + } + + public void testEnumMaps() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + EnumMap<TestEnum,String> value = mapper.readValue("{\"OK\":\"value\"}", + new TypeReference<EnumMap<TestEnum,String>>() { }); + assertEquals("value", value.get(TestEnum.OK)); + } + + // Test [JACKSON-214] + public void testSubclassedEnums() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + EnumWithSubClass value = mapper.readValue("\"A\"", EnumWithSubClass.class); + assertEquals(EnumWithSubClass.A, value); + } + + // [JACKSON-193] + public void testCreatorEnums() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + EnumWithCreator value = mapper.readValue("\"enumA\"", EnumWithCreator.class); + assertEquals(EnumWithCreator.A, value); + } + + // [JACKSON-212] + public void testToStringEnums() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.configure(DeserializationConfig.Feature.READ_ENUMS_USING_TO_STRING, true); + LowerCaseEnum value = mapper.readValue("\"c\"", LowerCaseEnum.class); + assertEquals(LowerCaseEnum.C, value); + } + + // [JACKSON-212] + public void testToStringEnumMaps() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.configure(DeserializationConfig.Feature.READ_ENUMS_USING_TO_STRING, true); + EnumMap<LowerCaseEnum,String> value = mapper.readValue("{\"a\":\"value\"}", + new TypeReference<EnumMap<LowerCaseEnum,String>>() { }); + assertEquals("value", value.get(LowerCaseEnum.A)); + } + + // [JACKSON-412], disallow use of numbers + public void testNumbersToEnums() throws Exception + { + // by default numbers are fine: + ObjectMapper mapper = new ObjectMapper(); + assertFalse(mapper.getDeserializationConfig().isEnabled(DeserializationConfig.Feature.FAIL_ON_NUMBERS_FOR_ENUMS)); + TestEnum value = mapper.readValue("1", TestEnum.class); + assertSame(TestEnum.RULES, value); + + // but can also be changed to errors: + mapper = new ObjectMapper(); + mapper.configure(DeserializationConfig.Feature.FAIL_ON_NUMBERS_FOR_ENUMS, true); + try { + value = mapper.readValue("1", TestEnum.class); + fail("Expected an error"); + } catch (JsonMappingException e) { + verifyException(e, "Not allowed to deserialize Enum value out of JSON number"); + } + } + + // [JACKSON-684], enums using index + public void testEnumsWithIndex() throws Exception + { + // by default numbers are fine: + ObjectMapper mapper = new ObjectMapper(); + mapper.enable(SerializationConfig.Feature.WRITE_ENUMS_USING_INDEX); + String json = mapper.writeValueAsString(TestEnum.RULES); + assertEquals(String.valueOf(TestEnum.RULES.ordinal()), json); + TestEnum result = mapper.readValue(json, TestEnum.class); + assertSame(TestEnum.RULES, result); + } + + // [JACKSON-756] + public void testEnumWithCreatorEnumMaps() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + EnumMap<EnumWithCreator,String> value = mapper.readValue("{\"enumA\":\"value\"}", + new TypeReference<EnumMap<EnumWithCreator,String>>() {}); + assertEquals("value", value.get(EnumWithCreator.A)); + } + + public void testEnumWithCreatorMaps() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + java.util.HashMap<EnumWithCreator,String> value = mapper.readValue("{\"enumA\":\"value\"}", + new TypeReference<java.util.HashMap<EnumWithCreator,String>>() {}); + assertEquals("value", value.get(EnumWithCreator.A)); + } + + public void testEnumWithCreatorEnumSets() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + EnumSet<EnumWithCreator> value = mapper.readValue("[\"enumA\"]", + new TypeReference<EnumSet<EnumWithCreator>>() {}); + assertTrue(value.contains(EnumWithCreator.A)); + } + + // [JACKSON-834] + public void testEnumsFromInts() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + TestEnumFor834 res = mapper.readValue("1 ", TestEnumFor834.class); + assertSame(TestEnumFor834.ENUM_A, res); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/deser/TestExceptionDeserialization.java b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestExceptionDeserialization.java new file mode 100644 index 0000000..18bb87f --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestExceptionDeserialization.java
@@ -0,0 +1,105 @@ +package org.codehaus.jackson.map.deser; + +import org.codehaus.jackson.map.BaseMapTest; + +import java.io.IOException; +import java.util.*; + +import org.codehaus.jackson.annotate.JsonAnySetter; +import org.codehaus.jackson.annotate.JsonCreator; +import org.codehaus.jackson.annotate.JsonProperty; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.JsonSerialize; + +/** + * Unit tests for verifying that simple exceptions can be deserialized. + */ +public class TestExceptionDeserialization + extends BaseMapTest +{ + @SuppressWarnings("serial") + static class MyException extends Exception + { + protected int value; + + protected String myMessage; + protected HashMap<String,Object> stuff = new HashMap<String, Object>(); + + @JsonCreator + MyException(@JsonProperty("message") String msg, @JsonProperty("value") int v) + { + super(msg); + myMessage = msg; + value = v; + } + + public int getValue() { return value; } + + public String getFoo() { return "bar"; } + + @JsonAnySetter public void setter(String key, Object value) + { + stuff.put(key, value); + } + } + + @SuppressWarnings("serial") + static class MyNoArgException extends Exception + { + @JsonCreator MyNoArgException() { } + } + + /* + /********************************************************** + /* Tests + /********************************************************** + */ + + final ObjectMapper MAPPER = new ObjectMapper(); + + public void testIOException() throws IOException + { + IOException ioe = new IOException("TEST"); + String json = MAPPER.writeValueAsString(ioe); + IOException result = MAPPER.readValue(json, IOException.class); + assertEquals(ioe.getMessage(), result.getMessage()); + } + + // As per [JACKSON-377] + public void testWithCreator() throws IOException + { + final String MSG = "the message"; + String json = MAPPER.writeValueAsString(new MyException(MSG, 3)); + + MyException result = MAPPER.readValue(json, MyException.class); + assertEquals(MSG, result.getMessage()); + assertEquals(3, result.value); + assertEquals(1, result.stuff.size()); + assertEquals(result.getFoo(), result.stuff.get("foo")); + } + + // [JACKSON-388] + public void testWithNullMessage() throws IOException + { + final ObjectMapper mapper = new ObjectMapper(); + mapper.setSerializationInclusion(JsonSerialize.Inclusion.NON_NULL); + String json = mapper.writeValueAsString(new IOException((String) null)); + IOException result = mapper.readValue(json, IOException.class); + assertNotNull(result); + assertNull(result.getMessage()); + } + + public void testNoArgsException() throws IOException + { + MyNoArgException exc = MAPPER.readValue("{}", MyNoArgException.class); + assertNotNull(exc); + } + + // [JACKSON-794]: try simulating JDK 7 behavior + public void testJDK7SuppressionProperty() throws IOException + { + Exception exc = MAPPER.readValue("{\"suppressed\":[]}", IOException.class); + assertNotNull(exc); + } +} +
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/deser/TestExceptionHandling.java b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestExceptionHandling.java new file mode 100644 index 0000000..e851ba1 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestExceptionHandling.java
@@ -0,0 +1,116 @@ +package org.codehaus.jackson.map.deser; + +import java.io.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.exc.UnrecognizedPropertyException; + +/** + * Unit test for verifying that exceptions are properly handled (caught, + * re-thrown or wrapped, depending) + * with Object deserialization. + */ +public class TestExceptionHandling + extends BaseMapTest +{ + static class Bean { + String x; + } + + /** + * Verification of [JACKSON-301] + */ + public void testHandlingOfUnrecognized() throws Exception + { + try { + new ObjectMapper().readValue("{\"bar\":3}", Bean.class); + fail("Should have failed binding"); + } catch (UnrecognizedPropertyException e) { + assertEquals("bar", e.getUnrecognizedPropertyName()); + assertEquals(Bean.class, e.getReferringClass()); + } + } + + /* + /********************************************************** + /* Test methods + /********************************************************** + */ + + /** + * Simple test to check behavior when end-of-stream is encountered + * without content. Should throw EOFException. + */ + public void testExceptionWithEmpty() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + try { + Object result = mapper.readValue(" ", Object.class); + fail("Expected an exception, but got result value: "+result); + } catch (Exception e) { + verifyException(e, EOFException.class, "No content"); + } + } + + public void testExceptionWithIncomplete() + throws Exception + { + BrokenStringReader r = new BrokenStringReader("[ 1, ", "TEST"); + JsonFactory f = new JsonFactory(); + JsonParser jp = f.createJsonParser(r); + ObjectMapper mapper = new ObjectMapper(); + try { + @SuppressWarnings("unused") + Object ob = mapper.readValue(jp, Object.class); + fail("Should have gotten an exception"); + } catch (IOException e) { + /* For "bona fide" IO problems (due to low-level problem, + * thrown by reader/stream), IOException must be thrown + */ + verifyException(e, IOException.class, "TEST"); + } + } + + public void testExceptionWithEOF() + throws Exception + { + StringReader r = new StringReader(" 3"); + JsonFactory f = new JsonFactory(); + JsonParser jp = f.createJsonParser(r); + ObjectMapper mapper = new ObjectMapper(); + + Integer I = mapper.readValue(jp, Integer.class); + assertEquals(3, I.intValue()); + + // and then end-of-input... + try { + I = mapper.readValue(jp, Integer.class); + fail("Should have gotten an exception"); + } catch (IOException e) { + verifyException(e, EOFException.class, "No content"); + } + // also: should have no current token after end-of-input + JsonToken t = jp.getCurrentToken(); + if (t != null) { + fail("Expected current token to be null after end-of-stream, was: "+t); + } + } + + /* + /********************************************************** + /* Helper methods + /********************************************************** + */ + + void verifyException(Exception e, Class<?> expType, String expMsg) + throws Exception + { + if (e.getClass() != expType) { + fail("Expected exception of type "+expType.getName()+", got "+e.getClass().getName()); + } + if (expMsg != null) { + verifyException(e, expMsg); + } + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/deser/TestFieldDeserialization.java b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestFieldDeserialization.java new file mode 100644 index 0000000..80a630b --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestFieldDeserialization.java
@@ -0,0 +1,163 @@ +package org.codehaus.jackson.map.deser; + +import org.codehaus.jackson.map.BaseMapTest; + +import org.codehaus.jackson.annotate.*; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.*; + +/** + * Unit tests for verifying that field-backed properties can also be + * deserialized (since version 1.1) as well as + * setter-accessible properties. + */ +public class TestFieldDeserialization + extends BaseMapTest +{ + /* + /********************************************************** + /* Annotated helper classes + /********************************************************** + */ + + static class SimpleFieldBean + { + public int x, y; + + // not auto-detectable, not public + int z; + + // ignored, not detectable either + @JsonIgnore public int a; + } + + static class SimpleFieldBean2 + { + @JsonDeserialize String[] values; + } + + @JsonAutoDetect(JsonMethod.SETTER) + static class NoAutoDetectBean + { + // not auto-detectable any more + public int z; + + @JsonProperty("z") + public int _z; + } + + // Let's test invalid bean too + static class DupFieldBean + { + public int z; + + @JsonProperty("z") + public int _z; + } + + public static class DupFieldBean2 + { + @JsonProperty("foo") + public int _z; + + @SuppressWarnings("unused") + @JsonDeserialize + private int foo; + } + + public static class OkDupFieldBean + extends SimpleFieldBean + { + @JsonProperty("x") + protected int myX = 10; + + public int y = 11; + } + + abstract static class Abstract { } + static class Concrete extends Abstract + { + String value; + + public Concrete(String v) { value = v; } + } + + static class AbstractWrapper { + @JsonDeserialize(as=Concrete.class) + public Abstract value; + } + + /* + /********************************************************** + /* Main tests + /********************************************************** + */ + + public void testSimpleAutoDetect() throws Exception + { + ObjectMapper m = new ObjectMapper(); + SimpleFieldBean result = m.readValue("{ \"x\" : -13 }", + SimpleFieldBean.class); + assertEquals(-13, result.x); + assertEquals(0, result.y); + } + + public void testSimpleAnnotation() throws Exception + { + ObjectMapper m = new ObjectMapper(); + SimpleFieldBean2 bean = m.readValue("{ \"values\" : [ \"x\", \"y\" ] }", + SimpleFieldBean2.class); + String[] values = bean.values; + assertNotNull(values); + assertEquals(2, values.length); + assertEquals("x", values[0]); + assertEquals("y", values[1]); + } + + public void testNoAutoDetect() throws Exception + { + ObjectMapper m = new ObjectMapper(); + NoAutoDetectBean bean = m.readValue("{ \"z\" : 7 }", + NoAutoDetectBean.class); + assertEquals(7, bean._z); + } + + public void testTypeAnnotation() throws Exception + { + ObjectMapper m = new ObjectMapper(); + AbstractWrapper w = m.readValue("{ \"value\" : \"abc\" }", + AbstractWrapper.class); + Abstract bean = w.value; + assertNotNull(bean); + assertEquals(Concrete.class, bean.getClass()); + assertEquals("abc", ((Concrete)bean).value); + } + + public void testFailureDueToDups() throws Exception + { + try { + writeAndMap(new ObjectMapper(), new DupFieldBean()); + } catch (JsonMappingException e) { + verifyException(e, "Multiple fields representing property"); + } + } + + public void testFailureDueToDups2() throws Exception + { + try { + writeAndMap(new ObjectMapper(), new DupFieldBean2()); + } catch (JsonMappingException e) { + verifyException(e, "Multiple fields representing property"); + } + } + + // For [JACKSON-226], acceptable field overrides + public void testOkFieldOverride() throws Exception + { + ObjectMapper m = new ObjectMapper(); + OkDupFieldBean result = m.readValue("{ \"x\" : 1, \"y\" : 2 }", + OkDupFieldBean.class); + assertEquals(1, result.myX); + assertEquals(2, result.y); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/deser/TestGenericCollectionDeser.java b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestGenericCollectionDeser.java new file mode 100644 index 0000000..701d7f6 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestGenericCollectionDeser.java
@@ -0,0 +1,83 @@ +package org.codehaus.jackson.map.deser; + +import org.codehaus.jackson.map.*; + +import java.util.*; + +import org.codehaus.jackson.map.annotate.JsonDeserialize; + +@SuppressWarnings("serial") +public class TestGenericCollectionDeser + extends BaseMapTest +{ + /* + /********************************************************** + /* Test classes, enums + /********************************************************** + */ + + static class ListSubClass extends ArrayList<StringWrapper> { } + + /** + * Map class that should behave like {@link MapSubClass}, but by + * using annotations. + */ + @JsonDeserialize(contentAs=StringWrapper.class) + static class AnnotatedStringList extends ArrayList<Object> { } + + @JsonDeserialize(contentAs=BooleanWrapper.class) + static class AnnotatedBooleanList extends ArrayList<Object> { } + + /* + /********************************************************** + /* Test methods + /********************************************************** + */ + + /* + /********************************************************** + /* Tests for sub-classing + /********************************************************** + */ + + /** + * Verifying that sub-classing works ok wrt generics information + */ + public void testListSubClass() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + ListSubClass result = mapper.readValue("[ \"123\" ]", ListSubClass.class); + assertEquals(1, result.size()); + Object value = result.get(0); + assertEquals(StringWrapper.class, value.getClass()); + StringWrapper bw = (StringWrapper) value; + assertEquals("123", bw.str); + } + + /* + /********************************************************** + /* Tests for annotations + /********************************************************** + */ + + // Verifying that sub-classing works ok wrt generics information + public void testAnnotatedLStringist() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + AnnotatedStringList result = mapper.readValue("[ \"...\" ]", AnnotatedStringList.class); + assertEquals(1, result.size()); + Object ob = result.get(0); + assertEquals(StringWrapper.class, ob.getClass()); + assertEquals("...", ((StringWrapper) ob).str); + } + + public void testAnnotatedBooleanList() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + AnnotatedBooleanList result = mapper.readValue("[ false ]", AnnotatedBooleanList.class); + assertEquals(1, result.size()); + Object ob = result.get(0); + assertEquals(BooleanWrapper.class, ob.getClass()); + assertFalse(((BooleanWrapper) ob).b); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/deser/TestGenericMapDeser.java b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestGenericMapDeser.java new file mode 100644 index 0000000..e422355 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestGenericMapDeser.java
@@ -0,0 +1,170 @@ +package org.codehaus.jackson.map.deser; + +import org.codehaus.jackson.map.*; + +import java.util.*; + +import org.codehaus.jackson.annotate.JsonCreator; +import org.codehaus.jackson.map.annotate.JsonDeserialize; +import org.codehaus.jackson.map.type.TypeFactory; + +@SuppressWarnings("serial") +public class TestGenericMapDeser + extends BaseMapTest +{ + /* + /********************************************************** + /* Test classes, enums + /********************************************************** + */ + + static class BooleanWrapper { + final Boolean b; + @JsonCreator BooleanWrapper(Boolean value) { b = value; } + } + + static class StringWrapper { + final String str; + @JsonCreator StringWrapper(String value) { + str = value; + } + } + + static class MapSubClass extends HashMap<String,BooleanWrapper> { } + + /** + * Map class that should behave like {@link MapSubClass}, but by + * using annotations. + */ + @JsonDeserialize(keyAs=StringWrapper.class, contentAs=BooleanWrapper.class) + static class AnnotatedMap extends HashMap<Object,Object> { } + + interface MapWrapper<K,V> extends java.io.Serializable { + public abstract Map<K,V> getEntries(); + } + + static class StringMap implements MapWrapper<String,Long> + { + private Map<String,Long> entries = new LinkedHashMap<String,Long>(); + + public StringMap() { } + + @Override + public Map<String,Long> getEntries() { return entries; } + } + + static class StringWrapperValueMap<KEY> extends HashMap<KEY,StringWrapper> { } + + static class StringStringWrapperMap extends StringWrapperValueMap<String> { } + + static class KeyTypeCtor { + protected String value; + public KeyTypeCtor(String v) { value = v; } + } + + static class KeyTypeFactory { + protected String value; + private KeyTypeFactory(String v, boolean foo) { value = v; } + + @JsonCreator + public static KeyTypeFactory create(String str) { + return new KeyTypeFactory(str, true); + } + } + + /* + /********************************************************** + /* Test methods for sub-classing + /********************************************************** + */ + + /** + * Verifying that sub-classing works ok wrt generics information + */ + public void testMapSubClass() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + MapSubClass result = mapper.readValue + ("{\"a\":true }", MapSubClass.class); + assertEquals(1, result.size()); + Object value = result.get("a"); + assertEquals(BooleanWrapper.class, value.getClass()); + BooleanWrapper bw = (BooleanWrapper) value; + assertEquals(Boolean.TRUE, bw.b); + } + + public void testMapWrapper() throws Exception + { + StringMap value = new ObjectMapper().readValue + ("{\"entries\":{\"a\":9} }", StringMap.class); + assertNotNull(value.getEntries()); + assertEquals(1, value.getEntries().size()); + assertEquals(Long.valueOf(9), value.getEntries().get("a")); + } + + public void testIntermediateTypes() throws Exception + { + StringStringWrapperMap result = new ObjectMapper().readValue + ("{\"a\":\"b\"}", StringStringWrapperMap.class); + assertEquals(1, result.size()); + Object value = result.get("a"); + assertNotNull(value); + assertEquals(value.getClass(), StringWrapper.class); + assertEquals("b", ((StringWrapper) value).str); + } + + /* + /********************************************************** + /* Test methods for sub-classing for annotation handling + /********************************************************** + */ + + /** + * Verifying that sub-classing works ok wrt generics information + */ + public void testAnnotatedMap() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + AnnotatedMap result = mapper.readValue + ("{\"a\":true }", AnnotatedMap.class); + assertEquals(1, result.size()); + Map.Entry<Object,Object> en = result.entrySet().iterator().next(); + assertEquals(StringWrapper.class, en.getKey().getClass()); + assertEquals(BooleanWrapper.class, en.getValue().getClass()); + assertEquals("a", ((StringWrapper) en.getKey()).str); + assertEquals(Boolean.TRUE, ((BooleanWrapper) en.getValue()).b); + } + + /* + /********************************************************** + /* Test methods for ensuring @JsonCreator works for keys + /********************************************************** + */ + + public void testKeyViaCtor() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + Map<KeyTypeCtor,Integer> map = mapper.readValue("{\"a\":123}", + TypeFactory.defaultInstance().constructMapType(HashMap.class, KeyTypeCtor.class, Integer.class)); + assertEquals(1, map.size()); + Map.Entry<?,?> entry = map.entrySet().iterator().next(); + assertEquals(Integer.valueOf(123), entry.getValue()); + Object key = entry.getKey(); + assertEquals(KeyTypeCtor.class, key.getClass()); + assertEquals("a", ((KeyTypeCtor) key).value); + } + + public void testKeyViaFactory() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + Map<KeyTypeCtor,Integer> map = mapper.readValue("{\"a\":123}", + TypeFactory.defaultInstance().constructMapType(HashMap.class, KeyTypeFactory.class, Integer.class)); + assertEquals(1, map.size()); + Map.Entry<?,?> entry = map.entrySet().iterator().next(); + assertEquals(Integer.valueOf(123), entry.getValue()); + Object key = entry.getKey(); + assertEquals(KeyTypeFactory.class, key.getClass()); + assertEquals("a", ((KeyTypeFactory) key).value); + } + +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/deser/TestGenericNumber.java b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestGenericNumber.java new file mode 100644 index 0000000..65d9947 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestGenericNumber.java
@@ -0,0 +1,114 @@ +package org.codehaus.jackson.map.deser; + +import java.io.*; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.*; + +import org.codehaus.jackson.map.*; + +/** + * Unit tests for verifying handling of non-specific numeric types. + */ +public class TestGenericNumber + extends BaseMapTest +{ + public void testIntAsNumber() throws Exception + { + /* Even if declared as 'generic' type, should return using most + * efficient type... here, Integer + */ + Number result = new ObjectMapper().readValue(new StringReader(" 123 "), Number.class); + assertEquals(Integer.valueOf(123), result); + } + + public void testLongAsNumber() throws Exception + { + // And beyond int range, should get long + long exp = 1234567890123L; + Number result = new ObjectMapper().readValue(String.valueOf(exp), Number.class); + assertEquals(Long.valueOf(exp), result); + } + + public void testBigIntAsNumber() throws Exception + { + // and after long, BigInteger + BigInteger biggie = new BigInteger("1234567890123456789012345678901234567890"); + Number result = new ObjectMapper().readValue(biggie.toString(), Number.class); + assertEquals(BigInteger.class, biggie.getClass()); + assertEquals(biggie, result); + } + + public void testIntTypeOverride() throws Exception + { + /* Slight twist; as per [JACKSON-100], can also request binding + * to BigInteger even if value would fit in Integer + */ + ObjectMapper m = new ObjectMapper(); + m.enable(DeserializationConfig.Feature.USE_BIG_INTEGER_FOR_INTS); + BigInteger exp = BigInteger.valueOf(123L); + + // first test as any Number + Number result = m.readValue(new StringReader(" 123 "), Number.class); + assertEquals(BigInteger.class, result.getClass()); + assertEquals(exp, result); + + // then as any Object + /*Object value =*/ m.readValue(new StringReader("123"), Object.class); + assertEquals(BigInteger.class, result.getClass()); + assertEquals(exp, result); + } + + /** + * Related to [JACKSON-72]: by default should wrap floating-point + * Number as Double + */ + public void testDoubleAsNumber() throws Exception + { + Number result = new ObjectMapper().readValue(new StringReader(" 1.0 "), Number.class); + assertEquals(Double.valueOf(1.0), result); + } + + /** + * Test for verifying [JACKSON-72]. + */ + public void testFpTypeOverrideSimple() throws Exception + { + ObjectMapper m = new ObjectMapper(); + m.enable(DeserializationConfig.Feature.USE_BIG_DECIMAL_FOR_FLOATS); + BigDecimal dec = new BigDecimal("0.1"); + + // First test generic stand-alone Number + Number result = m.readValue(dec.toString(), Number.class); + assertEquals(BigDecimal.class, result.getClass()); + assertEquals(dec, result); + + // Then plain old Object + Object value = m.readValue(dec.toString(), Object.class); + assertEquals(BigDecimal.class, result.getClass()); + assertEquals(dec, value); + } + + public void testFpTypeOverrideStructured() throws Exception + { + ObjectMapper m = new ObjectMapper(); + BigDecimal dec = new BigDecimal("-19.37"); + + m.enable(DeserializationConfig.Feature.USE_BIG_DECIMAL_FOR_FLOATS); + + // List element types + @SuppressWarnings("unchecked") + List<Object> list = (List<Object>)m.readValue("[ "+dec.toString()+" ]", List.class); + assertEquals(1, list.size()); + Object val = list.get(0); + assertEquals(BigDecimal.class, val.getClass()); + assertEquals(dec, val); + + // and a map + Map<?,?> map = m.readValue("{ \"a\" : "+dec.toString()+" }", Map.class); + assertEquals(1, map.size()); + val = map.get("a"); + assertEquals(BigDecimal.class, val.getClass()); + assertEquals(dec, val); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/deser/TestGenericSubTyping.java b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestGenericSubTyping.java new file mode 100644 index 0000000..bea268d --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestGenericSubTyping.java
@@ -0,0 +1,45 @@ +package org.codehaus.jackson.map.deser; + +import java.util.List; + +import org.codehaus.jackson.annotate.JsonProperty; +import org.codehaus.jackson.type.TypeReference; + +import org.codehaus.jackson.map.*; + +public class TestGenericSubTyping extends BaseMapTest +{ + // Types for [JACKSON-778] + + static class Document {} + static class Row {} + static class RowWithDoc<D extends Document> extends Row { + @JsonProperty("d") D d; + } + static class ResultSet<R extends Row> { + @JsonProperty("rows") List<R> rows; + } + static class ResultSetWithDoc<D extends Document> extends ResultSet<RowWithDoc<D>> {} + + static class MyDoc extends Document {} + + /* + /******************************************************* + /* Unit tests + /******************************************************* + */ + + public void testIssue778() throws Exception + { + final ObjectMapper mapper = new ObjectMapper(); + String json = "{\"rows\":[{\"d\":{}}]}"; + + final TypeReference<?> type = new TypeReference<ResultSetWithDoc<MyDoc>>() {}; + + // type passed is correct, but somehow it gets mangled when passed... + ResultSetWithDoc<MyDoc> rs = mapper.readValue(json, type); + Document d = rs.rows.iterator().next().d; + + assertEquals(MyDoc.class, d.getClass()); //expected MyDoc but was Document + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/deser/TestGenerics.java b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestGenerics.java new file mode 100644 index 0000000..afc6676 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestGenerics.java
@@ -0,0 +1,123 @@ +package org.codehaus.jackson.map.deser; + +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.type.TypeReference; + +public class TestGenerics + extends BaseMapTest +{ + static abstract class BaseNumberBean<T extends Number> + { + public abstract void setNumber(T value); + } + + static class NumberBean + extends BaseNumberBean<Long> + { + long _number; + + @Override + public void setNumber(Long value) + { + _number = value.intValue(); + } + } + + /** + * Very simple bean class + */ + static class SimpleBean + { + public int x; + } + + static class Wrapper<T> + { + public T value; + + public Wrapper() { } + + public Wrapper(T v) { value = v; } + + @Override + public boolean equals(Object o) { + return (o instanceof Wrapper<?>) && (((Wrapper<?>) o).value.equals(value)); + } + } + + /* + /*************************************************** + /* Test cases + /*************************************************** + */ + + public void testSimpleNumberBean() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + NumberBean result = mapper.readValue("{\"number\":17}", NumberBean.class); + assertEquals(17, result._number); + } + + /** + * Unit test for verifying fix to [JACKSON-109]. + */ + public void testGenericWrapper() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + Wrapper<SimpleBean> result = mapper.readValue + ("{\"value\": { \"x\" : 13 } }", + new TypeReference<Wrapper<SimpleBean>>() { }); + assertNotNull(result); + assertEquals(Wrapper.class, result.getClass()); + Object contents = result.value; + assertNotNull(contents); + assertEquals(SimpleBean.class, contents.getClass()); + SimpleBean bean = (SimpleBean) contents; + assertEquals(13, bean.x); + } + + /** + * Unit test for verifying that we can use different + * type bindings for individual generic types; + * problem with [JACKSON-190] + */ + public void testMultipleWrappers() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + + // First, numeric wrapper + Wrapper<Boolean> result = mapper.readValue + ("{\"value\": true}", new TypeReference<Wrapper<Boolean>>() { }); + assertEquals(new Wrapper<Boolean>(Boolean.TRUE), result); + + // Then string one + Wrapper<String> result2 = mapper.readValue + ("{\"value\": \"abc\"}", new TypeReference<Wrapper<String>>() { }); + assertEquals(new Wrapper<String>("abc"), result2); + + // And then number + Wrapper<Long> result3 = mapper.readValue + ("{\"value\": 7}", new TypeReference<Wrapper<Long>>() { }); + assertEquals(new Wrapper<Long>(7L), result3); + } + + /** + * Unit test for verifying fix to [JACKSON-109]. + */ + public void testArrayOfGenericWrappers() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + Wrapper<SimpleBean>[] result = mapper.readValue + ("[ {\"value\": { \"x\" : 9 } } ]", + new TypeReference<Wrapper<SimpleBean>[]>() { }); + assertNotNull(result); + assertEquals(Wrapper[].class, result.getClass()); + assertEquals(1, result.length); + Wrapper<SimpleBean> elem = result[0]; + Object contents = elem.value; + assertNotNull(contents); + assertEquals(SimpleBean.class, contents.getClass()); + SimpleBean bean = (SimpleBean) contents; + assertEquals(9, bean.x); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/deser/TestGenericsBounded.java b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestGenericsBounded.java new file mode 100644 index 0000000..5dc81aa --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestGenericsBounded.java
@@ -0,0 +1,98 @@ +package org.codehaus.jackson.map.deser; + +import java.util.*; + +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.type.TypeReference; + +import java.io.Serializable; + +public class TestGenericsBounded + extends BaseMapTest +{ + /* + /******************************************************* + /* Helper types + /******************************************************* + */ + + @SuppressWarnings("serial") + static class Range<E extends Comparable<E>> implements Serializable + { + protected E start, end; + + public Range(){ } + public Range(E start, E end) { + this.start = start; + this.end = end; + } + + public E getEnd() { return end; } + public void setEnd(E e) { end = e; } + + public E getStart() { return start; } + public void setStart(E s) { + start = s; + } + } + + @SuppressWarnings("serial") + static class DoubleRange extends Range<Double> { + public DoubleRange() { } + public DoubleRange(Double s, Double e) { super(s, e); } + } + + static class BoundedWrapper<A extends Serializable> + { + public List<A> values; + } + + @SuppressWarnings("serial") + static class IntBean implements Serializable + { + public int x; + } + + static class IntBeanWrapper<T extends IntBean> { + public T wrapped; + } + + /* + /******************************************************* + /* Unit tests + /******************************************************* + */ + + public void testLowerBound() throws Exception + { + IntBeanWrapper<?> result = new ObjectMapper().readValue("{\"wrapped\":{\"x\":3}}", + IntBeanWrapper.class); + assertNotNull(result); + assertEquals(IntBean.class, result.wrapped.getClass()); + assertEquals(3, result.wrapped.x); + } + + // Test related to type bound handling problem within [JACKSON-190] + public void testBounded() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + BoundedWrapper<IntBean> result = mapper.readValue + ("{\"values\":[ {\"x\":3} ] } ", new TypeReference<BoundedWrapper<IntBean>>() {}); + List<?> list = result.values; + assertEquals(1, list.size()); + Object ob = list.get(0); + assertEquals(IntBean.class, ob.getClass()); + assertEquals(3, result.values.get(0).x); + } + + public void testGenericsComplex() throws Exception + { + ObjectMapper m = new ObjectMapper(); + DoubleRange in = new DoubleRange(-0.5, 0.5); + String json = m.writeValueAsString(in); + DoubleRange out = m.readValue(json, DoubleRange.class); + assertNotNull(out); + assertEquals(-0.5, out.start); + assertEquals(0.5, out.end); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/deser/TestIgnoredTypes.java b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestIgnoredTypes.java new file mode 100644 index 0000000..b59b1e4 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestIgnoredTypes.java
@@ -0,0 +1,48 @@ +package org.codehaus.jackson.map.deser; + +import org.codehaus.jackson.annotate.JsonIgnoreType; +import org.codehaus.jackson.map.*; + +/** + * Test for [JACKSON-429] + */ +public class TestIgnoredTypes extends BaseMapTest +{ + /* + /********************************************************** + /* Annotated helper classes + /********************************************************** + */ + + @JsonIgnoreType + class IgnoredType { // note: non-static, can't be deserializer + public IgnoredType(IgnoredType src) { } + } + + @JsonIgnoreType(false) + static class NonIgnoredType + { + public int value = 13; + public IgnoredType ignored; + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + public void testIgnoredType() throws Exception + { + // First: should be ok in general, even though couldn't build deserializer (due to non-static inner class): + ObjectMapper mapper = new ObjectMapper(); + NonIgnoredType bean = mapper.readValue("{\"value\":13}", NonIgnoredType.class); + assertNotNull(bean); + assertEquals(13, bean.value); + + // And also ok to see something with that value; will just get ignored + bean = mapper.readValue("{ \"ignored\":[1,2,{}], \"value\":9 }", NonIgnoredType.class); + assertNotNull(bean); + assertEquals(9, bean.value); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/deser/TestInjectables.java b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestInjectables.java new file mode 100644 index 0000000..76963cd --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestInjectables.java
@@ -0,0 +1,119 @@ +package org.codehaus.jackson.map.deser; + +import org.codehaus.jackson.annotate.JsonProperty; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.JacksonInject; + +// @since 1.9 +public class TestInjectables extends BaseMapTest +{ + static class InjectedBean + { + @JacksonInject + protected String stuff; + + @JacksonInject("myId") + protected String otherStuff; + + protected long third; + + public int value; + + @JacksonInject + public void injectThird(long v) { + third = v; + } + } + + static class BadBean1 { + @JacksonInject protected String prop1; + @JacksonInject protected String prop2; + } + + static class BadBean2 { + @JacksonInject("x") protected String prop1; + @JacksonInject("x") protected String prop2; + } + + static class CtorBean { + protected String name; + protected int age; + + public CtorBean(@JacksonInject String n, @JsonProperty("age") int a) + { + name = n; + age = a; + } + } + + static class CtorBean2 { + protected String name; + protected Integer age; + + public CtorBean2(@JacksonInject String n, @JacksonInject("number") Integer a) + { + name = n; + age = a; + } + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + public void testSimple() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.setInjectableValues(new InjectableValues.Std() + .addValue(String.class, "stuffValue") + .addValue("myId", "xyz") + .addValue(Long.TYPE, Long.valueOf(37)) + ); + InjectedBean bean = mapper.readValue("{\"value\":3}", InjectedBean.class); + assertEquals(3, bean.value); + assertEquals("stuffValue", bean.stuff); + assertEquals("xyz", bean.otherStuff); + assertEquals(37L, bean.third); + } + + public void testWithCtors() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.setInjectableValues(new InjectableValues.Std() + .addValue(String.class, "Bubba") + ); + CtorBean bean = mapper.readValue("{\"age\":55}", CtorBean.class); + assertEquals(55, bean.age); + assertEquals("Bubba", bean.name); + } + + // [Issue-13] + public void testTwoInjectablesViaCreator() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.setInjectableValues(new InjectableValues.Std() + .addValue(String.class, "Bob") + .addValue("number", Integer.valueOf(13)) + ); + CtorBean2 bean = mapper.readValue("{ }", CtorBean2.class); + assertEquals(Integer.valueOf(13), bean.age); + assertEquals("Bob", bean.name); + } + + public void testInvalidDup() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + try { + mapper.readValue("{}", BadBean1.class); + } catch (Exception e) { + verifyException(e, "Duplicate injectable value"); + } + try { + mapper.readValue("{}", BadBean2.class); + } catch (Exception e) { + verifyException(e, "Duplicate injectable value"); + } + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/deser/TestInnerClass.java b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestInnerClass.java new file mode 100644 index 0000000..8b4fa6a --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestInnerClass.java
@@ -0,0 +1,56 @@ +package org.codehaus.jackson.map.deser; + +import org.codehaus.jackson.map.*; + +public class TestInnerClass extends BaseMapTest +{ + /* + /********************************************************** + /* Value classes + /********************************************************** + */ + + // [JACKSON-594] + static class Dog + { + public String name; + public Brain brain; + + public Dog() { } + public Dog(String n, boolean thinking) { + name = n; + brain = new Brain(); + brain.isThinking = thinking; + } + + // note: non-static + public class Brain { + public boolean isThinking; + + public String parentName() { return name; } + } + } + + /* + /********************************************************** + /* Tests + /********************************************************** + */ + + public void testSimpleNonStaticInner() throws Exception + { + // Let's actually verify by first serializing, then deserializing back + ObjectMapper mapper = new ObjectMapper(); + Dog input = new Dog("Smurf", true); + String json = mapper.writeValueAsString(input); +//System.out.println("JSON = "+json); + Dog output = mapper.readValue(json, Dog.class); + assertEquals("Smurf", output.name); + assertNotNull(output.brain); + assertTrue(output.brain.isThinking); + // and verify correct binding... + assertEquals("Smurf", output.brain.parentName()); + output.name = "Foo"; + assertEquals("Foo", output.brain.parentName()); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/deser/TestJacksonTypes.java b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestJacksonTypes.java new file mode 100644 index 0000000..b2dc590 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestJacksonTypes.java
@@ -0,0 +1,108 @@ +package org.codehaus.jackson.map.deser; + +import java.util.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.type.TypeFactory; +import org.codehaus.jackson.type.JavaType; +import org.codehaus.jackson.util.TokenBuffer; + +/** + * Unit tests for those Jackson types we want to ensure can be deserialized. + */ +public class TestJacksonTypes + extends org.codehaus.jackson.map.BaseMapTest +{ + public void testJsonLocation() throws Exception + { + ObjectMapper m = new ObjectMapper(); + // note: source reference is untyped, only String guaranteed to work + JsonLocation loc = new JsonLocation("whatever", -1, -1, 100, 13); + // Let's use serializer here; goal is round-tripping + String ser = serializeAsString(m, loc); + JsonLocation result = m.readValue(ser, JsonLocation.class); + assertEquals("Did not correctly deserialize standard serialization '"+ser+"'", + loc, result); + } + + // doesn't really belong here but... + public void testJsonLocationProps() + { + JsonLocation loc = new JsonLocation(null, -1, -1, 100, 13); + assertTrue(loc.equals(loc)); + assertFalse(loc.equals(null)); + assertFalse(loc.equals("abx")); + + // should we check it's not 0? + loc.hashCode(); + } + + /** + * Verify that {@link TokenBuffer} can be properly deserialized + * automatically, using the "standard" JSON sample document + * + * @since 1.5 + */ + public void testTokenBufferWithSample() throws Exception + { + ObjectMapper m = new ObjectMapper(); + // First, try standard sample doc: + TokenBuffer result = m.readValue(SAMPLE_DOC_JSON_SPEC, TokenBuffer.class); + verifyJsonSpecSampleDoc(result.asParser(), true); + } + + public void testTokenBufferWithSequence() throws Exception + { + ObjectMapper m = new ObjectMapper(); + // and then sequence of other things + JsonParser jp = createParserUsingReader("[ 32, [ 1 ], \"abc\", { \"a\" : true } ]"); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + TokenBuffer buf = m.readValue(jp, TokenBuffer.class); + + // check manually... + JsonParser bufParser = buf.asParser(); + assertToken(JsonToken.VALUE_NUMBER_INT, bufParser.nextToken()); + assertEquals(32, bufParser.getIntValue()); + assertNull(bufParser.nextToken()); + + // then bind to another + buf = m.readValue(jp, TokenBuffer.class); + bufParser = buf.asParser(); + assertToken(JsonToken.START_ARRAY, bufParser.nextToken()); + assertToken(JsonToken.VALUE_NUMBER_INT, bufParser.nextToken()); + assertEquals(1, bufParser.getIntValue()); + assertToken(JsonToken.END_ARRAY, bufParser.nextToken()); + assertNull(bufParser.nextToken()); + + // third one, with automatic binding + buf = m.readValue(jp, TokenBuffer.class); + String str = m.readValue(buf.asParser(), String.class); + assertEquals("abc", str); + + // and ditto for last one + buf = m.readValue(jp, TokenBuffer.class); + Map<?,?> map = m.readValue(buf.asParser(), Map.class); + assertEquals(1, map.size()); + assertEquals(Boolean.TRUE, map.get("a")); + + assertEquals(JsonToken.END_ARRAY, jp.nextToken()); + assertNull(jp.nextToken()); + } + + // @since 1.9 + public void testJavaType() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + TypeFactory tf = TypeFactory.defaultInstance(); + // first simple type: + String json = mapper.writeValueAsString(tf.constructType(String.class)); + assertEquals(quote(java.lang.String.class.getName()), json); + // and back + JavaType t = mapper.readValue(json, JavaType.class); + assertNotNull(t); + assertEquals(String.class, t.getRawClass()); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/deser/TestJdkTypes.java b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestJdkTypes.java new file mode 100644 index 0000000..447a377 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestJdkTypes.java
@@ -0,0 +1,328 @@ +package org.codehaus.jackson.map.deser; + +import java.io.*; +import java.net.*; +import java.nio.charset.Charset; +import java.util.Currency; +import java.util.List; +import java.util.Locale; +import java.util.regex.Pattern; + +import org.codehaus.jackson.annotate.JsonCreator; +import org.codehaus.jackson.annotate.JsonProperty; +import org.codehaus.jackson.map.*; + +public class TestJdkTypes + extends org.codehaus.jackson.map.BaseMapTest +{ + static class PrimitivesBean + { + public boolean booleanValue = true; + public byte byteValue = 3; + public char charValue = 'a'; + public short shortValue = 37; + public int intValue = 1; + public long longValue = 100L; + public float floatValue = 0.25f; + public double doubleValue = -1.0; + } + + // for [JACKSON-616] + static class WrappersBean + { + public Boolean booleanValue; + public Byte byteValue; + public Character charValue; + public Short shortValue; + public Integer intValue; + public Long longValue; + public Float floatValue; + public Double doubleValue; + } + + + static class ParamClassBean + { + public String name = "bar"; + public Class<String> clazz ; + + public ParamClassBean() { } + public ParamClassBean(String name) { + this.name = name; + clazz = String.class; + } + } + + static class BooleanBean { + public Boolean wrapper; + public boolean primitive; + + protected Boolean ctor; + + @JsonCreator + public BooleanBean(@JsonProperty("ctor") Boolean foo) { + ctor = foo; + } + } + + /* + /********************************************************** + /* Test methods + /********************************************************** + */ + + private final ObjectMapper mapper = new ObjectMapper(); + + /** + * Related to issue [JACKSON-155]. + */ + public void testFile() throws Exception + { + // Not portable etc... has to do: + File src = new File("/test").getAbsoluteFile(); + File result = mapper.readValue("\""+src.getAbsolutePath()+"\"", File.class); + assertEquals(src.getAbsolutePath(), result.getAbsolutePath()); + } + + public void testRegexps() throws IOException + { + final String PATTERN_STR = "abc:\\s?(\\d+)"; + Pattern exp = Pattern.compile(PATTERN_STR); + /* Ok: easiest way is to just serialize first; problem + * is the backslash + */ + String json = mapper.writeValueAsString(exp); + Pattern result = mapper.readValue(json, Pattern.class); + assertEquals(exp.pattern(), result.pattern()); + } + + public void testCurrency() throws IOException + { + Currency usd = Currency.getInstance("USD"); + assertEquals(usd, new ObjectMapper().readValue(quote("USD"), Currency.class)); + } + + /** + * Test for [JACKSON-419] + * + * @since 1.7 + */ + public void testLocale() throws IOException + { + assertEquals(new Locale("en"), mapper.readValue(quote("en"), Locale.class)); + assertEquals(new Locale("es", "ES"), mapper.readValue(quote("es_ES"), Locale.class)); + assertEquals(new Locale("FI", "fi", "savo"), mapper.readValue(quote("fi_FI_savo"), Locale.class)); + } + + /** + * Test for [JACKSON-420] (add DeserializationConfig.FAIL_ON_NULL_FOR_PRIMITIVES) + * + * @since 1.7 + */ + public void testNullForPrimitives() throws IOException + { + // by default, ok to rely on defaults + PrimitivesBean bean = mapper.readValue("{\"intValue\":null, \"booleanValue\":null, \"doubleValue\":null}", + PrimitivesBean.class); + assertNotNull(bean); + assertEquals(0, bean.intValue); + assertEquals(false, bean.booleanValue); + assertEquals(0.0, bean.doubleValue); + + bean = mapper.readValue("{\"byteValue\":null, \"longValue\":null, \"floatValue\":null}", + PrimitivesBean.class); + assertNotNull(bean); + assertEquals((byte) 0, bean.byteValue); + assertEquals(0L, bean.longValue); + assertEquals(0.0f, bean.floatValue); + + // but not when enabled + final ObjectMapper mapper2 = new ObjectMapper(); + mapper2.configure(DeserializationConfig.Feature.FAIL_ON_NULL_FOR_PRIMITIVES, true); + + // boolean + try { + mapper2.readValue("{\"booleanValue\":null}", PrimitivesBean.class); + fail("Expected failure for boolean + null"); + } catch (JsonMappingException e) { + verifyException(e, "Can not map JSON null into type boolean"); + } + // byte/char/short/int/long + try { + mapper2.readValue("{\"byteValue\":null}", PrimitivesBean.class); + fail("Expected failure for byte + null"); + } catch (JsonMappingException e) { + verifyException(e, "Can not map JSON null into type byte"); + } + try { + mapper2.readValue("{\"charValue\":null}", PrimitivesBean.class); + fail("Expected failure for char + null"); + } catch (JsonMappingException e) { + verifyException(e, "Can not map JSON null into type char"); + } + try { + mapper2.readValue("{\"shortValue\":null}", PrimitivesBean.class); + fail("Expected failure for short + null"); + } catch (JsonMappingException e) { + verifyException(e, "Can not map JSON null into type short"); + } + try { + mapper2.readValue("{\"intValue\":null}", PrimitivesBean.class); + fail("Expected failure for int + null"); + } catch (JsonMappingException e) { + verifyException(e, "Can not map JSON null into type int"); + } + try { + mapper2.readValue("{\"longValue\":null}", PrimitivesBean.class); + fail("Expected failure for long + null"); + } catch (JsonMappingException e) { + verifyException(e, "Can not map JSON null into type long"); + } + + // float/double + try { + mapper2.readValue("{\"floatValue\":null}", PrimitivesBean.class); + fail("Expected failure for float + null"); + } catch (JsonMappingException e) { + verifyException(e, "Can not map JSON null into type float"); + } + try { + mapper2.readValue("{\"doubleValue\":null}", PrimitivesBean.class); + fail("Expected failure for double + null"); + } catch (JsonMappingException e) { + verifyException(e, "Can not map JSON null into type double"); + } + } + + /** + * Test for [JACKSON-483], allow handling of CharSequence + */ + public void testCharSequence() throws IOException + { + CharSequence cs = mapper.readValue("\"abc\"", CharSequence.class); + assertEquals(String.class, cs.getClass()); + assertEquals("abc", cs.toString()); + } + + // [JACKSON-484] + public void testInetAddress() throws IOException + { + InetAddress address = mapper.readValue(quote("127.0.0.1"), InetAddress.class); + assertEquals("127.0.0.1", address.getHostAddress()); + + // should we try resolving host names? That requires connectivity... + final String HOST = "www.ning.com"; + address = mapper.readValue(quote(HOST), InetAddress.class); + assertEquals(HOST, address.getHostName()); + } + + // [JACKSON-597] + public void testClass() throws IOException + { + ObjectMapper mapper = new ObjectMapper(); + assertSame(String.class, mapper.readValue(quote("java.lang.String"), Class.class)); + + // then primitive types + assertSame(Boolean.TYPE, mapper.readValue(quote("boolean"), Class.class)); + assertSame(Byte.TYPE, mapper.readValue(quote("byte"), Class.class)); + assertSame(Short.TYPE, mapper.readValue(quote("short"), Class.class)); + assertSame(Character.TYPE, mapper.readValue(quote("char"), Class.class)); + assertSame(Integer.TYPE, mapper.readValue(quote("int"), Class.class)); + assertSame(Long.TYPE, mapper.readValue(quote("long"), Class.class)); + assertSame(Float.TYPE, mapper.readValue(quote("float"), Class.class)); + assertSame(Double.TYPE, mapper.readValue(quote("double"), Class.class)); + assertSame(Void.TYPE, mapper.readValue(quote("void"), Class.class)); + } + + // [JACKSON-605] + public void testClassWithParams() throws IOException + { + String json = mapper.writeValueAsString(new ParamClassBean("Foobar")); + + ParamClassBean result = mapper.readValue(json, ParamClassBean.class); + assertEquals("Foobar", result.name); + assertSame(String.class, result.clazz); + } + + // by default, should return nulls, n'est pas? + public void testEmptyStringForWrappers() throws IOException + { + WrappersBean bean; + + // by default, ok to rely on defaults + bean = mapper.readValue("{\"booleanValue\":\"\"}", WrappersBean.class); + assertNull(bean.booleanValue); + bean = mapper.readValue("{\"byteValue\":\"\"}", WrappersBean.class); + assertNull(bean.byteValue); + + // char/Character is different... not sure if this should work or not: + bean = mapper.readValue("{\"charValue\":\"\"}", WrappersBean.class); + assertNull(bean.charValue); + + bean = mapper.readValue("{\"shortValue\":\"\"}", WrappersBean.class); + assertNull(bean.shortValue); + bean = mapper.readValue("{\"intValue\":\"\"}", WrappersBean.class); + assertNull(bean.intValue); + bean = mapper.readValue("{\"longValue\":\"\"}", WrappersBean.class); + assertNull(bean.longValue); + bean = mapper.readValue("{\"floatValue\":\"\"}", WrappersBean.class); + assertNull(bean.floatValue); + bean = mapper.readValue("{\"doubleValue\":\"\"}", WrappersBean.class); + assertNull(bean.doubleValue); + } + + // for [JACKSON-616] + // @since 1.9 + public void testEmptyStringForPrimitives() throws IOException + { + PrimitivesBean bean; + bean = mapper.readValue("{\"booleanValue\":\"\"}", PrimitivesBean.class); + assertFalse(bean.booleanValue); + bean = mapper.readValue("{\"byteValue\":\"\"}", PrimitivesBean.class); + assertEquals((byte) 0, bean.byteValue); + bean = mapper.readValue("{\"charValue\":\"\"}", PrimitivesBean.class); + assertEquals((char) 0, bean.charValue); + bean = mapper.readValue("{\"shortValue\":\"\"}", PrimitivesBean.class); + assertEquals((short) 0, bean.shortValue); + bean = mapper.readValue("{\"intValue\":\"\"}", PrimitivesBean.class); + assertEquals(0, bean.intValue); + bean = mapper.readValue("{\"longValue\":\"\"}", PrimitivesBean.class); + assertEquals(0L, bean.longValue); + bean = mapper.readValue("{\"floatValue\":\"\"}", PrimitivesBean.class); + assertEquals(0.0f, bean.floatValue); + bean = mapper.readValue("{\"doubleValue\":\"\"}", PrimitivesBean.class); + assertEquals(0.0, bean.doubleValue); + } + + // for [JACKSON-652] + // @since 1.9 + public void testUntypedWithJsonArrays() throws Exception + { + // by default we get: + Object ob = mapper.readValue("[1]", Object.class); + assertTrue(ob instanceof List<?>); + + // but can change to produce Object[]: + mapper.configure(DeserializationConfig.Feature.USE_JAVA_ARRAY_FOR_JSON_ARRAY, true); + ob = mapper.readValue("[1]", Object.class); + assertEquals(Object[].class, ob.getClass()); + } + + // Test for verifying that Long values are coerced to boolean correctly as well + public void testLongToBoolean() throws Exception + { + long value = 1L + Integer.MAX_VALUE; + BooleanBean b = mapper.readValue("{\"primitive\" : "+value+", \"wrapper\":"+value+", \"ctor\":"+value+"}", + BooleanBean.class); + assertEquals(Boolean.TRUE, b.wrapper); + assertTrue(b.primitive); + assertEquals(Boolean.TRUE, b.ctor); + } + + // [JACKSON-789] + public void testCharset() throws Exception + { + Charset UTF8 = Charset.forName("UTF-8"); + assertSame(UTF8, mapper.readValue(quote("UTF-8"), Charset.class)); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/deser/TestMapDeserialization.java b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestMapDeserialization.java new file mode 100644 index 0000000..0e99fa2 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestMapDeserialization.java
@@ -0,0 +1,425 @@ +package org.codehaus.jackson.map.deser; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.JsonDeserialize; +import org.codehaus.jackson.map.deser.std.StdDeserializer; + +import java.io.IOException; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.*; + +import org.codehaus.jackson.type.TypeReference; + +public class TestMapDeserialization + extends BaseMapTest +{ + /* + /********************************************************** + /* Test classes, enums + /********************************************************** + */ + + enum Key { + KEY1, KEY2, WHATEVER; + } + + @SuppressWarnings("serial") + static class BrokenMap + extends HashMap<Object,Object> + { + // No default ctor, nor @JsonCreators + public BrokenMap(boolean dummy) { super(); } + } + + @SuppressWarnings("serial") + @JsonDeserialize(using=MapDeserializer.class) + static class CustomMap extends LinkedHashMap<String,String> { } + + static class MapDeserializer extends StdDeserializer<CustomMap> + { + public MapDeserializer() { super(CustomMap.class); } + @Override + public CustomMap deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException + { + CustomMap result = new CustomMap(); + result.put("x", jp.getText()); + return result; + } + } + + /* + /********************************************************** + /* Test methods, untyped (Object valued) maps + /********************************************************** + */ + + public void testUntypedMap() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + // to get "untyped" default map-to-map, pass Object.class + String JSON = "{ \"foo\" : \"bar\", \"crazy\" : true, \"null\" : null }"; + + // Not a guaranteed cast theoretically, but will work: + @SuppressWarnings("unchecked") + Map<String,Object> result = (Map<String,Object>)mapper.readValue(JSON, Object.class); + assertNotNull(result); + assertTrue(result instanceof Map<?,?>); + + assertEquals(3, result.size()); + + assertEquals("bar", result.get("foo")); + assertEquals(Boolean.TRUE, result.get("crazy")); + assertNull(result.get("null")); + + // Plus, non existing: + assertNull(result.get("bar")); + assertNull(result.get(3)); + } + + /** + * Let's also try another way to express "gimme a Map" deserialization; + * this time by specifying a Map class, to reduce need to cast + */ + public void testUntypedMap2() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + // to get "untyped" default map-to-map, pass Object.class + String JSON = "{ \"a\" : \"x\" }"; + + @SuppressWarnings("unchecked") + HashMap<String,Object> result = /*(HashMap<String,Object>)*/ mapper.readValue(JSON, HashMap.class); + assertNotNull(result); + assertTrue(result instanceof Map<?,?>); + + assertEquals(1, result.size()); + + assertEquals("x", result.get("a")); + } + + /** + * Unit test for [JACKSON-185] + */ + public void testUntypedMap3() throws Exception + { + String JSON = "{\"a\":[{\"a\":\"b\"},\"value\"]}"; + ObjectMapper m = new ObjectMapper(); + Map<?,?> result = m.readValue(JSON, Map.class); + assertTrue(result instanceof Map<?,?>); + assertEquals(1, result.size()); + Object ob = result.get("a"); + assertNotNull(ob); + Collection<?> list = (Collection<?>)ob; + assertEquals(2, list.size()); + + JSON = "{ \"var1\":\"val1\", \"var2\":\"val2\", " + +"\"subvars\": [" + +" { \"subvar1\" : \"subvar2\", \"x\" : \"y\" }, " + +" { \"a\":1 } ]" + +" }" + ; + result = m.readValue(JSON, Map.class); + assertTrue(result instanceof Map<?,?>); + assertEquals(3, result.size()); + } + + private static final String UNTYPED_MAP_JSON = + "{ \"double\":42.0, \"string\":\"string\"," + +"\"boolean\":true, \"list\":[\"list0\"]," + +"\"null\":null }"; + + @SuppressWarnings("serial") + static class ObjectWrapperMap extends HashMap<String, ObjectWrapper> { } + + public void testSpecialMap() throws IOException + { + final ObjectMapper mapper = new ObjectMapper(); + final ObjectWrapperMap map = mapper.readValue(UNTYPED_MAP_JSON, ObjectWrapperMap.class); + _doTestUntyped(map); + } + + public void testGenericMap() throws IOException + { + final ObjectMapper mapper = new ObjectMapper(); + final Map<String, ObjectWrapper> map = mapper.readValue + (UNTYPED_MAP_JSON, + new TypeReference<Map<String, ObjectWrapper>>() { }); + _doTestUntyped(map); + } + + private void _doTestUntyped(final Map<String, ObjectWrapper> map) + { + assertEquals(Double.valueOf(42), map.get("double").getObject()); + assertEquals("string", map.get("string").getObject()); + assertEquals(Boolean.TRUE, map.get("boolean").getObject()); + assertEquals(Collections.singletonList("list0"), map.get("list").getObject()); + assertTrue(map.containsKey("null")); + assertNull(map.get("null")); + assertEquals(5, map.size()); + } + + // [JACKSON-620]: allow "" to mean 'null' for Maps + public void testFromEmptyString() throws Exception + { + ObjectMapper m = new ObjectMapper(); + m.configure(DeserializationConfig.Feature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true); + Map<?,?> result = m.readValue(quote(""), Map.class); + assertNull(result); + } + + /* + /********************************************************** + /* Test methods, typed maps + /********************************************************** + */ + + public void testExactStringIntMap() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + // to get typing, must use type reference + String JSON = "{ \"foo\" : 13, \"bar\" : -39, \n \"\" : 0 }"; + Map<String,Integer> result = mapper.readValue + (JSON, new TypeReference<HashMap<String,Integer>>() { }); + + assertNotNull(result); + assertEquals(HashMap.class, result.getClass()); + assertEquals(3, result.size()); + + assertEquals(Integer.valueOf(13), result.get("foo")); + assertEquals(Integer.valueOf(-39), result.get("bar")); + assertEquals(Integer.valueOf(0), result.get("")); + assertNull(result.get("foobar")); + assertNull(result.get(" ")); + } + + /** + * Let's also check that it is possible to do type conversions + * to allow use of non-String Map keys. + */ + public void testIntBooleanMap() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + // to get typing, must use type reference + String JSON = "{ \"1\" : true, \"-1\" : false }"; + Map<String,Integer> result = mapper.readValue + (JSON, new TypeReference<HashMap<Integer,Boolean>>() { }); + + assertNotNull(result); + assertEquals(HashMap.class, result.getClass()); + assertEquals(2, result.size()); + + assertEquals(Boolean.TRUE, result.get(Integer.valueOf(1))); + assertEquals(Boolean.FALSE, result.get(Integer.valueOf(-1))); + assertNull(result.get("foobar")); + assertNull(result.get(0)); + } + + public void testExactStringStringMap() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + // to get typing, must use type reference + String JSON = "{ \"a\" : \"b\" }"; + Map<String,Integer> result = mapper.readValue + (JSON, new TypeReference<TreeMap<String,String>>() { }); + + assertNotNull(result); + assertEquals(TreeMap.class, result.getClass()); + assertEquals(1, result.size()); + + assertEquals("b", result.get("a")); + assertNull(result.get("b")); + } + + /** + * Unit test that verifies that it's ok to have incomplete + * information about Map class itself, as long as it's something + * we good guess about: for example, <code>Map.Class</code> will + * be replaced by something like <code>HashMap.class</code>, + * if given. + */ + public void testGenericStringIntMap() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + // to get typing, must use type reference; but with abstract type + String JSON = "{ \"a\" : 1, \"b\" : 2, \"c\" : -99 }"; + Map<String,Integer> result = mapper.readValue + (JSON, new TypeReference<Map<String,Integer>>() { }); + assertNotNull(result); + assertTrue(result instanceof Map<?,?>); + assertEquals(3, result.size()); + + assertEquals(Integer.valueOf(-99), result.get("c")); + assertEquals(Integer.valueOf(2), result.get("b")); + assertEquals(Integer.valueOf(1), result.get("a")); + + assertNull(result.get("")); + } + + /* + /********************************************************** + /* Test methods, maps with enums + /********************************************************** + */ + + public void testEnumMap() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + String JSON = "{ \"KEY1\" : \"\", \"WHATEVER\" : null }"; + + // to get typing, must use type reference + EnumMap<Key,String> result = mapper.readValue + (JSON, new TypeReference<EnumMap<Key,String>>() { }); + + assertNotNull(result); + assertEquals(EnumMap.class, result.getClass()); + assertEquals(2, result.size()); + + assertEquals("", result.get(Key.KEY1)); + // null should be ok too... + assertTrue(result.containsKey(Key.WHATEVER)); + assertNull(result.get(Key.WHATEVER)); + + // plus we have nothing for this key + assertFalse(result.containsKey(Key.KEY2)); + assertNull(result.get(Key.KEY2)); + } + + public void testMapWithEnums() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + String JSON = "{ \"KEY2\" : \"WHATEVER\" }"; + + // to get typing, must use type reference + Map<Enum<?>,Enum<?>> result = mapper.readValue + (JSON, new TypeReference<Map<Key,Key>>() { }); + + assertNotNull(result); + assertTrue(result instanceof Map<?,?>); + assertEquals(1, result.size()); + + assertEquals(Key.WHATEVER, result.get(Key.KEY2)); + assertNull(result.get(Key.WHATEVER)); + assertNull(result.get(Key.KEY1)); + } + + /* + /********************************************************** + /* Test methods, maps with Date + /********************************************************** + */ + public void testDateMap() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + Date date1=new Date(123456000L); + DateFormat fmt = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz"); + + String JSON = "{ \""+ fmt.format(date1)+"\" : \"\", \""+new Date(0).getTime()+"\" : null }"; + HashMap<Date,String> result= mapper.readValue + (JSON, new TypeReference<HashMap<Date,String>>() { }); + + assertNotNull(result); + assertEquals(HashMap.class, result.getClass()); + assertEquals(2, result.size()); + + assertTrue(result.containsKey(date1)); + assertEquals("", result.get(new Date(123456000L))); + + assertTrue(result.containsKey(new Date(0))); + assertNull(result.get(new Date(0))); + + + } + + /* + /********************************************************** + /* Test methods, maps with various alternative key types + /********************************************************** + */ + + public void testCalendarMap() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + Calendar c = Calendar.getInstance(); + c.setTimeInMillis(123456000L); + DateFormat fmt = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz"); + String JSON = "{ \""+fmt.format(c.getTime())+"\" : \"\", \""+new Date(0).getTime()+"\" : null }"; + HashMap<Calendar,String> result= mapper.readValue + (JSON, new TypeReference<HashMap<Calendar,String>>() { }); + + assertNotNull(result); + assertEquals(HashMap.class, result.getClass()); + assertEquals(2, result.size()); + + assertTrue(result.containsKey(c)); + assertEquals("", result.get(c)); + c.setTimeInMillis(0); + assertTrue(result.containsKey(c)); + assertNull(result.get(c)); + } + + // [JACKSON-726] + public void testUUIDKeyMap() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + UUID key = UUID.nameUUIDFromBytes("foobar".getBytes("UTF-8")); + String JSON = "{ \""+key+"\":4}"; + Map<UUID,Object> result = mapper.readValue(JSON, new TypeReference<Map<UUID,Object>>() { }); + assertNotNull(result); + assertEquals(1, result.size()); + Object ob = result.keySet().iterator().next(); + assertNotNull(ob); + assertEquals(UUID.class, ob.getClass()); + assertEquals(key, ob); + } + + /* + /********************************************************** + /* Test methods, annotated Maps + /********************************************************** + */ + + /** + * Simple test to ensure that @JsonDeserialize.using is + * recognized + */ + public void testMapWithDeserializer() throws IOException + { + ObjectMapper mapper = new ObjectMapper(); + CustomMap result = mapper.readValue(quote("xyz"), CustomMap.class); + assertEquals(1, result.size()); + assertEquals("xyz", result.get("x")); + } + + /* + /********************************************************** + /* Error tests + /********************************************************** + */ + + public void testMapError() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + try { + Object result = mapper.readValue("[ 1, 2 ]", + new TypeReference<Map<String,String>>() { }); + fail("Expected an exception, but got result value: "+result); + } catch (JsonMappingException jex) { + verifyException(jex, "START_ARRAY"); + } + } + + public void testNoCtorMap() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + try { + BrokenMap result = mapper.readValue("{ \"a\" : 3 }", BrokenMap.class); + // should never get here; assert added to remove compiler warning + assertNull(result); + } catch (JsonMappingException e) { + // instead, should get this exception: + verifyException(e, "no default constructor found"); + } + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/deser/TestNullHandling.java b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestNullHandling.java new file mode 100644 index 0000000..7a15b08 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestNullHandling.java
@@ -0,0 +1,53 @@ +package org.codehaus.jackson.map.deser; + +import java.io.IOException; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.module.SimpleModule; + +public class TestNullHandling extends BaseMapTest +{ + /* + /********************************************************** + /* Helper classes + /********************************************************** + */ + + static class FunnyNullDeserializer extends JsonDeserializer<String> + { + @Override + public String deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { + return "text"; + } + + @Override + public String getNullValue() { return "funny"; } + } + + /* + /********************************************************** + /* Test methods + /********************************************************** + */ + + // Test for [JACKSON-643] + public void testCustomRootNulls() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + SimpleModule module = new SimpleModule("test", Version.unknownVersion()); + module.addDeserializer(String.class, new FunnyNullDeserializer()); + mapper.registerModule(module); + + // should get non-default null directly: + String str = mapper.readValue("null", String.class); + assertNotNull(str); + assertEquals("funny", str); + + // as well as via ObjectReader + ObjectReader reader = mapper.reader(String.class); + str = reader.readValue("null"); + assertNotNull(str); + assertEquals("funny", str); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/deser/TestNumbers.java b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestNumbers.java new file mode 100644 index 0000000..c9b7dda --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestNumbers.java
@@ -0,0 +1,121 @@ +package org.codehaus.jackson.map.deser; + +import java.io.IOException; +import java.math.BigDecimal; +import java.math.BigInteger; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.JsonDeserialize; + +/** + * Tests related to [JACKSON-139] + */ +public class TestNumbers + extends BaseMapTest +{ + /* + /********************************************************************** + /* Helper classes, beans + /********************************************************************** + */ + + static class MyBeanHolder { + public Long id; + public MyBeanDefaultValue defaultValue; + } + + static class MyBeanDefaultValue + { + public MyBeanValue value; + } + + @JsonDeserialize(using=MyBeanDeserializer.class) + static class MyBeanValue { + public BigDecimal decimal; + public MyBeanValue() { this(null); } + public MyBeanValue(BigDecimal d) { this.decimal = d; } + } + + /* + /********************************************************************** + /* Helper classes, serializers/deserializers/resolvers + /********************************************************************** + */ + + static class MyBeanDeserializer extends JsonDeserializer<MyBeanValue> + { + @Override + public MyBeanValue deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException + { + return new MyBeanValue(jp.getDecimalValue()); + } + } + + /* + /********************************************************************** + /* Unit tests + /********************************************************************** + */ + + public void testFloatNaN() throws Exception + { + ObjectMapper m = new ObjectMapper(); + Float result = m.readValue(" \"NaN\"", Float.class); + assertEquals(Float.valueOf(Float.NaN), result); + } + + public void testDoubleInf() throws Exception + { + ObjectMapper m = new ObjectMapper(); + Double result = m.readValue(" \""+Double.POSITIVE_INFINITY+"\"", Double.class); + assertEquals(Double.valueOf(Double.POSITIVE_INFINITY), result); + + result = m.readValue(" \""+Double.NEGATIVE_INFINITY+"\"", Double.class); + assertEquals(Double.valueOf(Double.NEGATIVE_INFINITY), result); + } + + // [JACKSON-349] + public void testEmptyAsNumber() throws Exception + { + ObjectMapper m = new ObjectMapper(); + assertNull(m.readValue(quote(""), Integer.class)); + assertNull(m.readValue(quote(""), Long.class)); + assertNull(m.readValue(quote(""), Float.class)); + assertNull(m.readValue(quote(""), Double.class)); + assertNull(m.readValue(quote(""), BigInteger.class)); + assertNull(m.readValue(quote(""), BigDecimal.class)); + } + + // // Tests for [JACKSON-668] + + public void testDeserializeDecimalHappyPath() throws Exception { + ObjectMapper mapper = new ObjectMapper(); + String json = "{\"defaultValue\": { \"value\": 123 } }"; + MyBeanHolder result = mapper.readValue(json, MyBeanHolder.class); + assertEquals(BigDecimal.valueOf(123), result.defaultValue.value.decimal); + } + + public void testDeserializeDecimalProperException() throws Exception { + ObjectMapper mapper = new ObjectMapper(); + String json = "{\"defaultValue\": { \"value\": \"123\" } }"; + try { + mapper.readValue(json, MyBeanHolder.class); + fail("should have raised exception"); + } catch (JsonParseException e) { + verifyException(e, "not numeric"); + } + } + + public void testDeserializeDecimalProperExceptionWhenIdSet() throws Exception { + ObjectMapper mapper = new ObjectMapper(); + String json = "{\"id\": 5, \"defaultValue\": { \"value\": \"123\" } }"; + try { + MyBeanHolder result = mapper.readValue(json, MyBeanHolder.class); + fail("should have raised exception instead value was set to " + result.defaultValue.value.decimal.toString()); + } catch (JsonParseException e) { + verifyException(e, "not numeric"); + } + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/deser/TestOverloaded.java b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestOverloaded.java new file mode 100644 index 0000000..d42d7f6 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestOverloaded.java
@@ -0,0 +1,148 @@ +package org.codehaus.jackson.map.deser; + +import java.util.*; + +import org.codehaus.jackson.annotate.JsonProperty; +import org.codehaus.jackson.map.*; + +/** + * Unit tests related to handling of overloaded methods; + * and specifically addressing problem [JACKSON-189]. + * + * @since 1.5 + */ +public class TestOverloaded + extends BaseMapTest +{ + static class BaseListBean + { + List<String> list; + + BaseListBean() { } + + public void setList(List<String> l) { list = l; } + } + + static class ArrayListBean extends BaseListBean + { + ArrayListBean() { } + + public void setList(ArrayList<String> l) { super.setList(l); } + } + + // 27-Feb-2010, tatus: Won't fix immediately, need to comment out + /* + static class OverloadBean + { + String a; + + public OverloadBean() { } + + public void setA(int value) { a = String.valueOf(value); } + public void setA(String value) { a = value; } + } + */ + + static class NumberBean { + protected Object value; + + public void setValue(Number n) { value = n; } + } + + static class WasNumberBean extends NumberBean { + public void setValue(String str) { value = str; } + } + + // [JACKSON-739] + static class Overloaded739 + { + protected Object _value; + + @JsonProperty + public void setValue(String str) { _value = str; } + + // no annotation, should not be chosen: + public void setValue(Object o) { throw new UnsupportedOperationException(); } + } + + /** + * And then a Bean that is conflicting and should not work + */ + static class ConflictBean { + public void setA(ArrayList<Object> a) { } + public void setA(LinkedList<Object> a) { } + } + + /* + /************************************************************ + /* Unit tests + /************************************************************ + */ + + /** + * Unit test related to [JACKSON-189] + */ + // 27-Feb-2010, tatus: Won't fix immediately, need to comment out + /* + public void testSimpleOverload() throws Exception + { + OverloadBean bean; + try { + bean = new ObjectMapper().readValue("{ \"a\" : 13 }", OverloadBean.class); + } catch (JsonMappingException e) { + fail("Did not expect an exception, got: "+e.getMessage()); + return; + } + assertEquals("13", bean.a); + } + */ + + /** + * It should be ok to overload with specialized + * version; more specific method should be used. + */ + public void testSpecialization() throws Exception + { + ArrayListBean bean = new ObjectMapper().readValue + ("{\"list\":[\"a\",\"b\",\"c\"]}", ArrayListBean.class); + assertNotNull(bean.list); + assertEquals(3, bean.list.size()); + assertEquals(ArrayList.class, bean.list.getClass()); + assertEquals("a", bean.list.get(0)); + assertEquals("b", bean.list.get(1)); + assertEquals("c", bean.list.get(2)); + } + + /** + * As per [JACKSON-255], should also allow more general overriding, + * as long as there are no in-class conflicts. + */ + public void testOverride() throws Exception + { + WasNumberBean bean = new ObjectMapper().readValue + ("{\"value\" : \"abc\"}", WasNumberBean.class); + assertNotNull(bean); + assertEquals("abc", bean.value); + } + + // for [JACKSON-739] + public void testConflictResolution() throws Exception + { + Overloaded739 bean = new ObjectMapper().readValue + ("{\"value\":\"abc\"}", Overloaded739.class); + assertNotNull(bean); + assertEquals("abc", bean._value); + } + + /** + * For genuine setter conflict, an exception is to be thrown. + */ + public void testSetterConflict() throws Exception + { + try { + new ObjectMapper().readValue("{ }", ConflictBean.class); + } catch (Exception e) { + verifyException(e, "Conflicting setter definitions"); + } + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/deser/TestParentChildReferences.java b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestParentChildReferences.java new file mode 100644 index 0000000..4fe4239 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestParentChildReferences.java
@@ -0,0 +1,331 @@ +package org.codehaus.jackson.map.deser; + +import java.util.*; + +import org.codehaus.jackson.annotate.*; +import org.codehaus.jackson.map.*; + +import org.codehaus.jackson.map.BaseMapTest; + +public class TestParentChildReferences + extends BaseMapTest +{ + /* + /********************************************************** + /* Test classes + /********************************************************** + */ + + /** + * First, a simple 'tree': just parent/child linkage + */ + static class SimpleTreeNode + { + public String name; + + // Reference back to parent; reference, ignored during ser, + // re-constructed during deser + @JsonBackReference + public SimpleTreeNode parent; + + // Reference that is serialized normally during ser, back + // reference within pointed-to instance assigned to point to + // referring bean ("this") + @JsonManagedReference + public SimpleTreeNode child; + + public SimpleTreeNode() { this(null); } + public SimpleTreeNode(String n) { name = n; } + } + + static class SimpleTreeNode2 + { + public String name; + private SimpleTreeNode2 parent; + private SimpleTreeNode2 child; + + public SimpleTreeNode2() { this(null); } + public SimpleTreeNode2(String n) { name = n; } + + @JsonBackReference + public SimpleTreeNode2 getParent() { return parent; } + public void setParent(SimpleTreeNode2 p) { parent = p; } + + @JsonManagedReference + public SimpleTreeNode2 getChild() { return child; } + public void setChild(SimpleTreeNode2 c) { child = c; } + } + + /** + * Then nodes with two separate linkages; parent/child + * and prev/next-sibling + */ + static class FullTreeNode + { + public String name; + + // parent-child links + @JsonBackReference("parent") + public FullTreeNode parent; + @JsonManagedReference("parent") + public FullTreeNode firstChild; + + // sibling-links + @JsonManagedReference("sibling") + public FullTreeNode next; + @JsonBackReference("sibling") + protected FullTreeNode prev; + + public FullTreeNode() { this(null); } + public FullTreeNode(String name) { + this.name = name; + } + } + + /** + * Class for testing managed references via arrays + */ + static class NodeArray + { + @JsonManagedReference("arr") + public ArrayNode[] nodes; + } + + static class ArrayNode + { + public String name; + + @JsonBackReference("arr") + public NodeArray parent; + + public ArrayNode() { this(null); } + public ArrayNode(String n) { name = n; } + } + + /** + * Class for testing managed references via Collections + */ + static class NodeList + { + @JsonManagedReference + public List<NodeForList> nodes; + } + + static class NodeForList + { + public String name; + + @JsonBackReference + public NodeList parent; + + public NodeForList() { this(null); } + public NodeForList(String n) { name = n; } + } + + static class NodeMap + { + @JsonManagedReference + public Map<String,NodeForMap> nodes; + } + + static class NodeForMap + { + public String name; + + @JsonBackReference + public NodeMap parent; + + public NodeForMap() { this(null); } + public NodeForMap(String n) { name = n; } + } + + public static class Parent { + @JsonManagedReference + private final List<Child> children = new ArrayList<Child>(); + + public List<Child> getChildren() { return children; } + + public void addChild(Child child) { children.add(child); child.setParent(this); } + } + + public static class Child { + private Parent parent; + private final String value; // So that the bean is not empty of properties + + public Child(@JsonProperty("value") String value) { this.value = value; } + + public String getValue() { return value; } + + @JsonBackReference + public Parent getParent() { return parent; } + + public void setParent(Parent parent) { this.parent = parent; } + } + + // [JACKSON-708] + static class Model708 { } + + static class Advertisement708 extends Model708 { + public String title; + @JsonManagedReference public List<Photo708> photos; + } + + static class Photo708 extends Model708 { + public int id; + @JsonBackReference public Advertisement708 advertisement; + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + public void testSimpleRefs() throws Exception + { + SimpleTreeNode root = new SimpleTreeNode("root"); + SimpleTreeNode child = new SimpleTreeNode("kid"); + ObjectMapper mapper = new ObjectMapper(); + root.child = child; + child.parent = root; + + String json = mapper.writeValueAsString(root); + + SimpleTreeNode resultNode = mapper.readValue(json, SimpleTreeNode.class); + assertEquals("root", resultNode.name); + SimpleTreeNode resultChild = resultNode.child; + assertNotNull(resultChild); + assertEquals("kid", resultChild.name); + assertSame(resultChild.parent, resultNode); + } + + // [JACKSON-693] + public void testSimpleRefsWithGetter() throws Exception + { + SimpleTreeNode2 root = new SimpleTreeNode2("root"); + SimpleTreeNode2 child = new SimpleTreeNode2("kid"); + ObjectMapper mapper = new ObjectMapper(); + root.child = child; + child.parent = root; + + String json = mapper.writeValueAsString(root); + + SimpleTreeNode2 resultNode = mapper.readValue(json, SimpleTreeNode2.class); + assertEquals("root", resultNode.name); + SimpleTreeNode2 resultChild = resultNode.child; + assertNotNull(resultChild); + assertEquals("kid", resultChild.name); + assertSame(resultChild.parent, resultNode); + } + + public void testFullRefs() throws Exception + { + FullTreeNode root = new FullTreeNode("root"); + FullTreeNode child1 = new FullTreeNode("kid1"); + FullTreeNode child2 = new FullTreeNode("kid2"); + ObjectMapper mapper = new ObjectMapper(); + root.firstChild = child1; + child1.parent = root; + child1.next = child2; + child2.prev = child1; + + String json = mapper.writeValueAsString(root); + + FullTreeNode resultNode = mapper.readValue(json, FullTreeNode.class); + assertEquals("root", resultNode.name); + FullTreeNode resultChild = resultNode.firstChild; + assertNotNull(resultChild); + assertEquals("kid1", resultChild.name); + assertSame(resultChild.parent, resultNode); + + // and then sibling linkage + assertNull(resultChild.prev); + FullTreeNode resultChild2 = resultChild.next; + assertNotNull(resultChild2); + assertEquals("kid2", resultChild2.name); + assertSame(resultChild, resultChild2.prev); + assertNull(resultChild2.next); + } + + public void testArrayOfRefs() throws Exception + { + NodeArray root = new NodeArray(); + ArrayNode node1 = new ArrayNode("a"); + ArrayNode node2 = new ArrayNode("b"); + root.nodes = new ArrayNode[] { node1, node2 }; + ObjectMapper mapper = new ObjectMapper(); + String json = mapper.writeValueAsString(root); + + NodeArray result = mapper.readValue(json, NodeArray.class); + ArrayNode[] kids = result.nodes; + assertNotNull(kids); + assertEquals(2, kids.length); + assertEquals("a", kids[0].name); + assertEquals("b", kids[1].name); + assertSame(result, kids[0].parent); + assertSame(result, kids[1].parent); + } + + public void testListOfRefs() throws Exception + { + NodeList root = new NodeList(); + NodeForList node1 = new NodeForList("a"); + NodeForList node2 = new NodeForList("b"); + root.nodes = Arrays.asList(node1, node2); + ObjectMapper mapper = new ObjectMapper(); + String json = mapper.writeValueAsString(root); + + NodeList result = mapper.readValue(json, NodeList.class); + List<NodeForList> kids = result.nodes; + assertNotNull(kids); + assertEquals(2, kids.size()); + assertEquals("a", kids.get(0).name); + assertEquals("b", kids.get(1).name); + assertSame(result, kids.get(0).parent); + assertSame(result, kids.get(1).parent); + } + + public void testMapOfRefs() throws Exception + { + NodeMap root = new NodeMap(); + NodeForMap node1 = new NodeForMap("a"); + NodeForMap node2 = new NodeForMap("b"); + Map<String,NodeForMap> nodes = new HashMap<String, NodeForMap>(); + nodes.put("a1", node1); + nodes.put("b2", node2); + root.nodes = nodes; + ObjectMapper mapper = new ObjectMapper(); + String json = mapper.writeValueAsString(root); + + NodeMap result = mapper.readValue(json, NodeMap.class); + Map<String,NodeForMap> kids = result.nodes; + assertNotNull(kids); + assertEquals(2, kids.size()); + assertNotNull(kids.get("a1")); + assertNotNull(kids.get("b2")); + assertEquals("a", kids.get("a1").name); + assertEquals("b", kids.get("b2").name); + assertSame(result, kids.get("a1").parent); + assertSame(result, kids.get("b2").parent); + } + + public void testIssue693() throws Exception + { + Parent parent = new Parent(); + parent.addChild(new Child("foo")); + parent.addChild(new Child("bar")); + ObjectMapper mapper = new ObjectMapper(); + byte[] bytes = mapper.writeValueAsBytes(parent); + Parent value = mapper.readValue(bytes, Parent.class); + for (Child child : value.children) { + assertEquals(value, child.getParent()); + } + } + + public void testIssue708() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + Advertisement708 ad = mapper.readValue("{\"title\":\"Hroch\",\"photos\":[{\"id\":3}]}", Advertisement708.class); + assertNotNull(ad); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/deser/TestPolymorphicCreators.java b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestPolymorphicCreators.java new file mode 100644 index 0000000..4f602bb --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestPolymorphicCreators.java
@@ -0,0 +1,148 @@ +package org.codehaus.jackson.map.deser; + +import org.codehaus.jackson.annotate.*; +import org.codehaus.jackson.map.*; + +/** + * Unit tests for verifying that it is possible to annotate + * various kinds of things with {@link JsonCreator} annotation. + */ +public class TestPolymorphicCreators + extends BaseMapTest +{ + /* + /********************************************************** + /* Helper beans + /********************************************************** + */ + + static class Animal + { + // All animals have names, for our demo purposes... + public String name; + + protected Animal() { } + + /** + * Creator method that can instantiate instances of + * appropriate polymoprphic type + */ + @JsonCreator + public static Animal create(@JsonProperty("type") String type) + { + if ("dog".equals(type)) { + return new Dog(); + } + if ("cat".equals(type)) { + return new Cat(); + } + throw new IllegalArgumentException("No such animal type ('"+type+"')"); + } + } + + static class Dog extends Animal + { + double barkVolume; // in decibels + public Dog() { } + public void setBarkVolume(double v) { barkVolume = v; } + } + + static class Cat extends Animal + { + boolean likesCream; + public int lives; + public Cat() { } + public void setLikesCream(boolean likesCreamSurely) { likesCream = likesCreamSurely; } + } + + abstract static class AbstractRoot + { + private final String opt; + + private AbstractRoot(String opt) { + this.opt = opt; + } + + @JsonCreator + public static final AbstractRoot make(@JsonProperty("which") int which, + @JsonProperty("opt") String opt) { + if(1 == which) { + return new One(opt); + } + throw new RuntimeException("cannot instantiate " + which); + } + + abstract public int getWhich(); + + public final String getOpt() { + return opt; + } + } + + static final class One extends AbstractRoot { + private One(String opt) { + super(opt); + } + + @Override public int getWhich() { + return 1; + } + } + + /* + ********************************************** + * Actual tests + ********************************************** + */ + + /** + * Simple test to verify that it is possible to implement polymorphic + * deserialization manually. + */ + public void testManualPolymorphicDog() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + // first, a dog, start with type + Animal animal = mapper.readValue("{ \"type\":\"dog\", \"name\":\"Fido\", \"barkVolume\" : 95.0 }", Animal.class); + assertEquals(Dog.class, animal.getClass()); + assertEquals("Fido", animal.name); + assertEquals(95.0, ((Dog) animal).barkVolume); + } + + public void testManualPolymorphicCatBasic() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + // and finally, lactose-intolerant, but otherwise robust super-cat: + Animal animal = mapper.readValue("{ \"name\" : \"Macavity\", \"type\":\"cat\", \"lives\":18, \"likesCream\":false }", Animal.class); + assertEquals(Cat.class, animal.getClass()); + assertEquals("Macavity", animal.name); // ... there's no one like Macavity! + Cat cat = (Cat) animal; + assertEquals(18, cat.lives); + // ok, he can't drink dairy products. Let's verify: + assertEquals(false, cat.likesCream); + } + + public void testManualPolymorphicCatWithReorder() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + // Then cat; shuffle order to mandate buffering + Animal animal = mapper.readValue("{ \"likesCream\":true, \"name\" : \"Venla\", \"type\":\"cat\" }", Animal.class); + assertEquals(Cat.class, animal.getClass()); + assertEquals("Venla", animal.name); + // bah, of course cats like cream. But let's ensure Jackson won't mess with laws of nature! + assertTrue(((Cat) animal).likesCream); + } + + public void testManualPolymorphicWithNumbered() throws Exception + { + final ObjectMapper m = new ObjectMapper(); + final ObjectWriter w = m.writerWithType(AbstractRoot.class); + final ObjectReader r = m.reader(AbstractRoot.class); + + AbstractRoot input = AbstractRoot.make(1, "oh hai!"); + String json = w.writeValueAsString(input); + AbstractRoot result = r.readValue(json); + assertNotNull(result); + assertEquals("oh hai!", result.getOpt()); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/deser/TestSetterlessProperties.java b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestSetterlessProperties.java new file mode 100644 index 0000000..ea3ccbc --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestSetterlessProperties.java
@@ -0,0 +1,129 @@ +package org.codehaus.jackson.map.deser; + +import java.util.*; + +import org.codehaus.jackson.annotate.JsonProperty; +import org.codehaus.jackson.map.*; + +/** + * Unit tests for verifying that feature requested + * via [JACKSON-88] ("setterless collections") work as + * expected, similar to how Collections and Maps work + * with JAXB. + */ +public class TestSetterlessProperties + extends BaseMapTest +{ + /* + /********************************************************** + /* Helper beans + /********************************************************** + */ + + static class CollectionBean + { + List<String> _values = new ArrayList<String>(); + + public List<String> getValues() { return _values; } + } + + static class MapBean + { + Map<String,Integer> _values = new HashMap<String,Integer>(); + + public Map<String,Integer> getValues() { return _values; } + } + + // testing to verify that field has precedence over getter, for lists + static class Dual + { + @JsonProperty("list") protected List<Integer> values = new ArrayList<Integer>(); + + public Dual() { } + + public List<Integer> getList() { + throw new IllegalStateException("Should not get called"); + } + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + public void testSimpleSetterlessCollectionOk() + throws Exception + { + CollectionBean result = new ObjectMapper().readValue + ("{\"values\":[ \"abc\", \"def\" ]}", CollectionBean.class); + List<String> l = result._values; + assertEquals(2, l.size()); + assertEquals("abc", l.get(0)); + assertEquals("def", l.get(1)); + } + + /** + * Let's also verify that disabling the feature makes + * deserialization fail for setterless bean + */ + public void testSimpleSetterlessCollectionFailure() + throws Exception + { + ObjectMapper m = new ObjectMapper(); + // by default, it should be enabled + assertTrue(m.getDeserializationConfig().isEnabled(DeserializationConfig.Feature.USE_GETTERS_AS_SETTERS)); + m.configure(DeserializationConfig.Feature.USE_GETTERS_AS_SETTERS, false); + assertFalse(m.getDeserializationConfig().isEnabled(DeserializationConfig.Feature.USE_GETTERS_AS_SETTERS)); + + // and now this should fail + try { + m.readValue + ("{\"values\":[ \"abc\", \"def\" ]}", CollectionBean.class); + fail("Expected an exception"); + } catch (JsonMappingException e) { + /* Not a good exception, ideally could suggest a need for + * a setter...? + */ + verifyException(e, "Unrecognized field"); + } + } + + public void testSimpleSetterlessMapOk() + throws Exception + { + MapBean result = new ObjectMapper().readValue + ("{\"values\":{ \"a\": 15, \"b\" : -3 }}", MapBean.class); + Map<String,Integer> m = result._values; + assertEquals(2, m.size()); + assertEquals(Integer.valueOf(15), m.get("a")); + assertEquals(Integer.valueOf(-3), m.get("b")); + } + + public void testSimpleSetterlessMapFailure() + throws Exception + { + ObjectMapper m = new ObjectMapper(); + m.configure(DeserializationConfig.Feature.USE_GETTERS_AS_SETTERS, false); + // so this should fail now without a setter + try { + m.readValue + ("{\"values\":{ \"a\":3 }}", MapBean.class); + fail("Expected an exception"); + } catch (JsonMappingException e) { + verifyException(e, "Unrecognized field"); + } + } + + /* Test for [JACKSON-328], precedence of "getter-as-setter" (for Lists) versus + * field for same property. + */ + public void testSetterlessPrecedence() throws Exception + { + ObjectMapper m = new ObjectMapper(); + m.configure(DeserializationConfig.Feature.USE_GETTERS_AS_SETTERS, true); + Dual value = m.readValue("{\"list\":[1,2,3]}, valueType)", Dual.class); + assertNotNull(value); + assertEquals(3, value.values.size()); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/deser/TestSimpleAtomicTypes.java b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestSimpleAtomicTypes.java new file mode 100644 index 0000000..7931a60 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestSimpleAtomicTypes.java
@@ -0,0 +1,45 @@ +package org.codehaus.jackson.map.deser; + +import java.util.concurrent.atomic.*; + +import org.codehaus.jackson.map.ObjectMapper; + +public class TestSimpleAtomicTypes + extends org.codehaus.jackson.map.BaseMapTest +{ + public void testAtomicBoolean() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + AtomicBoolean b = mapper.readValue("true", AtomicBoolean.class); + assertTrue(b.get()); + } + + public void testAtomicInt() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + AtomicInteger value = mapper.readValue("13", AtomicInteger.class); + assertEquals(13, value.get()); + } + + public void testAtomicLong() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + AtomicLong value = mapper.readValue("12345678901", AtomicLong.class); + assertEquals(12345678901L, value.get()); + } + + public void testAtomicReference() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + AtomicReference<long[]> value = mapper.readValue("[1,2]", + new org.codehaus.jackson.type.TypeReference<AtomicReference<long[]>>() { }); + Object ob = value.get(); + assertNotNull(ob); + assertEquals(long[].class, ob.getClass()); + long[] longs = (long[]) ob; + assertNotNull(longs); + assertEquals(2, longs.length); + assertEquals(1, longs[0]); + assertEquals(2, longs[1]); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/deser/TestSimpleTypes.java b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestSimpleTypes.java new file mode 100644 index 0000000..f13d217 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestSimpleTypes.java
@@ -0,0 +1,437 @@ +package org.codehaus.jackson.map.deser; + +import java.io.*; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.net.URL; +import java.net.URI; +import java.util.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.util.TokenBuffer; + +/** + * Unit tests for verifying handling of simple basic non-structured + * types; primitives (and/or their wrappers), Strings. + */ +public class TestSimpleTypes + extends BaseMapTest +{ + final static String NAN_STRING = "NaN"; + + final static class BooleanBean { + boolean _v; + void setV(boolean v) { _v = v; } + } + + static class IntBean { + int _v; + void setV(int v) { _v = v; } + } + + final static class DoubleBean { + double _v; + void setV(double v) { _v = v; } + } + + final static class FloatBean { + float _v; + void setV(float v) { _v = v; } + } + + /** + * Also, let's ensure that it's ok to override methods. + */ + static class IntBean2 + extends IntBean + { + @Override + void setV(int v2) { super.setV(v2+1); } + } + + /* + /********************************************************** + /* Then tests for primitives + /********************************************************** + */ + + public void testBooleanPrimitive() throws Exception + { + // first, simple case: + ObjectMapper mapper = new ObjectMapper(); + BooleanBean result = mapper.readValue(new StringReader("{\"v\":true}"), BooleanBean.class); + assertTrue(result._v); + // then [JACKSON-79]: + result = mapper.readValue(new StringReader("{\"v\":null}"), BooleanBean.class); + assertNotNull(result); + assertFalse(result._v); + + // should work with arrays too.. + boolean[] array = mapper.readValue(new StringReader("[ null ]"), boolean[].class); + assertNotNull(array); + assertEquals(1, array.length); + assertFalse(array[0]); + } + + public void testIntPrimitive() throws Exception + { + // first, simple case: + ObjectMapper mapper = new ObjectMapper(); + IntBean result = mapper.readValue(new StringReader("{\"v\":3}"), IntBean.class); + assertEquals(3, result._v); + // then [JACKSON-79]: + result = mapper.readValue(new StringReader("{\"v\":null}"), IntBean.class); + assertNotNull(result); + assertEquals(0, result._v); + + // should work with arrays too.. + int[] array = mapper.readValue(new StringReader("[ null ]"), int[].class); + assertNotNull(array); + assertEquals(1, array.length); + assertEquals(0, array[0]); + } + + public void testDoublePrimitive() throws Exception + { + // first, simple case: + ObjectMapper mapper = new ObjectMapper(); + // bit tricky with binary fps but... + double value = 0.016; + DoubleBean result = mapper.readValue(new StringReader("{\"v\":"+value+"}"), DoubleBean.class); + assertEquals(value, result._v); + // then [JACKSON-79]: + result = mapper.readValue(new StringReader("{\"v\":null}"), DoubleBean.class); + assertNotNull(result); + assertEquals(0.0, result._v); + + // should work with arrays too.. + double[] array = mapper.readValue(new StringReader("[ null ]"), double[].class); + assertNotNull(array); + assertEquals(1, array.length); + assertEquals(0.0, array[0]); + } + + public void testDoublePrimitiveNonNumeric() throws Exception + { + // first, simple case: + ObjectMapper mapper = new ObjectMapper(); + // bit tricky with binary fps but... + double value = Double.POSITIVE_INFINITY; + DoubleBean result = mapper.readValue(new StringReader("{\"v\":\""+value+"\"}"), DoubleBean.class); + assertEquals(value, result._v); + + // should work with arrays too.. + double[] array = mapper.readValue(new StringReader("[ \"Infinity\" ]"), double[].class); + assertNotNull(array); + assertEquals(1, array.length); + assertEquals(Double.POSITIVE_INFINITY, array[0]); + } + + public void testFloatPrimitiveNonNumeric() throws Exception + { + // first, simple case: + ObjectMapper mapper = new ObjectMapper(); + // bit tricky with binary fps but... + float value = Float.POSITIVE_INFINITY; + FloatBean result = mapper.readValue(new StringReader("{\"v\":\""+value+"\"}"), FloatBean.class); + assertEquals(value, result._v); + + // should work with arrays too.. + float[] array = mapper.readValue(new StringReader("[ \"Infinity\" ]"), float[].class); + assertNotNull(array); + assertEquals(1, array.length); + assertEquals(Float.POSITIVE_INFINITY, array[0]); + } + + /** + * Beyond simple case, let's also ensure that method overriding works as + * expected. + */ + public void testIntWithOverride() throws Exception + { + // first, simple case: + ObjectMapper mapper = new ObjectMapper(); + IntBean2 result = mapper.readValue(new StringReader("{\"v\":8}"), IntBean2.class); + assertEquals(9, result._v); + + } + + /* + /********************************************************** + /* Then tests for wrappers + /********************************************************** + */ + + /** + * Simple unit test to verify that we can map boolean values to + * java.lang.Boolean. + */ + public void testBooleanWrapper() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + Boolean result = mapper.readValue(new StringReader("true"), Boolean.class); + assertEquals(Boolean.TRUE, result); + result = mapper.readValue(new StringReader("false"), Boolean.class); + assertEquals(Boolean.FALSE, result); + + /* [JACKSON-78]: should accept ints too, (0 == false, otherwise true) + */ + result = mapper.readValue(new StringReader("0"), Boolean.class); + assertEquals(Boolean.FALSE, result); + result = mapper.readValue(new StringReader("1"), Boolean.class); + assertEquals(Boolean.TRUE, result); + } + + public void testByteWrapper() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + Byte result = mapper.readValue(new StringReader(" -42\t"), Byte.class); + assertEquals(Byte.valueOf((byte)-42), result); + + // Also: should be able to coerce floats, strings: + result = mapper.readValue(new StringReader(" \"-12\""), Byte.class); + assertEquals(Byte.valueOf((byte)-12), result); + + result = mapper.readValue(new StringReader(" 39.07"), Byte.class); + assertEquals(Byte.valueOf((byte)39), result); + } + + public void testShortWrapper() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + Short result = mapper.readValue(new StringReader("37"), Short.class); + assertEquals(Short.valueOf((short)37), result); + + // Also: should be able to coerce floats, strings: + result = mapper.readValue(new StringReader(" \"-1009\""), Short.class); + assertEquals(Short.valueOf((short)-1009), result); + + result = mapper.readValue(new StringReader("-12.9"), Short.class); + assertEquals(Short.valueOf((short)-12), result); + } + + public void testCharacterWrapper() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + // First: canonical value is 1-char string + Character result = mapper.readValue(new StringReader("\"a\""), Character.class); + assertEquals(Character.valueOf('a'), result); + + // But can also pass in ascii code + result = mapper.readValue(new StringReader(" "+((int) 'X')), Character.class); + assertEquals(Character.valueOf('X'), result); + } + + public void testIntWrapper() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + Integer result = mapper.readValue(new StringReader(" -42\t"), Integer.class); + assertEquals(Integer.valueOf(-42), result); + + // Also: should be able to coerce floats, strings: + result = mapper.readValue(new StringReader(" \"-1200\""), Integer.class); + assertEquals(Integer.valueOf(-1200), result); + + result = mapper.readValue(new StringReader(" 39.07"), Integer.class); + assertEquals(Integer.valueOf(39), result); + } + + public void testLongWrapper() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + Long result = mapper.readValue(new StringReader("12345678901"), Long.class); + assertEquals(Long.valueOf(12345678901L), result); + + // Also: should be able to coerce floats, strings: + result = mapper.readValue(new StringReader(" \"-9876\""), Long.class); + assertEquals(Long.valueOf(-9876), result); + + result = mapper.readValue(new StringReader("1918.3"), Long.class); + assertEquals(Long.valueOf(1918), result); + } + + /* Note: dealing with floating-point values is tricky; not sure if + * we can really use equality tests here... JDK does have decent + * conversions though, to retain accuracy and round-trippability. + * But still... + */ + public void testFloatWrapper() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + + // Also: should be able to coerce floats, strings: + String[] STRS = new String[] { + "1.0", "0.0", "-0.3", "0.7", "42.012", "-999.0", NAN_STRING + }; + + for (String str : STRS) { + Float exp = Float.valueOf(str); + Float result; + + if (NAN_STRING != str) { + // First, as regular floating point value + result = mapper.readValue(new StringReader(str), Float.class); + assertEquals(exp, result); + } + + // and then as coerced String: + result = mapper.readValue(new StringReader(" \""+str+"\""), Float.class); + assertEquals(exp, result); + } + } + + public void testDoubleWrapper() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + + // Also: should be able to coerce doubles, strings: + String[] STRS = new String[] { + "1.0", "0.0", "-0.3", "0.7", "42.012", "-999.0", NAN_STRING + }; + + for (String str : STRS) { + Double exp = Double.valueOf(str); + Double result; + + // First, as regular double value + if (NAN_STRING != str) { + result = mapper.readValue(new StringReader(str), Double.class); + assertEquals(exp, result); + } + // and then as coerced String: + result = mapper.readValue(new StringReader(" \""+str+"\""), Double.class); + assertEquals(exp, result); + } + } + + /* + /********************************************************** + /* Simple non-primitive types + /********************************************************** + */ + + public void testSingleString() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + String value = "FOO!"; + String result = mapper.readValue(new StringReader("\""+value+"\""), String.class); + assertEquals(value, result); + } + + public void testNull() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + // null doesn't really have a type, fake by assuming Object + Object result = mapper.readValue(" null", Object.class); + assertNull(result); + } + + public void testClass() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + Class<?> result = mapper.readValue("\"java.lang.String\"", Class.class); + assertEquals(String.class, result); + } + + public void testBigDecimal() throws Exception + { + BigDecimal value = new BigDecimal("0.001"); + BigDecimal result = new ObjectMapper().readValue(new StringReader(value.toString()), BigDecimal.class); + assertEquals(value, result); + } + + public void testBigInteger() throws Exception + { + BigInteger value = new BigInteger("-1234567890123456789012345567809"); + BigInteger result = new ObjectMapper().readValue(new StringReader(value.toString()), BigInteger.class); + assertEquals(value, result); + } + + public void testUUID() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + UUID value = UUID.fromString("76e6d183-5f68-4afa-b94a-922c1fdb83f8"); + assertEquals(value, mapper.readValue("\""+value.toString()+"\"", UUID.class)); + + // [JACKSON-393] fix: + + // first, null should come as null + TokenBuffer buf = new TokenBuffer(null); + buf.writeObject(null); + assertNull(mapper.readValue(buf.asParser(), UUID.class)); + + // then, UUID itself come as is: + buf = new TokenBuffer(null); + buf.writeObject(value); + assertSame(value, mapper.readValue(buf.asParser(), UUID.class)); + + // and finally from byte[] + // oh crap; JDK UUID just... sucks. Not even byte[] accessors or constructors? Huh? + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + DataOutputStream out = new DataOutputStream(bytes); + out.writeLong(value.getMostSignificantBits()); + out.writeLong(value.getLeastSignificantBits()); + byte[] data = bytes.toByteArray(); + assertEquals(16, data.length); + + buf.writeObject(data); + + UUID value2 = mapper.readValue(buf.asParser(), UUID.class); + + assertEquals(value, value2); + } + + public void testURL() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + + URL value = new URL("http://foo.com"); + assertEquals(value, mapper.readValue("\""+value.toString()+"\"", URL.class)); + + // trivial case; null to null, embedded URL to URL + TokenBuffer buf = new TokenBuffer(null); + buf.writeObject(null); + assertNull(mapper.readValue(buf.asParser(), URL.class)); + + // then, UUID itself come as is: + buf = new TokenBuffer(null); + buf.writeObject(value); + assertSame(value, mapper.readValue(buf.asParser(), URL.class)); + } + + public void testURI() throws Exception + { + URI value = new URI("http://foo.com"); + assertEquals(value, new ObjectMapper().readValue("\""+value.toString()+"\"", URI.class)); + } + + /* + /********************************************************** + /* Sequence tests + /********************************************************** + */ + + /** + * Then a unit test to verify that we can conveniently bind sequence of + * space-separate simple values + */ + public void testSequenceOfInts() throws Exception + { + final int NR_OF_INTS = 100; + + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < NR_OF_INTS; ++i) { + sb.append(" "); + sb.append(i); + } + + ObjectMapper mapper = new ObjectMapper(); + JsonParser jp = mapper.getJsonFactory().createJsonParser(sb.toString()); + for (int i = 0; i < NR_OF_INTS; ++i) { + Integer result = mapper.readValue(jp, Integer.class); + assertEquals(Integer.valueOf(i), result); + } + } +} +
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/deser/TestStatics.java b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestStatics.java new file mode 100644 index 0000000..cd5ddcc --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestStatics.java
@@ -0,0 +1,35 @@ +package org.codehaus.jackson.map.deser; + +import org.codehaus.jackson.annotate.*; +import org.codehaus.jackson.map.*; + +/** + * Tests for checking that static methods are not recognized as accessors + * for properties + */ +public class TestStatics + extends BaseMapTest +{ + static class Bean + { + int _x; + + public static void setX(int value) { throw new Error("Should NOT call static method"); } + + @JsonProperty("x") public void assignX(int x) { _x = x; } + } + + /* + /********************************************************** + /* Test methods + /********************************************************** + */ + + public void testSimpleIgnore() throws Exception + { + ObjectMapper m = new ObjectMapper(); + // should not care about static setter... + Bean result = m.readValue("{ \"x\":3}", Bean.class); + assertEquals(3, result._x); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/deser/TestTimestampDeserialization.java b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestTimestampDeserialization.java new file mode 100644 index 0000000..34e1440 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestTimestampDeserialization.java
@@ -0,0 +1,42 @@ +package org.codehaus.jackson.map.deser; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; + +import org.codehaus.jackson.map.*; + +public class TestTimestampDeserialization + extends BaseMapTest +{ + // As for TestDateDeserialization except we don't need to test date conversion routines, so + // just check we pick up timestamp class + + public void testTimestampUtil() throws Exception + { + long now = 123456789L; + java.sql.Timestamp value = new java.sql.Timestamp(now); + + // First from long + assertEquals(value, new ObjectMapper().readValue(""+now, java.sql.Timestamp.class)); + + String dateStr = serializeTimestampAsString(value); + java.sql.Timestamp result = new ObjectMapper().readValue("\""+dateStr+"\"", java.sql.Timestamp.class); + + assertEquals("Date: expect "+value+" ("+value.getTime()+"), got "+result+" ("+result.getTime()+")", value.getTime(), result.getTime()); + } + + /* + /********************************************************** + /* Helper methods + /********************************************************** + */ + + private String serializeTimestampAsString(java.sql.Timestamp value) + { + /* Then from String. This is bit tricky, since JDK does not really + * suggest a 'standard' format. So let's try using something... + */ + DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); + return df.format(value); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/deser/TestUnknownProperties.java b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestUnknownProperties.java new file mode 100644 index 0000000..c8f14c1 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestUnknownProperties.java
@@ -0,0 +1,210 @@ +package org.codehaus.jackson.map.deser; + +import java.io.*; +import java.util.HashMap; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.annotate.JsonIgnore; +import org.codehaus.jackson.annotate.JsonIgnoreProperties; +import org.codehaus.jackson.map.*; + +/** + * Unit tests for checking handling of unknown properties + */ +public class TestUnknownProperties + extends BaseMapTest +{ + final static String JSON_UNKNOWN_FIELD = "{ \"a\" : 1, \"foo\" : [ 1, 2, 3], \"b\" : -1 }"; + + /* + /********************************************************** + /* Helper classes + /********************************************************** + */ + + final static class TestBean + { + String _unknown; + + int _a, _b; + + public TestBean() { } + + public void setA(int a) { _a = a; } + public void setB(int b) { _b = b; } + + public void markUnknown(String unk) { _unknown = unk; } + } + + /** + * Simple {@link DeserializationProblemHandler} sub-class that + * just marks unknown property/ies when encountered, along with + * Json value of the property. + */ + final static class MyHandler + extends DeserializationProblemHandler + { + @Override + public boolean handleUnknownProperty(DeserializationContext ctxt, JsonDeserializer<?> deserializer, + Object bean, String propertyName) + throws IOException, JsonProcessingException + { + JsonParser jp = ctxt.getParser(); + // very simple, just to verify that we do see correct token type + ((TestBean) bean).markUnknown(propertyName+":"+jp.getCurrentToken().toString()); + // Yup, we are good to go; must skip whatever value we'd have: + jp.skipChildren(); + return true; + } + } + + @JsonIgnoreProperties({"b", "c"}) + static class IgnoreSome + { + public int a, b; + private String c, d; + + public IgnoreSome() { } + + public String c() { return c; } + public void setC(String value) { c = value; } + public String d() { return d; } + public void setD(String value) { d = value; } + } + + @JsonIgnoreProperties(ignoreUnknown=true) + static class IgnoreUnknown { + public int a; + } + + @SuppressWarnings("serial") + @JsonIgnoreProperties({"a", "d"}) + static class IgnoreMap extends HashMap<String,Object> { } + + static class ImplicitIgnores { + @JsonIgnore public int a; + @JsonIgnore public void setB(int b) { } + public int c; + } + + /* + /********************************************************** + /* Test methods + /********************************************************** + */ + + /** + * By default we should just get an exception if an unknown property + * is encountered + */ + public void testUnknownHandlingDefault() + throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + try { + mapper.readValue(new StringReader(JSON_UNKNOWN_FIELD), TestBean.class); + } catch (JsonMappingException jex) { + verifyException(jex, "Unrecognized field \"foo\""); + } + } + + /** + * Test that verifies that it is possible to ignore unknown properties using + * {@link DeserializationProblemHandler}. + */ + public void testUnknownHandlingIgnoreWithHandler() + throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.getDeserializationConfig().clearHandlers(); + mapper.getDeserializationConfig().addHandler(new MyHandler()); + TestBean result = mapper.readValue(new StringReader(JSON_UNKNOWN_FIELD), TestBean.class); + assertNotNull(result); + assertEquals(1, result._a); + assertEquals(-1, result._b); + assertEquals("foo:START_ARRAY", result._unknown); + } + + /** + * Test for checking that it is also possible to simply suppress + * error reporting for unknown properties. + * + * @since 1.2 + */ + public void testUnknownHandlingIgnoreWithFeature() + throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.configure(DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false); + TestBean result = null; + try { + result = mapper.readValue(new StringReader(JSON_UNKNOWN_FIELD), TestBean.class); + } catch (JsonMappingException jex) { + fail("Did not expect a problem, got: "+jex.getMessage()); + } + assertNotNull(result); + assertEquals(1, result._a); + assertNull(result._unknown); + assertEquals(-1, result._b); + } + + /// @since 1.4 + public void testWithClassIgnore() + throws Exception + { + IgnoreSome result = new ObjectMapper().readValue("{ \"a\":1,\"b\":2,\"c\":\"x\",\"d\":\"y\"}", + IgnoreSome.class); + // first: should deserialize 2 of properties normally + assertEquals(1, result.a); + assertEquals("y", result.d()); + // and not take other 2 + assertEquals(0, result.b); + assertNull(result.c()); + } + + /// @since 1.4 + public void testClassIgnoreWithMap() throws Exception + { + // Let's actually use incompatible types for "a" and "d"; should not matter when ignored + IgnoreMap result = new ObjectMapper().readValue + ("{ \"a\":[ 1],\n" + +"\"b\":2,\n" + +"\"c\": \"x\",\n" + +"\"d\":false }", IgnoreMap.class); + assertEquals(2, result.size()); + Object ob = result.get("b"); + assertEquals(Integer.class, ob.getClass()); + assertEquals(Integer.valueOf(2), ob); + assertEquals("x", result.get("c")); + assertFalse(result.containsKey("a")); + assertFalse(result.containsKey("d")); + } + + /// @since 1.4 + public void testClassWithIgnoreUnknown() throws Exception + { + IgnoreUnknown result = new ObjectMapper().readValue + ("{\"b\":3,\"c\":[1,2],\"x\":{ },\"a\":-3}", IgnoreUnknown.class); + assertEquals(-3, result.a); + } + + /** + * Test that verifies that use of {@link JsonIgnore} will add implicit + * skipping of matching properties. + */ + public void testClassWithUnknownAndIgnore() throws Exception + { + ObjectMapper m = new ObjectMapper(); + // should be ok: "a" and "b" ignored, "c" mapped: + ImplicitIgnores result = m.readValue + ("{\"a\":1,\"b\":2,\"c\":3 }", ImplicitIgnores.class); + assertEquals(3, result.c); + + // but "d" is not defined, so should still error + try { + m.readValue("{\"a\":1,\"b\":2,\"c\":3,\"d\":4 }", ImplicitIgnores.class); + } catch (JsonMappingException e) { + verifyException(e, "Unrecognized field \"d\""); + } + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/deser/TestValueAnnotations.java b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestValueAnnotations.java new file mode 100644 index 0000000..c581908 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/deser/TestValueAnnotations.java
@@ -0,0 +1,397 @@ +package org.codehaus.jackson.map.deser; + +import main.BaseTest; + +import java.io.IOException; +import java.util.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.JsonDeserialize; +import org.codehaus.jackson.map.deser.std.StdDeserializer; + +/** + * This unit test suite tests use of "value" Annotations; + * annotations that define actual type (Class) to use for + * deserialization. + */ +public class TestValueAnnotations + extends BaseTest +{ + /* + /********************************************************** + /* Annotated root classes for @JsonDeserialize#as + /********************************************************** + */ + + @JsonDeserialize(using=RootStringDeserializer.class) + interface RootString { + public String contents(); + } + + static class RootStringImpl implements RootString + { + final String _contents; + + public RootStringImpl(String x) { _contents = x; } + + @Override + public String contents() { return _contents; } + public String contents2() { return _contents; } + } + + @JsonDeserialize(as=RootInterfaceImpl.class) + interface RootInterface { + public String getA(); + } + + static class RootInterfaceImpl implements RootInterface { + public String a; + + public RootInterfaceImpl() { } + + @Override + public String getA() { return a; } + } + + @SuppressWarnings("serial") + @JsonDeserialize(contentAs=RootStringImpl.class) + static class RootMap extends HashMap<String,RootStringImpl> { } + + @SuppressWarnings("serial") + @JsonDeserialize(contentAs=RootStringImpl.class) + static class RootList extends LinkedList<RootStringImpl> { } + + static class RootStringDeserializer + extends StdDeserializer<RootString> + { + public RootStringDeserializer() { super(RootString.class); } + + @Override + public RootString deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + if (jp.getCurrentToken() == JsonToken.VALUE_STRING) { + return new RootStringImpl(jp.getText()); + } + throw ctxt.mappingException(_valueClass); + } + } + + /* + /********************************************************** + /* Annotated helper classes for @JsonDeserialize#as + /********************************************************** + */ + + /* Class for testing valid {@link JsonDeserialize} annotation + * with 'as' parameter to define concrete class to deserialize to + */ + final static class CollectionHolder + { + Collection<String> _strings; + + /* Default for 'Collection' would probably be ArrayList or so; + * let's try to make it a TreeSet instead. + */ + @JsonDeserialize(as=TreeSet.class) + public void setStrings(Collection<String> s) + { + _strings = s; + } + } + + /* Another class for testing valid {@link JsonDeserialize} annotation + * with 'as' parameter to define concrete class to deserialize to + */ + final static class MapHolder + { + // Let's also coerce numbers into Strings here + Map<String,String> _data; + + /* Default for 'Collection' would be HashMap, + * let's try to make it a TreeMap instead. + */ + @JsonDeserialize(as=TreeMap.class) + public void setStrings(Map<String,String> s) + { + _data = s; + } + } + + /* Another class for testing valid {@link JsonDeserialize} annotation + * with 'as' parameter, but with array + */ + final static class ArrayHolder + { + String[] _strings; + + @JsonDeserialize(as=String[].class) + public void setStrings(Object[] o) + { + // should be passed instances of proper type, as per annotation + _strings = (String[]) o; + } + } + + /* Another class for testing broken {@link JsonDeserialize} annotation + * with 'as' parameter; one with incompatible type + */ + final static class BrokenCollectionHolder + { + @JsonDeserialize(as=String.class) // not assignable to Collection + public void setStrings(Collection<String> s) { } + } + + /* + /********************************************************** + /* Annotated helper classes for @JsonDeserialize.keyAs + /********************************************************** + */ + + final static class StringWrapper + { + final String _string; + + public StringWrapper(String s) { _string = s; } + } + + final static class MapKeyHolder + { + Map<Object, String> _map; + + @JsonDeserialize(keyAs=StringWrapper.class) + public void setMap(Map<Object,String> m) + { + // type should be ok, but no need to cast here (won't matter) + _map = m; + } + } + + final static class BrokenMapKeyHolder + { + // Invalid: Integer not a sub-class of String + @JsonDeserialize(keyAs=Integer.class) + public void setStrings(Map<String,String> m) { } + } + + /* + /********************************************************** + /* Annotated helper classes for @JsonDeserialize#contentAs + /********************************************************** + */ + + final static class ListContentHolder + { + List<?> _list; + + @JsonDeserialize(contentAs=StringWrapper.class) + public void setList(List<?> l) { + _list = l; + } + } + + final static class InvalidContentClass + { + /* Such annotation not allowed, since it makes no sense; + * non-container classes have no contents to annotate (but + * note that it is possible to first use @JsonDesiarialize.as + * to mark Object as, say, a List, and THEN use + * @JsonDeserialize.contentAs!) + */ + @JsonDeserialize(contentAs=String.class) + public void setValue(Object x) { } + } + + final static class ArrayContentHolder + { + Object[] _data; + + @JsonDeserialize(contentAs=Long.class) + public void setData(Object[] o) + { // should have proper type, but no need to coerce here + _data = o; + } + } + + final static class MapContentHolder + { + Map<Object,Object> _map; + + @JsonDeserialize(contentAs=Integer.class) + public void setMap(Map<Object,Object> m) + { + _map = m; + } + } + + /* + /********************************************************** + /* Test methods for @JsonDeserialize#as + /********************************************************** + */ + + public void testOverrideClassValid() throws Exception + { + ObjectMapper m = new ObjectMapper(); + CollectionHolder result = m.readValue + ("{ \"strings\" : [ \"test\" ] }", CollectionHolder.class); + + Collection<String> strs = result._strings; + assertEquals(1, strs.size()); + assertEquals(TreeSet.class, strs.getClass()); + assertEquals("test", strs.iterator().next()); + } + + public void testOverrideMapValid() throws Exception + { + ObjectMapper m = new ObjectMapper(); + // note: expecting conversion from number to String, as well + MapHolder result = m.readValue + ("{ \"strings\" : { \"a\" : 3 } }", MapHolder.class); + + Map<String,String> strs = result._data; + assertEquals(1, strs.size()); + assertEquals(TreeMap.class, strs.getClass()); + String value = strs.get("a"); + assertEquals("3", value); + } + + public void testOverrideArrayClass() throws Exception + { + ObjectMapper m = new ObjectMapper(); + ArrayHolder result = m.readValue + ("{ \"strings\" : [ \"test\" ] }", ArrayHolder.class); + + String[] strs = result._strings; + assertEquals(1, strs.length); + assertEquals(String[].class, strs.getClass()); + assertEquals("test", strs[0]); + } + + public void testOverrideClassInvalid() throws Exception + { + // should fail due to incompatible Annotation + try { + BrokenCollectionHolder result = new ObjectMapper().readValue + ("{ \"strings\" : [ ] }", BrokenCollectionHolder.class); + fail("Expected a failure, but got results: "+result); + } catch (JsonMappingException jme) { + verifyException(jme, "is not assignable to"); + } + } + + /* + /********************************************************** + /* Test methods for @JsonDeserialize#as used for root values + /********************************************************** + */ + + public void testRootInterfaceAs() throws Exception + { + RootInterface value = new ObjectMapper().readValue("{\"a\":\"abc\" }", RootInterface.class); + assertTrue(value instanceof RootInterfaceImpl); + assertEquals("abc", value.getA()); + } + + public void testRootInterfaceUsing() throws Exception + { + RootString value = new ObjectMapper().readValue("\"xxx\"", RootString.class); + assertTrue(value instanceof RootString); + assertEquals("xxx", value.contents()); + } + + public void testRootListAs() throws Exception + { + RootMap value = new ObjectMapper().readValue("{\"a\":\"b\"}", RootMap.class); + assertEquals(1, value.size()); + Object v2 = value.get("a"); + assertEquals(RootStringImpl.class, v2.getClass()); + assertEquals("b", ((RootString) v2).contents()); + } + + public void testRootMapAs() throws Exception + { + RootList value = new ObjectMapper().readValue("[ \"c\" ]", RootList.class); + assertEquals(1, value.size()); + Object v2 = value.get(0); + assertEquals(RootStringImpl.class, v2.getClass()); + assertEquals("c", ((RootString) v2).contents()); + } + + /* + /********************************************************** + /* Test methods for @JsonDeserialize#keyAs + /********************************************************** + */ + + @SuppressWarnings("unchecked") + public void testOverrideKeyClassValid() throws Exception + { + ObjectMapper m = new ObjectMapper(); + MapKeyHolder result = m.readValue("{ \"map\" : { \"xxx\" : \"yyy\" } }", MapKeyHolder.class); + Map<StringWrapper, String> map = (Map<StringWrapper,String>)(Map<?,?>)result._map; + assertEquals(1, map.size()); + Map.Entry<StringWrapper, String> en = map.entrySet().iterator().next(); + + StringWrapper key = en.getKey(); + assertEquals(StringWrapper.class, key.getClass()); + assertEquals("xxx", key._string); + assertEquals("yyy", en.getValue()); + } + + public void testOverrideKeyClassInvalid() throws Exception + { + // should fail due to incompatible Annotation + try { + BrokenMapKeyHolder result = new ObjectMapper().readValue + ("{ \"123\" : \"xxx\" }", BrokenMapKeyHolder.class); + fail("Expected a failure, but got results: "+result); + } catch (JsonMappingException jme) { + verifyException(jme, "is not assignable to"); + } + } + + /* + /********************************************************** + /* Test methods for @JsonDeserialize#contentAs + /********************************************************** + */ + + @SuppressWarnings("unchecked") + public void testOverrideContentClassValid() throws Exception + { + ObjectMapper m = new ObjectMapper(); + ListContentHolder result = m.readValue("{ \"list\" : [ \"abc\" ] }", ListContentHolder.class); + List<StringWrapper> list = (List<StringWrapper>)result._list; + assertEquals(1, list.size()); + Object value = list.get(0); + assertEquals(StringWrapper.class, value.getClass()); + assertEquals("abc", ((StringWrapper) value)._string); + } + + public void testOverrideArrayContents() throws Exception + { + ObjectMapper m = new ObjectMapper(); + ArrayContentHolder result = m.readValue("{ \"data\" : [ 1, 2, 3 ] }", + ArrayContentHolder.class); + Object[] data = result._data; + assertEquals(3, data.length); + assertEquals(Long[].class, data.getClass()); + assertEquals(1L, data[0]); + assertEquals(2L, data[1]); + assertEquals(3L, data[2]); + } + + public void testOverrideMapContents() throws Exception + { + ObjectMapper m = new ObjectMapper(); + MapContentHolder result = m.readValue("{ \"map\" : { \"a\" : 9 } }", + MapContentHolder.class); + Map<Object,Object> map = result._map; + assertEquals(1, map.size()); + Object ob = map.values().iterator().next(); + assertEquals(Integer.class, ob.getClass()); + assertEquals(Integer.valueOf(9), ob); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/ext/TestCoreXMLTypes.java b/1.9.10/src/test/org/codehaus/jackson/map/ext/TestCoreXMLTypes.java new file mode 100644 index 0000000..0bd6181 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/ext/TestCoreXMLTypes.java
@@ -0,0 +1,121 @@ +package org.codehaus.jackson.map.ext; + +import javax.xml.datatype.*; +import javax.xml.namespace.QName; + +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.ext.CoreXMLDeserializers; + +/** + * Core XML types (javax.xml) are considered "external" (or more precisely "optional") + * since some Java(-like) platforms do not include them: specifically, Google AppEngine + * and Android seem to skimp on their inclusion. As such, they are dynamically loaded + * only as needed, and need bit special handling. + * + * @author tatu + */ +public class TestCoreXMLTypes + extends BaseMapTest +{ + /* + /********************************************************** + /* Serializer tests + /********************************************************** + */ + + public void testQNameSer() throws Exception + { + QName qn = new QName("http://abc", "tag", "prefix"); + assertEquals(quote(qn.toString()), serializeAsString(qn)); + } + + public void testDurationSer() throws Exception + { + DatatypeFactory dtf = DatatypeFactory.newInstance(); + // arbitrary value + Duration dur = dtf.newDurationDayTime(false, 15, 19, 58, 1); + assertEquals(quote(dur.toString()), serializeAsString(dur)); + } + + public void testXMLGregorianCalendarSerAndDeser() throws Exception + { + DatatypeFactory dtf = DatatypeFactory.newInstance(); + XMLGregorianCalendar cal = dtf.newXMLGregorianCalendar + (1974, 10, 10, 18, 15, 17, 123, 0); + /* Due to [JACKSON-308], 1.6 will use configurable Date serialization; + * and it defaults to using timestamp. So let's try couple of combinations. + */ + ObjectMapper mapper = new ObjectMapper(); + long timestamp = cal.toGregorianCalendar().getTimeInMillis(); + String numStr = String.valueOf(timestamp); + assertEquals(numStr, mapper.writeValueAsString(cal)); + + // [JACKSON-403] Needs to come back ok as well: + XMLGregorianCalendar calOut = mapper.readValue(numStr, XMLGregorianCalendar.class); + assertNotNull(calOut); + assertEquals(timestamp, calOut.toGregorianCalendar().getTimeInMillis()); + + // and then textual variant + mapper.configure(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS, false); + // this is ALMOST same as default for XMLGregorianCalendar... just need to unify Z/+0000 + String exp = cal.toXMLFormat(); + String act = mapper.writeValueAsString(cal); + act = act.substring(1, act.length() - 1); // remove quotes + exp = removeZ(exp); + act = removeZ(act); + assertEquals(exp, act); + } + + private String removeZ(String dateStr) { + if (dateStr.endsWith("Z")) { + return dateStr.substring(0, dateStr.length()-1); + } + if (dateStr.endsWith("+0000")) { + return dateStr.substring(0, dateStr.length()-5); + } + return dateStr; + } + + /* + /********************************************************** + /* Deserializer tests + /********************************************************** + */ + + // First things first: must be able to load the deserializers... + public void testDeserializerLoading() + { + new CoreXMLDeserializers.DurationDeserializer(); + new CoreXMLDeserializers.GregorianCalendarDeserializer(); + new CoreXMLDeserializers.QNameDeserializer(); + } + + public void testQNameDeser() throws Exception + { + QName qn = new QName("http://abc", "tag", "prefix"); + String qstr = qn.toString(); + ObjectMapper mapper = new ObjectMapper(); + assertEquals("Should deserialize to equal QName (exp serialization: '"+qstr+"')", + qn, mapper.readValue(quote(qstr), QName.class)); + } + + public void testCalendarDeser() throws Exception + { + DatatypeFactory dtf = DatatypeFactory.newInstance(); + XMLGregorianCalendar cal = dtf.newXMLGregorianCalendar + (1974, 10, 10, 18, 15, 17, 123, 0); + String exp = cal.toXMLFormat(); + assertEquals("Should deserialize to equal XMLGregorianCalendar ('"+exp+"')", cal, + new ObjectMapper().readValue(quote(exp), XMLGregorianCalendar.class)); + } + + public void testDurationDeser() throws Exception + { + DatatypeFactory dtf = DatatypeFactory.newInstance(); + // arbitrary value, like... say, 27d5h15m59s + Duration dur = dtf.newDurationDayTime(true, 27, 5, 15, 59); + String exp = dur.toString(); + assertEquals("Should deserialize to equal Duration ('"+exp+"')", dur, + new ObjectMapper().readValue(quote(exp), Duration.class)); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/ext/TestDOM.java b/1.9.10/src/test/org/codehaus/jackson/map/ext/TestDOM.java new file mode 100644 index 0000000..7dec8f8 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/ext/TestDOM.java
@@ -0,0 +1,101 @@ +package org.codehaus.jackson.map.ext; + +import java.io.StringReader; +import javax.xml.parsers.DocumentBuilderFactory; + +import org.xml.sax.InputSource; +import org.w3c.dom.*; + +import org.codehaus.jackson.map.ObjectMapper; + +public class TestDOM extends org.codehaus.jackson.map.BaseMapTest +{ + final static String SIMPLE_XML = + "<root attr='3'><leaf>Rock & Roll!</leaf><?proc instr?></root>"; + final static String SIMPLE_XML_NS = + "<root ns:attr='abc' xmlns:ns='http://foo' />"; + + public void testSerializeSimpleNonNS() throws Exception + { + // Let's just parse first, easiest + Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse + (new InputSource(new StringReader(SIMPLE_XML))); + assertNotNull(doc); + ObjectMapper mapper = new ObjectMapper(); + // need to strip xml declaration, if any + String outputRaw = mapper.writeValueAsString(doc); + // And re-parse as String, since JSON has quotes... + String output = mapper.readValue(outputRaw, String.class); + /* ... and finally, normalize to (close to) canonical XML + * output (single vs double quotes, xml declaration etc) + */ + assertEquals(SIMPLE_XML, normalizeOutput(output)); + } + + public void testDeserializeNonNS() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + for (int i = 0; i < 2; ++i) { + Document doc; + + if (i == 0) { + // First, as Document: + doc = mapper.readValue(quote(SIMPLE_XML), Document.class); + } else { + // and then as plain Node (no difference) + Node node = mapper.readValue(quote(SIMPLE_XML), Node.class); + doc = (Document) node; + } + Element root = doc.getDocumentElement(); + assertNotNull(root); + // non-ns, simple... + assertEquals("root", root.getTagName()); + assertEquals("3", root.getAttribute("attr")); + assertEquals(1, root.getAttributes().getLength()); + NodeList nodes = root.getChildNodes(); + assertEquals(2, nodes.getLength()); + Element leaf = (Element) nodes.item(0); + assertEquals("leaf", leaf.getTagName()); + assertEquals(0, leaf.getAttributes().getLength()); + //"<root attr='3'><leaf>Rock & Roll!</leaf><?proc instr?></root>"; + ProcessingInstruction pi = (ProcessingInstruction) nodes.item(1); + assertEquals("proc", pi.getTarget()); + assertEquals("instr", pi.getData()); + } + } + + public void testDeserializeNS() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + Document doc = mapper.readValue(quote(SIMPLE_XML_NS), Document.class); + Element root = doc.getDocumentElement(); + assertNotNull(root); + assertEquals("root", root.getTagName()); + // Not sure if it ought to be "" or null... + String uri = root.getNamespaceURI(); + assertTrue((uri == null) || "".equals(uri)); + // no child nodes: + assertEquals(0, root.getChildNodes().getLength()); + // DOM is weird, includes ns decls as attributes... + assertEquals(2, root.getAttributes().getLength()); + assertEquals("abc", root.getAttributeNS("http://foo", "attr")); + } + + /* + ********************************************************** + * Helper methods + ********************************************************** + */ + + protected static String normalizeOutput(String output) + { + // XML declaration to get rid of? + output = output.trim(); + if (output.startsWith("<?xml")) { + // can find closing '>' of xml decl... + output = output.substring(output.indexOf('>')+1).trim(); + } + // And replace double quotes with single-quotes... + return output.replace('"', '\''); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/ext/TestJodaTime.java b/1.9.10/src/test/org/codehaus/jackson/map/ext/TestJodaTime.java new file mode 100644 index 0000000..6fd7dcb --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/ext/TestJodaTime.java
@@ -0,0 +1,244 @@ +package org.codehaus.jackson.map.ext; + +import java.io.*; +import java.util.*; + +import org.codehaus.jackson.map.*; + +import org.joda.time.*; + +/** + * Unit tests for verifying limited interoperability for Joda time. + * Basic support is added for handling {@link DateTime}; more can be + * added over time if and when requested. + */ +public class TestJodaTime + extends org.codehaus.jackson.map.BaseMapTest +{ + /* + /********************************************************** + /* Tests for DateTime (and closely related) + /********************************************************** + */ + + /** + * First: let's ensure that serialization does not fail + * with an error (see [JACKSON-157]). + */ + public void testSerialization() throws IOException + { + ObjectMapper m = new ObjectMapper(); + // let's use epoch time (Jan 1, 1970, UTC) + DateTime dt = new DateTime(0L, DateTimeZone.UTC); + // by default, dates use timestamp, so: + assertEquals("0", serializeAsString(m, dt)); + + // but if re-configured, as regular ISO-8601 string + m = new ObjectMapper(); + m.configure(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS, false); + assertEquals(quote("1970-01-01T00:00:00.000Z"), serializeAsString(m, dt)); + } + + /** + * Ok, then: should be able to convert from JSON String or Number, + * with standard deserializer we provide. + */ + public void testDeserFromNumber() throws IOException + { + Calendar cal = new GregorianCalendar(TimeZone.getTimeZone("GMT")); + // use some arbitrary but non-default time point (after 1.1.1970) + cal.set(Calendar.YEAR, 1972); + long timepoint = cal.getTime().getTime(); + + ObjectMapper mapper = new ObjectMapper(); + // Ok, first: using JSON number (milliseconds since epoch) + DateTime dt = mapper.readValue(String.valueOf(timepoint), DateTime.class); + assertEquals(timepoint, dt.getMillis()); + + // And then ISO-8601 String + dt = mapper.readValue(quote("1972-12-28T12:00:01.000+0000"), DateTime.class); + assertEquals("1972-12-28T12:00:01.000Z", dt.toString()); + } + + // @since 1.6 + public void testDeserReadableDateTime() throws IOException + { + ObjectMapper mapper = new ObjectMapper(); + ReadableDateTime date = mapper.readValue(quote("1972-12-28T12:00:01.000+0000"), ReadableDateTime.class); + assertNotNull(date); + assertEquals("1972-12-28T12:00:01.000Z", date.toString()); + + // since 1.6.1, for [JACKSON-360] + assertNull(mapper.readValue(quote(""), ReadableDateTime.class)); + } + + // @since 1.6 + public void testDeserReadableInstant() throws IOException + { + ObjectMapper mapper = new ObjectMapper(); + ReadableInstant date = mapper.readValue(quote("1972-12-28T12:00:01.000+0000"), ReadableInstant.class); + assertNotNull(date); + assertEquals("1972-12-28T12:00:01.000Z", date.toString()); + + // since 1.6.1, for [JACKSON-360] + assertNull(mapper.readValue(quote(""), ReadableInstant.class)); + } + + /* + /********************************************************** + /* Tests for DateMidnight type + /********************************************************** + */ + + // @since 1.5 + public void testDateMidnightSer() throws IOException + { + DateMidnight date = new DateMidnight(2001, 5, 25); + ObjectMapper mapper = new ObjectMapper(); + // default format is that of JSON array... + assertEquals("[2001,5,25]", mapper.writeValueAsString(date)); + // but we can force it to be a String as well (note: here we assume this is + // dynamically changeable) + mapper.configure(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS, false); + assertEquals(quote("2001-05-25"), mapper.writeValueAsString(date)); + } + + // @since 1.5 + public void testDateMidnightDeser() throws IOException + { + ObjectMapper mapper = new ObjectMapper(); + // couple of acceptable formats, so: + DateMidnight date = mapper.readValue("[2001,5,25]", DateMidnight.class); + assertEquals(2001, date.getYear()); + assertEquals(5, date.getMonthOfYear()); + assertEquals(25, date.getDayOfMonth()); + + DateMidnight date2 = mapper.readValue(quote("2005-07-13"), DateMidnight.class); + assertEquals(2005, date2.getYear()); + assertEquals(7, date2.getMonthOfYear()); + assertEquals(13, date2.getDayOfMonth()); + + // since 1.6.1, for [JACKSON-360] + assertNull(mapper.readValue(quote(""), DateMidnight.class)); + } + + /* + /********************************************************** + /* Tests for LocalDate type + /********************************************************** + */ + + // @since 1.5 + public void testLocalDateSer() throws IOException + { + LocalDate date = new LocalDate(2001, 5, 25); + ObjectMapper mapper = new ObjectMapper(); + // default format is that of JSON array... + assertEquals("[2001,5,25]", mapper.writeValueAsString(date)); + // but we can force it to be a String as well (note: here we assume this is + // dynamically changeable) + mapper.configure(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS, false); + assertEquals(quote("2001-05-25"), mapper.writeValueAsString(date)); + } + + // @since 1.5 + public void testLocalDateDeser() throws IOException + { + ObjectMapper mapper = new ObjectMapper(); + // couple of acceptable formats, so: + LocalDate date = mapper.readValue("[2001,5,25]", LocalDate.class); + assertEquals(2001, date.getYear()); + assertEquals(5, date.getMonthOfYear()); + assertEquals(25, date.getDayOfMonth()); + + LocalDate date2 = mapper.readValue(quote("2005-07-13"), LocalDate.class); + assertEquals(2005, date2.getYear()); + assertEquals(7, date2.getMonthOfYear()); + assertEquals(13, date2.getDayOfMonth()); + + // since 1.6.1, for [JACKSON-360] + assertNull(mapper.readValue(quote(""), LocalDate.class)); + } + + /* + /********************************************************** + /* Tests for LocalDateTime type + /********************************************************** + */ + + // @since 1.5 + public void testLocalDateTimeSer() throws IOException + { + LocalDateTime date = new LocalDateTime(2001, 5, 25, + 10, 15, 30, 37); + ObjectMapper mapper = new ObjectMapper(); + // default format is that of JSON array... + assertEquals("[2001,5,25,10,15,30,37]", mapper.writeValueAsString(date)); + // but we can force it to be a String as well (note: here we assume this is + // dynamically changeable) + mapper.configure(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS, false); + assertEquals(quote("2001-05-25T10:15:30.037"), mapper.writeValueAsString(date)); + } + + // @since 1.5 + public void testLocalDateTimeDeser() throws IOException + { + ObjectMapper mapper = new ObjectMapper(); + // couple of acceptable formats again: + LocalDateTime date = mapper.readValue("[2001,5,25,10,15,30,37]", LocalDateTime.class); + assertEquals(2001, date.getYear()); + assertEquals(5, date.getMonthOfYear()); + assertEquals(25, date.getDayOfMonth()); + + assertEquals(10, date.getHourOfDay()); + assertEquals(15, date.getMinuteOfHour()); + assertEquals(30, date.getSecondOfMinute()); + assertEquals(37, date.getMillisOfSecond()); + + LocalDateTime date2 = mapper.readValue(quote("2007-06-30T08:34:09.001"), LocalDateTime.class); + assertEquals(2007, date2.getYear()); + assertEquals(6, date2.getMonthOfYear()); + assertEquals(30, date2.getDayOfMonth()); + + assertEquals(8, date2.getHourOfDay()); + assertEquals(34, date2.getMinuteOfHour()); + assertEquals(9, date2.getSecondOfMinute()); + assertEquals(1, date2.getMillisOfSecond()); + + // since 1.6.1, for [JACKSON-360] + assertNull(mapper.readValue(quote(""), LocalDateTime.class)); + } + + /* + /********************************************************** + /* Tests for Period type + /********************************************************** + */ + + // @since 1.9.2 + public void testPeriodSer() throws IOException + { + Period in = new Period(1, 2, 3, 4); + String json = new ObjectMapper().writeValueAsString(in); + assertEquals(quote("PT1H2M3.004S"), json); + } + + // @since 1.9.2 + public void testPeriodDeser() throws IOException + { + Period out = new ObjectMapper().readValue(quote("PT1H2M3.004S"), Period.class); + assertEquals(1, out.getHours()); + assertEquals(2, out.getMinutes()); + assertEquals(3, out.getSeconds()); + assertEquals(4, out.getMillis()); + + // also, should work as number: + String json = String.valueOf(1000 * out.toStandardSeconds().getSeconds()); + out = new ObjectMapper().readValue(json, Period.class); + assertEquals(1, out.getHours()); + assertEquals(2, out.getMinutes()); + assertEquals(3, out.getSeconds()); + // but millis are actually truncated... + assertEquals(0, out.getMillis()); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/interop/TestCglibUsage.java b/1.9.10/src/test/org/codehaus/jackson/map/interop/TestCglibUsage.java new file mode 100644 index 0000000..3126f36 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/interop/TestCglibUsage.java
@@ -0,0 +1,75 @@ +package org.codehaus.jackson.map.interop; + +import main.BaseTest; + +import java.io.*; +import java.lang.reflect.Method; +import java.util.*; + +import net.sf.cglib.proxy.Enhancer; +import net.sf.cglib.proxy.MethodInterceptor; +import net.sf.cglib.proxy.MethodProxy; + +import org.codehaus.jackson.map.*; + +/** + * Unit test for checking that we can serialize CGLib generated proxies. + */ +public class TestCglibUsage + extends BaseTest +{ + /* + /********************************************************** + /* Helper classes + /********************************************************** + */ + + interface BeanInterface { + public int getX(); + } + + /* + /********************************************************** + /* Tests + /********************************************************** + */ + + public void testSimpleProxied() throws Exception + { + Enhancer enh = new Enhancer(); + enh.setInterfaces(new Class[] { BeanInterface.class }); + enh.setCallback(new MethodInterceptor() { + @Override + public Object intercept(Object obj, Method method, + Object[] args, MethodProxy proxy) + throws Throwable + { + if ("getX".equals(method.getName ())) { + return Integer.valueOf(13); + } + return proxy.invokeSuper(obj, args); + } + }); + BeanInterface bean = (BeanInterface) enh.create(); + ObjectMapper mapper = new ObjectMapper(); + Map<String,Object> result = writeAndMap(mapper, bean); + assertEquals(1, result.size()); + assertEquals(Integer.valueOf(13), result.get("x")); + } + + /* + ////////////////////////////////////////////// + // Helper methods + ////////////////////////////////////////////// + */ + + @SuppressWarnings("unchecked") + private Map<String,Object> writeAndMap(ObjectMapper m, Object value) + throws IOException + { + StringWriter sw = new StringWriter(); + m.writeValue(sw, value); + return (Map<String,Object>) m.readValue(sw.toString(), Object.class); + } +} +
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/interop/TestGoogleCollections.java b/1.9.10/src/test/org/codehaus/jackson/map/interop/TestGoogleCollections.java new file mode 100644 index 0000000..4e60dda --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/interop/TestGoogleCollections.java
@@ -0,0 +1,62 @@ +package org.codehaus.jackson.map.interop; + +import com.google.common.collect.*; + +import org.codehaus.jackson.annotate.JsonValue; +import org.codehaus.jackson.map.*; + +/** + * NOTE: this is bogus test currently (as of Jackson 1.6) -- not support + * has been added! + * + * @author tatu + */ +public class TestGoogleCollections + extends org.codehaus.jackson.map.BaseMapTest +{ + static class MapBean + { + // both class and method left non-public to verify that access is overridden + @JsonValue + protected ImmutableMap<String,Integer> toMap() + { + return new ImmutableMap.Builder<String,Integer>().put("a", 1).build(); + } + } + + // !!! NOTE: does not test that it produces anything useful... + public void testTrivialMultiMapSerialize() throws Exception + { + Multimap<String,String> map = HashMultimap.create(); + map.put("a", "1"); + String json = new ObjectMapper().writeValueAsString(map); + assertNotNull(json); + + /* + assertEquals("{\"a\":[\"1\"]}", json); + */ + } + + public void testMapWithJsonValue() throws Exception + { + assertEquals("{\"a\":1}", new ObjectMapper().writeValueAsString(new MapBean())); + } + + /*// fails similarly, for same reason + static class StdMapBean + { + @JsonValue + public Map<String,String> toMap() + { + HashMap<String,String> map = new HashMap<String,String>(); + map.put("a", "1"); + return map; + } + } + + public void testMapWithJsonValue2() throws Exception + { + assertEquals("{\"a\":1}", new ObjectMapper().writeValueAsString(new StdMapBean())); + } + */ +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/interop/TestGroovyBeans.java b/1.9.10/src/test/org/codehaus/jackson/map/interop/TestGroovyBeans.java new file mode 100644 index 0000000..2d474fb --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/interop/TestGroovyBeans.java
@@ -0,0 +1,75 @@ +package org.codehaus.jackson.map.interop; + +import java.util.*; + +import groovy.lang.GroovyClassLoader; + +import org.codehaus.jackson.map.*; + +/** + * Basic tests to see that simple Groovy beans can be serialized + * and deserialized + */ +public class TestGroovyBeans + extends org.codehaus.jackson.map.BaseMapTest +{ + final static String SIMPLE_POGO = + "public class GBean {\n" + +"long id = 3;\n" + +"String name = \"whome\";\n" + +"}"; + + + public void testSimpleSerialization() throws Exception + { + Object ob = newGroovyObject(SIMPLE_POGO); + Map<String,Object> result = writeAndMap(ob); + assertEquals(2, result.size()); + assertEquals("whome", result.get("name")); + /* 26-Nov-2009, tatu: Strange... Groovy seems to decide + * 'long' means 'int'... Oh well. + */ + Object num = result.get("id"); + assertNotNull(num); + assertTrue(num instanceof Number); + assertEquals(3, ((Number) num).intValue()); + } + + public void testSimpleDeserialization() throws Exception + { + Class<?> cls = defineGroovyClass(SIMPLE_POGO); + // First: deserialize from data + Object pogo = new ObjectMapper().readValue("{\"id\":9,\"name\":\"Bob\"}", cls); + assertNotNull(pogo); + /* Hmmh. Could try to access using Reflection, or by defining + * a Java interface it implements. Or, maybe simplest, just + * re-serialize and see what we got. + */ + Map<String,Object> result = writeAndMap(pogo); + assertEquals(2, result.size()); + assertEquals("Bob", result.get("name")); + // as per earlier, we just get a number... + Object num = result.get("id"); + assertNotNull(num); + assertTrue(num instanceof Number); + assertEquals(9, ((Number) num).intValue()); + } + + /* + ************************************************* + * Helper methods + ************************************************* + */ + + protected Class<?> defineGroovyClass(String src) throws Exception + { + return new GroovyClassLoader(getClass().getClassLoader()).parseClass(src); + + } + + protected Object newGroovyObject(String src) throws Exception + { + Class<?> cls = defineGroovyClass(src); + return cls.newInstance(); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/interop/TestHibernate.java b/1.9.10/src/test/org/codehaus/jackson/map/interop/TestHibernate.java new file mode 100644 index 0000000..e567307 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/interop/TestHibernate.java
@@ -0,0 +1,85 @@ +package org.codehaus.jackson.map.interop; + +import main.BaseTest; + +import java.io.*; +import java.lang.reflect.Method; +import java.util.*; + +import org.hibernate.repackage.cglib.proxy.Enhancer; +import org.hibernate.repackage.cglib.proxy.MethodInterceptor; +import org.hibernate.repackage.cglib.proxy.MethodProxy; + +import org.codehaus.jackson.map.*; + +/** + * Basic tests covering Hibernate-compatibility features. + */ +public class TestHibernate + extends BaseTest +{ + /* + /********************************************************** + /* Helper classes + /********************************************************** + */ + + interface BeanInterfaceHib { + public int getX(); + } + + /* + /********************************************************** + /* Tests + /********************************************************** + */ + + /* + * Unit test to test [JACKSON-177] + */ + public void testHibernateCglib() throws Exception + { + /* 03-Sep-2010, tatu: This often fails form Eclipse (on some platforms like Mac OS X), + * so let's only run it from Ant/CLI + */ + if (!runsFromAnt()) { + return; + } + + Enhancer enh = new Enhancer(); + enh.setInterfaces(new Class[] { BeanInterfaceHib.class }); + enh.setCallback(new MethodInterceptor() { + @Override + public Object intercept(Object obj, Method method, + Object[] args, MethodProxy proxy) + throws Throwable + { + if ("getX".equals(method.getName ())) { + return Integer.valueOf(13); + } + return proxy.invokeSuper(obj, args); + } + }); + BeanInterfaceHib bean = (BeanInterfaceHib) enh.create(); + ObjectMapper mapper = new ObjectMapper(); + Map<String,Object> result = writeAndMap(mapper, bean); + assertEquals(1, result.size()); + assertEquals(Integer.valueOf(13), result.get("x")); + } + + /* + /********************************************************** + /* Helper methods + /********************************************************** + */ + + @SuppressWarnings("unchecked") + private Map<String,Object> writeAndMap(ObjectMapper m, Object value) + throws IOException + { + StringWriter sw = new StringWriter(); + m.writeValue(sw, value); + return (Map<String,Object>) m.readValue(sw.toString(), Object.class); + } +} +
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/interop/TestJDKProxy.java b/1.9.10/src/test/org/codehaus/jackson/map/interop/TestJDKProxy.java new file mode 100644 index 0000000..ffec85f --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/interop/TestJDKProxy.java
@@ -0,0 +1,70 @@ +package org.codehaus.jackson.map.interop; + +import java.lang.reflect.*; + +import org.codehaus.jackson.map.*; + +// mostly for [Issue#57] +public class TestJDKProxy extends BaseMapTest +{ + final ObjectMapper MAPPER = new ObjectMapper(); + + public interface IPlanet { + String getName(); + String setName(String s); + } + + // bit silly example; usually wouldn't implement interface (no need to proxy if it did) + static class Planet implements IPlanet { + private String name; + + public Planet() { } + public Planet(String s) { name = s; } + + public String getName(){return name;} + public String setName(String iName) {name = iName; + return name; + } + } + + /* + /******************************************************** + /* Test methods + /******************************************************** + */ + + public void testSimple() throws Exception + { + IPlanet input = getProxy(IPlanet.class, new Planet("Foo")); + String json = MAPPER.writeValueAsString(input); + assertEquals("{\"name\":\"Foo\"}", json); + + // and just for good measure + Planet output = MAPPER.readValue(json, Planet.class); + assertEquals("Foo", output.getName()); + } + + /* + /******************************************************** + /* Helper methods + /******************************************************** + */ + + public static <T> T getProxy(Class<T> type, Object toProxy) { + class ProxyUtil implements InvocationHandler { + Object obj; + public ProxyUtil(Object o) { + obj = o; + } + public Object invoke(Object proxy, Method m, Object[] args) throws Throwable { + Object result = null; + result = m.invoke(obj, args); + return result; + } + } + @SuppressWarnings("unchecked") + T proxy = (T) Proxy.newProxyInstance(type.getClassLoader(), new Class[] { type }, + new ProxyUtil(toProxy)); + return proxy; + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/introspect/TestAnnotationMerging.java b/1.9.10/src/test/org/codehaus/jackson/map/introspect/TestAnnotationMerging.java new file mode 100644 index 0000000..6a03d82 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/introspect/TestAnnotationMerging.java
@@ -0,0 +1,96 @@ +package org.codehaus.jackson.map.introspect; + +import org.codehaus.jackson.annotate.JsonCreator; +import org.codehaus.jackson.annotate.JsonProperty; +import org.codehaus.jackson.annotate.JsonTypeInfo; +import org.codehaus.jackson.map.BaseMapTest; +import org.codehaus.jackson.map.ObjectMapper; + +/** + * Tests to verify that annotations are shared and merged between members + * of a property (getter and setter and so on) + * + * @since 1.9 + */ +public class TestAnnotationMerging extends BaseMapTest +{ + static class Wrapper + { + protected Object value; + + public Wrapper() { } + public Wrapper(Object o) { value = o; } + + @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS) + public Object getValue() { return value; } + + public void setValue(Object o) { value = o; } + } + + static class SharedName { + @JsonProperty("x") + protected int value; + + public SharedName(int v) { value = v; } + + public int getValue() { return value; } + } + + static class SharedName2 + { + @JsonProperty("x") + public int getValue() { return 1; } + public void setValue(int x) { } + } + + // Testing to ensure that ctor param and getter can "share" @JsonTypeInfo stuff + static class TypeWrapper + { + protected Object value; + + @JsonCreator + public TypeWrapper( + @JsonProperty("value") + @JsonTypeInfo(use = JsonTypeInfo.Id.CLASS) Object o) { + value = o; + } + public Object getValue() { return value; } + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + public void testSharedNames() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + assertEquals("{\"x\":6}", mapper.writeValueAsString(new SharedName(6))); + } + + public void testSharedNamesFromGetterToSetter() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + String json = mapper.writeValueAsString(new SharedName2()); + assertEquals("{\"x\":1}", json); + SharedName2 result = mapper.readValue(json, SharedName2.class); + assertNotNull(result); + } + + public void testSharedTypeInfo() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + String json = mapper.writeValueAsString(new Wrapper(13L)); + Wrapper result = mapper.readValue(json, Wrapper.class); + assertEquals(Long.class, result.value.getClass()); + } + + public void testSharedTypeInfoWithCtor() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + String json = mapper.writeValueAsString(new TypeWrapper(13L)); + TypeWrapper result = mapper.readValue(json, TypeWrapper.class); + assertEquals(Long.class, result.value.getClass()); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/introspect/TestJacksonAnnotationIntrospector.java b/1.9.10/src/test/org/codehaus/jackson/map/introspect/TestJacksonAnnotationIntrospector.java new file mode 100644 index 0000000..d867512 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/introspect/TestJacksonAnnotationIntrospector.java
@@ -0,0 +1,218 @@ +package org.codehaus.jackson.map.introspect; + +import java.io.IOException; +import java.io.StringWriter; +import java.util.*; +import javax.xml.namespace.QName; + +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.annotate.*; +import org.codehaus.jackson.annotate.JsonTypeInfo; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.JsonDeserialize; +import org.codehaus.jackson.map.annotate.JsonSerialize; +import org.codehaus.jackson.map.annotate.JsonTypeResolver; +import org.codehaus.jackson.map.deser.std.StdDeserializer; +import org.codehaus.jackson.map.jsontype.TypeResolverBuilder; +import org.codehaus.jackson.map.jsontype.impl.StdTypeResolverBuilder; +import org.codehaus.jackson.map.type.TypeFactory; +import org.codehaus.jackson.type.JavaType; + +/** + * @author Ryan Heaton + */ +public class TestJacksonAnnotationIntrospector + extends BaseMapTest +{ + public static enum EnumExample { + VALUE1; + } + + public static class JacksonExample + { + private String attributeProperty; + private String elementProperty; + private List<String> wrappedElementProperty; + private EnumExample enumProperty; + private QName qname; + + @JsonSerialize(using=QNameSerializer.class) + public QName getQname() + { + return qname; + } + + @JsonDeserialize(using=QNameDeserializer.class) + public void setQname(QName qname) + { + this.qname = qname; + } + + @JsonProperty("myattribute") + public String getAttributeProperty() + { + return attributeProperty; + } + + @JsonProperty("myattribute") + public void setAttributeProperty(String attributeProperty) + { + this.attributeProperty = attributeProperty; + } + + @JsonProperty("myelement") + public String getElementProperty() + { + return elementProperty; + } + + @JsonProperty("myelement") + public void setElementProperty(String elementProperty) + { + this.elementProperty = elementProperty; + } + + @JsonProperty("mywrapped") + public List<String> getWrappedElementProperty() + { + return wrappedElementProperty; + } + + @JsonProperty("mywrapped") + public void setWrappedElementProperty(List<String> wrappedElementProperty) + { + this.wrappedElementProperty = wrappedElementProperty; + } + + public EnumExample getEnumProperty() + { + return enumProperty; + } + + public void setEnumProperty(EnumExample enumProperty) + { + this.enumProperty = enumProperty; + } + } + + public static class QNameSerializer extends JsonSerializer<QName> { + + @Override + public void serialize(QName value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonProcessingException + { + jgen.writeString(value.toString()); + } + } + + + public static class QNameDeserializer extends StdDeserializer<QName> + { + public QNameDeserializer() { super(QName.class); } + @Override + public QName deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + return QName.valueOf(jp.readValueAs(String.class)); + } + } + + public static class DummyBuilder extends StdTypeResolverBuilder + //<DummyBuilder> + { + } + + @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS) + @JsonTypeResolver(DummyBuilder.class) + static class TypeResolverBean { } + + // @since 1.7 + @JsonIgnoreType + static class IgnoredType { } + + static class IgnoredSubType extends IgnoredType { } + + // Test to ensure we can override enum settings + static class LcEnumIntrospector extends JacksonAnnotationIntrospector + { + @Override + public String findEnumValue(Enum<?> value) + { + return value.name().toLowerCase(); + } + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + /** + * tests getting serializer/deserializer instances. + */ + public void testSerializeDeserializeWithJaxbAnnotations() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.enable(SerializationConfig.Feature.INDENT_OUTPUT); + JacksonExample ex = new JacksonExample(); + QName qname = new QName("urn:hi", "hello"); + ex.setQname(qname); + ex.setAttributeProperty("attributeValue"); + ex.setElementProperty("elementValue"); + ex.setWrappedElementProperty(Arrays.asList("wrappedElementValue")); + ex.setEnumProperty(EnumExample.VALUE1); + StringWriter writer = new StringWriter(); + mapper.writeValue(writer, ex); + writer.flush(); + writer.close(); + + String json = writer.toString(); + JacksonExample readEx = mapper.readValue(json, JacksonExample.class); + + assertEquals(ex.qname, readEx.qname); + assertEquals(ex.attributeProperty, readEx.attributeProperty); + assertEquals(ex.elementProperty, readEx.elementProperty); + assertEquals(ex.wrappedElementProperty, readEx.wrappedElementProperty); + assertEquals(ex.enumProperty, readEx.enumProperty); + } + + public void testJsonTypeResolver() throws Exception + { + JacksonAnnotationIntrospector ai = new JacksonAnnotationIntrospector(); + AnnotatedClass ac = AnnotatedClass.constructWithoutSuperTypes(TypeResolverBean.class, ai, null); + JavaType baseType = TypeFactory.defaultInstance().constructType(TypeResolverBean.class); + ObjectMapper mapper = new ObjectMapper(); + TypeResolverBuilder<?> rb = ai.findTypeResolver(mapper.getDeserializationConfig(), ac, baseType); + assertNotNull(rb); + assertSame(DummyBuilder.class, rb.getClass()); + } + + /** + * Tests to ensure that {@link JsonIgnoreType} is detected as expected + * by the standard introspector. + * + * @since 1.7 + */ + public void testIgnoredType() throws Exception + { + JacksonAnnotationIntrospector ai = new JacksonAnnotationIntrospector(); + AnnotatedClass ac = AnnotatedClass.construct(IgnoredType.class, ai, null); + assertEquals(Boolean.TRUE, ai.isIgnorableType(ac)); + + // also, should inherit as expected + ac = AnnotatedClass.construct(IgnoredSubType.class, ai, null); + assertEquals(Boolean.TRUE, ai.isIgnorableType(ac)); + } + + public void testEnumHandling() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.setAnnotationIntrospector(new LcEnumIntrospector()); + assertEquals("\"value1\"", mapper.writeValueAsString(EnumExample.VALUE1)); + EnumExample result = mapper.readValue(quote("value1"), EnumExample.class); + assertEquals(EnumExample.VALUE1, result); + } +} \ No newline at end of file
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/introspect/TestPOJOPropertiesCollector.java b/1.9.10/src/test/org/codehaus/jackson/map/introspect/TestPOJOPropertiesCollector.java new file mode 100644 index 0000000..404bfd1 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/introspect/TestPOJOPropertiesCollector.java
@@ -0,0 +1,388 @@ +package org.codehaus.jackson.map.introspect; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import org.codehaus.jackson.annotate.*; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.JsonDeserialize; + +/** + * @since 1.9 + */ +public class TestPOJOPropertiesCollector + extends BaseMapTest +{ + static class Simple { + public int value; + + @JsonProperty("value") + public void valueSetter(int v) { value = v; } + + @JsonProperty("value") + public int getFoobar() { return value; } + } + + static class SimpleFieldDeser + { + @JsonDeserialize String[] values; + } + + static class SimpleGetterVisibility { + public int getA() { return 0; } + protected int getB() { return 1; } + @SuppressWarnings("unused") + private int getC() { return 2; } + } + + // Class for testing 'shared ignore' + static class Empty { + public int value; + + public void setValue(int v) { value = v; } + + @JsonIgnore + public int getValue() { return value; } + } + + static class IgnoredSetter { + @JsonProperty + public int value; + + @JsonIgnore + public void setValue(int v) { value = v; } + + public int getValue() { return value; } + } + + static class ImplicitIgnores { + @JsonIgnore public int a; + @JsonIgnore public void setB(int b) { } + public int c; + } + + // Should find just one setter for "y", due to partial ignore + static class IgnoredRenamedSetter { + @JsonIgnore public void setY(int value) { } + @JsonProperty("y") void foobar(int value) { } + } + + // should produce a single property, "x" + static class RenamedProperties { + @JsonProperty("x") + public int value; + + public void setValue(int v) { value = v; } + + public int getX() { return value; } + } + + static class RenamedProperties2 + { + @JsonProperty("renamed") + public int getValue() { return 1; } + public void setValue(int x) { } + } + + // Testing that we can "merge" properties with renaming + static class MergedProperties { + public int x; + + @JsonProperty("x") + public void setFoobar(int v) { x = v; } + } + + // Testing that property order is obeyed, even for deserialization purposes + @JsonPropertyOrder({"a", "b", "c", "d"}) + static class SortedProperties + { + public int b; + public int c; + + public void setD(int value) { } + public void setA(int value) { } + } + + // [JACKSON-700]: test property type detection, selection + static class TypeTestBean + { + protected Long value; + + @JsonCreator + public TypeTestBean(@JsonProperty("value") String value) { } + + // If you remove this method, the test will pass + public Integer getValue() { return 0; } + } + + static class Jackson703 + { + private List<FoodOrgLocation> location = new ArrayList<FoodOrgLocation>(); + + { + location.add(new FoodOrgLocation()); + } + + public List<FoodOrgLocation> getLocation() { return location; } + } + + static class FoodOrgLocation + { + protected Long id; + public String name; + protected Location location; + + public FoodOrgLocation() { + location = new Location(); + } + + public FoodOrgLocation(final Location foodOrg) { } + + public FoodOrgLocation(final Long id, final String name, final Location location) { } + + public Location getLocation() { return location; } + } + + static class Location { + public BigDecimal lattitude; + public BigDecimal longitude; + + public Location() { } + + public Location(final BigDecimal lattitude, final BigDecimal longitude) { } + } + + class Issue701Bean { // important: non-static! + private int i; + + // annotation does not matter -- just need one on the last argument + public Issue701Bean(@JsonProperty int i) { this.i = i; } + + public int getX() { return i; } + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + public void testSimple() + { + POJOPropertiesCollector coll = collector(Simple.class, true); + Map<String, POJOPropertyBuilder> props = coll.getPropertyMap(); + assertEquals(1, props.size()); + POJOPropertyBuilder prop = props.get("value"); + assertNotNull(prop); + assertTrue(prop.hasSetter()); + assertTrue(prop.hasGetter()); + assertTrue(prop.hasField()); + } + + public void testSimpleFieldVisibility() + { + // false -> deserialization + POJOPropertiesCollector coll = collector(SimpleFieldDeser.class, false); + Map<String, POJOPropertyBuilder> props = coll.getPropertyMap(); + assertEquals(1, props.size()); + POJOPropertyBuilder prop = props.get("values"); + assertNotNull(prop); + assertFalse(prop.hasSetter()); + assertFalse(prop.hasGetter()); + assertTrue(prop.hasField()); + } + + public void testSimpleGetterVisibility() + { + POJOPropertiesCollector coll = collector(SimpleGetterVisibility.class, true); + Map<String, POJOPropertyBuilder> props = coll.getPropertyMap(); + assertEquals(1, props.size()); + POJOPropertyBuilder prop = props.get("a"); + assertNotNull(prop); + assertFalse(prop.hasSetter()); + assertTrue(prop.hasGetter()); + assertFalse(prop.hasField()); + } + + // Unit test for verifying that a single @JsonIgnore can remove the + // whole property, unless explicit property marker exists + public void testEmpty() + { + POJOPropertiesCollector coll = collector(Empty.class, true); + Map<String, POJOPropertyBuilder> props = coll.getPropertyMap(); + assertEquals(0, props.size()); + } + + // Unit test for verifying handling of 'partial' @JsonIgnore; that is, + // if there is at least one explicit annotation to indicate property, + // only parts that are ignored are, well, ignored + public void testPartialIgnore() + { + POJOPropertiesCollector coll = collector(IgnoredSetter.class, true); + Map<String, POJOPropertyBuilder> props = coll.getPropertyMap(); + assertEquals(1, props.size()); + POJOPropertyBuilder prop = props.get("value"); + assertNotNull(prop); + assertFalse(prop.hasSetter()); + assertTrue(prop.hasGetter()); + assertTrue(prop.hasField()); + } + + public void testSimpleRenamed() + { + POJOPropertiesCollector coll = collector(RenamedProperties.class, true); + Map<String, POJOPropertyBuilder> props = coll.getPropertyMap(); + assertEquals(1, props.size()); + POJOPropertyBuilder prop = props.get("x"); + assertNotNull(prop); + assertTrue(prop.hasSetter()); + assertTrue(prop.hasGetter()); + assertTrue(prop.hasField()); + } + + public void testSimpleRenamed2() + { + POJOPropertiesCollector coll = collector(RenamedProperties2.class, true); + Map<String, POJOPropertyBuilder> props = coll.getPropertyMap(); + assertEquals(1, props.size()); + POJOPropertyBuilder prop = props.get("renamed"); + assertNotNull(prop); + assertTrue(prop.hasSetter()); + assertTrue(prop.hasGetter()); + assertFalse(prop.hasField()); + } + + public void testMergeWithRename() + { + POJOPropertiesCollector coll = collector(MergedProperties.class, true); + Map<String, POJOPropertyBuilder> props = coll.getPropertyMap(); + assertEquals(1, props.size()); + POJOPropertyBuilder prop = props.get("x"); + assertNotNull(prop); + assertTrue(prop.hasSetter()); + assertFalse(prop.hasGetter()); + assertTrue(prop.hasField()); + } + + public void testSimpleIgnoreAndRename() + { + POJOPropertiesCollector coll = collector(IgnoredRenamedSetter.class, true); + Map<String, POJOPropertyBuilder> props = coll.getPropertyMap(); + assertEquals(1, props.size()); + POJOPropertyBuilder prop = props.get("y"); + assertNotNull(prop); + assertTrue(prop.hasSetter()); + assertFalse(prop.hasGetter()); + assertFalse(prop.hasField()); + } + + public void testGlobalVisibilityForGetters() + { + ObjectMapper m = new ObjectMapper(); + m.configure(SerializationConfig.Feature.AUTO_DETECT_GETTERS, false); + POJOPropertiesCollector coll = collector(m, SimpleGetterVisibility.class, true); + // should be 1, expect that we disabled getter auto-detection, so + Map<String, POJOPropertyBuilder> props = coll.getPropertyMap(); + assertEquals(0, props.size()); + } + + public void testCollectionOfIgnored() + { + ObjectMapper m = new ObjectMapper(); + POJOPropertiesCollector coll = collector(m, ImplicitIgnores.class, false); + // should be 1, due to ignorals + Map<String, POJOPropertyBuilder> props = coll.getPropertyMap(); + assertEquals(1, props.size()); + // but also have 2 ignored properties + Collection<String> ign = coll.getIgnoredPropertyNames(); + assertEquals(2, ign.size()); + assertTrue(ign.contains("a")); + assertTrue(ign.contains("b")); + } + + public void testSimpleOrderingForDeserialization() + { + ObjectMapper m = new ObjectMapper(); + POJOPropertiesCollector coll = collector(m, SortedProperties.class, false); + List<BeanPropertyDefinition> props = coll.getProperties(); + assertEquals(4, props.size()); + assertEquals("a", props.get(0).getName()); + assertEquals("b", props.get(1).getName()); + assertEquals("c", props.get(2).getName()); + assertEquals("d", props.get(3).getName()); + } + + public void testSimpleWithType() + { + ObjectMapper mapper = new ObjectMapper(); + // first for serialization; should base choice on getter + POJOPropertiesCollector coll = collector(mapper, TypeTestBean.class, true); + List<BeanPropertyDefinition> props = coll.getProperties(); + assertEquals(1, props.size()); + assertEquals("value", props.get(0).getName()); + AnnotatedMember m = props.get(0).getAccessor(); + assertTrue(m instanceof AnnotatedMethod); + assertEquals(Integer.class, m.getRawType()); + + // then for deserialization; prefer ctor param + coll = collector(mapper, TypeTestBean.class, false); + props = coll.getProperties(); + assertEquals(1, props.size()); + assertEquals("value", props.get(0).getName()); + m = props.get(0).getMutator(); + assertEquals(AnnotatedParameter.class, m.getClass()); + assertEquals(String.class, m.getRawType()); + } + + // for [JACKSON-701] + public void testInnerClassWithAnnotationsInCreator() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + BasicBeanDescription beanDesc; + // first with serialization + beanDesc = mapper.getSerializationConfig().introspect(mapper.constructType(Issue701Bean.class)); + assertNotNull(beanDesc); + // then with deserialization + beanDesc = mapper.getDeserializationConfig().introspect(mapper.constructType(Issue701Bean.class)); + assertNotNull(beanDesc); + } + + public void testJackson703() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.configure(SerializationConfig.Feature.USE_ANNOTATIONS, false); + BasicBeanDescription beanDesc = mapper.getSerializationConfig().introspect(mapper.constructType(Jackson703.class)); + assertNotNull(beanDesc); + + Jackson703 bean = new Jackson703(); + String json = mapper.writeValueAsString(bean); + assertNotNull(json); + } + + /* + /********************************************************** + /* Helper methods + /********************************************************** + */ + + protected POJOPropertiesCollector collector(Class<?> cls, boolean forSerialization) + { + return collector(new ObjectMapper(), cls, forSerialization); + } + + protected POJOPropertiesCollector collector(ObjectMapper mapper, + Class<?> cls, boolean forSerialization) + { + BasicClassIntrospector bci = new BasicClassIntrospector(); + // no real difference between serialization, deserialization, at least here + if (forSerialization) { + return bci.collectProperties(mapper.getSerializationConfig(), + mapper.constructType(cls), null, true); + } + return bci.collectProperties(mapper.getDeserializationConfig(), + mapper.constructType(cls), null, false); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestAbstractTypeNames.java b/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestAbstractTypeNames.java new file mode 100644 index 0000000..48f0025 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestAbstractTypeNames.java
@@ -0,0 +1,135 @@ +package org.codehaus.jackson.map.jsontype; + +import java.util.ArrayList; +import java.util.List; + +import org.codehaus.jackson.annotate.*; +import org.codehaus.jackson.annotate.JsonTypeInfo.As; +import org.codehaus.jackson.annotate.JsonTypeInfo.Id; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.ObjectMapper.DefaultTyping; + +/** + * Unit tests for checking how combination of interfaces, implementation + * classes are handled, with respect to type names. + * + * @since 1.8 + */ +public class TestAbstractTypeNames extends BaseMapTest +{ + @JsonTypeName("Employee") + public interface Employee extends User { + public abstract String getEmployer(); + } + + @JsonTypeInfo(use=Id.NAME, include=As.PROPERTY, property="userType") + @JsonTypeName("User") + @JsonSubTypes({ @JsonSubTypes.Type(value=Employee.class,name="Employee") }) + public interface User { + public abstract String getName(); + public abstract List<User> getFriends(); + } + + @JsonTypeName("Employee") + static class DefaultEmployee extends DefaultUser implements Employee + { + private String _employer; + + @JsonCreator + public DefaultEmployee(@JsonProperty("name") String name, + @JsonProperty("friends") List<User> friends, + @JsonProperty("employer") String employer) { + super(name, friends); + _employer = employer; + } + + @Override + public String getEmployer() { + return _employer; + } + } + + @JsonTypeInfo(use=Id.NAME, include=As.PROPERTY, property="userType") + @JsonTypeName("User") + @JsonSubTypes({ @JsonSubTypes.Type(value=DefaultEmployee.class,name="Employee") }) + static class DefaultUser implements User + { + private String _name; + private List<User> _friends; + + @JsonCreator + public DefaultUser(@JsonProperty("name") String name, + @JsonProperty("friends") List<User> friends) + { + super(); + _name = name; + _friends = friends; + } + + @Override public String getName() { + return _name; + } + + @Override public List<User> getFriends() { + return _friends; + } + } + + static class BaseValue { + public int value = 42; + + public int getValue() { return value; } + } + + final static class BeanWithAnon { + public BaseValue bean = new BaseValue() { + @Override + public String toString() { return "sub!"; } + }; + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + // Testing [JACKSON-498], partial fix + public void testEmptyCollection() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, true); + List<User>friends = new ArrayList<User>(); + friends.add(new DefaultUser("Joe Hildebrandt", null)); + friends.add(new DefaultEmployee("Richard Nasr",null,"MDA")); + + User user = new DefaultEmployee("John Vanspronssen", friends, "MDA"); + String json = mapper.writeValueAsString(user); + + /* 24-Feb-2011, tatu: For now let's simply require registration of + * concrete subtypes; can't think of a way to avoid that for now + */ + mapper = new ObjectMapper(); + mapper.registerSubtypes(DefaultEmployee.class); + mapper.registerSubtypes(DefaultUser.class); + + User result = mapper.readValue(json, User.class); + assertNotNull(result); + assertEquals(DefaultEmployee.class, result.getClass()); + + friends = result.getFriends(); + assertEquals(2, friends.size()); + assertEquals(DefaultUser.class, friends.get(0).getClass()); + assertEquals(DefaultEmployee.class, friends.get(1).getClass()); + } + + // [JACKSON-584]: change anonymous non-static inner type into static type: + public void testInnerClassWithType() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.enableDefaultTyping(DefaultTyping.NON_FINAL); + String json = mapper.writeValueAsString(new BeanWithAnon()); + BeanWithAnon result = mapper.readValue(json, BeanWithAnon.class); + assertEquals(BeanWithAnon.class, result.getClass()); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestCustomTypeIdResolver.java b/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestCustomTypeIdResolver.java new file mode 100644 index 0000000..cc17c11 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestCustomTypeIdResolver.java
@@ -0,0 +1,94 @@ +package org.codehaus.jackson.map.jsontype; + +import java.util.*; + +import org.codehaus.jackson.annotate.JsonTypeInfo; +import org.codehaus.jackson.annotate.JsonTypeInfo.Id; +import org.codehaus.jackson.annotate.JsonTypeInfo.As; +import org.codehaus.jackson.map.BaseMapTest; +import org.codehaus.jackson.map.ObjectMapper; +import org.codehaus.jackson.map.annotate.JsonTypeIdResolver; +import org.codehaus.jackson.map.jsontype.TypeIdResolver; +import org.codehaus.jackson.map.type.TypeFactory; +import org.codehaus.jackson.type.JavaType; + +public class TestCustomTypeIdResolver extends BaseMapTest +{ + @JsonTypeInfo(use=Id.CUSTOM, include=As.WRAPPER_OBJECT) + @JsonTypeIdResolver(CustomResolver.class) + static class CustomBean { + public int x; + + public CustomBean() { } + public CustomBean(int x) { this.x = x; } + } + + static class CustomResolver implements TypeIdResolver + { + static List<JavaType> initTypes; + + public CustomResolver() { } + + @Override + public Id getMechanism() { + return Id.CUSTOM; + } + + @Override + public String idFromValue(Object value) + { + if (value.getClass() == CustomBean.class) { + return "*"; + } + return "unknown"; + } + + @Override + public String idFromValueAndType(Object value, Class<?> type) { + return idFromValue(value); + } + + @Override + public void init(JavaType baseType) { + if (initTypes != null) { + initTypes.add(baseType); + } + } + + @Override + public JavaType typeFromId(String id) + { + if ("*".equals(id)) { + return TypeFactory.defaultInstance().constructType(CustomBean.class); + } + return null; + } + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + // for [JACKSON-359] + public void testCustomTypeIdResolver() throws Exception + { + ObjectMapper m = new ObjectMapper(); + List<JavaType> types = new ArrayList<JavaType>(); + CustomResolver.initTypes = types; + String json = m.writeValueAsString(new CustomBean[] { new CustomBean(28) }); + assertEquals("[{\"*\":{\"x\":28}}]", json); + assertEquals(1, types.size()); + assertEquals(CustomBean.class, types.get(0).getRawClass()); + + types = new ArrayList<JavaType>(); + CustomResolver.initTypes = types; + CustomBean[] result = m.readValue(json, CustomBean[].class); + assertNotNull(result); + assertEquals(1, result.length); + assertEquals(28, result[0].x); + assertEquals(1, types.size()); + assertEquals(CustomBean.class, types.get(0).getRawClass()); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestDefaultForArrays.java b/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestDefaultForArrays.java new file mode 100644 index 0000000..49683af --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestDefaultForArrays.java
@@ -0,0 +1,106 @@ +package org.codehaus.jackson.map.jsontype; + +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.annotate.JsonTypeInfo; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.ObjectMapper.DefaultTyping; + +public class TestDefaultForArrays extends BaseMapTest +{ + /* + /********************************************************** + /* Helper types + /********************************************************** + */ + + static class ArrayBean { + public Object[] values; + + public ArrayBean() { this(null); } + public ArrayBean(Object[] v) { values = v; } + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + /** + * Simple unit test for verifying that we get String array + * back, even though declared type is Object array + */ + public void testArrayTypingSimple() throws Exception + { + ObjectMapper m = new ObjectMapper(); + m.enableDefaultTyping(DefaultTyping.NON_CONCRETE_AND_ARRAYS); + ArrayBean bean = new ArrayBean(new String[0]); + String json = m.writeValueAsString(bean); + ArrayBean result = m.readValue(json, ArrayBean.class); + assertNotNull(result.values); + assertEquals(String[].class, result.values.getClass()); + } + + // And let's try it with deeper array as well + public void testArrayTypingNested() throws Exception + { + ObjectMapper m = new ObjectMapper(); + m.enableDefaultTyping(DefaultTyping.NON_CONCRETE_AND_ARRAYS); + ArrayBean bean = new ArrayBean(new String[0][0]); + String json = m.writeValueAsString(bean); + ArrayBean result = m.readValue(json, ArrayBean.class); + assertNotNull(result.values); + assertEquals(String[][].class, result.values.getClass()); + } + + // @since 1.8 + public void testNodeInArray() throws Exception + { + JsonNode node = new ObjectMapper().readTree("{\"a\":3}"); + + ObjectMapper m = new ObjectMapper(); + m.enableDefaultTyping(DefaultTyping.JAVA_LANG_OBJECT); + Object[] obs = new Object[] { node }; + String json = m.writeValueAsString(obs); + Object[] result = m.readValue(json, Object[].class); + assertEquals(1, result.length); + Object ob = result[0]; + assertTrue(ob instanceof JsonNode); + } + + + // test for [JACKSON-845] + public void testArraysOfArrays() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY); + + Object value = new Object[][] { new Object[] {} }; + String json = mapper.writeValueAsString(value); + + // try with different (but valid) nominal types: + _testArraysAs(mapper, json, Object[][].class); + _testArraysAs(mapper, json, Object[].class); + _testArraysAs(mapper, json, Object.class); + } + + /* + /********************************************************** + /* Helper methods + /********************************************************** + */ + + protected void _testArraysAs(ObjectMapper mapper, String json, Class<?> type) + throws Exception + { + Object o = mapper.readValue(json, type); + assertNotNull(o); + assertTrue(o instanceof Object[]); + Object[] main = (Object[]) o; + assertEquals(1, main.length); + Object element = main[0]; + assertNotNull(element); + assertTrue(element instanceof Object[]); + assertEquals(0, ((Object[]) element).length); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestDefaultForEnums.java b/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestDefaultForEnums.java new file mode 100644 index 0000000..f8a5d6e --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestDefaultForEnums.java
@@ -0,0 +1,77 @@ +package org.codehaus.jackson.map.jsontype; + +import java.util.concurrent.TimeUnit; + +import org.codehaus.jackson.map.BaseMapTest; +import org.codehaus.jackson.map.ObjectMapper; + +public class TestDefaultForEnums + extends BaseMapTest +{ + public enum TestEnum { + A, B; + } + + static final class EnumHolder + { + public Object value; // "untyped" + + public EnumHolder() { } + public EnumHolder(TestEnum e) { value = e; } + } + + protected static class TimeUnitBean { + public TimeUnit timeUnit; + } + + /* + /********************************************************** + /* Test methods + /********************************************************** + */ + + public void testSimpleEnumBean() throws Exception + { + TimeUnitBean bean = new TimeUnitBean(); + bean.timeUnit = TimeUnit.HOURS; + + // First, without type info + ObjectMapper m = new ObjectMapper(); + String json = m.writeValueAsString(bean); + TimeUnitBean result = m.readValue(json, TimeUnitBean.class); + assertEquals(TimeUnit.HOURS, result.timeUnit); + + // then with type info + m = new ObjectMapper(); + m.enableDefaultTyping(); + json = m.writeValueAsString(bean); + result = m.readValue(json, TimeUnitBean.class); + + assertEquals(TimeUnit.HOURS, result.timeUnit); + } + + public void testSimpleEnumsInObjectArray() throws Exception + { + ObjectMapper m = new ObjectMapper(); + m.enableDefaultTyping(); + + // Typing is needed for enums + String json = m.writeValueAsString(new Object[] { TestEnum.A }); + assertEquals("[[\"org.codehaus.jackson.map.jsontype.TestDefaultForEnums$TestEnum\",\"A\"]]", json); + + // and let's verify we get it back ok as well: + Object[] value = m.readValue(json, Object[].class); + assertEquals(1, value.length); + assertSame(TestEnum.A, value[0]); + } + + public void testSimpleEnumsAsField() throws Exception + { + ObjectMapper m = new ObjectMapper(); + m.enableDefaultTyping(); + String json = m.writeValueAsString(new EnumHolder(TestEnum.B)); + assertEquals("{\"value\":[\"org.codehaus.jackson.map.jsontype.TestDefaultForEnums$TestEnum\",\"B\"]}", json); + EnumHolder holder = m.readValue(json, EnumHolder.class); + assertSame(TestEnum.B, holder.value); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestDefaultForLists.java b/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestDefaultForLists.java new file mode 100644 index 0000000..caa746e --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestDefaultForLists.java
@@ -0,0 +1,145 @@ +package org.codehaus.jackson.map.jsontype; + +import java.util.*; + +import org.codehaus.jackson.annotate.JsonTypeInfo; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.ObjectMapper.DefaultTyping; + +public class TestDefaultForLists + extends BaseMapTest +{ + /* + /********************************************************** + /* Helper types + /********************************************************** + */ + + /** + * Wrapper bean needed before there is a way to force + * type of the root value. Long is used because it is a final + * type, but not one of "untypeable" ones. + */ + static class ListOfLongs { + public List<Long> longs; + + public ListOfLongs() { } + public ListOfLongs(Long ... ls) { + longs = new ArrayList<Long>(); + for (Long l: ls) { + longs.add(l); + } + } + } + + static class ListOfNumbers { + public List<Number> nums; + + public ListOfNumbers() { } + public ListOfNumbers(Number ... numbers) { + nums = new ArrayList<Number>(); + for (Number n : numbers) { + nums.add(n); + } + } + } + + static class ObjectListBean { + public List<Object> values; + } + + interface Foo { } + + static class SetBean { + public Set<String> names; + + public SetBean() { } + public SetBean(String str) { + names = new HashSet<String>(); + names.add(str); + } + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + public void testListOfLongs() throws Exception + { + ObjectMapper m = new ObjectMapper(); + m.enableDefaultTyping(); + ListOfLongs input = new ListOfLongs(1L, 2L, 3L); + String json = m.writeValueAsString(input); + assertEquals("{\"longs\":[\"java.util.ArrayList\",[1,2,3]]}", json); + ListOfLongs output = m.readValue(json, ListOfLongs.class); + + assertNotNull(output.longs); + assertEquals(3, output.longs.size()); + assertEquals(Long.valueOf(1L), output.longs.get(0)); + assertEquals(Long.valueOf(2L), output.longs.get(1)); + assertEquals(Long.valueOf(3L), output.longs.get(2)); + } + + /** + * Then bit more heterogenous list; also tests mixing of + * regular scalar types, and non-typed ones (int and double + * will never have type info added; other numbers will if + * necessary) + */ + public void testListOfNumbers() throws Exception + { + ObjectMapper m = new ObjectMapper(); + m.enableDefaultTyping(); + ListOfNumbers input = new ListOfNumbers(Long.valueOf(1L), Integer.valueOf(2), Double.valueOf(3.0)); + String json = m.writeValueAsString(input); + assertEquals("{\"nums\":[\"java.util.ArrayList\",[[\"java.lang.Long\",1],2,3.0]]}", json); + ListOfNumbers output = m.readValue(json, ListOfNumbers.class); + + assertNotNull(output.nums); + assertEquals(3, output.nums.size()); + assertEquals(Long.valueOf(1L), output.nums.get(0)); + assertEquals(Integer.valueOf(2), output.nums.get(1)); + assertEquals(Double.valueOf(3.0), output.nums.get(2)); + } + + public void testDateTypes() throws Exception + { + ObjectMapper m = new ObjectMapper(); + m.enableDefaultTyping(); + ObjectListBean input = new ObjectListBean(); + List<Object> inputList = new ArrayList<Object>(); + inputList.add(TimeZone.getTimeZone("EST")); + inputList.add(Locale.CHINESE); + input.values = inputList; + String json = m.writeValueAsString(input); + + ObjectListBean output = m.readValue(json, ObjectListBean.class); + List<Object> outputList = output.values; + assertEquals(2, outputList.size()); + assertTrue(outputList.get(0) instanceof TimeZone); + assertTrue(outputList.get(1) instanceof Locale); + } + + public void testJackson628() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.enableDefaultTyping(DefaultTyping.NON_FINAL); + ArrayList<Foo> data = new ArrayList<Foo>(); + String json = mapper.writeValueAsString(data); + List<?> output = mapper.readValue(json, List.class); + assertTrue(output.isEmpty()); + } + + public void testJackson667() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, + JsonTypeInfo.As.PROPERTY); + String json = mapper.writeValueAsString(new SetBean("abc")); + SetBean bean = mapper.readValue(json, SetBean.class); + assertNotNull(bean); + assertTrue(bean.names instanceof HashSet); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestDefaultForMaps.java b/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestDefaultForMaps.java new file mode 100644 index 0000000..15be85e --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestDefaultForMaps.java
@@ -0,0 +1,97 @@ +package org.codehaus.jackson.map.jsontype; + +import java.util.*; + +import org.codehaus.jackson.annotate.JsonTypeInfo; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.JsonDeserialize; +import org.codehaus.jackson.map.jsontype.impl.TypeNameIdResolver; +import org.codehaus.jackson.map.type.TypeFactory; + +public class TestDefaultForMaps + extends BaseMapTest +{ + /* + /********************************************************** + /* Helper types + /********************************************************** + */ + + static class MapKey { + public String key; + + public MapKey(String k) { key = k; } + + @Override public String toString() { return key; } + } + + static class MapKeyDeserializer extends KeyDeserializer + { + @Override + public Object deserializeKey(String key, DeserializationContext ctxt) { + return new MapKey(key); + } + } + + static class MapHolder + { + @JsonDeserialize(keyAs=MapKey.class, keyUsing=MapKeyDeserializer.class) + public Map<MapKey,List<Object>> map; + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + public void testJackson428() throws Exception + { + ObjectMapper serMapper = new ObjectMapper(); + + TypeResolverBuilder<?> serializerTyper = new ObjectMapper.DefaultTypeResolverBuilder(ObjectMapper.DefaultTyping.NON_FINAL); + serializerTyper = serializerTyper.init(JsonTypeInfo.Id.NAME, createTypeNameIdResolver(true)); + serializerTyper = serializerTyper.inclusion(JsonTypeInfo.As.PROPERTY); + serMapper.setDefaultTyping(serializerTyper); + + // Let's start by constructing something to serialize first + MapHolder holder = new MapHolder(); + holder.map = new HashMap<MapKey,List<Object>>(); + List<Object> ints = new ArrayList<Object>(); + ints.add(Integer.valueOf(3)); + holder.map.put(new MapKey("key"), ints); + String json = serMapper.writeValueAsString(holder); + + // Then deserialize: need separate mapper to initialize type id resolver appropriately + ObjectMapper deserMapper = new ObjectMapper(); + TypeResolverBuilder<?> deserializerTyper = new ObjectMapper.DefaultTypeResolverBuilder(ObjectMapper.DefaultTyping.NON_FINAL); + deserializerTyper = deserializerTyper.init(JsonTypeInfo.Id.NAME, createTypeNameIdResolver(false)); + deserializerTyper = deserializerTyper.inclusion(JsonTypeInfo.As.PROPERTY); + deserMapper.setDefaultTyping(deserializerTyper); + + MapHolder result = deserMapper.readValue(json, MapHolder.class); + assertNotNull(result); + Map<?,?> map = result.map; + assertEquals(1, map.size()); + Map.Entry<?,?> entry = map.entrySet().iterator().next(); + Object key = entry.getKey(); + assertEquals(MapKey.class, key.getClass()); + Object value = entry.getValue(); + assertTrue(value instanceof List<?>); + List<?> list = (List<?>) value; + assertEquals(1, list.size()); + assertEquals(Integer.class, list.get(0).getClass()); + assertEquals(Integer.valueOf(3), list.get(0)); + } + + protected TypeNameIdResolver createTypeNameIdResolver(boolean forSerialization) + { + Collection<NamedType> subtypes = new ArrayList<NamedType>(); + subtypes.add(new NamedType(MapHolder.class, "mapHolder")); + subtypes.add(new NamedType(ArrayList.class, "AList")); + subtypes.add(new NamedType(HashMap.class, "HMap")); + ObjectMapper mapper = new ObjectMapper(); + return TypeNameIdResolver.construct(mapper.getDeserializationConfig(), + TypeFactory.defaultInstance().constructType(Object.class), subtypes, forSerialization, !forSerialization); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestDefaultForObject.java b/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestDefaultForObject.java new file mode 100644 index 0000000..d97526d --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestDefaultForObject.java
@@ -0,0 +1,359 @@ +package org.codehaus.jackson.map.jsontype; + +import java.util.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.annotate.JsonTypeInfo; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.util.TokenBuffer; + +public class TestDefaultForObject + extends BaseMapTest +{ + /* + /********************************************************** + /* Helper types + /********************************************************** + */ + + static abstract class AbstractBean { } + + static class StringBean extends AbstractBean { // ha, punny! + public String name; + + public StringBean() { this(null); } + protected StringBean(String n) { name = n; } + } + + enum Choice { YES, NO; } + + /** + * Another enum type, but this time forcing sub-classing + */ + enum ComplexChoice { + MAYBE(true), PROBABLY_NOT(false); + + private boolean state; + + private ComplexChoice(boolean b) { state = b; } + + @Override + public String toString() { return String.valueOf(state); } + } + + // [JACKSON-311] + static class PolymorphicType { + public String foo; + public Object bar; + + public PolymorphicType() { } + public PolymorphicType(String foo, int bar) { + this.foo = foo; + this.bar = bar; + } + } + + final static class BeanHolder + { + public AbstractBean bean; + + public BeanHolder() { } + public BeanHolder(AbstractBean b) { bean = b; } + } + + final static class ObjectHolder + { + public Object value; + + public ObjectHolder() { } + public ObjectHolder(Object v) { value = v; } + } + + // [JACKSON-352] + static class DomainBean { + public int weight; + } + + static class DiscussBean extends DomainBean { + public String subject; + } + + static public class DomainBeanWrapper { + public String name; + public Object myBean; + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + /** + * Unit test that verifies that a bean is stored with type information, + * when declared type is <code>Object.class</code> (since it is within + * Object[]), and default type information is enabled. + */ + public void testBeanAsObject() throws Exception + { + ObjectMapper m = new ObjectMapper(); + m.enableDefaultTyping(); + // note: need to wrap, to get declared as Object + String str = m.writeValueAsString(new Object[] { new StringBean("abc") }); + + _verifySerializationAsMap(str); + + // Ok: serialization seems to work as expected. Now deserialize: + Object ob = m.readValue(str, Object[].class); + assertNotNull(ob); + Object[] result = (Object[]) ob; + assertNotNull(result[0]); + assertEquals(StringBean.class, result[0].getClass()); + assertEquals("abc", ((StringBean) result[0]).name); + } + + /** + * Unit test that verifies that an abstract bean is stored with type information + * if default type information is enabled for non-concrete types. + */ + public void testAbstractBean() throws Exception + { + // First, let's verify that we'd fail without enabling default type info + ObjectMapper m = new ObjectMapper(); + AbstractBean[] input = new AbstractBean[] { new StringBean("xyz") }; + String serial = m.writeValueAsString(input); + try { + m.readValue(serial, AbstractBean[].class); + fail("Should have failed"); + } catch (JsonMappingException e) { + // let's use whatever is currently thrown exception... may change tho + verifyException(e, "can not construct"); + } + + // and then that we will succeed with default type info + m = new ObjectMapper(); + m.enableDefaultTyping(ObjectMapper.DefaultTyping.OBJECT_AND_NON_CONCRETE); + serial = m.writeValueAsString(input); + AbstractBean[] beans = m.readValue(serial, AbstractBean[].class); + assertEquals(1, beans.length); + assertEquals(StringBean.class, beans[0].getClass()); + assertEquals("xyz", ((StringBean) beans[0]).name); + } + + /** + * Unit test to verify that type information is included for + * all non-final types, if default typing suitably configured + */ + public void testNonFinalBean() throws Exception + { + ObjectMapper m = new ObjectMapper(); + // first: use "object or abstract" typing: should produce no type info: + m.enableDefaultTyping(ObjectMapper.DefaultTyping.OBJECT_AND_NON_CONCRETE); + StringBean bean = new StringBean("x"); + assertEquals("{\"name\":\"x\"}", m.writeValueAsString(bean)); + // then non-final, and voila: + m = new ObjectMapper(); + m.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + assertEquals("[\""+StringBean.class.getName()+"\",{\"name\":\"x\"}]", + m.writeValueAsString(bean)); + } + + public void testNullValue() throws Exception + { + ObjectMapper m = new ObjectMapper(); + m.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + BeanHolder h = new BeanHolder(); + String json = m.writeValueAsString(h); + assertNotNull(json); + BeanHolder result = m.readValue(json, BeanHolder.class); + assertNotNull(result); + assertNull(result.bean); + } + + public void testEnumAsObject() throws Exception + { + // wrapping to be declared as object + Object[] input = new Object[] { Choice.YES }; + Object[] input2 = new Object[] { ComplexChoice.MAYBE}; + // first, without type info: + assertEquals("[\"YES\"]", serializeAsString(input)); + assertEquals("[\"MAYBE\"]", serializeAsString(input2)); + + // and then with it + ObjectMapper m = new ObjectMapper(); + m.enableDefaultTyping(); + + String json = m.writeValueAsString(input); + assertEquals("[[\""+Choice.class.getName()+"\",\"YES\"]]", json); + + // which we should get back same way + Object[] output = m.readValue(json, Object[].class); + assertEquals(1, output.length); + assertEquals(Choice.YES, output[0]); + + // ditto for more complicated enum + json = m.writeValueAsString(input2); + assertEquals("[[\""+ComplexChoice.class.getName()+"\",\"MAYBE\"]]", json); + output = m.readValue(json, Object[].class); + assertEquals(1, output.length); + assertEquals(ComplexChoice.MAYBE, output[0]); + } + + @SuppressWarnings("unchecked") + public void testEnumSet() throws Exception + { + EnumSet<Choice> set = EnumSet.of(Choice.NO); + Object[] input = new Object[] { set }; + ObjectMapper m = new ObjectMapper(); + m.enableDefaultTyping(); + String json = m.writeValueAsString(input); + Object[] output = m.readValue(json, Object[].class); + assertEquals(1, output.length); + Object ob = output[0]; + assertTrue(ob instanceof EnumSet<?>); + EnumSet<Choice> set2 = (EnumSet<Choice>) ob; + assertEquals(1, set2.size()); + assertTrue(set2.contains(Choice.NO)); + assertFalse(set2.contains(Choice.YES)); + } + + @SuppressWarnings("unchecked") + public void testEnumMap() throws Exception + { + EnumMap<Choice,String> map = new EnumMap<Choice,String>(Choice.class); + map.put(Choice.NO, "maybe"); + Object[] input = new Object[] { map }; + ObjectMapper m = new ObjectMapper(); + m.enableDefaultTyping(); + String json = m.writeValueAsString(input); + Object[] output = m.readValue(json, Object[].class); + assertEquals(1, output.length); + Object ob = output[0]; + assertTrue(ob instanceof EnumMap<?,?>); + EnumMap<Choice,String> map2 = (EnumMap<Choice,String>) ob; + assertEquals(1, map2.size()); + assertEquals("maybe", map2.get(Choice.NO)); + assertNull(map2.get(Choice.YES)); + } + + public void testJackson311() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + String json = mapper.writeValueAsString(new PolymorphicType("hello", 2)); + PolymorphicType value = mapper.readValue(json, PolymorphicType.class); + assertEquals("hello", value.foo); + assertEquals(Integer.valueOf(2), value.bar); + } + + // Also, let's ensure TokenBuffer gets properly handled + public void testTokenBuffer() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + + // Ok, first test JSON Object containing buffer: + TokenBuffer buf = new TokenBuffer(mapper); + buf.writeStartObject(); + buf.writeNumberField("num", 42); + buf.writeEndObject(); + String json = mapper.writeValueAsString(new ObjectHolder(buf)); + ObjectHolder holder = mapper.readValue(json, ObjectHolder.class); + assertNotNull(holder.value); + assertSame(TokenBuffer.class, holder.value.getClass()); + JsonParser jp = ((TokenBuffer) holder.value).asParser(); + assertToken(JsonToken.START_OBJECT, jp.nextToken()); + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertToken(JsonToken.END_OBJECT, jp.nextToken()); + assertNull(jp.nextToken()); + jp.close(); + + // then as an array: + buf = new TokenBuffer(mapper); + buf.writeStartArray(); + buf.writeBoolean(true); + buf.writeEndArray(); + json = mapper.writeValueAsString(new ObjectHolder(buf)); + holder = mapper.readValue(json, ObjectHolder.class); + assertNotNull(holder.value); + assertSame(TokenBuffer.class, holder.value.getClass()); + jp = ((TokenBuffer) holder.value).asParser(); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + assertToken(JsonToken.VALUE_TRUE, jp.nextToken()); + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + assertNull(jp.nextToken()); + jp.close(); + + // and finally as scalar + buf = new TokenBuffer(mapper); + buf.writeNumber(321); + json = mapper.writeValueAsString(new ObjectHolder(buf)); + holder = mapper.readValue(json, ObjectHolder.class); + assertNotNull(holder.value); + assertSame(TokenBuffer.class, holder.value.getClass()); + jp = ((TokenBuffer) holder.value).asParser(); + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(321, jp.getIntValue()); + assertNull(jp.nextToken()); + jp.close(); + } + + /** + * Test for [JACKSON-352] + */ + public void testIssue352() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.enableDefaultTyping (ObjectMapper.DefaultTyping.OBJECT_AND_NON_CONCRETE, JsonTypeInfo.As.PROPERTY); + DiscussBean d1 = new DiscussBean(); + d1.subject = "mouse"; + d1.weight=88; + DomainBeanWrapper wrapper = new DomainBeanWrapper(); + wrapper.name = "mickey"; + wrapper.myBean = d1; + String json = mapper.writeValueAsString(wrapper); + DomainBeanWrapper result = mapper.readValue(json, DomainBeanWrapper.class); + assertNotNull(result); + assertNotNull(wrapper.myBean); + assertSame(DiscussBean.class, wrapper.myBean.getClass()); + } + + // Test to ensure we can also use "As.PROPERTY" inclusion and custom property name + public void testFeature432() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.enableDefaultTypingAsProperty(ObjectMapper.DefaultTyping.OBJECT_AND_NON_CONCRETE, "*CLASS*"); + String json = mapper.writeValueAsString(new BeanHolder(new StringBean("punny"))); + assertEquals("{\"bean\":{\"*CLASS*\":\"org.codehaus.jackson.map.jsontype.TestDefaultForObject$StringBean\",\"name\":\"punny\"}}", json); + } + + /* + /********************************************************** + /* Helper methods + /********************************************************** + */ + + @SuppressWarnings("unchecked") + private void _verifySerializationAsMap(String str) throws Exception + { + // First: validate that structure looks correct (as Map etc) + // note: should look something like: + // "[["org.codehaus.jackson.map.jsontype.TestDefaultForObject$StringBean",{"name":"abc"}]]") + + // note: must have default mapper, default typer NOT enabled (to get 'plain' map) + ObjectMapper m = new ObjectMapper(); + List<Object> list = m.readValue(str, List.class); + assertEquals(1, list.size()); // no type for main List, just single entry + Object entryOb = list.get(0); + assertTrue(entryOb instanceof List<?>); + // but then type wrapper for bean + List<?> entryList = (List<?>)entryOb; + assertEquals(2, entryList.size()); + assertEquals(StringBean.class.getName(), entryList.get(0)); + assertTrue(entryList.get(1) instanceof Map); + Map<?,?> map = (Map<?,?>) entryList.get(1); + assertEquals(1, map.size()); + assertEquals("abc", map.get("name")); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestDefaultForScalars.java b/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestDefaultForScalars.java new file mode 100644 index 0000000..6a896fd --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestDefaultForScalars.java
@@ -0,0 +1,111 @@ +package org.codehaus.jackson.map.jsontype; + +import java.util.*; + +import static org.junit.Assert.*; + +import org.codehaus.jackson.map.*; + +/** + * Unit tests to verify that Java/JSON scalar values (non-structured values) + * are handled properly with respect to additional type information. + * + * @since 1.5 + * @author tatu + */ +public class TestDefaultForScalars + extends BaseMapTest +{ + static class Jackson417Bean { + public String foo = "bar"; + public java.io.Serializable bar = new Integer(13); + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + /** + * Unit test to verify that limited number of core types do NOT include + * type information, even if declared as Object. This is only done for types + * that JSON scalar values natively map to: String, Integer and Boolean (and + * nulls never have type information) + */ + public void testNumericScalars() throws Exception + { + ObjectMapper m = new ObjectMapper(); + m.enableDefaultTyping(); + + // no typing for Integer, Double, yes for others + assertEquals("[123]", m.writeValueAsString(new Object[] { Integer.valueOf(123) })); + assertEquals("[[\"java.lang.Long\",37]]", m.writeValueAsString(new Object[] { Long.valueOf(37) })); + assertEquals("[0.25]", m.writeValueAsString(new Object[] { Double.valueOf(0.25) })); + assertEquals("[[\"java.lang.Float\",0.5]]", m.writeValueAsString(new Object[] { Float.valueOf(0.5f) })); + } + + public void testDateScalars() throws Exception + { + ObjectMapper m = new ObjectMapper(); + m.enableDefaultTyping(); + + long ts = 12345678L; + assertEquals("[[\"java.util.Date\","+ts+"]]", + m.writeValueAsString(new Object[] { new Date(ts) })); + + // Calendar is trickier... hmmh. Need to ensure round-tripping + Calendar c = Calendar.getInstance(); + c.setTimeInMillis(ts); + String json = m.writeValueAsString(new Object[] { c }); + assertEquals("[[\""+c.getClass().getName()+"\","+ts+"]]", json); + // and let's make sure it also comes back same way: + Object[] result = m.readValue(json, Object[].class); + assertEquals(1, result.length); + assertTrue(result[0] instanceof Calendar); + assertEquals(ts, ((Calendar) result[0]).getTimeInMillis()); + } + + public void testMiscScalars() throws Exception + { + ObjectMapper m = new ObjectMapper(); + m.enableDefaultTyping(); + + // no typing for Strings, booleans + assertEquals("[\"abc\"]", m.writeValueAsString(new Object[] { "abc" })); + assertEquals("[true,null,false]", m.writeValueAsString(new Boolean[] { true, null, false })); + } + + /** + * Test for verifying that contents of "untyped" homogenous arrays are properly + * handled, + */ + public void testScalarArrays() throws Exception + { + ObjectMapper m = new ObjectMapper(); + m.enableDefaultTyping(ObjectMapper.DefaultTyping.JAVA_LANG_OBJECT); + Object[] input = new Object[] { + "abc", new Date(1234567), null, Integer.valueOf(456) + }; + String json = m.writeValueAsString(input); + assertEquals("[\"abc\",[\"java.util.Date\",1234567],null,456]", json); + + // and should deserialize back as well: + Object[] output = m.readValue(json, Object[].class); + assertArrayEquals(input, output); + } + + /** + * Loosely scalar; for [JACKSON-417] + */ + public void test417() throws Exception + { + ObjectMapper m = new ObjectMapper(); + m.enableDefaultTyping(); + Jackson417Bean input = new Jackson417Bean(); + String json = m.writeValueAsString(input); + Jackson417Bean result = m.readValue(json, Jackson417Bean.class); + assertEquals(input.foo, result.foo); + assertEquals(input.bar, result.bar); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestDefaultWithCreators.java b/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestDefaultWithCreators.java new file mode 100644 index 0000000..ba53c3d --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestDefaultWithCreators.java
@@ -0,0 +1,62 @@ +package org.codehaus.jackson.map.jsontype; + +import org.codehaus.jackson.annotate.JsonCreator; +import org.codehaus.jackson.annotate.JsonProperty; + +import org.codehaus.jackson.map.BaseMapTest; +import org.codehaus.jackson.map.ObjectMapper; + +public class TestDefaultWithCreators + extends BaseMapTest +{ + /* + /********************************************************** + /* Helper types + /********************************************************** + */ + + static abstract class Job + { + public long id; + } + + static class UrlJob extends Job + { + private final String url; + private final int count; + + @JsonCreator + public UrlJob(@JsonProperty("id") long id, @JsonProperty("url") String url, + @JsonProperty("count") int count) + { + this.id = id; + this.url = url; + this.count = count; + } + + public String getUrl() { return url; } + public int getCount() { return count; } + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + public void testWithCreators() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + UrlJob input = new UrlJob(123L, "http://foo", 3); + String json = mapper.writeValueAsString(input); + assertNotNull(json); + Job output = mapper.readValue(json, Job.class); + assertNotNull(output); + assertSame(UrlJob.class, output.getClass()); + UrlJob o2 = (UrlJob) output; + assertEquals(123L, o2.id); + assertEquals("http://foo", o2.getUrl()); + assertEquals(3, o2.getCount()); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestEnumTyping.java b/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestEnumTyping.java new file mode 100644 index 0000000..8803675 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestEnumTyping.java
@@ -0,0 +1,104 @@ +package org.codehaus.jackson.map.jsontype; + +import java.util.*; + +import org.codehaus.jackson.annotate.JsonTypeInfo; +import org.codehaus.jackson.map.BaseMapTest; +import org.codehaus.jackson.map.ObjectMapper; + +@SuppressWarnings("serial") +public class TestEnumTyping extends BaseMapTest +{ + /* + /********************************************************** + /* Helper types + /********************************************************** + */ + + // note: As.WRAPPER_ARRAY worked initially; but as per [JACKSON-485], As.PROPERTY had issues + @JsonTypeInfo(use=JsonTypeInfo.Id.MINIMAL_CLASS, include=JsonTypeInfo.As.PROPERTY) + public interface EnumInterface { } + + public enum Tag implements EnumInterface + { A, B }; + + static class EnumInterfaceWrapper { + public EnumInterface value; + } + + static class EnumInterfaceList extends ArrayList<EnumInterface> { } + + static class TagList extends ArrayList<Tag> { } + + static enum TestEnum { A, B, C; } + + static class UntypedEnumBean + { + @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY, property="__type") + public Object value; + + public UntypedEnumBean() { } + public UntypedEnumBean(TestEnum v) { value = v; } + + @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY, property="__type") + public void setValue(Object o) { + value = o; + } + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + public void testTagList() throws Exception + { + ObjectMapper m = new ObjectMapper(); + TagList list = new TagList(); + list.add(Tag.A); + list.add(Tag.B); + String json = m.writeValueAsString(list); + + TagList result = m.readValue(json, TagList.class); + assertEquals(2, result.size()); + assertSame(Tag.A, result.get(0)); + assertSame(Tag.B, result.get(1)); + } + + public void testEnumInterface() throws Exception + { + ObjectMapper m = new ObjectMapper(); + String json = m.writeValueAsString(Tag.B); + + EnumInterface result = m.readValue(json, EnumInterface.class); + assertSame(Tag.B, result); + } + + public void testEnumInterfaceList() throws Exception + { + ObjectMapper m = new ObjectMapper(); + EnumInterfaceList list = new EnumInterfaceList(); + list.add(Tag.A); + list.add(Tag.B); + String json = m.writeValueAsString(list); + + EnumInterfaceList result = m.readValue(json, EnumInterfaceList.class); + assertEquals(2, result.size()); + assertSame(Tag.A, result.get(0)); + assertSame(Tag.B, result.get(1)); + } + + public void testUntypedEnum() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + String str = mapper.writeValueAsString(new UntypedEnumBean(TestEnum.B)); + UntypedEnumBean result = mapper.readValue(str, UntypedEnumBean.class); + assertNotNull(result); + assertNotNull(result.value); + Object ob = result.value; + assertSame(TestEnum.class, ob.getClass()); + assertEquals(TestEnum.B, result.value); + } + +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestExternalId.java b/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestExternalId.java new file mode 100644 index 0000000..44c3698 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestExternalId.java
@@ -0,0 +1,209 @@ +package org.codehaus.jackson.map.jsontype; + +import org.codehaus.jackson.annotate.JsonCreator; +import org.codehaus.jackson.annotate.JsonProperty; +import org.codehaus.jackson.annotate.JsonSubTypes; +import org.codehaus.jackson.annotate.JsonTypeInfo; +import org.codehaus.jackson.annotate.JsonTypeInfo.As; +import org.codehaus.jackson.annotate.JsonTypeInfo.Id; +import org.codehaus.jackson.annotate.JsonTypeName; +import org.codehaus.jackson.map.BaseMapTest; +import org.codehaus.jackson.map.ObjectMapper; + +// Tests for [JACKSON-453] +public class TestExternalId extends BaseMapTest +{ + /* + /********************************************************** + /* Helper types + /********************************************************** + */ + + static class ExternalBean + { + @JsonTypeInfo(use=Id.NAME, include=As.EXTERNAL_PROPERTY, property="extType") + public Object bean; + + public ExternalBean() { } + public ExternalBean(int v) { + bean = new ValueBean(v); + } + } + + static class ExternalBean3 + { + @JsonTypeInfo(use=Id.NAME, include=As.EXTERNAL_PROPERTY, property="extType1") + public Object value1; + + @JsonTypeInfo(use=Id.NAME, include=As.EXTERNAL_PROPERTY, property="extType2") + public Object value2; + + public int foo; + + @JsonTypeInfo(use=Id.NAME, include=As.EXTERNAL_PROPERTY, property="extType3") + public Object value3; + + public ExternalBean3() { } + public ExternalBean3(int v) { + value1 = new ValueBean(v); + value2 = new ValueBean(v+1); + value3 = new ValueBean(v+2); + foo = v; + } + } + + static class ExternalBeanWithCreator + { + @JsonTypeInfo(use=Id.NAME, include=As.EXTERNAL_PROPERTY, property="extType") + public Object value; + + public int foo; + + @JsonCreator + public ExternalBeanWithCreator(@JsonProperty("foo") int f) + { + foo = f; + value = new ValueBean(f); + } + } + + @JsonTypeName("vbean") + static class ValueBean { + public int value; + + public ValueBean() { } + public ValueBean(int v) { value = v; } + } + + @JsonTypeName("funk") + @JsonTypeInfo(use=Id.NAME, include=As.EXTERNAL_PROPERTY, property="extType") + static class FunkyExternalBean { + public int i = 3; + } + + // [JACKSON-831] + + interface Pet {} + + static class Dog implements Pet { + public String name; + } + + static class House831 { + private String petType; + + @JsonTypeInfo(use = Id.NAME, include = As.EXTERNAL_PROPERTY, property = "petType") + @JsonSubTypes({@JsonSubTypes.Type(name = "dog", value = Dog.class)}) + public Pet pet; + + public String getPetType() { + return petType; + } + + public void setPetType(String petType) { + this.petType = petType; + } + } + + /* + /********************************************************** + /* Unit tests, serialization + /********************************************************** + */ + + public void testSimpleSerialization() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.registerSubtypes(ValueBean.class); + // This may look odd, but one implementation nastiness is the fact + // that we can not properly serialize type id before the object, + // because call is made after property name (for object) has already + // been written out. So we'll write it after... + // Deserializer will work either way as it can not rely on ordering + // anyway. + assertEquals("{\"bean\":{\"value\":11},\"extType\":\"vbean\"}", + mapper.writeValueAsString(new ExternalBean(11))); + } + + // If trying to use with Class, should just become "PROPERTY" instead: + public void testImproperExternalIdSerialization() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + assertEquals("{\"extType\":\"funk\",\"i\":3}", + mapper.writeValueAsString(new FunkyExternalBean())); + } + + /* + /********************************************************** + /* Unit tests, deserialization + /********************************************************** + */ + + public void testSimpleDeserialization() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.registerSubtypes(ValueBean.class); + ExternalBean result = mapper.readValue("{\"bean\":{\"value\":11},\"extType\":\"vbean\"}", ExternalBean.class); + assertNotNull(result); + assertNotNull(result.bean); + ValueBean vb = (ValueBean) result.bean; + assertEquals(11, vb.value); + } + + /** + * Test for verifying that it's ok to have multiple (say, 3) + * externally typed things, mixed with other stuff... + */ + public void testMultipleTypeIdsDeserialization() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.registerSubtypes(ValueBean.class); + String json = mapper.writeValueAsString(new ExternalBean3(3)); + ExternalBean3 result = mapper.readValue(json, ExternalBean3.class); + assertNotNull(result); + assertNotNull(result.value1); + assertNotNull(result.value2); + assertNotNull(result.value3); + assertEquals(3, ((ValueBean)result.value1).value); + assertEquals(4, ((ValueBean)result.value2).value); + assertEquals(5, ((ValueBean)result.value3).value); + assertEquals(3, result.foo); + } + + /** + * Also, it should be ok to use @JsonCreator as well... + */ + public void testExternalTypeWithCreator() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.registerSubtypes(ValueBean.class); + String json = mapper.writeValueAsString(new ExternalBeanWithCreator(7)); + ExternalBeanWithCreator result = mapper.readValue(json, ExternalBeanWithCreator.class); + assertNotNull(result); + assertNotNull(result.value); + assertEquals(7, ((ValueBean)result.value).value); + assertEquals(7, result.foo); + } + + // If trying to use with Class, should just become "PROPERTY" instead: + public void testImproperExternalIdDeserialization() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + FunkyExternalBean result = mapper.readValue("{\"extType\":\"funk\",\"i\":3}", FunkyExternalBean.class); + assertNotNull(result); + assertEquals(3, result.i); + } + + // There seems to be some problems if type is also visible... + public void testIssue831() throws Exception + { + final String JSON = "{ \"petType\": \"dog\",\n" + +"\"pet\": { \"name\": \"Pluto\" }\n}"; + ObjectMapper mapper = new ObjectMapper(); + House831 result = mapper.readValue(JSON, House831.class); + assertNotNull(result); + assertNotNull(result.pet); + assertSame(Dog.class, result.pet.getClass()); + assertEquals("dog", result.petType); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestGenericListSerialization.java b/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestGenericListSerialization.java new file mode 100644 index 0000000..649b3c0 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestGenericListSerialization.java
@@ -0,0 +1,94 @@ +package org.codehaus.jackson.map.jsontype; + +import java.util.ArrayList; +import java.util.List; + +import org.codehaus.jackson.Version; +import org.codehaus.jackson.annotate.JsonTypeInfo; +import org.codehaus.jackson.map.BaseMapTest; +import org.codehaus.jackson.map.ObjectMapper; +import org.codehaus.jackson.map.SerializationConfig; +import org.codehaus.jackson.map.type.TypeFactory; +import org.codehaus.jackson.type.JavaType; +import org.codehaus.jackson.type.TypeReference; + +public class TestGenericListSerialization + extends BaseMapTest +{ + // [JACKSON-356] + public static class JSONResponse<T> { + + private T result; + + public T getResult() { + return result; + } + + public void setResult(T result) { + this.result = result; + } + } + + @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY, property="@class") + public static class Parent { + public String parentContent = "PARENT"; + } + + public static class Child1 extends Parent { + public String childContent1 = "CHILD1"; + } + + public static class Child2 extends Parent { + public String childContent2 = "CHILD2"; + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + public void testSubTypesFor356() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + /* 06-Sep-2010, tatus: This was not fixed for 1.6; and to keep junit test + * suite green, let's not run it for versions prior to 1.7... + */ + Version v = mapper.version(); + if (v.getMajorVersion() == 1 && v.getMinorVersion() == 6) { + System.err.println("Note: skipping test for Jackson 1.6"); + return; + } + + JSONResponse<List<Parent>> input = new JSONResponse<List<Parent>>(); + + List<Parent> embedded = new ArrayList<Parent>(); + embedded.add(new Child1()); + embedded.add(new Child2()); + input.setResult(embedded); + mapper.configure(SerializationConfig.Feature.USE_STATIC_TYPING, true); + + JavaType rootType = TypeFactory.defaultInstance().constructType(new TypeReference<JSONResponse<List<Parent>>>() { }); + byte[] json = mapper.writerWithType(rootType).writeValueAsBytes(input); +// byte[] json = mapper.writeValueAsBytes(input); + +// System.out.println("After Serialization: " + new String(json)); + + JSONResponse<List<Parent>> out = mapper.readValue(json, 0, json.length, rootType); + + List<Parent> deserializedContent = (List<Parent>) out.getResult(); + + assertEquals(2, deserializedContent.size()); + assertTrue(deserializedContent.get(0) instanceof Parent); + assertTrue(deserializedContent.get(0) instanceof Child1); + assertFalse(deserializedContent.get(0) instanceof Child2); + assertTrue(deserializedContent.get(1) instanceof Child2); + assertFalse(deserializedContent.get(1) instanceof Child1); + + assertEquals("PARENT", ((Child1) deserializedContent.get(0)).parentContent); + assertEquals("PARENT", ((Child2) deserializedContent.get(1)).parentContent); + assertEquals("CHILD1", ((Child1) deserializedContent.get(0)).childContent1); + assertEquals("CHILD2", ((Child2) deserializedContent.get(1)).childContent2); + } + +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestNoTypeInfo.java b/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestNoTypeInfo.java new file mode 100644 index 0000000..82822b3 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestNoTypeInfo.java
@@ -0,0 +1,39 @@ +package org.codehaus.jackson.map.jsontype; + +import org.codehaus.jackson.annotate.*; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.JsonDeserialize; + +public class TestNoTypeInfo extends BaseMapTest +{ + @JsonTypeInfo(use=JsonTypeInfo.Id.NONE) + @JsonDeserialize(as=NoType.class) + private static interface NoTypeInterface { + } + + private final static class NoType implements NoTypeInterface { + public int a = 3; + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + // for [JACKSON-746] + public void testWithIdNone() throws Exception + { + final ObjectMapper mapper = new ObjectMapper(); + mapper.enableDefaultTyping(); + // serialize without type info + String json = mapper.writeValueAsString(new NoType()); + assertEquals("{\"a\":3}", json); + + // and deserialize successfully + NoTypeInterface bean = mapper.readValue("{\"a\":6}", NoTypeInterface.class); + assertNotNull(bean); + NoType impl = (NoType) bean; + assertEquals(6, impl.a); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestPropertyTypeInfo.java b/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestPropertyTypeInfo.java new file mode 100644 index 0000000..c275a76 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestPropertyTypeInfo.java
@@ -0,0 +1,202 @@ +package org.codehaus.jackson.map.jsontype; + +import java.util.*; + +import org.codehaus.jackson.annotate.*; +import org.codehaus.jackson.map.BaseMapTest; +import org.codehaus.jackson.map.ObjectMapper; + +/** + * Testing to verify that {@link JsonTypeInfo} works + * for properties as well as types (see [JACKSON-280] for details) + * + * @since 1.7 + */ +@SuppressWarnings("serial") +public class TestPropertyTypeInfo extends BaseMapTest +{ + /* + /********************************************************** + /* Helper types + /********************************************************** + */ + + static class FieldWrapperBean + { + @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.WRAPPER_ARRAY) + public Object value; + + public FieldWrapperBean() { } + public FieldWrapperBean(Object o) { value = o; } + } + + static class FieldWrapperBeanList extends ArrayList<FieldWrapperBean> { } + static class FieldWrapperBeanMap extends HashMap<String,FieldWrapperBean> { } + static class FieldWrapperBeanArray { + @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.WRAPPER_ARRAY) + public FieldWrapperBean[] beans; + + public FieldWrapperBeanArray() { } + public FieldWrapperBeanArray(FieldWrapperBean[] beans) { this.beans = beans; } + } + + static class MethodWrapperBean + { + private Object value; + + @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.WRAPPER_ARRAY) + public Object getValue() { return value; } + + @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.WRAPPER_ARRAY) + public void setValue(Object v) { value = v; } + + public MethodWrapperBean() { } + public MethodWrapperBean(Object o) { value = o; } + } + + static class MethodWrapperBeanList extends ArrayList<MethodWrapperBean> { } + static class MethodWrapperBeanMap extends HashMap<String,MethodWrapperBean> { } + static class MethodWrapperBeanArray { + protected MethodWrapperBean[] beans; + + @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.WRAPPER_ARRAY) + public MethodWrapperBean[] getValue() { return beans; } + + @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.WRAPPER_ARRAY) + public void setValue(MethodWrapperBean[] v) { beans = v; } + + public MethodWrapperBeanArray() { } + public MethodWrapperBeanArray(MethodWrapperBean[] beans) { this.beans = beans; } + } + + static class OtherBean { + public int x = 1, y = 1; + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + public void testSimpleField() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + String json = mapper.writeValueAsString(new FieldWrapperBean(new StringWrapper("foo"))); +//System.out.println("JSON/field+object == "+json); + FieldWrapperBean bean = mapper.readValue(json, FieldWrapperBean.class); + assertNotNull(bean.value); + assertEquals(StringWrapper.class, bean.value.getClass()); + assertEquals(((StringWrapper) bean.value).str, "foo"); + } + + public void testSimpleMethod() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + String json = mapper.writeValueAsString(new FieldWrapperBean(new IntWrapper(37))); +//System.out.println("JSON/method+object == "+json); + FieldWrapperBean bean = mapper.readValue(json, FieldWrapperBean.class); + assertNotNull(bean.value); + assertEquals(IntWrapper.class, bean.value.getClass()); + assertEquals(((IntWrapper) bean.value).i, 37); + } + + public void testSimpleListField() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + FieldWrapperBeanList list = new FieldWrapperBeanList(); + list.add(new FieldWrapperBean(new OtherBean())); + String json = mapper.writeValueAsString(list); +//System.out.println("JSON/field+list == "+json); + FieldWrapperBeanList result = mapper.readValue(json, FieldWrapperBeanList.class); + assertNotNull(result); + assertEquals(1, result.size()); + FieldWrapperBean bean = list.get(0); + assertEquals(OtherBean.class, bean.value.getClass()); + assertEquals(((OtherBean) bean.value).x, 1); + assertEquals(((OtherBean) bean.value).y, 1); + } + + public void testSimpleListMethod() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + MethodWrapperBeanList list = new MethodWrapperBeanList(); + list.add(new MethodWrapperBean(new BooleanWrapper(true))); + list.add(new MethodWrapperBean(new StringWrapper("x"))); + list.add(new MethodWrapperBean(new OtherBean())); + String json = mapper.writeValueAsString(list); + MethodWrapperBeanList result = mapper.readValue(json, MethodWrapperBeanList.class); + assertNotNull(result); + assertEquals(3, result.size()); + MethodWrapperBean bean = result.get(0); + assertEquals(BooleanWrapper.class, bean.value.getClass()); + assertEquals(((BooleanWrapper) bean.value).b, Boolean.TRUE); + bean = result.get(1); + assertEquals(StringWrapper.class, bean.value.getClass()); + assertEquals(((StringWrapper) bean.value).str, "x"); + bean = result.get(2); + assertEquals(OtherBean.class, bean.value.getClass()); + } + + public void testSimpleArrayField() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + FieldWrapperBeanArray array = new FieldWrapperBeanArray(new + FieldWrapperBean[] { new FieldWrapperBean(new BooleanWrapper(true)) }); + String json = mapper.writeValueAsString(array); + FieldWrapperBeanArray result = mapper.readValue(json, FieldWrapperBeanArray.class); + assertNotNull(result); + FieldWrapperBean[] beans = result.beans; + assertEquals(1, beans.length); + FieldWrapperBean bean = beans[0]; + assertEquals(BooleanWrapper.class, bean.value.getClass()); + assertEquals(((BooleanWrapper) bean.value).b, Boolean.TRUE); + } + + public void testSimpleArrayMethod() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + MethodWrapperBeanArray array = new MethodWrapperBeanArray(new + MethodWrapperBean[] { new MethodWrapperBean(new StringWrapper("A")) }); + String json = mapper.writeValueAsString(array); + MethodWrapperBeanArray result = mapper.readValue(json, MethodWrapperBeanArray.class); + assertNotNull(result); + MethodWrapperBean[] beans = result.beans; + assertEquals(1, beans.length); + MethodWrapperBean bean = beans[0]; + assertEquals(StringWrapper.class, bean.value.getClass()); + assertEquals(((StringWrapper) bean.value).str, "A"); + } + + public void testSimpleMapField() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + FieldWrapperBeanMap map = new FieldWrapperBeanMap(); + map.put("foop", new FieldWrapperBean(new IntWrapper(13))); + String json = mapper.writeValueAsString(map); + FieldWrapperBeanMap result = mapper.readValue(json, FieldWrapperBeanMap.class); + assertNotNull(result); + assertEquals(1, result.size()); + FieldWrapperBean bean = result.get("foop"); + assertNotNull(bean); + Object ob = bean.value; + assertEquals(IntWrapper.class, ob.getClass()); + assertEquals(((IntWrapper) ob).i, 13); + } + + public void testSimpleMapMethod() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + MethodWrapperBeanMap map = new MethodWrapperBeanMap(); + map.put("xyz", new MethodWrapperBean(new BooleanWrapper(true))); + String json = mapper.writeValueAsString(map); + MethodWrapperBeanMap result = mapper.readValue(json, MethodWrapperBeanMap.class); + assertNotNull(result); + assertEquals(1, result.size()); + MethodWrapperBean bean = result.get("xyz"); + assertNotNull(bean); + Object ob = bean.value; + assertEquals(BooleanWrapper.class, ob.getClass()); + assertEquals(((BooleanWrapper) ob).b, Boolean.TRUE); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestScalars.java b/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestScalars.java new file mode 100644 index 0000000..d4baa90 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestScalars.java
@@ -0,0 +1,106 @@ +package org.codehaus.jackson.map.jsontype; + +import java.io.Serializable; + +import org.codehaus.jackson.annotate.JsonTypeInfo; +import org.codehaus.jackson.map.BaseMapTest; +import org.codehaus.jackson.map.ObjectMapper; + +public class TestScalars extends BaseMapTest +{ + private static class DynamicWrapper { + @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY) + public Object value; + + @SuppressWarnings("unused") + public DynamicWrapper() { } + public DynamicWrapper(Object v) { value = v; } + } + + static enum TestEnum { A, B; } + + private static class AbstractWrapper { + @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY) + public Serializable value; + + @SuppressWarnings("unused") + public AbstractWrapper() { } + public AbstractWrapper(Serializable v) { value = v; } + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + /** + * Ensure that per-property dynamic types work, both for "native" types + * and others + */ + public void testScalarsWithTyping() throws Exception + { + ObjectMapper m = new ObjectMapper(); + String json; + DynamicWrapper result; + + // first, check "native" types + json = m.writeValueAsString(new DynamicWrapper(Integer.valueOf(3))); + result = m.readValue(json, DynamicWrapper.class); + assertEquals(Integer.valueOf(3), result.value); + + json = m.writeValueAsString(new DynamicWrapper("abc")); + result = m.readValue(json, DynamicWrapper.class); + assertEquals("abc", result.value); + + json = m.writeValueAsString(new DynamicWrapper("abc")); + result = m.readValue(json, DynamicWrapper.class); + assertEquals("abc", result.value); + + json = m.writeValueAsString(new DynamicWrapper(Boolean.TRUE)); + result = m.readValue(json, DynamicWrapper.class); + assertEquals(Boolean.TRUE, result.value); + + // then verify other scalars + json = m.writeValueAsString(new DynamicWrapper(Long.valueOf(7L))); + result = m.readValue(json, DynamicWrapper.class); + assertEquals(Long.valueOf(7), result.value); + + json = m.writeValueAsString(new DynamicWrapper(TestEnum.B)); + result = m.readValue(json, DynamicWrapper.class); + assertEquals(TestEnum.B, result.value); + } + + public void testScalarsViaAbstractType() throws Exception + { + ObjectMapper m = new ObjectMapper(); + String json; + AbstractWrapper result; + + // first, check "native" types + json = m.writeValueAsString(new AbstractWrapper(Integer.valueOf(3))); + result = m.readValue(json, AbstractWrapper.class); + assertEquals(Integer.valueOf(3), result.value); + + json = m.writeValueAsString(new AbstractWrapper("abc")); + result = m.readValue(json, AbstractWrapper.class); + assertEquals("abc", result.value); + + json = m.writeValueAsString(new AbstractWrapper("abc")); + result = m.readValue(json, AbstractWrapper.class); + assertEquals("abc", result.value); + + json = m.writeValueAsString(new AbstractWrapper(Boolean.TRUE)); + result = m.readValue(json, AbstractWrapper.class); + assertEquals(Boolean.TRUE, result.value); + + // then verify other scalars + json = m.writeValueAsString(new AbstractWrapper(Long.valueOf(7L))); + result = m.readValue(json, AbstractWrapper.class); + assertEquals(Long.valueOf(7), result.value); + + json = m.writeValueAsString(new AbstractWrapper(TestEnum.B)); + result = m.readValue(json, AbstractWrapper.class); + assertEquals(TestEnum.B, result.value); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestSubtypes.java b/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestSubtypes.java new file mode 100644 index 0000000..3c87e86 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestSubtypes.java
@@ -0,0 +1,201 @@ +package org.codehaus.jackson.map.jsontype; + +import org.codehaus.jackson.Version; +import org.codehaus.jackson.annotate.JsonTypeInfo; +import org.codehaus.jackson.annotate.JsonTypeInfo.As; +import org.codehaus.jackson.annotate.JsonTypeName; +import org.codehaus.jackson.map.JsonMappingException; +import org.codehaus.jackson.map.ObjectMapper; +import org.codehaus.jackson.map.SerializationConfig; +import org.codehaus.jackson.map.module.SimpleModule; + +public class TestSubtypes extends org.codehaus.jackson.map.BaseMapTest +{ + @JsonTypeInfo(use=JsonTypeInfo.Id.NAME) + static abstract class SuperType { + } + + @JsonTypeName("TypeB") + static class SubB extends SuperType { + public int b = 1; + } + + static class SubC extends SuperType { + public int c = 2; + } + + static class SubD extends SuperType { + public int d; + } + + // "Empty" bean, to test [JACKSON-366] + @JsonTypeInfo(use=JsonTypeInfo.Id.NAME) + static abstract class BaseBean { } + + static class EmptyBean extends BaseBean { } + + static class EmptyNonFinal { } + + // Verify combinations with [JACKSON-510] + + static class PropertyBean + { + @JsonTypeInfo(use=JsonTypeInfo.Id.NAME) + public SuperType value; + + public PropertyBean() { this(null); } + public PropertyBean(SuperType v) { value = v; } + } + + // And then [JACKSON-614] + @JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=As.PROPERTY, + property="#type", + defaultImpl=DefaultImpl.class) + static abstract class SuperTypeWithDefault { } + + static class DefaultImpl extends SuperTypeWithDefault { + public int a; + } + + @JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=As.PROPERTY, property="#type") + static abstract class SuperTypeWithoutDefault { } + + static class DefaultImpl505 extends SuperTypeWithoutDefault { + public int a; + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + // JACKSON-510 + public void testPropertyWithSubtypes() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + // must register subtypes + mapper.registerSubtypes(SubB.class, SubC.class, SubD.class); + String json = mapper.writeValueAsString(new PropertyBean(new SubC())); + PropertyBean result = mapper.readValue(json, PropertyBean.class); + assertSame(SubC.class, result.value.getClass()); + } + + public void testSerialization() throws Exception + { + // serialization can detect type name ok without anything extra: + SubB bean = new SubB(); + ObjectMapper mapper = new ObjectMapper(); + assertEquals("{\"@type\":\"TypeB\",\"b\":1}", mapper.writeValueAsString(bean)); + + // but we can override type name here too + mapper = new ObjectMapper(); + mapper.registerSubtypes(new NamedType(SubB.class, "typeB")); + assertEquals("{\"@type\":\"typeB\",\"b\":1}", mapper.writeValueAsString(bean)); + + // and default name ought to be simple class name; with context + assertEquals("{\"@type\":\"TestSubtypes$SubD\",\"d\":0}", mapper.writeValueAsString(new SubD())); + } + + public void testDeserializationNonNamed() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.registerSubtypes(SubC.class); + + // default name should be unqualified class name + SuperType bean = mapper.readValue("{\"@type\":\"TestSubtypes$SubC\", \"c\":1}", SuperType.class); + assertSame(SubC.class, bean.getClass()); + assertEquals(1, ((SubC) bean).c); + } + + public void testDeserializatioNamed() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.registerSubtypes(SubB.class); + mapper.registerSubtypes(new NamedType(SubD.class, "TypeD")); + + SuperType bean = mapper.readValue("{\"@type\":\"TypeB\", \"b\":13}", SuperType.class); + assertSame(SubB.class, bean.getClass()); + assertEquals(13, ((SubB) bean).b); + + // but we can also explicitly register name too + bean = mapper.readValue("{\"@type\":\"TypeD\", \"d\":-4}", SuperType.class); + assertSame(SubD.class, bean.getClass()); + assertEquals(-4, ((SubD) bean).d); + } + + // Trying to reproduce [JACKSON-366] + public void testEmptyBean() throws Exception + { + // First, with annotations + ObjectMapper mapper = new ObjectMapper(); + mapper.configure(SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS, true); + String json = mapper.writeValueAsString(new EmptyBean()); + assertEquals("{\"@type\":\"TestSubtypes$EmptyBean\"}", json); + + mapper = new ObjectMapper(); + mapper.configure(SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS, false); + json = mapper.writeValueAsString(new EmptyBean()); + assertEquals("{\"@type\":\"TestSubtypes$EmptyBean\"}", json); + + // and then with defaults + mapper = new ObjectMapper(); + mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL); + mapper.configure(SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS, false); + json = mapper.writeValueAsString(new EmptyNonFinal()); + assertEquals("[\"org.codehaus.jackson.map.jsontype.TestSubtypes$EmptyNonFinal\",{}]", json); + } + + public void testDefaultImpl() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + // first, test with no type information + SuperTypeWithDefault bean = mapper.readValue("{\"a\":13}", SuperTypeWithDefault.class); + assertEquals(DefaultImpl.class, bean.getClass()); + assertEquals(13, ((DefaultImpl) bean).a); + + // and then with unmapped info + bean = mapper.readValue("{\"a\":14,\"#type\":\"foobar\"}", SuperTypeWithDefault.class); + assertEquals(DefaultImpl.class, bean.getClass()); + assertEquals(14, ((DefaultImpl) bean).a); + + bean = mapper.readValue("{\"#type\":\"foobar\",\"a\":15}", SuperTypeWithDefault.class); + assertEquals(DefaultImpl.class, bean.getClass()); + assertEquals(15, ((DefaultImpl) bean).a); + + bean = mapper.readValue("{\"#type\":\"foobar\"}", SuperTypeWithDefault.class); + assertEquals(DefaultImpl.class, bean.getClass()); + assertEquals(0, ((DefaultImpl) bean).a); + } + + // [JACKSON-505]: ok to also default to mapping there might be for base type + public void testDefaultImplViaModule() throws Exception + { + final String JSON = "{\"a\":123}"; + + // first: without registration etc, epic fail: + ObjectMapper mapper = new ObjectMapper(); + try { + mapper.readValue(JSON, SuperTypeWithoutDefault.class); + fail("Expected an exception"); + } catch (JsonMappingException e) { + verifyException(e, "missing property"); + } + + // but then succeed when we register default impl + mapper = new ObjectMapper(); + SimpleModule module = new SimpleModule("test", Version.unknownVersion()); + module.addAbstractTypeMapping(SuperTypeWithoutDefault.class, DefaultImpl505.class); + mapper.registerModule(module); + SuperTypeWithoutDefault bean = mapper.readValue(JSON, SuperTypeWithoutDefault.class); + assertNotNull(bean); + assertEquals(DefaultImpl505.class, bean.getClass()); + assertEquals(123, ((DefaultImpl505) bean).a); + + bean = mapper.readValue("{\"#type\":\"foobar\"}", SuperTypeWithoutDefault.class); + assertEquals(DefaultImpl505.class, bean.getClass()); + assertEquals(0, ((DefaultImpl505) bean).a); + + } +} +
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestTypeNames.java b/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestTypeNames.java new file mode 100644 index 0000000..22cecaa --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestTypeNames.java
@@ -0,0 +1,154 @@ +package org.codehaus.jackson.map.jsontype; + +import java.util.*; + +import org.codehaus.jackson.annotate.JsonSubTypes; +import org.codehaus.jackson.annotate.JsonTypeInfo; +import org.codehaus.jackson.annotate.JsonTypeName; +import org.codehaus.jackson.annotate.JsonSubTypes.Type; +import org.codehaus.jackson.annotate.JsonTypeInfo.As; +import org.codehaus.jackson.annotate.JsonTypeInfo.Id; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.type.TypeFactory; + +/** + * Separate tests for verifying that "type name" type id mechanism + * works. + * + * @author tatu + */ +public class TestTypeNames extends BaseMapTest +{ + @SuppressWarnings("serial") + static class AnimalMap extends LinkedHashMap<String,Animal> { } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + public void testSerialization() throws Exception + { + ObjectMapper m = new ObjectMapper(); + + // Note: need to use wrapper array just so that we can define + // static type on serialization. If we had root static types, + // could use those; but at the moment root type is dynamic + + assertEquals("[{\"doggy\":{\"name\":\"Spot\",\"ageInYears\":3}}]", + m.writeValueAsString(new Animal[] { new Dog("Spot", 3) })); + assertEquals("[{\"MaineCoon\":{\"name\":\"Belzebub\",\"purrs\":true}}]", + m.writeValueAsString(new Animal[] { new MaineCoon("Belzebub", true)})); + } + + public void testRoundTrip() throws Exception + { + ObjectMapper m = new ObjectMapper(); + Animal[] input = new Animal[] { + new Dog("Odie", 7), + null, + new MaineCoon("Piru", false), + new Persian("Khomeini", true) + }; + String json = m.writeValueAsString(input); + List<Animal> output = m.readValue(json, + TypeFactory.defaultInstance().constructCollectionType(ArrayList.class, Animal.class)); + assertEquals(input.length, output.size()); + for (int i = 0, len = input.length; i < len; ++i) { + assertEquals("Entry #"+i+" differs, input = '"+json+"'", + input[i], output.get(i)); + } + } + + public void testRoundTripMap() throws Exception + { + ObjectMapper m = new ObjectMapper(); + AnimalMap input = new AnimalMap(); + input.put("venla", new MaineCoon("Venla", true)); + input.put("ama", new Dog("Amadeus", 13)); + String json = m.writeValueAsString(input); + AnimalMap output = m.readValue(json, AnimalMap.class); + assertEquals(input, output); + } +} + +/* +/********************************************************** +/* Helper types +/********************************************************** + */ + +@JsonTypeInfo(use=Id.NAME, include=As.WRAPPER_OBJECT) +@JsonSubTypes({ + @Type(value=Dog.class, name="doggy"), + @Type(Cat.class) /* defaults to "TestTypedNames$Cat" then */ +}) +class Animal +{ + public String name; + + + @Override + public boolean equals(Object o) { + if (o == this) return true; + if (o == null) return false; + if (o.getClass() != getClass()) return false; + return name.equals(((Animal) o).name); + } + +} + +class Dog extends Animal +{ + public int ageInYears; + + public Dog() { } + public Dog(String n, int y) { + name = n; + ageInYears = y; + } + + @Override + public boolean equals(Object o) { + return super.equals(o) + && ((Dog) o).ageInYears == ageInYears; + } +} + +@JsonSubTypes({ + @Type(MaineCoon.class), + @Type(Persian.class) +}) +abstract class Cat extends Animal { + public boolean purrs; + public Cat() { } + public Cat(String n, boolean p) { + name = n; + purrs = p; + } + + @Override + public boolean equals(Object o) { + return super.equals(o) && ((Cat) o).purrs == purrs; + } +} + +/* uses default name ("MaineCoon") since there's no @JsonTypeName, + * nor did supertype specify name + */ +class MaineCoon extends Cat { + public MaineCoon() { super(); } + public MaineCoon(String n, boolean p) { + super(n, p); + } +} + +@JsonTypeName("persialaisKissa") +class Persian extends Cat { + public Persian() { super(); } + public Persian(String n, boolean p) { + super(n, p); + } +} +
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestTypedArrayDeserialization.java b/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestTypedArrayDeserialization.java new file mode 100644 index 0000000..2893032 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestTypedArrayDeserialization.java
@@ -0,0 +1,114 @@ +package org.codehaus.jackson.map.jsontype; + +import java.util.ArrayList; +import java.util.LinkedList; + +import static org.junit.Assert.assertArrayEquals; + +import org.codehaus.jackson.annotate.JsonTypeInfo; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.type.TypeFactory; +import org.codehaus.jackson.type.JavaType; + +public class TestTypedArrayDeserialization + extends BaseMapTest +{ + /* + /********************************************************** + /* Helper types + /********************************************************** + */ + + /** + * Let's claim we need type here too (although we won't + * really use any sub-classes) + */ + @SuppressWarnings("serial") + @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.WRAPPER_ARRAY) + static class TypedList<T> extends ArrayList<T> { } + + @SuppressWarnings("serial") + @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY) + static class TypedListAsProp<T> extends ArrayList<T> { } + + @SuppressWarnings("serial") + @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.WRAPPER_OBJECT) + static class TypedListAsWrapper<T> extends LinkedList<T> { } + + // Mix-in to force wrapper for things like primitive arrays + @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.WRAPPER_OBJECT) + interface WrapperMixIn { } + + /* + /********************************************************** + /* Unit tests, Lists + /********************************************************** + */ + + public void testIntList() throws Exception + { + ObjectMapper m = new ObjectMapper(); + // uses WRAPPER_OBJECT inclusion + String JSON = "{\""+TypedListAsWrapper.class.getName()+"\":[4,5, 6]}"; + JavaType type = TypeFactory.defaultInstance().constructCollectionType(TypedListAsWrapper.class, Integer.class); + TypedListAsWrapper<Integer> result = m.readValue(JSON, type); + assertNotNull(result); + assertEquals(3, result.size()); + assertEquals(Integer.valueOf(4), result.get(0)); + assertEquals(Integer.valueOf(5), result.get(1)); + assertEquals(Integer.valueOf(6), result.get(2)); + } + + /** + * Similar to above, but this time let's request adding type info + * as property. That would not work (since there's no JSON Object to + * add property in), so it will basically be same as using WRAPPER_ARRAY + */ + public void testBooleanListAsProp() throws Exception + { + ObjectMapper m = new ObjectMapper(); + // tries to use PROPERTY inclusion; but for ARRAYS (and scalars) will become ARRAY_WRAPPER + String JSON = "[\""+TypedListAsProp.class.getName()+"\",[true, false]]"; + JavaType type = TypeFactory.defaultInstance().constructCollectionType(TypedListAsProp.class, Boolean.class); + TypedListAsProp<Object> result = m.readValue(JSON, type); + assertNotNull(result); + assertEquals(2, result.size()); + assertEquals(Boolean.TRUE, result.get(0)); + assertEquals(Boolean.FALSE, result.get(1)); + } + + public void testLongListAsWrapper() throws Exception + { + ObjectMapper m = new ObjectMapper(); + // uses OBJECT_ARRAY, works just fine + + String JSON = "{\""+TypedListAsWrapper.class.getName()+"\":[1, 3]}"; + JavaType type = TypeFactory.defaultInstance().constructCollectionType(TypedListAsWrapper.class, Long.class); + TypedListAsWrapper<Object> result = m.readValue(JSON, type); + assertNotNull(result); + assertEquals(2, result.size()); + + assertEquals(Long.class, result.get(0).getClass()); + assertEquals(Long.valueOf(1), result.get(0)); + assertEquals(Long.class, result.get(1).getClass()); + assertEquals(Long.valueOf(3), result.get(1)); + } + + /* + /********************************************************** + /* Unit tests, primitive arrays + /********************************************************** + */ + + public void testLongArray() throws Exception + { + ObjectMapper m = new ObjectMapper(); + // use class name, WRAPPER_OBJECT + m.getDeserializationConfig().addMixInAnnotations(long[].class, WrapperMixIn.class); + String JSON = "{\""+long[].class.getName()+"\":[5, 6, 7]}"; + long[] value = m.readValue(JSON, long[].class); + assertNotNull(value); + assertEquals(3, value.length); + assertArrayEquals(new long[] { 5L, 6L, 7L} , value); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestTypedArraySerialization.java b/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestTypedArraySerialization.java new file mode 100644 index 0000000..2de753a --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestTypedArraySerialization.java
@@ -0,0 +1,160 @@ +package org.codehaus.jackson.map.jsontype; + +import java.util.*; + +import org.codehaus.jackson.annotate.JsonSubTypes; +import org.codehaus.jackson.annotate.JsonTypeInfo; +import org.codehaus.jackson.annotate.JsonTypeName; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.JsonView; + +/** + * Unit tests for verifying that types that serialize as JSON Arrays + * get properly serialized with types (esp. for contents, and + * gracefully handling Lists themselves too) + * + * @author tatus + * @since 1.5 + */ +public class TestTypedArraySerialization + extends BaseMapTest +{ + /* + /********************************************************** + /* Helper types + /********************************************************** + */ + + /** + * Let's claim we need type here too (although we won't + * really use any sub-classes) + */ + @SuppressWarnings("serial") + @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.WRAPPER_ARRAY) + static class TypedList<T> extends ArrayList<T> { } + + @SuppressWarnings("serial") + @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY) + static class TypedListAsProp<T> extends ArrayList<T> { } + + @SuppressWarnings("serial") + @JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.WRAPPER_OBJECT) + static class TypedListAsWrapper<T> extends LinkedList<T> { } + + // Mix-in to force wrapper for things like primitive arrays + @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.WRAPPER_OBJECT) + interface WrapperMixIn { } + + // for [JACKSON-341] + @JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.WRAPPER_OBJECT) + @JsonSubTypes({ @JsonSubTypes.Type(B.class) }) + interface A { } + + @JsonTypeName("BB") + static class B implements A { + public int value = 2; + } + + @JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.PROPERTY) + @JsonTypeName("bean") + static class Bean { + public int x = 0; + } + + static class BeanListWrapper { + @JsonView({Object.class}) + public List<Bean> beans = new ArrayList<Bean>(); + { + beans.add(new Bean()); + } + } + + /* + /********************************************************** + /* Unit tests, Lists + /********************************************************** + */ + + public void testListWithPolymorphic() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + BeanListWrapper beans = new BeanListWrapper(); + assertEquals("{\"beans\":[{\"@type\":\"bean\",\"x\":0}]}", mapper.writeValueAsString(beans)); + // Related to [JACKSON-364] + ObjectWriter w = mapper.writerWithView(Object.class); + assertEquals("{\"beans\":[{\"@type\":\"bean\",\"x\":0}]}", w.writeValueAsString(beans)); + } + + public void testIntList() throws Exception + { + TypedList<Integer> input = new TypedList<Integer>(); + input.add(5); + input.add(13); + // uses WRAPPER_ARRAY inclusion: + assertEquals("[\""+TypedList.class.getName()+"\",[5,13]]", serializeAsString(input)); + } + + // Similar to above, but this time let's request adding type info + // as property. That would not work (since there's no JSON Object to + // add property in), so it should revert to method used with + // ARRAY_WRAPPER method. + public void testStringListAsProp() throws Exception + { + TypedListAsProp<String> input = new TypedListAsProp<String>(); + input.add("a"); + input.add("b"); + assertEquals("[\""+TypedListAsProp.class.getName()+"\",[\"a\",\"b\"]]", + serializeAsString(input)); + } + + public void testStringListAsObjectWrapper() throws Exception + { + TypedListAsWrapper<Boolean> input = new TypedListAsWrapper<Boolean>(); + input.add(true); + input.add(null); + input.add(false); + // Can wrap in JSON Object for wrapped style... also, will use + // non-qualified class name as type name, since there are no + // annotations + String expName = "TestTypedArraySerialization$TypedListAsWrapper"; + assertEquals("{\""+expName+"\":[true,null,false]}", + serializeAsString(input)); + } + + /* + /********************************************************** + /* Unit tests, primitive arrays + /********************************************************** + */ + + public void testIntArray() throws Exception + { + ObjectMapper m = new ObjectMapper(); + m.getSerializationConfig().addMixInAnnotations(int[].class, WrapperMixIn.class); + int[] input = new int[] { 1, 2, 3 }; + String clsName = int[].class.getName(); + assertEquals("{\""+clsName+"\":[1,2,3]}", serializeAsString(m, input)); + } + + /* + /********************************************************** + /* Unit tests, generic arrays + /********************************************************** + */ + + public void testGenericArray() throws Exception + { + ObjectMapper m; + final A[] input = new A[] { new B() }; + final String EXP = "[{\"BB\":{\"value\":2}}]"; + + // first, with defaults + m = new ObjectMapper(); + assertEquals(EXP, m.writeValueAsString(input)); + + // then with static typing enabled: + m = new ObjectMapper(); + m.configure(SerializationConfig.Feature.USE_STATIC_TYPING, true); + assertEquals(EXP, m.writeValueAsString(input)); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestTypedContainerSerialization.java b/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestTypedContainerSerialization.java new file mode 100644 index 0000000..a6909c6 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestTypedContainerSerialization.java
@@ -0,0 +1,162 @@ +package org.codehaus.jackson.map.jsontype; + +import java.util.*; + +import org.junit.Assert; + +import org.codehaus.jackson.annotate.JsonCreator; +import org.codehaus.jackson.annotate.JsonProperty; +import org.codehaus.jackson.annotate.JsonSubTypes; +import org.codehaus.jackson.annotate.JsonTypeInfo; +import org.codehaus.jackson.annotate.JsonTypeName; +import org.codehaus.jackson.annotate.JsonSubTypes.Type; +import org.codehaus.jackson.annotate.JsonTypeInfo.As; +import org.codehaus.jackson.annotate.JsonTypeInfo.Id; +import org.codehaus.jackson.map.BaseMapTest; +import org.codehaus.jackson.map.ObjectMapper; +import org.codehaus.jackson.map.annotate.JsonSerialize; +import org.codehaus.jackson.map.type.TypeFactory; +import org.codehaus.jackson.type.JavaType; +import org.codehaus.jackson.type.TypeReference; + +public class TestTypedContainerSerialization + extends BaseMapTest +{ + /* + /********************************************************** + /* Helper types + /********************************************************** + */ + + @JsonTypeInfo(use = Id.NAME, include = As.PROPERTY, property = "object-type") + @JsonSubTypes( { @Type(value = Dog.class, name = "doggy"), + @Type(value = Cat.class, name = "kitty") }) + static abstract class Animal { + public String name; + + protected Animal(String n) { + name = n; + } + } + + @JsonTypeName("doggie") + static class Dog extends Animal { + public int boneCount; + + public Dog() { + super(null); + } + + @JsonCreator + public Dog(@JsonProperty("name") String name) { + super(name); + } + + public void setBoneCount(int i) { + boneCount = i; + } + } + + @JsonTypeName("kitty") + static class Cat extends Animal { + public String furColor; + + public Cat() { + super(null); + } + + @JsonCreator + public Cat(@JsonProperty("furColor") String c) { + super(null); + furColor = c; + } + + public void setName(String n) { + name = n; + } + } + + static class Container1 { + Animal animal; + + public Animal getAnimal() { + return animal; + } + + public void setAnimal(Animal animal) { + this.animal = animal; + } + } + + static class Container2<T extends Animal> { + @JsonSerialize + T animal; + + public T getAnimal() { + return animal; + } + + public void setAnimal(T animal) { + this.animal = animal; + } + + } + + @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY, property="@class") + static class Issue508A { } + static class Issue508B extends Issue508A { } + + private final static ObjectMapper mapper = new ObjectMapper(); + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + public void testIssue265() throws Exception + { + Dog dog = new Dog("medor"); + dog.setBoneCount(3); + Container1 c1 = new Container1(); + c1.setAnimal(dog); + String s1 = mapper.writeValueAsString(c1); + Assert.assertTrue("polymorphic type info is kept (1)", s1 + .indexOf("\"object-type\":\"doggy\"") >= 0); + Container2<Animal> c2 = new Container2<Animal>(); + c2.setAnimal(dog); + String s2 = mapper.writeValueAsString(c2); + Assert.assertTrue("polymorphic type info is kept (2)", s2 + .indexOf("\"object-type\":\"doggy\"") >= 0); + } + + public void testIssue329() throws Exception + { + ArrayList<Animal> animals = new ArrayList<Animal>(); + animals.add(new Dog("Spot")); + JavaType rootType = TypeFactory.defaultInstance().constructParametricType(Iterator.class, Animal.class); + String json = mapper.writerWithType(rootType).writeValueAsString(animals.iterator()); + if (json.indexOf("\"object-type\":\"doggy\"") < 0) { + fail("No polymorphic type retained, should be; JSON = '"+json+"'"); + } + } + + public void testIssue508() throws Exception + { + List<List<Issue508A>> l = new ArrayList<List<Issue508A>>(); + List<Issue508A> l2 = new ArrayList<Issue508A>(); + l2.add(new Issue508A()); + l.add(l2); + TypeReference<?> typeRef = new TypeReference<List<List<Issue508A>>>() {}; + String json = mapper.writerWithType(typeRef).writeValueAsString(l); + + List<?> output = mapper.readValue(json, typeRef); + assertEquals(1, output.size()); + Object ob = output.get(0); + assertTrue(ob instanceof List<?>); + List<?> list2 = (List<?>) ob; + assertEquals(1, list2.size()); + ob = list2.get(0); + assertSame(Issue508A.class, ob.getClass()); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestTypedDeserialization.java b/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestTypedDeserialization.java new file mode 100644 index 0000000..b7bfb97 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestTypedDeserialization.java
@@ -0,0 +1,247 @@ +package org.codehaus.jackson.map.jsontype; + +import java.util.*; + +import org.codehaus.jackson.annotate.*; +import org.codehaus.jackson.annotate.JsonSubTypes.Type; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.type.TypeFactory; +import org.codehaus.jackson.type.JavaType; + +import static org.codehaus.jackson.annotate.JsonTypeInfo.*; + +/** + * @since 1.5 + */ +public class TestTypedDeserialization + extends BaseMapTest +{ + /* + /********************************************************** + /* Helper types + /********************************************************** + */ + + /** + * Polymorphic base class + */ + @JsonTypeInfo(use=Id.CLASS, include=As.PROPERTY, property="@classy") + static abstract class Animal { + public String name; + + protected Animal(String n) { name = n; } + } + + @JsonTypeName("doggie") + static class Dog extends Animal + { + public int boneCount; + + @JsonCreator + public Dog(@JsonProperty("name") String name) { + super(name); + } + + public void setBoneCount(int i) { boneCount = i; } + } + + @JsonTypeName("kitty") + static class Cat extends Animal + { + public String furColor; + + @JsonCreator + public Cat(@JsonProperty("furColor") String c) { + super(null); + furColor = c; + } + + public void setName(String n) { name = n; } + } + + // for [JACKSON-319] -- allow "empty" beans + @JsonTypeName("fishy") + static class Fish extends Animal + { + @JsonCreator + public Fish() + { + super(null); + } + } + + static class AnimalContainer { + public Animal animal; + } + + // base class with no useful info + @JsonTypeInfo(use=Id.CLASS, include=As.WRAPPER_ARRAY) + static abstract class DummyBase { + protected DummyBase(boolean foo) { } + } + + static class DummyImpl extends DummyBase { + public int x; + + public DummyImpl() { super(true); } + } + + @JsonTypeInfo(use=Id.MINIMAL_CLASS, include=As.WRAPPER_OBJECT) + interface TypeWithWrapper { } + + @JsonTypeInfo(use=Id.CLASS, include=As.WRAPPER_ARRAY) + interface TypeWithArray { } + + static class Issue506DateBean { + @JsonTypeInfo(use = Id.NAME, include = As.PROPERTY, property = "type2") + public Date date; + } + + static class Issue506NumberBean + { + @JsonTypeInfo(use = Id.NAME, include = As.PROPERTY, property = "type3") + @JsonSubTypes({ @Type(Long.class), @Type(Integer.class) }) + public Number number; + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + /** + * First things first, let's ensure we can serialize using + * class name, written as main-level property name + */ + public void testSimpleClassAsProperty() throws Exception + { + ObjectMapper m = new ObjectMapper(); + Animal a = m.readValue(asJSONObjectValueString("@classy", Cat.class.getName(), + "furColor", "tabby", "name", "Garfield"), Animal.class); + assertNotNull(a); + assertEquals(Cat.class, a.getClass()); + Cat c = (Cat) a; + assertEquals("Garfield", c.name); + assertEquals("tabby", c.furColor); + } + + // Test inclusion using wrapper style + public void testTypeAsWrapper() throws Exception + { + ObjectMapper m = new ObjectMapper(); + m.getDeserializationConfig().addMixInAnnotations(Animal.class, TypeWithWrapper.class); + String JSON = "{\".TestTypedDeserialization$Dog\" : " + +asJSONObjectValueString(m, "name", "Scooby", "boneCount", "6")+" }"; + Animal a = m.readValue(JSON, Animal.class); + assertTrue(a instanceof Animal); + assertEquals(Dog.class, a.getClass()); + Dog d = (Dog) a; + assertEquals("Scooby", d.name); + assertEquals(6, d.boneCount); + } + + // Test inclusion using 2-element array + public void testTypeAsArray() throws Exception + { + ObjectMapper m = new ObjectMapper(); + m.getDeserializationConfig().addMixInAnnotations(Animal.class, TypeWithArray.class); + // hmmh. Not good idea to rely on exact output, order may change. But... + String JSON = "[\""+Dog.class.getName()+"\", " + +asJSONObjectValueString(m, "name", "Martti", "boneCount", "11")+" ]"; + Animal a = m.readValue(JSON, Animal.class); + assertEquals(Dog.class, a.getClass()); + Dog d = (Dog) a; + assertEquals("Martti", d.name); + assertEquals(11, d.boneCount); + } + + // Use basic Animal as contents of a regular List + public void testListAsArray() throws Exception + { + ObjectMapper m = new ObjectMapper(); + // This time using PROPERTY style (default) again + String JSON = "[\n" + +asJSONObjectValueString(m, "@classy", Cat.class.getName(), "name", "Hello", "furColor", "white") + +",\n" + // let's shuffle doggy's fields a bit for testing + +asJSONObjectValueString(m, + "boneCount", Integer.valueOf(1), + "@classy", Dog.class.getName(), + "name", "Bob" + ) + +",\n" + +asJSONObjectValueString(m, "@classy", Fish.class.getName()) + +", null\n]"; + + JavaType expType = TypeFactory.defaultInstance().constructCollectionType(ArrayList.class, Animal.class); + List<Animal> animals = m.readValue(JSON, expType); + assertNotNull(animals); + assertEquals(4, animals.size()); + Cat c = (Cat) animals.get(0); + assertEquals("Hello", c.name); + assertEquals("white", c.furColor); + Dog d = (Dog) animals.get(1); + assertEquals("Bob", d.name); + assertEquals(1, d.boneCount); + Fish f = (Fish) animals.get(2); + assertNotNull(f); + assertNull(animals.get(3)); + } + + public void testCagedAnimal() throws Exception + { + ObjectMapper m = new ObjectMapper(); + String jsonCat = asJSONObjectValueString(m, "@classy", Cat.class.getName(), "name", "Nilson", "furColor", "black"); + String JSON = "{\"animal\":"+jsonCat+"}"; + + AnimalContainer cont = m.readValue(JSON, AnimalContainer.class); + assertNotNull(cont); + Animal a = cont.animal; + assertNotNull(a); + Cat c = (Cat) a; + assertEquals("Nilson", c.name); + assertEquals("black", c.furColor); + } + + /** + * Test that verifies that there are few limitations on polymorphic + * base class. + */ + public void testAbstractEmptyBaseClass() throws Exception + { + DummyBase result = new ObjectMapper().readValue( + "[\""+DummyImpl.class.getName()+"\",{\"x\":3}]", DummyBase.class); + assertNotNull(result); + assertEquals(DummyImpl.class, result.getClass()); + assertEquals(3, ((DummyImpl) result).x); + } + + // [JACKSON-506], wrt Date + public void testIssue506WithDate() throws Exception + { + Issue506DateBean input = new Issue506DateBean(); + input.date = new Date(1234L); + + ObjectMapper mapper = new ObjectMapper(); + String json = mapper.writeValueAsString(input); + + Issue506DateBean output = mapper.readValue(json, Issue506DateBean.class); + assertEquals(input.date, output.date); + } + + // [JACKSON-506], wrt Number + public void testIssue506WithNumber() throws Exception + { + Issue506NumberBean input = new Issue506NumberBean(); + input.number = Long.valueOf(4567L); + + ObjectMapper mapper = new ObjectMapper(); + String json = mapper.writeValueAsString(input); + + Issue506NumberBean output = mapper.readValue(json, Issue506NumberBean.class); + assertEquals(input.number, output.number); + } +} + +
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestTypedDeserializationWithDefault.java b/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestTypedDeserializationWithDefault.java new file mode 100644 index 0000000..00139a9 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestTypedDeserializationWithDefault.java
@@ -0,0 +1,78 @@ +package org.codehaus.jackson.map.jsontype; + +import java.util.*; + +import org.codehaus.jackson.annotate.*; +import org.codehaus.jackson.map.ObjectMapper; + +/** + * Unit tests for [JACKSON-712]; custom handling of invalid type id embedding. + */ +public class TestTypedDeserializationWithDefault + extends org.codehaus.jackson.map.BaseMapTest +{ + private final ObjectMapper mapper = new ObjectMapper(); + + @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type", defaultImpl = LegacyInter.class) + @JsonSubTypes(value = {@JsonSubTypes.Type(name = "mine", value = MyInter.class)}) + public static interface Inter { } + + public static class MyInter implements Inter + { + @JsonProperty("blah") + public List<String> blah; + } + + public static class LegacyInter extends MyInter + { + @JsonCreator + LegacyInter(Object obj) + { + if (obj instanceof List) { + blah = new ArrayList<String>(); + for (Object o : (List<?>) obj) { + blah.add(o.toString()); + } + } + else if (obj instanceof String) { + blah = Arrays.asList(((String) obj).split(",")); + } + else { + throw new IllegalArgumentException("Unknown type: " + obj.getClass()); + } + } + } + + public void testDeserializationWithObject() throws Exception + { + Inter inter = mapper.readValue("{\"type\": \"mine\", \"blah\": [\"a\", \"b\", \"c\"]}", Inter.class); + + assertTrue(inter instanceof MyInter); + assertFalse(inter instanceof LegacyInter); + assertEquals(Arrays.asList("a", "b", "c"), ((MyInter) inter).blah); + } + + public void testDeserializationWithString() throws Exception + { + Inter inter = mapper.readValue("\"a,b,c,d\"", Inter.class); + + assertTrue(inter instanceof LegacyInter); + assertEquals(Arrays.asList("a", "b", "c", "d"), ((MyInter) inter).blah); + } + + public void testDeserializationWithArray() throws Exception + { + Inter inter = mapper.readValue("[\"a\", \"b\", \"c\", \"d\"]", Inter.class); + + assertTrue(inter instanceof LegacyInter); + assertEquals(Arrays.asList("a", "b", "c", "d"), ((MyInter) inter).blah); + } + + public void testDeserializationWithArrayOfSize2() throws Exception + { + Inter inter = mapper.readValue("[\"a\", \"b\"]", Inter.class); + + assertTrue(inter instanceof LegacyInter); + assertEquals(Arrays.asList("a", "b"), ((MyInter) inter).blah); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestTypedSerialization.java b/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestTypedSerialization.java new file mode 100644 index 0000000..9efa341 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestTypedSerialization.java
@@ -0,0 +1,202 @@ +package org.codehaus.jackson.map.jsontype; + +import java.util.*; + +import org.codehaus.jackson.annotate.JsonTypeInfo; +import org.codehaus.jackson.annotate.JsonTypeName; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.type.TypeReference; + +import static org.codehaus.jackson.annotate.JsonTypeInfo.*; + +public class TestTypedSerialization + extends BaseMapTest +{ + /* + /********************************************************** + /* Helper types + /********************************************************** + */ + + /** + * Polymorphic base class + */ + @JsonTypeInfo(use=Id.CLASS, include=As.PROPERTY) + static abstract class Animal { + public String name; + + protected Animal(String n) { name = n; } + } + + @JsonTypeName("doggie") + static class Dog extends Animal + { + public int boneCount; + + private Dog() { super(null); } + public Dog(String name, int b) { + super(name); + boneCount = b; + } + } + + @JsonTypeName("kitty") + static class Cat extends Animal + { + public String furColor; + + private Cat() { super(null); } + public Cat(String name, String c) { + super(name); + furColor = c; + } + } + + public class AnimalWrapper { + public Animal animal; + + public AnimalWrapper(Animal a) { animal = a; } + } + + @JsonTypeInfo(use=Id.MINIMAL_CLASS, include=As.WRAPPER_OBJECT) + interface TypeWithWrapper { } + + @JsonTypeInfo(use=Id.CLASS, include=As.WRAPPER_ARRAY) + interface TypeWithArray { } + + @JsonTypeInfo(use=Id.NAME) + @JsonTypeName("empty") + public class Empty { } + + @JsonTypeInfo(include=As.PROPERTY, use=Id.CLASS) + public class Super {} + public class A extends Super {} + public class B extends Super {} + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + /** + * First things first, let's ensure we can serialize using + * class name, written as main-level property name + */ + public void testSimpleClassAsProperty() throws Exception + { + Map<String,Object> result = writeAndMap(new Cat("Beelzebub", "tabby")); + assertEquals(3, result.size()); + assertEquals("Beelzebub", result.get("name")); + assertEquals("tabby", result.get("furColor")); + // should we try customized class name? + String classProp = Id.CLASS.getDefaultPropertyName(); + assertEquals(Cat.class.getName(), result.get(classProp)); + } + + /** + * Test inclusion using wrapper style + */ + public void testTypeAsWrapper() throws Exception + { + ObjectMapper m = new ObjectMapper(); + m.getSerializationConfig().addMixInAnnotations(Animal.class, TypeWithWrapper.class); + Map<String,Object> result = writeAndMap(m, new Cat("Venla", "black")); + // should get a wrapper; keyed by minimal class name ("Cat" here) + assertEquals(1, result.size()); + // minimal class name is prefixed by dot, and for inner classes it's bit longer + Map<?,?> cat = (Map<?,?>) result.get(".TestTypedSerialization$Cat"); + assertNotNull(cat); + assertEquals(2, cat.size()); + assertEquals("Venla", cat.get("name")); + assertEquals("black", cat.get("furColor")); + } + + /** + * Test inclusion using 2-element array + */ + public void testTypeAsArray() throws Exception + { + ObjectMapper m = new ObjectMapper(); + m.getSerializationConfig().addMixInAnnotations(Animal.class, TypeWithArray.class); + // hmmh. Not good idea to rely on exact output, order may change. But... + Map<String,Object> result = writeAndMap(m, new AnimalWrapper(new Dog("Amadeus", 7))); + // First level, wrapper + assertEquals(1, result.size()); + List<?> l = (List<?>) result.get("animal"); + assertNotNull(l); + assertEquals(2, l.size()); + assertEquals(Dog.class.getName(), l.get(0)); + Map<?,?> doggie = (Map<?,?>) l.get(1); + assertNotNull(doggie); + assertEquals(2, doggie.size()); + assertEquals("Amadeus", doggie.get("name")); + assertEquals(Integer.valueOf(7), doggie.get("boneCount")); + } + + /* !!! 30-Jan-2010, tatus: I am not completely sure below works as it should + * Problem is, context of "untyped" map should prevent type information + * being added to Animal entries, because Object.class has no type. + * If type information is included, it will not be useful for deserialization, + * since static type does not carry through (unlike in serialization). + * + * But it is not quite clear how type information should be pushed through + * array types... + */ + @SuppressWarnings("unchecked") + public void testInArray() throws Exception + { + // ensure we'll use mapper with default configs + ObjectMapper m = new ObjectMapper(); + // ... so this should NOT be needed... + m.disableDefaultTyping(); + + Animal[] animals = new Animal[] { new Cat("Miuku", "white"), new Dog("Murre", 9) }; + Map<String,Object> map = new HashMap<String,Object>(); + map.put("a", animals); + String json = m.writeValueAsString(map); + Map<String,Object> result = m.readValue(json, Map.class); + assertEquals(1, result.size()); + Object ob = result.get("a"); + if (!(ob instanceof List<?>)) { + // 03-Feb-2010, tatu: Weird; seems to fail sometimes... + fail("Did not map to entry with 'a' as List (but as "+ob.getClass().getName()+"): JSON == '"+json+"'"); + } + List<?> l = (List<?>)ob; + assertNotNull(l); + assertEquals(2, l.size()); + Map<?,?> a1 = (Map<?,?>) l.get(0); + assertEquals(3, a1.size()); + String classProp = Id.CLASS.getDefaultPropertyName(); + assertEquals(Cat.class.getName(), a1.get(classProp)); + Map<?,?> a2 = (Map<?,?>) l.get(1); + assertEquals(3, a2.size()); + assertEquals(Dog.class.getName(), a2.get(classProp)); + } + + /** + * Simple unit test to verify that serializing "empty" beans is ok + */ + public void testEmptyBean() throws Exception + { + ObjectMapper m = new ObjectMapper(); + m.configure(SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS, false); + assertEquals("{\"@type\":\"empty\"}", m.writeValueAsString(new Empty())); + } + + /** + * Unit test for [JACKSON-543] + */ + public void testTypedMaps() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + + Map<Long, Collection<Super>> map = new HashMap<Long, Collection<Super>>(); + List<Super> list = new ArrayList<Super>(); + list.add(new A()); + map.put(1L, list); + String json = mapper.writerWithType(new TypeReference<Map<Long, Collection<Super>>>() {}).writeValueAsString(map); + assertTrue(json, json.contains("@class")); + } +} +
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestWithGenerics.java b/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestWithGenerics.java new file mode 100644 index 0000000..10bfa3e --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/jsontype/TestWithGenerics.java
@@ -0,0 +1,205 @@ +package org.codehaus.jackson.map.jsontype; + +import java.io.IOException; +import java.util.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.annotate.*; +import org.codehaus.jackson.annotate.JsonSubTypes.Type; +import org.codehaus.jackson.annotate.JsonTypeInfo.As; +import org.codehaus.jackson.annotate.JsonTypeInfo.Id; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.JsonSerialize; +import org.codehaus.jackson.map.introspect.BasicBeanDescription; +import org.codehaus.jackson.map.ser.BeanSerializerFactory; +import org.codehaus.jackson.map.type.TypeFactory; + +public class TestWithGenerics extends BaseMapTest +{ + @JsonTypeInfo(use = Id.NAME, include = As.PROPERTY, property = "object-type") + @JsonSubTypes( { @Type(value = Dog.class, name = "doggy") }) + static abstract class Animal { + public String name; + } + + static class Dog extends Animal { + public int boneCount; + + public Dog(String name, int b) { + super(); + this.name = name; + boneCount = b; + } + } + + static class ContainerWithGetter<T extends Animal> { + private T animal; + + public ContainerWithGetter(T a) { animal = a; } + + public T getAnimal() { return animal; } + } + + static class ContainerWithField<T extends Animal> { + public T animal; + + public ContainerWithField(T a) { animal = a; } + } + + // Beans for [JACKSON-387], [JACKSON-430] + + @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY, property="@classAttr1") + static class MyClass { + public List<MyParam<?>> params = new ArrayList<MyParam<?>>(); + } + + @JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY, property="@classAttr2") + static class MyParam<T>{ + public T value; + + public MyParam() { } + public MyParam(T v) { value = v; } + } + + private static class SomeObject { + @SuppressWarnings("unused") + public String someValue = UUID.randomUUID().toString(); + } + + // Beans for [JACKSON-430] + + static class CustomJsonSerializer extends JsonSerializer<Object> + implements ResolvableSerializer + { + private final JsonSerializer<Object> beanSerializer; + + public CustomJsonSerializer( JsonSerializer<Object> beanSerializer ) { this.beanSerializer = beanSerializer; } + + @Override + public void serialize( Object value, JsonGenerator jgen, SerializerProvider provider ) + throws IOException, JsonProcessingException + { + beanSerializer.serialize( value, jgen, provider ); + } + + @Override + public Class<Object> handledType() { return beanSerializer.handledType(); } + + @Override + public void serializeWithType( Object value, JsonGenerator jgen, SerializerProvider provider, TypeSerializer typeSer ) + throws IOException, JsonProcessingException + { + beanSerializer.serializeWithType( value, jgen, provider, typeSer ); + } + + @Override + public void resolve(SerializerProvider provider) throws JsonMappingException + { + if (beanSerializer instanceof ResolvableSerializer) { + ((ResolvableSerializer) beanSerializer).resolve(provider); + } + } + } + + protected static class CustomJsonSerializerFactory extends BeanSerializerFactory + { + public CustomJsonSerializerFactory() { super(null); } + + @Override + protected JsonSerializer<Object> constructBeanSerializer( SerializationConfig config, BasicBeanDescription beanDesc, + BeanProperty property) + throws JsonMappingException + { + return new CustomJsonSerializer( super.constructBeanSerializer( config, beanDesc, property) ); + } + } + + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + public void testWrapperWithGetter() throws Exception + { + Dog dog = new Dog("Fluffy", 3); + String json = new ObjectMapper().writeValueAsString(new ContainerWithGetter<Animal>(dog)); + if (json.indexOf("\"object-type\":\"doggy\"") < 0) { + fail("polymorphic type not kept, result == "+json+"; should contain 'object-type':'...'"); + } + } + + public void testWrapperWithField() throws Exception + { + Dog dog = new Dog("Fluffy", 3); + String json = new ObjectMapper().writeValueAsString(new ContainerWithField<Animal>(dog)); + if (json.indexOf("\"object-type\":\"doggy\"") < 0) { + fail("polymorphic type not kept, result == "+json+"; should contain 'object-type':'...'"); + } + } + + public void testWrapperWithExplicitType() throws Exception + { + Dog dog = new Dog("Fluffy", 3); + ContainerWithGetter<Animal> c2 = new ContainerWithGetter<Animal>(dog); + ObjectMapper mapper = new ObjectMapper(); + String json = mapper.writerWithType(TypeFactory.defaultInstance().constructParametricType(ContainerWithGetter.class, Animal.class)).writeValueAsString(c2); + if (json.indexOf("\"object-type\":\"doggy\"") < 0) { + fail("polymorphic type not kept, result == "+json+"; should contain 'object-type':'...'"); + } + } + + @SuppressWarnings("deprecation") + public void testJackson387() throws Exception + { + ObjectMapper om = new ObjectMapper(); + om.enableDefaultTyping( ObjectMapper.DefaultTyping.JAVA_LANG_OBJECT, JsonTypeInfo.As.PROPERTY ); + om.getSerializationConfig().setSerializationInclusion( JsonSerialize.Inclusion.NON_NULL ); + om.getSerializationConfig().set( SerializationConfig.Feature.INDENT_OUTPUT, true ); + + MyClass mc = new MyClass(); + + MyParam<Integer> moc1 = new MyParam<Integer>(1); + MyParam<String> moc2 = new MyParam<String>("valueX"); + + SomeObject so = new SomeObject(); + so.someValue = "xxxxxx"; + MyParam<SomeObject> moc3 = new MyParam<SomeObject>(so); + + List<SomeObject> colist = new ArrayList<SomeObject>(); + colist.add( new SomeObject() ); + colist.add( new SomeObject() ); + colist.add( new SomeObject() ); + MyParam<List<SomeObject>> moc4 = new MyParam<List<SomeObject>>(colist); + + mc.params.add( moc1 ); + mc.params.add( moc2 ); + mc.params.add( moc3 ); + mc.params.add( moc4 ); + + String json = om.writeValueAsString( mc ); + + MyClass mc2 = om.readValue(json, MyClass.class ); + assertNotNull(mc2); + assertNotNull(mc2.params); + assertEquals(4, mc2.params.size()); + } + + public void testJackson430() throws Exception + { + ObjectMapper om = new ObjectMapper(); +// om.getSerializationConfig().setSerializationInclusion( Inclusion.NON_NULL ); + om.setSerializerFactory( new CustomJsonSerializerFactory() ); + MyClass mc = new MyClass(); + mc.params.add(new MyParam<Integer>(1)); + + String str = om.writeValueAsString( mc ); +// System.out.println( str ); + + MyClass mc2 = om.readValue( str, MyClass.class ); + assertNotNull(mc2); + assertNotNull(mc2.params); + assertEquals(1, mc2.params.size()); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/mixins/TestMixinDeserForClass.java b/1.9.10/src/test/org/codehaus/jackson/map/mixins/TestMixinDeserForClass.java new file mode 100644 index 0000000..dba149c --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/mixins/TestMixinDeserForClass.java
@@ -0,0 +1,98 @@ +package org.codehaus.jackson.map.mixins; + +import java.io.*; + +import org.codehaus.jackson.annotate.JsonAutoDetect; +import org.codehaus.jackson.annotate.JsonMethod; +import org.codehaus.jackson.annotate.JsonProperty; +import org.codehaus.jackson.map.*; + +public class TestMixinDeserForClass + extends BaseMapTest +{ + /* + /********************************************************** + /* Helper bean classes + /********************************************************** + */ + + static class BaseClass + { + /* property that is always found; but has lower priority than + * setter method if both found + */ + @JsonProperty + public String a; + + // setter that may or may not be auto-detected + public void setA(String v) { a = "XXX"+v; } + } + + @JsonAutoDetect(JsonMethod.ALL) + static class LeafClass + extends BaseClass { } + + @JsonAutoDetect(JsonMethod.NONE) + interface MixIn { } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + public void testClassMixInsTopLevel() throws IOException + { + ObjectMapper m = new ObjectMapper(); + // First: test default behavior: should use setter + LeafClass result = m.readValue("{\"a\":\"value\"}", LeafClass.class); + assertEquals("XXXvalue", result.a); + + /* Then with leaf-level mix-in; without (method) auto-detect, should + * use field + */ + m = new ObjectMapper(); + m.getDeserializationConfig().addMixInAnnotations(LeafClass.class, MixIn.class); + result = m.readValue("{\"a\":\"value\"}", LeafClass.class); + assertEquals("value", result.a); + } + + /* and then a test for mid-level mixin; should have no effect + * when deserializing leaf (but will if deserializing base class) + */ + public void testClassMixInsMidLevel() throws IOException + { + ObjectMapper m = new ObjectMapper(); + m.getDeserializationConfig().addMixInAnnotations(BaseClass.class, MixIn.class); + { + BaseClass result = m.readValue("{\"a\":\"value\"}", BaseClass.class); + assertEquals("value", result.a); + } + + // whereas with leaf class, reverts to default + { + LeafClass result = m.readValue("{\"a\":\"value\"}", LeafClass.class); + assertEquals("XXXvalue", result.a); + } + } + + /* Also: when mix-in attached to Object.class, will work, if + * visible (similar to mid-level, basically) + */ + public void testClassMixInsForObjectClass() throws IOException + { + ObjectMapper m = new ObjectMapper(); + m.getDeserializationConfig().addMixInAnnotations(Object.class, MixIn.class); + // will be seen for BaseClass + { + BaseClass result = m.readValue("{\"a\":\"\"}", BaseClass.class); + assertEquals("", result.a); + } + + // but LeafClass still overrides + { + LeafClass result = m.readValue("{\"a\":\"\"}", LeafClass.class); + assertEquals("XXX", result.a); + } + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/mixins/TestMixinDeserForCreators.java b/1.9.10/src/test/org/codehaus/jackson/map/mixins/TestMixinDeserForCreators.java new file mode 100644 index 0000000..574fc45 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/mixins/TestMixinDeserForCreators.java
@@ -0,0 +1,116 @@ +package org.codehaus.jackson.map.mixins; + +import java.io.*; + +import org.codehaus.jackson.annotate.*; +import org.codehaus.jackson.map.*; + +public class TestMixinDeserForCreators + extends BaseMapTest +{ + /* + /////////////////////////////////////////////////////////// + // Helper bean classes + /////////////////////////////////////////////////////////// + */ + + static class BaseClass + { + protected String _a; + + public BaseClass(String a) { + _a = a+"..."; + } + + private BaseClass(String value, boolean dummy) { + _a = value; + } + + public static BaseClass myFactory(String a) { + return new BaseClass(a+"X", true); + } + } + + static class BaseClassWithPrivateCtor + { + protected String _a; + private BaseClassWithPrivateCtor(String a) { + _a = a+"..."; + } + + } + + /** + * Mix-in class that will effectively suppresses String constructor, + * and marks a non-auto-detectable static method as factory method + * as a creator. + *<p> + * Note that method implementations are not used for anything; but + * we have to a class: interface won't do, as they can't have + * constructors or static methods. + */ + static class MixIn + { + @JsonIgnore protected MixIn(String s) { } + + @JsonCreator + static BaseClass myFactory(String a) { return null; } + } + + static class MixInForPrivate + { + @JsonCreator MixInForPrivate(String s) { } + } + + static class StringWrapper { + String _value; + private StringWrapper(String s, boolean foo) { _value = s; } + + @SuppressWarnings("unused") + private static StringWrapper create(String str) { + return new StringWrapper(str, false); + } + } + + abstract static class StringWrapperMixIn { + @JsonCreator static StringWrapper create(String str) { return null; } + } + + /* + /////////////////////////////////////////////////////////// + // Unit tests + /////////////////////////////////////////////////////////// + */ + + public void testForConstructor() throws IOException + { + ObjectMapper m = new ObjectMapper(); + m.getDeserializationConfig().addMixInAnnotations(BaseClassWithPrivateCtor.class, MixInForPrivate.class); + BaseClassWithPrivateCtor result = m.readValue("\"?\"", BaseClassWithPrivateCtor.class); + assertEquals("?...", result._a); + } + + public void testForFactoryAndCtor() throws IOException + { + ObjectMapper m = new ObjectMapper(); + BaseClass result; + + // First: test default behavior: should use constructor + result = m.readValue("\"string\"", BaseClass.class); + assertEquals("string...", result._a); + + // Then with simple mix-in: should change to use the factory method + m = new ObjectMapper(); + m.getDeserializationConfig().addMixInAnnotations(BaseClass.class, MixIn.class); + result = m.readValue("\"string\"", BaseClass.class); + assertEquals("stringX", result._a); + } + + public void testFactoryMixIn() throws IOException + { + ObjectMapper m = new ObjectMapper(); + m.getDeserializationConfig().addMixInAnnotations(StringWrapper.class, StringWrapperMixIn.class); + StringWrapper result = m.readValue("\"a\"", StringWrapper.class); + assertEquals("a", result._value); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/mixins/TestMixinDeserForMethods.java b/1.9.10/src/test/org/codehaus/jackson/map/mixins/TestMixinDeserForMethods.java new file mode 100644 index 0000000..96921ba --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/mixins/TestMixinDeserForMethods.java
@@ -0,0 +1,54 @@ +package org.codehaus.jackson.map.mixins; + +import java.io.*; +import java.util.*; + +import org.codehaus.jackson.annotate.*; +import org.codehaus.jackson.map.*; + +public class TestMixinDeserForMethods + extends BaseMapTest +{ + /* + /********************************************************** + /* Helper bean classes + /********************************************************** + */ + + static class BaseClass + { + protected HashMap<String,Object> values = new HashMap<String,Object>(); + + public BaseClass() { } + + protected void addValue(String key, Object value) { + values.put(key, value); + } + } + + interface MixIn + { + @JsonAnySetter void addValue(String key, Object value); + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + /** + * Unit test that verifies that we can mix in @JsonAnySetter + * annotation, as expected. + */ + public void testWithAnySetter() throws IOException + { + ObjectMapper m = new ObjectMapper(); + m.getDeserializationConfig().addMixInAnnotations(BaseClass.class, MixIn.class); + BaseClass result = m.readValue("{ \"a\" : 3, \"b\" : true }", BaseClass.class); + assertNotNull(result); + assertEquals(2, result.values.size()); + assertEquals(Integer.valueOf(3), result.values.get("a")); + assertEquals(Boolean.TRUE, result.values.get("b")); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/mixins/TestMixinInheritance.java b/1.9.10/src/test/org/codehaus/jackson/map/mixins/TestMixinInheritance.java new file mode 100644 index 0000000..28c967f --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/mixins/TestMixinInheritance.java
@@ -0,0 +1,72 @@ +package org.codehaus.jackson.map.mixins; + +import java.io.IOException; +import java.util.Map; + +import org.codehaus.jackson.annotate.JsonProperty; +import org.codehaus.jackson.map.*; + +public class TestMixinInheritance + extends BaseMapTest +{ + // [Issue-14] + static class Beano { + public int ido = 42; + public String nameo = "Bob"; + } + + static class BeanoMixinSuper { + @JsonProperty("name") + public String nameo; + } + + static class BeanoMixinSub extends BeanoMixinSuper { + @JsonProperty("id") + public int ido; + } + + static class Beano2 { + public int getIdo() { return 13; } + public String getNameo() { return "Bill"; } + } + + static abstract class BeanoMixinSuper2 extends Beano2 { + @Override + @JsonProperty("name") + public abstract String getNameo(); + } + + static abstract class BeanoMixinSub2 extends BeanoMixinSuper2 { + @Override + @JsonProperty("id") + public abstract int getIdo(); + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + public void testMixinFieldInheritance() throws IOException + { + ObjectMapper mapper = new ObjectMapper(); + mapper.getSerializationConfig().addMixInAnnotations(Beano.class, BeanoMixinSub.class); + Map<String,Object> result; + result = writeAndMap(mapper, new Beano()); + assertEquals(2, result.size()); + assertTrue(result.containsKey("id")); + assertTrue(result.containsKey("name")); + } + + public void testMixinMethodInheritance() throws IOException + { + ObjectMapper mapper = new ObjectMapper(); + mapper.getSerializationConfig().addMixInAnnotations(Beano2.class, BeanoMixinSub2.class); + Map<String,Object> result; + result = writeAndMap(mapper, new Beano2()); + assertEquals(2, result.size()); + assertTrue(result.containsKey("id")); + assertTrue(result.containsKey("name")); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/mixins/TestMixinSerForClass.java b/1.9.10/src/test/org/codehaus/jackson/map/mixins/TestMixinSerForClass.java new file mode 100644 index 0000000..b975889 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/mixins/TestMixinSerForClass.java
@@ -0,0 +1,118 @@ +package org.codehaus.jackson.map.mixins; + +import java.io.*; +import java.util.*; + +import org.codehaus.jackson.annotate.JsonAutoDetect; +import org.codehaus.jackson.annotate.JsonMethod; +import org.codehaus.jackson.annotate.JsonProperty; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.JsonSerialize; + +public class TestMixinSerForClass + extends BaseMapTest +{ + /* + /////////////////////////////////////////////////////////// + // Helper bean classes + /////////////////////////////////////////////////////////// + */ + + @JsonSerialize(include=JsonSerialize.Inclusion.ALWAYS) + static class BaseClass + { + protected String _a, _b; + protected String _c = "c"; + + protected BaseClass() { } + + public BaseClass(String a) { + _a = a; + } + + // will be auto-detectable unless disabled: + public String getA() { return _a; } + + @JsonProperty + public String getB() { return _b; } + + @JsonProperty + public String getC() { return _c; } + } + + @JsonSerialize(include=JsonSerialize.Inclusion.NON_DEFAULT) + static class LeafClass + extends BaseClass + { + public LeafClass() { super(null); } + + public LeafClass(String a) { + super(a); + } + } + + /** + * This interface only exists to add "mix-in annotations": that is, any + * annotations it has can be virtually added to mask annotations + * of other classes + */ + @JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) + interface MixIn { } + + // test disabling of autodetect... + @JsonAutoDetect(JsonMethod.NONE) + interface MixInAutoDetect { } + + /* + /////////////////////////////////////////////////////////// + // Unit tests + /////////////////////////////////////////////////////////// + */ + + public void testClassMixInsTopLevel() throws IOException + { + ObjectMapper mapper = new ObjectMapper(); + Map<String,Object> result; + + // first: with no mix-ins: + result = writeAndMap(mapper, new LeafClass("abc")); + assertEquals(1, result.size()); + assertEquals("abc", result.get("a")); + + // then with top-level override + mapper = new ObjectMapper(); + mapper.getSerializationConfig().addMixInAnnotations(LeafClass.class, MixIn.class); + result = writeAndMap(mapper, new LeafClass("abc")); + assertEquals(2, result.size()); + assertEquals("abc", result.get("a")); + assertEquals("c", result.get("c")); + + // mid-level override; should not have any effect + mapper = new ObjectMapper(); + mapper.getSerializationConfig().addMixInAnnotations(BaseClass.class, MixIn.class); + result = writeAndMap(mapper, new LeafClass("abc")); + assertEquals(1, result.size()); + assertEquals("abc", result.get("a")); + } + + public void testClassMixInsMidLevel() throws IOException + { + ObjectMapper mapper = new ObjectMapper(); + Map<String,Object> result; + LeafClass bean = new LeafClass("xyz"); + bean._c = "c2"; + + // with no mix-ins first... + result = writeAndMap(mapper, bean); + assertEquals(2, result.size()); + assertEquals("xyz", result.get("a")); + assertEquals("c2", result.get("c")); + + // then with working mid-level override, which effectively suppresses 'a' + mapper = new ObjectMapper(); + mapper.getSerializationConfig().addMixInAnnotations(BaseClass.class, MixInAutoDetect.class); + result = writeAndMap(mapper, bean); + assertEquals(1, result.size()); + assertEquals("c2", result.get("c")); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/mixins/TestMixinSerForFields.java b/1.9.10/src/test/org/codehaus/jackson/map/mixins/TestMixinSerForFields.java new file mode 100644 index 0000000..2dd9950 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/mixins/TestMixinSerForFields.java
@@ -0,0 +1,95 @@ +package org.codehaus.jackson.map.mixins; + +import java.io.*; +import java.util.*; + +import org.codehaus.jackson.annotate.*; +import org.codehaus.jackson.map.*; + +public class TestMixinSerForFields + extends BaseMapTest +{ + /* + /////////////////////////////////////////////////////////// + // Helper bean classes + /////////////////////////////////////////////////////////// + */ + + static class BaseClass + { + public String a; + protected String b; + + public BaseClass(String a, String b) { + this.a = a; + this.b = b; + } + } + + static class SubClass + extends BaseClass + { + public SubClass(String a, String b) { + super(a, b); + } + } + + abstract class MixIn { + // Let's add 'b' as "banana" + @JsonProperty("banana") + public String b; + } + + abstract class MixIn2 { + // Let's remove 'a' + @JsonIgnore + public String a; + + // also: add a dummy field that is NOT to match anything + @JsonProperty public String xyz; + } + + /* + /////////////////////////////////////////////////////////// + // Unit tests + /////////////////////////////////////////////////////////// + */ + + public void testFieldMixInsTopLevel() throws IOException + { + ObjectMapper mapper = new ObjectMapper(); + Map<String,Object> result; + BaseClass bean = new BaseClass("1", "2"); + + // first: with no mix-ins: + result = writeAndMap(mapper, bean); + assertEquals(1, result.size()); + assertEquals("1", result.get("a")); + + // and then with simple mix-in + mapper = new ObjectMapper(); + mapper.getSerializationConfig().addMixInAnnotations(BaseClass.class, MixIn.class); + result = writeAndMap(mapper, bean); + assertEquals(2, result.size()); + assertEquals("1", result.get("a")); + assertEquals("2", result.get("banana")); + } + + public void testMultipleFieldMixIns() throws IOException + { + ObjectMapper mapper = new ObjectMapper(); + Map<String,Object> result; + // ordering here shouldn't matter really... + HashMap<Class<?>,Class<?>> mixins = new HashMap<Class<?>,Class<?>>(); + // first, clear (not strictly needed -- just for fun) + mapper.getSerializationConfig().setMixInAnnotations(null); + mixins.put(SubClass.class, MixIn.class); + mixins.put(BaseClass.class, MixIn2.class); + mapper.getSerializationConfig().setMixInAnnotations(mixins); + + result = writeAndMap(mapper, new SubClass("1", "2")); + assertEquals(1, result.size()); + // 'a' should be suppressed; 'b' mapped to 'banana' + assertEquals("2", result.get("banana")); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/mixins/TestMixinSerForMethods.java b/1.9.10/src/test/org/codehaus/jackson/map/mixins/TestMixinSerForMethods.java new file mode 100644 index 0000000..0d2070a --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/mixins/TestMixinSerForMethods.java
@@ -0,0 +1,190 @@ +package org.codehaus.jackson.map.mixins; + +import java.io.*; +import java.util.*; + +import org.codehaus.jackson.annotate.*; +import org.codehaus.jackson.map.*; + +public class TestMixinSerForMethods + extends BaseMapTest +{ + /* + /********************************************************** + /* Helper bean classes + /********************************************************** + */ + + // base class: just one visible property ('b') + static class BaseClass + { + @SuppressWarnings("unused") private String a; + private String b; + + protected BaseClass() { } + + public BaseClass(String a, String b) { + this.a = a; + this.b = b; + } + + @JsonProperty("b") + public String takeB() { return b; } + } + + /* extends, just for fun; and to show possible benefit of being + * able to declare that a method is overridden (compile-time check + * that our intended mix-in override will match a method) + */ + abstract static class MixIn + extends BaseClass + { + // let's make 'a' visible + @JsonProperty String a; + + @Override + @JsonProperty("b2") + public abstract String takeB(); + + // also: just for fun; add a "red herring"... unmatched method + @JsonProperty abstract String getFoobar(); + } + + static class LeafClass + extends BaseClass + { + public LeafClass(String a, String b) { super(a, b); } + + @Override + @JsonIgnore + public String takeB() { return null; } + } + + interface ObjectMixIn + { + // and then ditto for hashCode.. + @Override + @JsonProperty public int hashCode(); + } + + static class EmptyBean { } + + static class SimpleBean extends EmptyBean + { + int x() { return 42; } + } + + /** + * This mix-in is to be attached to EmptyBean, but really modify + * methods that its subclass, SimpleBean, has. + */ + abstract class MixInForSimple + { + // This should apply to sub-class + @JsonProperty("x") abstract int x(); + + // and this matches nothing, should be ignored + @JsonProperty("notreally") public int xxx() { return 3; } + + // nor this + public abstract int getIt(); + } + + /* + /////////////////////////////////////////////////////////// + // Unit tests + /////////////////////////////////////////////////////////// + */ + + /** + * Unit test for verifying that leaf-level mix-ins work ok; + * that is, any annotations added properly override all annotations + * that masked methods (fields etc) have. + */ + public void testLeafMixin() throws IOException + { + ObjectMapper mapper = new ObjectMapper(); + Map<String,Object> result; + BaseClass bean = new BaseClass("a1", "b2"); + + // first: with no mix-ins: + result = writeAndMap(mapper, bean); + assertEquals(1, result.size()); + assertEquals("b2", result.get("b")); + + // then with leaf-level mix-in + mapper = new ObjectMapper(); + mapper.getSerializationConfig().addMixInAnnotations(BaseClass.class, MixIn.class); + result = writeAndMap(mapper, bean); + assertEquals(2, result.size()); + assertEquals("b2", result.get("b2")); + assertEquals("a1", result.get("a")); + } + + /** + * Unit test for verifying that having a mix-in "between" classes + * (overriding annotations of a base class, but being overridden + * further by a sub-class) works as expected + */ + public void testIntermediateMixin() throws IOException + { + ObjectMapper mapper = new ObjectMapper(); + Map<String,Object> result; + LeafClass bean = new LeafClass("XXX", "b2"); + + mapper.getSerializationConfig().addMixInAnnotations(BaseClass.class, MixIn.class); + result = writeAndMap(mapper, bean); + assertEquals(1, result.size()); + assertEquals("XXX", result.get("a")); + } + + /** + * Another intermediate mix-in, to verify that annotations + * properly "trickle up" + */ + public void testIntermediateMixin2() throws IOException + { + ObjectMapper mapper = new ObjectMapper(); + mapper.getSerializationConfig().addMixInAnnotations(EmptyBean.class, MixInForSimple.class); + Map<String,Object> result = writeAndMap(mapper, new SimpleBean()); + assertEquals(1, result.size()); + assertEquals(Integer.valueOf(42), result.get("x")); + } + + /** + * Unit test for verifying that it is actually possible to attach + * mix-in annotations to basic <code>Object.class</code>. This + * will essentially apply to any and all Objects. + */ + public void testObjectMixin() throws IOException + { + ObjectMapper mapper = new ObjectMapper(); + mapper.getSerializationConfig().addMixInAnnotations(Object.class, ObjectMixIn.class); + + // First, with our bean... + Map<String,Object> result = writeAndMap(mapper, new BaseClass("a", "b")); + + assertEquals(2, result.size()); + assertEquals("b", result.get("b")); + Object ob = result.get("hashCode"); + assertNotNull(ob); + assertEquals(Integer.class, ob.getClass()); + + /* 15-Oct-2010, tatu: Actually, we now block serialization (attemps) of plain Objects, by default + * (since generally that makes no sense -- may need to revisit). As such, need to comment out + * this part of test + */ + /* Hmmh. For plain Object.class... I suppose getClass() does + * get serialized (and can't really be blocked either). + * Fine. + */ + /* + result = writeAndMap(mapper, new Object()); + assertEquals(2, result.size()); + ob = result.get("hashCode"); + assertNotNull(ob); + assertEquals(Integer.class, ob.getClass()); + assertEquals("java.lang.Object", result.get("class")); + */ + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/mixins/TestMixinSerWithViews.java b/1.9.10/src/test/org/codehaus/jackson/map/mixins/TestMixinSerWithViews.java new file mode 100644 index 0000000..2312292 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/mixins/TestMixinSerWithViews.java
@@ -0,0 +1,209 @@ +package org.codehaus.jackson.map.mixins; + +import java.util.*; + +import org.codehaus.jackson.annotate.JsonProperty; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.JsonSerialize; +import org.codehaus.jackson.map.annotate.JsonView; + +import org.codehaus.jackson.map.BaseMapTest; + +public class TestMixinSerWithViews + extends BaseMapTest +{ + /* + /********************************************************** + /* Helper bean classes + /********************************************************** + */ + + static class SimpleTestData + { + private String name = "shown"; + private String nameHidden = "hidden"; + + public String getName() { return name; } + public String getNameHidden( ) { return nameHidden; } + + public void setName( String name ) { + this.name = name; + } + + public void setNameHidden( String nameHidden ) { + this.nameHidden = nameHidden; + } + } + + static class ComplexTestData + { + String nameNull = null; + + String nameComplex = "complexValue"; + + String nameComplexHidden = "nameComplexHiddenValue"; + + SimpleTestData testData = new SimpleTestData( ); + + SimpleTestData[] testDataArray = new SimpleTestData[] { new SimpleTestData( ), null }; + + public String getNameNull() + { + return nameNull; + } + + public void setNameNull( String nameNull ) + { + this.nameNull = nameNull; + } + + public String getNameComplex() + { + return nameComplex; + } + + public void setNameComplex( String nameComplex ) + { + this.nameComplex = nameComplex; + } + + public String getNameComplexHidden() + { + return nameComplexHidden; + } + + public void setNameComplexHidden( String nameComplexHidden ) + { + this.nameComplexHidden = nameComplexHidden; + } + + public SimpleTestData getTestData() + { + return testData; + } + + public void setTestData( SimpleTestData testData ) + { + this.testData = testData; + } + + public SimpleTestData[] getTestDataArray() + { + return testDataArray; + } + + public void setTestDataArray( SimpleTestData[] testDataArray ) + { + this.testDataArray = testDataArray; + } + } + + public interface TestDataJAXBMixin + { + @JsonView( Views.View.class ) + String getName( ); + } + + public interface TestComplexDataJAXBMixin + { + @JsonView( Views.View.class ) + String getNameNull(); + + @JsonView( Views.View.class ) + String getNameComplex(); + + @JsonView( Views.View.class ) + String getNameComplexHidden(); + + @JsonView( Views.View.class ) + SimpleTestData getTestData(); + + @JsonView( Views.View.class ) + SimpleTestData[] getTestDataArray( ); + } + + static class Views { + static class View { } + } + + public class A { + private String name; + private int age; + private String surname; + + public A(String name, int age, String surname) { super(); this.name = name; this.age = age; this.surname = surname; } + + public String getName() { return name; } + + public void setName(String name) { this.name = name; } + + public int getAge() { return age; } + + public void setAge(int age) { this.age = age; } + + public String getSurname() { return surname; } + + public void setSurname(String surname) { this.surname = surname; } + } + + public interface AView { } + + public abstract class AMixInAnnotation { + @JsonProperty("name") + @JsonView(AView.class) + abstract String getName(); + @JsonProperty("age") @JsonView(AView.class) + abstract int getAge(); + } + + /* + /********************************************************** + /* Tests + /********************************************************** + */ + + public void testDataBindingUsage( ) throws Exception + { + ObjectMapper objectMapper = createObjectMapper(); + ObjectWriter objectWriter = objectMapper.writerWithView(Views.View.class).withDefaultPrettyPrinter(); + Object object = new ComplexTestData(); + String json = objectWriter.writeValueAsString(object); + assertTrue( json.indexOf( "nameHidden" ) == -1 ); + assertTrue( json.indexOf( "\"name\" : \"shown\"" ) > 0 ); + } + + public void testIssue560() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + A a = new A("myname", 29, "mysurname"); + + // Property SerializationConfig.Feature.DEFAULT_VIEW_INCLUSION set to false + mapper.configure(SerializationConfig.Feature.DEFAULT_VIEW_INCLUSION, Boolean.FALSE); + mapper.getSerializationConfig().addMixInAnnotations(A.class, AMixInAnnotation.class); + String json = mapper.writerWithView(AView.class).writeValueAsString(a); + + assertTrue(json.indexOf("\"name\"") > 0); + } + + /* + /********************************************************** + /* Helper methods + /********************************************************** + */ + + @SuppressWarnings("deprecation") + private ObjectMapper createObjectMapper( ) + { + ObjectMapper objectMapper = new ObjectMapper( ); + objectMapper.configure( SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS, false ); + objectMapper.getSerializationConfig( ).setSerializationInclusion( JsonSerialize.Inclusion.NON_NULL ); + objectMapper.configure( SerializationConfig.Feature.DEFAULT_VIEW_INCLUSION, false ); + + Map<Class<?>, Class<?>> sourceMixins = new HashMap<Class<?>, Class<?>>( ); + sourceMixins.put( SimpleTestData.class, TestDataJAXBMixin.class ); + sourceMixins.put( ComplexTestData.class, TestComplexDataJAXBMixin.class ); + + objectMapper.getSerializationConfig( ).setMixInAnnotations(sourceMixins); + return objectMapper; + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/module/TestAbstractTypes.java b/1.9.10/src/test/org/codehaus/jackson/map/module/TestAbstractTypes.java new file mode 100644 index 0000000..a65713a --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/module/TestAbstractTypes.java
@@ -0,0 +1,77 @@ +package org.codehaus.jackson.map.module; + +import java.util.*; + +import org.codehaus.jackson.Version; +import org.codehaus.jackson.map.BaseMapTest; +import org.codehaus.jackson.map.ObjectMapper; + +public class TestAbstractTypes extends BaseMapTest +{ + /* + /********************************************************** + /* Helper classes; simple beans and their handlers + /********************************************************** + */ + + static class MyString implements CharSequence + { + protected String value; + + public MyString(String s) { value = s; } + + @Override + public char charAt(int index) { + return value.charAt(index); + } + + @Override + public int length() { + return value.length(); + } + + @Override + public CharSequence subSequence(int arg0, int arg1) { return this; } + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + public void testCollectionDefaulting() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + SimpleModule mod = new SimpleModule("test", Version.unknownVersion()); + // let's ensure we get hierarchic mapping + mod.addAbstractTypeMapping(Collection.class, List.class); + mod.addAbstractTypeMapping(List.class, LinkedList.class); + mapper.registerModule(mod); + Collection<?> result = mapper.readValue("[]", Collection.class); + assertEquals(LinkedList.class, result.getClass()); + } + + public void testMapDefaulting() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + SimpleModule mod = new SimpleModule("test", Version.unknownVersion()); + // default is HashMap, so: + mod.addAbstractTypeMapping(Map.class, TreeMap.class); + mapper.registerModule(mod); + Map<?,?> result = mapper.readValue("{}", Map.class); + assertEquals(TreeMap.class, result.getClass()); + } + + public void testInterfaceDefaulting() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + SimpleModule mod = new SimpleModule("test", Version.unknownVersion()); + // let's ensure we get hierarchic mapping + mod.addAbstractTypeMapping(CharSequence.class, MyString.class); + mapper.registerModule(mod); + Object result = mapper.readValue(quote("abc"), CharSequence.class); + assertEquals(MyString.class, result.getClass()); + assertEquals("abc", ((MyString) result).value); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/module/TestSimpleModule.java b/1.9.10/src/test/org/codehaus/jackson/map/module/TestSimpleModule.java new file mode 100644 index 0000000..0282a65 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/module/TestSimpleModule.java
@@ -0,0 +1,287 @@ +package org.codehaus.jackson.map.module; + +import java.io.IOException; +import java.lang.reflect.Type; +import java.util.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.annotate.JsonPropertyOrder; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.ser.std.ScalarSerializerBase; +import org.codehaus.jackson.map.ser.std.SerializerBase; + +public class TestSimpleModule extends BaseMapTest +{ + /* + /********************************************************** + /* Helper classes; simple beans and their handlers + /********************************************************** + */ + + /** + * Trivial bean that requires custom serializer and deserializer + */ + final static class CustomBean + { + protected String str; + protected int num; + + public CustomBean(String s, int i) { + str = s; + num = i; + } + } + + static enum SimpleEnum { A, B; } + + // Extend SerializerBase to get access to declared handledType + static class CustomBeanSerializer extends SerializerBase<CustomBean> + { + public CustomBeanSerializer() { super(CustomBean.class); } + + @Override + public void serialize(CustomBean value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonProcessingException + { + // We will write it as a String, with '|' as delimiter + jgen.writeString(value.str + "|" + value.num); + } + + @Override + public JsonNode getSchema(SerializerProvider provider, Type typeHint) throws JsonMappingException { + return null; + } + } + + static class CustomBeanDeserializer extends JsonDeserializer<CustomBean> + { + @Override + public CustomBean deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + String text = jp.getText(); + int ix = text.indexOf('|'); + if (ix < 0) { + throw new IOException("Failed to parse String value of \""+text+"\""); + } + String str = text.substring(0, ix); + int num = Integer.parseInt(text.substring(ix+1)); + return new CustomBean(str, num); + } + } + + static class SimpleEnumSerializer extends SerializerBase<SimpleEnum> + { + public SimpleEnumSerializer() { super(SimpleEnum.class); } + + @Override + public void serialize(SimpleEnum value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonProcessingException + { + jgen.writeString(value.name().toLowerCase()); + } + + @Override + public JsonNode getSchema(SerializerProvider provider, Type typeHint) throws JsonMappingException { + return null; + } + } + + static class SimpleEnumDeserializer extends JsonDeserializer<SimpleEnum> + { + @Override + public SimpleEnum deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + return SimpleEnum.valueOf(jp.getText().toUpperCase()); + } + } + + interface Base { + public String getText(); + } + + static class Impl1 implements Base { + @Override + public String getText() { return "1"; } + } + + static class Impl2 extends Impl1 { + @Override + public String getText() { return "2"; } + } + + static class BaseSerializer extends ScalarSerializerBase<Base> + { + public BaseSerializer() { super(Base.class); } + + @Override + public void serialize(Base value, JsonGenerator jgen, SerializerProvider provider) throws IOException { + jgen.writeString("Base:"+value.getText()); + } + } + + static class MixableBean { + public int a = 1; + public int b = 2; + public int c = 3; + } + + @JsonPropertyOrder({"c", "a", "b"}) + static class MixInForOrder { } + + /* + /********************************************************** + /* Unit tests; first, verifying need for custom handlers + /********************************************************** + */ + + /** + * Basic test to ensure we do not have functioning default + * serializers for custom types used in tests. + */ + public void testWithoutModule() + { + ObjectMapper mapper = new ObjectMapper(); + // first: serialization failure: + try { + mapper.writeValueAsString(new CustomBean("foo", 3)); + fail("Should have caused an exception"); + } catch (IOException e) { + verifyException(e, "No serializer found"); + } + + // then deserialization + try { + mapper.readValue("{\"str\":\"ab\",\"num\":2}", CustomBean.class); + fail("Should have caused an exception"); + } catch (IOException e) { + verifyException(e, "No suitable constructor found"); + } + } + + protected static class MySimpleSerializers extends SimpleSerializers { } + protected static class MySimpleDeserializers extends SimpleDeserializers { } + + /** + * Test module which uses custom 'serializers' and 'deserializers' container; used + * to trigger type problems. + */ + protected static class MySimpleModule extends SimpleModule + { + public MySimpleModule(String name, Version version) { + super(name, version); + _deserializers = new MySimpleDeserializers(); + _serializers = new MySimpleSerializers(); + } + } + + /* + /********************************************************** + /* Unit tests; simple serializers + /********************************************************** + */ + + public void testSimpleBeanSerializer() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + SimpleModule mod = new SimpleModule("test", new Version(1, 0, 0, null)); + mod.addSerializer(new CustomBeanSerializer()); + mapper.registerModule(mod); + assertEquals(quote("abcde|5"), mapper.writeValueAsString(new CustomBean("abcde", 5))); + } + + public void testSimpleEnumSerializer() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + SimpleModule mod = new SimpleModule("test", new Version(1, 0, 0, null)); + mod.addSerializer(new SimpleEnumSerializer()); + mapper.registerModule(mod); + assertEquals(quote("b"), mapper.writeValueAsString(SimpleEnum.B)); + } + + // for [JACKSON-550] + public void testSimpleInterfaceSerializer() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + SimpleModule mod = new SimpleModule("test", new Version(1, 0, 0, null)); + mod.addSerializer(new BaseSerializer()); + mapper.registerModule(mod); + assertEquals(quote("Base:1"), mapper.writeValueAsString(new Impl1())); + assertEquals(quote("Base:2"), mapper.writeValueAsString(new Impl2())); + } + + /* + /********************************************************** + /* Unit tests; simple deserializers + /********************************************************** + */ + + public void testSimpleBeanDeserializer() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + SimpleModule mod = new SimpleModule("test", new Version(1, 0, 0, null)); + mod.addDeserializer(CustomBean.class, new CustomBeanDeserializer()); + mapper.registerModule(mod); + CustomBean bean = mapper.readValue(quote("xyz|3"), CustomBean.class); + assertEquals("xyz", bean.str); + assertEquals(3, bean.num); + } + + public void testSimpleEnumDeserializer() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + SimpleModule mod = new SimpleModule("test", new Version(1, 0, 0, null)); + mod.addDeserializer(SimpleEnum.class, new SimpleEnumDeserializer()); + mapper.registerModule(mod); + SimpleEnum result = mapper.readValue(quote("a"), SimpleEnum.class); + assertSame(SimpleEnum.A, result); + } + + // Simple verification of [JACKSON-455] + public void testMultipleModules() throws Exception + { + MySimpleModule mod1 = new MySimpleModule("test1", new Version(1, 0, 0, null)); + SimpleModule mod2 = new SimpleModule("test2", new Version(1, 0, 0, null)); + mod1.addSerializer(SimpleEnum.class, new SimpleEnumSerializer()); + mod1.addDeserializer(CustomBean.class, new CustomBeanDeserializer()); + mod2.addDeserializer(SimpleEnum.class, new SimpleEnumDeserializer()); + mod2.addSerializer(CustomBean.class, new CustomBeanSerializer()); + + ObjectMapper mapper = new ObjectMapper(); + mapper.registerModule(mod1); + mapper.registerModule(mod2); + assertEquals(quote("b"), mapper.writeValueAsString(SimpleEnum.B)); + SimpleEnum result = mapper.readValue(quote("a"), SimpleEnum.class); + assertSame(SimpleEnum.A, result); + + // also let's try it with different order of registration, just in case + mapper = new ObjectMapper(); + mapper.registerModule(mod2); + mapper.registerModule(mod1); + assertEquals(quote("b"), mapper.writeValueAsString(SimpleEnum.B)); + result = mapper.readValue(quote("a"), SimpleEnum.class); + assertSame(SimpleEnum.A, result); + } + + /* + /********************************************************** + /* Unit tests; other + /********************************************************** + */ + + // [JACKSON-644]: ability to register mix-ins + public void testMixIns() throws Exception + { + SimpleModule module = new SimpleModule("test", Version.unknownVersion()); + module.setMixInAnnotation(MixableBean.class, MixInForOrder.class); + ObjectMapper mapper = new ObjectMapper(); + mapper.registerModule(module); + Map<String,Object> props = this.writeAndMap(mapper, new MixableBean()); + assertEquals(3, props.size()); + assertEquals(Integer.valueOf(3), props.get("c")); + assertEquals(Integer.valueOf(1), props.get("a")); + assertEquals(Integer.valueOf(2), props.get("b")); + } +} +
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/module/TestTypeModifiers.java b/1.9.10/src/test/org/codehaus/jackson/map/module/TestTypeModifiers.java new file mode 100644 index 0000000..f7246ee --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/module/TestTypeModifiers.java
@@ -0,0 +1,278 @@ +package org.codehaus.jackson.map.module; + +import java.io.IOException; +import java.lang.reflect.Type; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.JsonSerialize; +import org.codehaus.jackson.map.type.CollectionLikeType; +import org.codehaus.jackson.map.type.MapLikeType; +import org.codehaus.jackson.map.type.TypeBindings; +import org.codehaus.jackson.map.type.TypeFactory; +import org.codehaus.jackson.map.type.TypeModifier; +import org.codehaus.jackson.type.JavaType; + +public class TestTypeModifiers extends BaseMapTest +{ + /* + /********************************************************** + /* Helper classes + /********************************************************** + */ + + static class ModifierModule extends SimpleModule + { + public ModifierModule() { + super("test", Version.unknownVersion()); + } + + @Override + public void setupModule(SetupContext context) + { + context.addSerializers(new Serializers.Base() { + @Override + public JsonSerializer<?> findMapLikeSerializer(SerializationConfig config, + MapLikeType type, BeanDescription beanDesc, BeanProperty property, + JsonSerializer<Object> keySerializer, + TypeSerializer elementTypeSerializer, JsonSerializer<Object> elementValueSerializer) + { + if (MapMarker.class.isAssignableFrom(type.getRawClass())) { + return new MyMapSerializer(keySerializer, elementValueSerializer); + } + return null; + } + + @Override + public JsonSerializer<?> findCollectionLikeSerializer(SerializationConfig config, + CollectionLikeType type, BeanDescription beanDesc, BeanProperty property, + TypeSerializer elementTypeSerializer, JsonSerializer<Object> elementValueSerializer) + { + if (CollectionMarker.class.isAssignableFrom(type.getRawClass())) { + return new MyCollectionSerializer(); + } + return null; + } + }); + context.addDeserializers(new SimpleDeserializers() { + @Override + public JsonDeserializer<?> findCollectionLikeDeserializer(CollectionLikeType type, DeserializationConfig config, + DeserializerProvider provider, BeanDescription beanDesc, BeanProperty property, + TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer) + throws JsonMappingException + { + if (CollectionMarker.class.isAssignableFrom(type.getRawClass())) { + return new MyCollectionDeserializer(); + } + return null; + } + @Override + public JsonDeserializer<?> findMapLikeDeserializer(MapLikeType type, DeserializationConfig config, + DeserializerProvider provider, BeanDescription beanDesc, BeanProperty property, + KeyDeserializer keyDeserializer, + TypeDeserializer elementTypeDeserializer, JsonDeserializer<?> elementDeserializer) + throws JsonMappingException + { + if (MapMarker.class.isAssignableFrom(type.getRawClass())) { + return new MyMapDeserializer(); + } + return null; + } + }); + } + } + + static class XxxSerializer extends JsonSerializer<Object> + { + @Override + public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider) throws IOException { + jgen.writeString("xxx:"+value); + } + } + + interface MapMarker<K,V> { + public K getKey(); + public V getValue(); + } + interface CollectionMarker<V> { + public V getValue(); + } + + @JsonSerialize(contentUsing=XxxSerializer.class) + static class MyMapLikeType implements MapMarker<String,Integer> { + public String key; + public int value; + + public MyMapLikeType() { } + public MyMapLikeType(String k, int v) { + key = k; + value = v; + } + + @Override + public String getKey() { return key; } + @Override + public Integer getValue() { return value; } + } + + static class MyCollectionLikeType implements CollectionMarker<Integer> + { + public int value; + + public MyCollectionLikeType() { } + public MyCollectionLikeType(int v) { + value = v; + } + + @Override + public Integer getValue() { return value; } + } + + static class MyMapSerializer extends JsonSerializer<MapMarker<?,?>> + { + protected final JsonSerializer<Object> _keySerializer; + protected final JsonSerializer<Object> _valueSerializer; + + public MyMapSerializer(JsonSerializer<Object> keySer, JsonSerializer<Object> valueSer) { + _keySerializer = keySer; + _valueSerializer = valueSer; + } + + @Override + public void serialize(MapMarker<?,?> value, JsonGenerator jgen, SerializerProvider provider) throws IOException { + jgen.writeStartObject(); + if (_keySerializer == null) { + jgen.writeFieldName((String) value.getKey()); + } else { + _keySerializer.serialize(value.getKey(), jgen, provider); + } + if (_valueSerializer == null) { + jgen.writeNumber(((Number) value.getValue()).intValue()); + } else { + _valueSerializer.serialize(value.getValue(), jgen, provider); + } + jgen.writeEndObject(); + } + } + static class MyMapDeserializer extends JsonDeserializer<MapMarker<?,?>> + { + @Override + public MapMarker<?,?> deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { + if (jp.getCurrentToken() != JsonToken.START_OBJECT) throw new IOException("Wrong token: "+jp.getCurrentToken()); + if (jp.nextToken() != JsonToken.FIELD_NAME) throw new IOException("Wrong token: "+jp.getCurrentToken()); + String key = jp.getCurrentName(); + if (jp.nextToken() != JsonToken.VALUE_NUMBER_INT) throw new IOException("Wrong token: "+jp.getCurrentToken()); + int value = jp.getIntValue(); + if (jp.nextToken() != JsonToken.END_OBJECT) throw new IOException("Wrong token: "+jp.getCurrentToken()); + return new MyMapLikeType(key, value); + } + } + + static class MyCollectionSerializer extends JsonSerializer<MyCollectionLikeType> + { + @Override + public void serialize(MyCollectionLikeType value, JsonGenerator jgen, SerializerProvider provider) throws IOException { + jgen.writeStartArray(); + jgen.writeNumber(value.value); + jgen.writeEndArray(); + } + } + static class MyCollectionDeserializer extends JsonDeserializer<MyCollectionLikeType> + { + @Override + public MyCollectionLikeType deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException { + if (jp.getCurrentToken() != JsonToken.START_ARRAY) throw new IOException("Wrong token: "+jp.getCurrentToken()); + if (jp.nextToken() != JsonToken.VALUE_NUMBER_INT) throw new IOException("Wrong token: "+jp.getCurrentToken()); + int value = jp.getIntValue(); + if (jp.nextToken() != JsonToken.END_ARRAY) throw new IOException("Wrong token: "+jp.getCurrentToken()); + return new MyCollectionLikeType(value); + } + } + + static class MyTypeModifier extends TypeModifier + { + @Override + public JavaType modifyType(JavaType type, Type jdkType, TypeBindings context, TypeFactory typeFactory) + { + Class<?> raw = type.getRawClass(); + if (MapMarker.class.isAssignableFrom(raw)) { + JavaType[] params = typeFactory.findTypeParameters(type, MapMarker.class); + return typeFactory.constructMapLikeType(raw, params[0], params[1]); + } + if (CollectionMarker.class.isAssignableFrom(raw)) { + JavaType[] params = typeFactory.findTypeParameters(type, CollectionMarker.class); + return typeFactory.constructCollectionLikeType(raw, params[0]); + } + return type; + } + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + /** + * Basic test for ensuring that we can get "xxx-like" types recognized. + */ + public void testLikeTypeConstruction() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.setTypeFactory(mapper.getTypeFactory().withModifier(new MyTypeModifier())); + JavaType type = mapper.constructType(MyMapLikeType.class); + assertTrue(type.isMapLikeType()); + // also, must have resolved type info + JavaType param = ((MapLikeType) type).getKeyType(); + assertNotNull(param); + assertSame(String.class, param.getRawClass()); + param = ((MapLikeType) type).getContentType(); + assertNotNull(param); + assertSame(Integer.class, param.getRawClass()); + + type = mapper.constructType(MyCollectionLikeType.class); + assertTrue(type.isCollectionLikeType()); + param = ((CollectionLikeType) type).getContentType(); + assertNotNull(param); + assertSame(Integer.class, param.getRawClass()); + } + + public void testCollectionLikeSerialization() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.setTypeFactory(mapper.getTypeFactory().withModifier(new MyTypeModifier())); + mapper.registerModule(new ModifierModule()); + assertEquals("[19]", mapper.writeValueAsString(new MyCollectionLikeType(19))); + } + + public void testMapLikeSerialization() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.setTypeFactory(mapper.getTypeFactory().withModifier(new MyTypeModifier())); + mapper.registerModule(new ModifierModule()); + // Due to custom serializer, should get: + assertEquals("{\"x\":\"xxx:3\"}", mapper.writeValueAsString(new MyMapLikeType("x", 3))); + } + + + public void testCollectionLikeDeserialization() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.setTypeFactory(mapper.getTypeFactory().withModifier(new MyTypeModifier())); + mapper.registerModule(new ModifierModule()); + // !!! TBI + MyMapLikeType result = mapper.readValue("{\"a\":13}", MyMapLikeType.class); + assertEquals("a", result.getKey()); + assertEquals(Integer.valueOf(13), result.getValue()); + } + + public void testMapLikeDeserialization() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.setTypeFactory(mapper.getTypeFactory().withModifier(new MyTypeModifier())); + mapper.registerModule(new ModifierModule()); + // !!! TBI + MyCollectionLikeType result = mapper.readValue("[-37]", MyCollectionLikeType.class); + assertEquals(Integer.valueOf(-37), result.getValue()); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/module/TestValueInstantiator.java b/1.9.10/src/test/org/codehaus/jackson/map/module/TestValueInstantiator.java new file mode 100644 index 0000000..6434ec9 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/module/TestValueInstantiator.java
@@ -0,0 +1,518 @@ +package org.codehaus.jackson.map.module; + +import java.util.*; + +import org.codehaus.jackson.Version; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.JsonValueInstantiator; +import org.codehaus.jackson.map.deser.*; +import org.codehaus.jackson.map.deser.impl.CreatorProperty; +import org.codehaus.jackson.map.type.TypeFactory; +import org.codehaus.jackson.type.JavaType; + +/** + * Test related to [JACKSON-580] (allow specifying custom instantiators) + */ +public class TestValueInstantiator extends BaseMapTest +{ + static class MyBean + { + String _secret; + + public MyBean(String s, boolean bogus) { + _secret = s; + } + } + + static class MysteryBean + { + Object value; + + public MysteryBean(Object v) { value = v; } + } + + static class CreatorBean + { + String _secret; + + public String value; + + protected CreatorBean(String s) { + _secret = s; + } + } + + static abstract class InstantiatorBase extends ValueInstantiator + { + @Override + public String getValueTypeDesc() { + return "UNKNOWN"; + } + } + + static abstract class PolymorphicBeanBase { } + + static class PolymorphicBean extends PolymorphicBeanBase + { + public String name; + } + + @SuppressWarnings("serial") + static class MyList extends ArrayList<Object> + { + public MyList(boolean b) { super(); } + } + + @SuppressWarnings("serial") + static class MyMap extends HashMap<String,Object> + { + public MyMap(boolean b) { super(); } + public MyMap(String name) { + super(); + put(name, name); + } + } + + static class MyBeanInstantiator extends ValueInstantiator + { + @Override + public String getValueTypeDesc() { + return MyBean.class.getName(); + } + + @Override + public boolean canCreateUsingDefault() { return true; } + + @Override + public MyBean createUsingDefault() { + return new MyBean("secret!", true); + } + } + + /** + * Something more ambitious: semi-automated approach to polymorphic + * deserialization, using ValueInstantiator; from Object to any + * type... + */ + static class PolymorphicBeanInstantiator extends ValueInstantiator + { + @Override + public String getValueTypeDesc() { + return Object.class.getName(); + } + + @Override + public boolean canCreateFromObjectWith() { return true; } + + @Override + public CreatorProperty[] getFromObjectArguments() { + return new CreatorProperty[] { + new CreatorProperty("type", TypeFactory.defaultInstance().constructType(Class.class), + null, null, null, 0, null) + }; + } + + @Override + public Object createFromObjectWith(Object[] args) { + try { + Class<?> cls = (Class<?>) args[0]; + return cls.newInstance(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + } + + static class CreatorMapInstantiator extends ValueInstantiator + { + @Override + public String getValueTypeDesc() { + return MyMap.class.getName(); + } + + @Override + public boolean canCreateFromObjectWith() { return true; } + + @Override + public CreatorProperty[] getFromObjectArguments() { + return new CreatorProperty[] { + new CreatorProperty("name", TypeFactory.defaultInstance().constructType(String.class), + null, null, null, 0, null) + }; + } + + @Override + public Object createFromObjectWith(Object[] args) { + return new MyMap((String) args[0]); + } + } + + static class MyDelegateBeanInstantiator extends ValueInstantiator + { + @Override + public String getValueTypeDesc() { return "xxx"; } + + @Override + public boolean canCreateUsingDelegate() { return true; } + + @Override + public JavaType getDelegateType() { + return TypeFactory.defaultInstance().constructType(Object.class); + } + + @Override + public Object createUsingDelegate(Object delegate) { + return new MyBean(""+delegate, true); + } + } + + static class MyListInstantiator extends ValueInstantiator + { + @Override + public String getValueTypeDesc() { + return MyList.class.getName(); + } + + @Override + public boolean canCreateUsingDefault() { return true; } + + @Override + public MyList createUsingDefault() { + return new MyList(true); + } + } + + static class MyDelegateListInstantiator extends ValueInstantiator + { + @Override + public String getValueTypeDesc() { return "xxx"; } + + @Override + public boolean canCreateUsingDelegate() { return true; } + + @Override + public JavaType getDelegateType() { + return TypeFactory.defaultInstance().constructType(Object.class); + } + + @Override + public Object createUsingDelegate(Object delegate) { + MyList list = new MyList(true); + list.add(delegate); + return list; + } + } + + static class MyMapInstantiator extends ValueInstantiator + { + @Override + public String getValueTypeDesc() { + return MyMap.class.getName(); + } + + @Override + public boolean canCreateUsingDefault() { return true; } + + @Override + public MyMap createUsingDefault() { + return new MyMap(true); + } + } + + static class MyDelegateMapInstantiator extends ValueInstantiator + { + @Override + public String getValueTypeDesc() { return "xxx"; } + + @Override + public boolean canCreateUsingDelegate() { return true; } + + @Override + public JavaType getDelegateType() { + return TypeFactory.defaultInstance().constructType(Object.class); + } + + @Override + public Object createUsingDelegate(Object delegate) { + MyMap map = new MyMap(true); + map.put("value", delegate); + return map; + } + } + + @JsonValueInstantiator(AnnotatedBeanInstantiator.class) + static class AnnotatedBean { + protected final String a; + protected final int b; + + public AnnotatedBean(String a, int b) { + this.a = a; + this.b = b; + } + } + + static class AnnotatedBeanInstantiator extends ValueInstantiator + { + @Override + public String getValueTypeDesc() { + return MyMap.class.getName(); + } + + @Override + public boolean canCreateUsingDefault() { return true; } + + @Override + public AnnotatedBean createUsingDefault() { + return new AnnotatedBean("foo", 3); + } + } + + static class MyModule extends SimpleModule + { + public MyModule(Class<?> cls, ValueInstantiator inst) + { + super("Test", Version.unknownVersion()); + this.addValueInstantiator(cls, inst); + } + } + + /* + /********************************************************** + /* Unit tests for default creators + /********************************************************** + */ + + public void testCustomBeanInstantiator() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.registerModule(new MyModule(MyBean.class, new MyBeanInstantiator())); + MyBean bean = mapper.readValue("{}", MyBean.class); + assertNotNull(bean); + assertEquals("secret!", bean._secret); + } + + public void testCustomListInstantiator() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.registerModule(new MyModule(MyList.class, new MyListInstantiator())); + MyList result = mapper.readValue("[]", MyList.class); + assertNotNull(result); + assertEquals(MyList.class, result.getClass()); + assertEquals(0, result.size()); + } + + public void testCustomMapInstantiator() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.registerModule(new MyModule(MyMap.class, new MyMapInstantiator())); + MyMap result = mapper.readValue("{ \"a\":\"b\" }", MyMap.class); + assertNotNull(result); + assertEquals(MyMap.class, result.getClass()); + assertEquals(1, result.size()); + } + + /* + /********************************************************** + /* Unit tests for delegate creators + /********************************************************** + */ + + public void testDelegateBeanInstantiator() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.registerModule(new MyModule(MyBean.class, new MyDelegateBeanInstantiator())); + MyBean bean = mapper.readValue("123", MyBean.class); + assertNotNull(bean); + assertEquals("123", bean._secret); + } + + public void testDelegateListInstantiator() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.registerModule(new MyModule(MyList.class, new MyDelegateListInstantiator())); + MyList result = mapper.readValue("123", MyList.class); + assertNotNull(result); + assertEquals(1, result.size()); + assertEquals(Integer.valueOf(123), result.get(0)); + } + + public void testDelegateMapInstantiator() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.registerModule(new MyModule(MyMap.class, new MyDelegateMapInstantiator())); + MyMap result = mapper.readValue("123", MyMap.class); + assertNotNull(result); + assertEquals(1, result.size()); + assertEquals(Integer.valueOf(123), result.values().iterator().next()); + } + + /* + /********************************************************** + /* Unit tests for property-based creators + /********************************************************** + */ + + public void testPropertyBasedBeanInstantiator() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.registerModule(new MyModule(CreatorBean.class, + new InstantiatorBase() { + @Override + public boolean canCreateFromObjectWith() { return true; } + + @Override + public CreatorProperty[] getFromObjectArguments() { + return new CreatorProperty[] { + new CreatorProperty("secret", TypeFactory.defaultInstance().constructType(String.class), + null, null, null, 0, null) + }; + } + + @Override + public Object createFromObjectWith(Object[] args) { + return new CreatorBean((String) args[0]); + } + })); + CreatorBean bean = mapper.readValue("{\"secret\":123,\"value\":37}", CreatorBean.class); + assertNotNull(bean); + assertEquals("123", bean._secret); + } + + public void testPropertyBasedMapInstantiator() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.registerModule(new MyModule(MyMap.class, new CreatorMapInstantiator())); + MyMap result = mapper.readValue("{\"name\":\"bob\", \"x\":\"y\"}", MyMap.class); + assertNotNull(result); + assertEquals(2, result.size()); + assertEquals("bob", result.get("bob")); + assertEquals("y", result.get("x")); + } + + /* + /********************************************************** + /* Unit tests for scalar-delegates + /********************************************************** + */ + + public void testBeanFromString() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.registerModule(new MyModule(MysteryBean.class, + new InstantiatorBase() { + @Override + public boolean canCreateFromString() { return true; } + + @Override + public Object createFromString(String value) { + return new MysteryBean(value); + } + })); + MysteryBean result = mapper.readValue(quote("abc"), MysteryBean.class); + assertNotNull(result); + assertEquals("abc", result.value); + } + + public void testBeanFromInt() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.registerModule(new MyModule(MysteryBean.class, + new InstantiatorBase() { + @Override + public boolean canCreateFromInt() { return true; } + + @Override + public Object createFromInt(int value) { + return new MysteryBean(value+1); + } + })); + MysteryBean result = mapper.readValue("37", MysteryBean.class); + assertNotNull(result); + assertEquals(Integer.valueOf(38), result.value); + } + + public void testBeanFromLong() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.registerModule(new MyModule(MysteryBean.class, + new InstantiatorBase() { + @Override + public boolean canCreateFromLong() { return true; } + + @Override + public Object createFromLong(long value) { + return new MysteryBean(value+1L); + } + })); + MysteryBean result = mapper.readValue("9876543210", MysteryBean.class); + assertNotNull(result); + assertEquals(Long.valueOf(9876543211L), result.value); + } + + public void testBeanFromDouble() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.registerModule(new MyModule(MysteryBean.class, + new InstantiatorBase() { + @Override + public boolean canCreateFromDouble() { return true; } + + @Override + public Object createFromDouble(double value) { + return new MysteryBean(2.0 * value); + } + })); + MysteryBean result = mapper.readValue("0.25", MysteryBean.class); + assertNotNull(result); + assertEquals(Double.valueOf(0.5), result.value); + } + + public void testBeanFromBoolean() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.registerModule(new MyModule(MysteryBean.class, + new InstantiatorBase() { + @Override + public boolean canCreateFromBoolean() { return true; } + + @Override + public Object createFromBoolean(boolean value) { + return new MysteryBean(Boolean.valueOf(value)); + } + })); + MysteryBean result = mapper.readValue("true", MysteryBean.class); + assertNotNull(result); + assertEquals(Boolean.TRUE, result.value); + } + + /* + /********************************************************** + /* Other tests + /********************************************************** + */ + + + /** + * Beyond basic features, it should be possible to even implement + * polymorphic handling... + */ + public void testPolymorphicCreatorBean() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.registerModule(new MyModule(PolymorphicBeanBase.class, new PolymorphicBeanInstantiator())); + String JSON = "{\"type\":"+quote(PolymorphicBean.class.getName())+",\"name\":\"Axel\"}"; + PolymorphicBeanBase result = mapper.readValue(JSON, PolymorphicBeanBase.class); + assertNotNull(result); + assertSame(PolymorphicBean.class, result.getClass()); + assertEquals("Axel", ((PolymorphicBean) result).name); + } + + public void testJackson633() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + AnnotatedBean bean = mapper.readValue("{}", AnnotatedBean.class); + assertNotNull(bean); + assertEquals("foo", bean.a); + assertEquals(3, bean.b); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/ser/TestAnnotationAnyGetter.java b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestAnnotationAnyGetter.java new file mode 100644 index 0000000..27d52e6 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestAnnotationAnyGetter.java
@@ -0,0 +1,75 @@ +package org.codehaus.jackson.map.ser; + +import java.util.*; + +import org.codehaus.jackson.annotate.JsonAnyGetter; +import org.codehaus.jackson.map.BaseMapTest; +import org.codehaus.jackson.map.ObjectMapper; +import org.codehaus.jackson.map.SerializationConfig; + +public class TestAnnotationAnyGetter + extends BaseMapTest +{ + /* + /********************************************************** + /* Helper bean classes + /********************************************************** + */ + + static class Bean + { + final static Map<String,Boolean> extra = new HashMap<String,Boolean>(); + static { + extra.put("a", Boolean.TRUE); + } + + public int getX() { return 3; } + + @JsonAnyGetter + public Map<String,Boolean> getExtra() { return extra; } + } + + static class AnyOnlyBean + { + @JsonAnyGetter + public Map<String,Integer> any() { + HashMap<String,Integer> map = new HashMap<String,Integer>(); + map.put("a", 3); + return map; + } + } + + /* + /********************************************************** + /* Test cases + /********************************************************** + */ + + public void testSimpleJsonValue() throws Exception + { + ObjectMapper m = new ObjectMapper(); + String json = serializeAsString(m, new Bean()); + Map<?,?> map = m.readValue(json, Map.class); + assertEquals(2, map.size()); + assertEquals(Integer.valueOf(3), map.get("x")); + assertEquals(Boolean.TRUE, map.get("a")); + } + + // [JACKSON-392] + public void testAnyOnly() throws Exception + { + ObjectMapper m; + + // First, with normal fail settings: + m = new ObjectMapper(); + m.configure(SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS, true); + String json = serializeAsString(m, new AnyOnlyBean()); + assertEquals("{\"a\":3}", json); + + // then without fail + m = new ObjectMapper(); + m.configure(SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS, false); + json = serializeAsString(m, new AnyOnlyBean()); + assertEquals("{\"a\":3}", json); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/ser/TestAnnotationIgnore.java b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestAnnotationIgnore.java new file mode 100644 index 0000000..e72e580 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestAnnotationIgnore.java
@@ -0,0 +1,129 @@ +package org.codehaus.jackson.map.ser; + +import org.codehaus.jackson.map.BaseMapTest; + +import java.util.*; + +import org.codehaus.jackson.annotate.*; +import org.codehaus.jackson.map.*; + +/** + * This unit test suite tests use of {@link JsonIgnore} annotations + * with bean serialization; as well as (since 1.7) + * {@link JsonIgnoreType}. + */ +public class TestAnnotationIgnore + extends BaseMapTest +{ + /* + /********************************************************** + /* Annotated helper classes + /********************************************************** + */ + + /// Class for testing enabled {@link JsonIgnore} annotation + final static class SizeClassEnabledIgnore + { + @JsonIgnore public int getY() { return 9; } + + // note: must be public to be seen + public int getX() { return 1; } + + @JsonIgnore public int getY2() { return 1; } + @JsonIgnore public int getY3() { return 2; } + } + + /// Class for testing disabled {@link JsonIgnore} annotation + final static class SizeClassDisabledIgnore + { + // note: must be public to be seen + public int getX() { return 3; } + @JsonIgnore(false) public int getY() { return 4; } + } + + static class BaseClassIgnore + { + @JsonProperty("x") + @JsonIgnore + public int x() { return 1; } + + public int getY() { return 2; } + } + + static class SubClassNonIgnore + extends BaseClassIgnore + { + /* Annotations to disable ignorance, in sub-class; note that + * we must still get "JsonProperty" fro super class + */ + @Override + @JsonIgnore(false) + public int x() { return 3; } + } + + @JsonIgnoreType + static class IgnoredType { } + + @JsonIgnoreType(false) + static class NonIgnoredType + { + public int value = 13; + + public IgnoredType ignored = new IgnoredType(); + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + public void testSimpleIgnore() throws Exception + { + ObjectMapper m = new ObjectMapper(); + // Should see "x", not "y" + Map<String,Object> result = writeAndMap(m, new SizeClassEnabledIgnore()); + assertEquals(1, result.size()); + assertEquals(Integer.valueOf(1), result.get("x")); + assertNull(result.get("y")); + } + + public void testDisabledIgnore() throws Exception + { + ObjectMapper m = new ObjectMapper(); + // Should see "x" and "y" + Map<String,Object> result = writeAndMap(m, new SizeClassDisabledIgnore()); + assertEquals(2, result.size()); + assertEquals(Integer.valueOf(3), result.get("x")); + assertEquals(Integer.valueOf(4), result.get("y")); + } + + /** + * Test case to verify that ignore tag can also be disabled + * via inheritance + */ + public void testIgnoreOver() throws Exception + { + ObjectMapper m = new ObjectMapper(); + + // should only see "y" + Map<String,Object> result = writeAndMap(m, new BaseClassIgnore()); + assertEquals(1, result.size()); + assertEquals(Integer.valueOf(2), result.get("y")); + + // Should see "x" and "y" + result = writeAndMap(m, new SubClassNonIgnore()); + assertEquals(2, result.size()); + assertEquals(Integer.valueOf(3), result.get("x")); + assertEquals(Integer.valueOf(2), result.get("y")); + } + + /** + * @since 1.7 + */ + public void testIgnoreType() throws Exception + { + ObjectMapper m = new ObjectMapper(); + assertEquals("{\"value\":13}", m.writeValueAsString(new NonIgnoredType())); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/ser/TestAnnotationInheritance.java b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestAnnotationInheritance.java new file mode 100644 index 0000000..6468339 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestAnnotationInheritance.java
@@ -0,0 +1,111 @@ +package org.codehaus.jackson.map.ser; + +import main.BaseTest; + +import java.io.*; +import java.util.*; + +import org.codehaus.jackson.annotate.*; +import org.codehaus.jackson.map.*; + +/** + * This unit test suite tests use of Annotations for + * bean serialization. + */ +public class TestAnnotationInheritance + extends BaseTest +{ + /* + /********************************************************** + /* Annotated helper classes + /********************************************************** + */ + + /// Base class for testing {@link JsonProperty} annotations + static class BasePojo + { + @JsonProperty public int width() { return 3; } + @JsonProperty public int length() { return 7; } + } + + /** + * It should also be possible to specify annotations on interfaces, + * to be implemented by classes. This should not only work when interface + * is used (which may be the case for de-serialization) but also + * when implementing class is used and overrides methods. In latter + * case overriding methods should still "inherit" annotations -- this + * is not something JVM runtime provides, but Jackson class + * instrospector does. + */ + interface PojoInterface + { + @JsonProperty int width(); + @JsonProperty int length(); + } + + /** + * Sub-class for testing that inheritance is handled properly + * wrt annotations. + */ + static class PojoSubclass extends BasePojo + { + /** + * Should still be recognized as a Getter here. + */ + @Override + public int width() { return 9; } + } + + static class PojoImpl implements PojoInterface + { + // Both should be recognized as getters here + + @Override + public int width() { return 1; } + @Override + public int length() { return 2; } + + public int getFoobar() { return 5; } + } + + /* + /********************************************************** + /* Main tests + /********************************************************** + */ + + public void testSimpleGetterInheritance() throws Exception + { + ObjectMapper m = new ObjectMapper(); + Map<String,Object> result = writeAndMap(m, new PojoSubclass()); + assertEquals(2, result.size()); + assertEquals(Integer.valueOf(7), result.get("length")); + assertEquals(Integer.valueOf(9), result.get("width")); + } + + public void testSimpleGetterInterfaceImpl() throws Exception + { + ObjectMapper m = new ObjectMapper(); + Map<String,Object> result = writeAndMap(m, new PojoImpl()); + // should get 2 from interface, and one more from impl itself + assertEquals(3, result.size()); + assertEquals(Integer.valueOf(5), result.get("foobar")); + assertEquals(Integer.valueOf(1), result.get("width")); + assertEquals(Integer.valueOf(2), result.get("length")); + } + + /* + ////////////////////////////////////////////// + // Helper methods + ////////////////////////////////////////////// + */ + + @SuppressWarnings("unchecked") + private Map<String,Object> writeAndMap(ObjectMapper m, Object value) + throws IOException + { + StringWriter sw = new StringWriter(); + m.writeValue(sw, value); + return (Map<String,Object>) m.readValue(sw.toString(), Object.class); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/ser/TestAnnotationJsonRawValue.java b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestAnnotationJsonRawValue.java new file mode 100644 index 0000000..6851fb0 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestAnnotationJsonRawValue.java
@@ -0,0 +1,70 @@ +package org.codehaus.jackson.map.ser; + +import org.codehaus.jackson.annotate.JsonProperty; +import org.codehaus.jackson.annotate.JsonPropertyOrder; +import org.codehaus.jackson.annotate.JsonRawValue; +import org.codehaus.jackson.map.BaseMapTest; +import org.codehaus.jackson.map.ObjectMapper; + +/** + * This unit test suite tests functioning of {@link JsonRawValue} + * annotation with bean serialization. + */ +public class TestAnnotationJsonRawValue + extends BaseMapTest +{ + /* + /********************************************************* + /* Helper bean classes + /********************************************************* + */ + + /// Class for testing {@link JsonRawValue} annotations with getters returning String + @JsonPropertyOrder(alphabetic=true) + final static class ClassGetter<T> + { + private final T _value; + + private ClassGetter(T value) { _value = value;} + + public T getNonRaw() { return _value; } + + @JsonProperty("raw") @JsonRawValue public T foobar() { return _value; } + + @JsonProperty @JsonRawValue protected T value() { return _value; } + } + + /* + /********************************************************* + /* Test cases + /********************************************************* + */ + + public void testSimpleStringGetter() throws Exception + { + ObjectMapper m = new ObjectMapper(); + String value = "abc"; + String result = m.writeValueAsString(new ClassGetter<String>(value)); + String expected = String.format("{\"nonRaw\":\"%s\",\"raw\":%s,\"value\":%s}", value, value, value); + assertEquals(expected, result); + } + + public void testSimpleNonStringGetter() throws Exception + { + ObjectMapper m = new ObjectMapper(); + int value = 123; + String result = m.writeValueAsString(new ClassGetter<Integer>(value)); + String expected = String.format("{\"nonRaw\":%d,\"raw\":%d,\"value\":%d}", value, value, value); + assertEquals(expected, result); + } + + public void testNullStringGetter() throws Exception + { + ObjectMapper m = new ObjectMapper(); + String value = null; + String result = m.writeValueAsString(new ClassGetter<String>(value)); + String expected = String.format("{\"nonRaw\":%d,\"raw\":%d,\"value\":%d}", value, value, value); + assertEquals(expected, result); + } + +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/ser/TestAnnotationJsonSerialize.java b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestAnnotationJsonSerialize.java new file mode 100644 index 0000000..3028b05 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestAnnotationJsonSerialize.java
@@ -0,0 +1,233 @@ +package org.codehaus.jackson.map.ser; + +import org.codehaus.jackson.map.BaseMapTest; + +import java.io.IOException; +import java.util.*; + +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.annotate.*; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.JsonSerialize; + +/** + * This unit test suite tests use of @JsonClass Annotation + * with bean serialization. + */ +public class TestAnnotationJsonSerialize + extends BaseMapTest +{ + /* + /********************************************************** + /* Annotated helper classes + /********************************************************** + */ + + interface ValueInterface { + public int getX(); + } + + static class ValueClass + implements ValueInterface + { + @Override + public int getX() { return 3; } + public int getY() { return 5; } + } + + /** + * Test class to verify that <code>JsonSerialize.as</code> + * works as expected + */ + static class WrapperClassForAs + { + @JsonSerialize(as=ValueInterface.class) + public ValueClass getValue() { + return new ValueClass(); + } + } + + // This should indicate that static type be used for all fields + @JsonSerialize(typing=JsonSerialize.Typing.STATIC) + static class WrapperClassForStaticTyping + { + public ValueInterface getValue() { + return new ValueClass(); + } + } + + static class WrapperClassForStaticTyping2 + { + @JsonSerialize(typing=JsonSerialize.Typing.STATIC) + public ValueInterface getStaticValue() { + return new ValueClass(); + } + + @JsonSerialize(typing=JsonSerialize.Typing.DYNAMIC) + public ValueInterface getDynamicValue() { + return new ValueClass(); + } + } + + /** + * Test bean that has an invalid {@link JsonClass} annotation. + */ + static class BrokenClass + { + // invalid annotation: String not a supertype of Long + @JsonSerialize(as=String.class) + public Long getValue() { + return Long.valueOf(4L); + } + } + + @SuppressWarnings("serial") + static class ValueMap extends HashMap<String,ValueInterface> { } + @SuppressWarnings("serial") + static class ValueList extends ArrayList<ValueInterface> { } + @SuppressWarnings("serial") + static class ValueLinkedList extends LinkedList<ValueInterface> { } + + // Classes for [JACKSON-294] + @SuppressWarnings("unused") + static class Foo294 + { + @JsonProperty private String id; + @JsonSerialize(using = Bar294Serializer.class) + private Bar294 bar; + + public Foo294() { } + public Foo294(String id, String id2) { + this.id = id; + bar = new Bar294(id2); + } + } + + static class Bar294{ + @JsonProperty private String id; + @JsonProperty private String name; + + public Bar294() { } + public Bar294(String id) { + this.id = id; + } + + public String getId() { return id; } + public String getName() { return name; } + } + + static class Bar294Serializer extends JsonSerializer<Bar294> + { + @Override + public void serialize(Bar294 bar, JsonGenerator jgen, + SerializerProvider provider) throws IOException + { + jgen.writeString(bar.id); + } + } + + /* + /********************************************************** + /* Main tests + /********************************************************** + */ + + @SuppressWarnings("unchecked") + public void testSimpleValueDefinition() throws Exception + { + ObjectMapper m = new ObjectMapper(); + Map<String,Object> result = writeAndMap(m, new WrapperClassForAs()); + assertEquals(1, result.size()); + Object ob = result.get("value"); + // Should see only "x", not "y" + result = (Map<String,Object>) ob; + assertEquals(1, result.size()); + assertEquals(Integer.valueOf(3), result.get("x")); + } + + public void testBrokenAnnotation() throws Exception + { + ObjectMapper m = new ObjectMapper(); + try { + serializeAsString(m, new BrokenClass()); + } catch (Exception e) { + verifyException(e, "not a super-type of"); + } + } + + @SuppressWarnings("unchecked") + public void testStaticTypingForClass() throws Exception + { + ObjectMapper m = new ObjectMapper(); + Map<String,Object> result = writeAndMap(m, new WrapperClassForStaticTyping()); + assertEquals(1, result.size()); + Object ob = result.get("value"); + // Should see only "x", not "y" + result = (Map<String,Object>) ob; + assertEquals(1, result.size()); + assertEquals(Integer.valueOf(3), result.get("x")); + } + + @SuppressWarnings("unchecked") + public void testMixedTypingForClass() throws Exception + { + ObjectMapper m = new ObjectMapper(); + Map<String,Object> result = writeAndMap(m, new WrapperClassForStaticTyping2()); + assertEquals(2, result.size()); + + Object obStatic = result.get("staticValue"); + // Should see only "x", not "y" + Map<String,Object> stat = (Map<String,Object>) obStatic; + assertEquals(1, stat.size()); + assertEquals(Integer.valueOf(3), stat.get("x")); + + Object obDynamic = result.get("dynamicValue"); + // Should see both + Map<String,Object> dyn = (Map<String,Object>) obDynamic; + assertEquals(2, dyn.size()); + assertEquals(Integer.valueOf(3), dyn.get("x")); + assertEquals(Integer.valueOf(5), dyn.get("y")); + } + + public void testStaticTypingWithMap() throws Exception + { + ObjectMapper m = new ObjectMapper(); + m.configure(SerializationConfig.Feature.USE_STATIC_TYPING, true); + ValueMap map = new ValueMap(); + map.put("a", new ValueClass()); + assertEquals("{\"a\":{\"x\":3}}", serializeAsString(m, map)); + } + + public void testStaticTypingWithArrayList() throws Exception + { + ObjectMapper m = new ObjectMapper(); + m.configure(SerializationConfig.Feature.USE_STATIC_TYPING, true); + ValueList list = new ValueList(); + list.add(new ValueClass()); + assertEquals("[{\"x\":3}]", m.writeValueAsString(list)); + } + + public void testStaticTypingWithLinkedList() throws Exception + { + ObjectMapper m = new ObjectMapper(); + m.configure(SerializationConfig.Feature.USE_STATIC_TYPING, true); + ValueLinkedList list = new ValueLinkedList(); + list.add(new ValueClass()); + assertEquals("[{\"x\":3}]", serializeAsString(m, list)); + } + + public void testStaticTypingWithArray() throws Exception + { + ObjectMapper m = new ObjectMapper(); + m.configure(SerializationConfig.Feature.USE_STATIC_TYPING, true); + ValueInterface[] array = new ValueInterface[] { new ValueClass() }; + assertEquals("[{\"x\":3}]", serializeAsString(m, array)); + } + + public void testProblem294() throws Exception + { + assertEquals("{\"id\":\"fooId\",\"bar\":\"barId\"}", + new ObjectMapper().writeValueAsString(new Foo294("fooId", "barId"))); + } + +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/ser/TestAnnotationJsonSerialize2.java b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestAnnotationJsonSerialize2.java new file mode 100644 index 0000000..9cf1959 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestAnnotationJsonSerialize2.java
@@ -0,0 +1,246 @@ +package org.codehaus.jackson.map.ser; + +import java.io.IOException; +import java.util.*; + +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.annotate.JsonPropertyOrder; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.JsonSerialize; +import org.codehaus.jackson.map.ser.std.NullSerializer; + +@SuppressWarnings("serial") +public class TestAnnotationJsonSerialize2 + extends BaseMapTest +{ + // [JACKSON-480] + + static class SimpleKey { + protected final String key; + + public SimpleKey(String str) { key = str; } + + @Override public String toString() { return "toString:"+key; } + } + + static class SimpleValue { + public final String value; + + public SimpleValue(String str) { value = str; } + } + + @JsonPropertyOrder({"value", "value2"}) + static class ActualValue extends SimpleValue + { + public final String other = "123"; + + public ActualValue(String str) { super(str); } + } + + static class SimpleKeySerializer extends JsonSerializer<SimpleKey> { + @Override + public void serialize(SimpleKey key, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonProcessingException { + jgen.writeFieldName("key "+key.key); + } + } + + static class SimpleValueSerializer extends JsonSerializer<SimpleValue> { + @Override + public void serialize(SimpleValue value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonProcessingException { + jgen.writeString("value "+value.value); + } + } + + @JsonSerialize(contentAs=SimpleValue.class) + static class SimpleValueList extends ArrayList<ActualValue> { } + + @JsonSerialize(contentAs=SimpleValue.class) + static class SimpleValueMap extends HashMap<SimpleKey, ActualValue> { } + + @JsonSerialize(contentUsing=SimpleValueSerializer.class) + static class SimpleValueListWithSerializer extends ArrayList<ActualValue> { } + + @JsonSerialize(keyUsing=SimpleKeySerializer.class, contentUsing=SimpleValueSerializer.class) + static class SimpleValueMapWithSerializer extends HashMap<SimpleKey, ActualValue> { } + + static class ListWrapperSimple + { + @JsonSerialize(contentAs=SimpleValue.class) + public final ArrayList<ActualValue> values = new ArrayList<ActualValue>(); + + public ListWrapperSimple(String value) { + values.add(new ActualValue(value)); + } + } + + static class ListWrapperWithSerializer + { + @JsonSerialize(contentUsing=SimpleValueSerializer.class) + public final ArrayList<ActualValue> values = new ArrayList<ActualValue>(); + + public ListWrapperWithSerializer(String value) { + values.add(new ActualValue(value)); + } + } + + static class MapWrapperSimple + { + @JsonSerialize(contentAs=SimpleValue.class) + public final HashMap<SimpleKey, ActualValue> values = new HashMap<SimpleKey, ActualValue>(); + + public MapWrapperSimple(String key, String value) { + values.put(new SimpleKey(key), new ActualValue(value)); + } + } + + static class MapWrapperWithSerializer + { + @JsonSerialize(keyUsing=SimpleKeySerializer.class, contentUsing=SimpleValueSerializer.class) + public final HashMap<SimpleKey, ActualValue> values = new HashMap<SimpleKey, ActualValue>(); + + public MapWrapperWithSerializer(String key, String value) { + values.put(new SimpleKey(key), new ActualValue(value)); + } + } + + static class NullBean + { + @JsonSerialize(using=NullSerializer.class) + public String value = "abc"; + } + + // [JACKSON-799] stuff: + + public interface Fooable { + public int getFoo(); + } + + // force use of interface + @JsonSerialize(as=Fooable.class) + public static class FooImpl implements Fooable { + public int getFoo() { return 42; } + public int getBar() { return 15; } + } + + public class FooableWrapper { + public FooImpl getFoo() { + return new FooImpl(); + } + } + + public void testSerializeAsForSimpleProp() throws IOException + { + ObjectMapper mapper = new ObjectMapper(); + assertEquals("{\"foo\":{\"foo\":42}}", mapper.writeValueAsString(new FooableWrapper())); + } + + /* + /********************************************************** + /* Test methods + /********************************************************** + */ + + // [JACKSON-480], test value annotation applied to List value class + public void testSerializedAsListWithClassAnnotations() throws IOException + { + ObjectMapper m = new ObjectMapper(); + SimpleValueList list = new SimpleValueList(); + list.add(new ActualValue("foo")); + assertEquals("[{\"value\":\"foo\"}]", m.writeValueAsString(list)); + } + + // [JACKSON-480], test value annotation applied to Map value class + public void testSerializedAsMapWithClassAnnotations() throws IOException + { + ObjectMapper m = new ObjectMapper(); + SimpleValueMap map = new SimpleValueMap(); + map.put(new SimpleKey("x"), new ActualValue("y")); + assertEquals("{\"toString:x\":{\"value\":\"y\"}}", m.writeValueAsString(map)); + } + + // [JACKSON-480], test Serialization annotation with List + public void testSerializedAsListWithClassSerializer() throws IOException + { + ObjectMapper m = new ObjectMapper(); + SimpleValueListWithSerializer list = new SimpleValueListWithSerializer(); + list.add(new ActualValue("foo")); + assertEquals("[\"value foo\"]", m.writeValueAsString(list)); + } + + // [JACKSON-480], test Serialization annotation with Map + public void testSerializedAsMapWithClassSerializer() throws IOException + { + ObjectMapper m = new ObjectMapper(); + SimpleValueMapWithSerializer map = new SimpleValueMapWithSerializer(); + map.put(new SimpleKey("abc"), new ActualValue("123")); + assertEquals("{\"key abc\":\"value 123\"}", m.writeValueAsString(map)); + } + + // [JACKSON-480], test annotations when applied to List property (getter, setter) + public void testSerializedAsListWithPropertyAnnotations() throws IOException + { + ObjectMapper m = new ObjectMapper(); + ListWrapperSimple input = new ListWrapperSimple("bar"); + assertEquals("{\"values\":[{\"value\":\"bar\"}]}", m.writeValueAsString(input)); + } + + public void testSerializedAsListWithPropertyAnnotations2() throws IOException + { + ObjectMapper m = new ObjectMapper(); + ListWrapperWithSerializer input = new ListWrapperWithSerializer("abc"); + assertEquals("{\"values\":[\"value abc\"]}", m.writeValueAsString(input)); + } + + // [JACKSON-480], test annotations when applied to Map property (getter, setter) + public void testSerializedAsMapWithPropertyAnnotations() throws IOException + { + ObjectMapper m = new ObjectMapper(); + MapWrapperSimple input = new MapWrapperSimple("a", "b"); + assertEquals("{\"values\":{\"toString:a\":{\"value\":\"b\"}}}", m.writeValueAsString(input)); + } + + public void testSerializedAsMapWithPropertyAnnotations2() throws IOException + { + ObjectMapper m = new ObjectMapper(); + MapWrapperWithSerializer input = new MapWrapperWithSerializer("foo", "b"); + assertEquals("{\"values\":{\"key foo\":\"value b\"}}", m.writeValueAsString(input)); + } + + // [JACKSON-602]: Include.NON_EMPTY + public void testEmptyInclusion() throws IOException + { + ObjectMapper defMapper = new ObjectMapper(); + ObjectMapper inclMapper = new ObjectMapper().setSerializationInclusion(JsonSerialize.Inclusion.NON_EMPTY); + + StringWrapper str = new StringWrapper(""); + assertEquals("{\"str\":\"\"}", defMapper.writeValueAsString(str)); + assertEquals("{}", inclMapper.writeValueAsString(str)); + assertEquals("{}", inclMapper.writeValueAsString(new StringWrapper())); + + ListWrapper<String> list = new ListWrapper<String>(); + assertEquals("{\"list\":[]}", defMapper.writeValueAsString(list)); + assertEquals("{}", inclMapper.writeValueAsString(list)); + assertEquals("{}", inclMapper.writeValueAsString(new ListWrapper<String>())); + + MapWrapper<String,Integer> map = new MapWrapper<String,Integer>(new HashMap<String,Integer>()); + assertEquals("{\"map\":{}}", defMapper.writeValueAsString(map)); + assertEquals("{}", inclMapper.writeValueAsString(map)); + assertEquals("{}", inclMapper.writeValueAsString(new MapWrapper<String,Integer>(null))); + + ArrayWrapper<Integer> array = new ArrayWrapper<Integer>(new Integer[0]); + assertEquals("{\"array\":[]}", defMapper.writeValueAsString(array)); + assertEquals("{}", inclMapper.writeValueAsString(array)); + assertEquals("{}", inclMapper.writeValueAsString(new ArrayWrapper<Integer>(null))); + } + + // [JACKSON-699] + public void testNullSerializer() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + String json = mapper.writeValueAsString(new NullBean()); + assertEquals("{\"value\":null}", json); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/ser/TestAnnotationJsonValue.java b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestAnnotationJsonValue.java new file mode 100644 index 0000000..4d244b9 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestAnnotationJsonValue.java
@@ -0,0 +1,141 @@ +package org.codehaus.jackson.map.ser; + +import java.util.HashMap; +import java.util.Map; + +import org.codehaus.jackson.map.BaseMapTest; +import org.codehaus.jackson.map.ObjectMapper; + +import org.codehaus.jackson.annotate.*; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.JsonSerialize; +import org.codehaus.jackson.map.ser.std.ToStringSerializer; + +/** + * This unit test suite tests functioning of {@link JsonValue} + * annotation with bean serialization. + */ +public class TestAnnotationJsonValue + extends BaseMapTest +{ + /* + /********************************************************* + /* Helper bean classes + /********************************************************* + */ + + static class ValueClass<T> + { + final T _value; + + public ValueClass(T v) { _value = v; } + + @JsonValue T value() { return _value; } + + // shouldn't need this, but may be useful for troubleshooting: + @Override + public String toString() { return "???"; } + } + + /** + * Another test class to check that it is also possible to + * force specific serializer to use with @JsonValue annotated + * method. Difference is between Integer serialization, and + * conversion to a Json String. + */ + final static class ToStringValueClass<T> + extends ValueClass<T> + { + public ToStringValueClass(T value) { super(value); } + + // Also, need to use this annotation to help + @JsonSerialize(using=ToStringSerializer.class) + @Override + @JsonValue T value() { return super.value(); } + } + + final static class ToStringValueClass2 + extends ValueClass<String> + { + public ToStringValueClass2(String value) { super(value); } + + /* Simple as well, but let's ensure that other getters won't matter... + */ + + @JsonProperty int getFoobar() { return 4; } + + public String[] getSomethingElse() { return new String[] { "1", "a" }; } + } + + static class ValueBase { + public String a = "a"; + } + + static class ValueType extends ValueBase { + public String b = "b"; + } + + // Finally, let's also test static vs dynamic type + static class ValueWrapper { + @JsonValue + public ValueBase getX() { return new ValueType(); } + } + + static class MapBean + { + @JsonValue + public Map<String,String> toMap() + { + HashMap<String,String> map = new HashMap<String,String>(); + map.put("a", "1"); + return map; + } + } + + /* + /********************************************************* + /* Test cases + /********************************************************* + */ + + public void testSimpleJsonValue() throws Exception + { + ObjectMapper m = new ObjectMapper(); + String result = serializeAsString(m, new ValueClass<String>("abc")); + assertEquals("\"abc\"", result); + } + + public void testJsonValueWithUseSerializer() throws Exception + { + ObjectMapper m = new ObjectMapper(); + String result = serializeAsString(m, new ToStringValueClass<Integer>(Integer.valueOf(123))); + assertEquals("\"123\"", result); + } + + /** + * Test for verifying that additional getters won't confuse serializer. + */ + public void testMixedJsonValue() throws Exception + { + ObjectMapper m = new ObjectMapper(); + String result = serializeAsString(m, new ToStringValueClass2("xyz")); + assertEquals("\"xyz\"", result); + } + + public void testValueWithStaticType() throws Exception + { + // Ok; first, with dynamic type: + ObjectMapper m = new ObjectMapper(); + assertEquals("{\"a\":\"a\",\"b\":\"b\"}", serializeAsString(m, new ValueWrapper())); + + // then static + m = new ObjectMapper(); + m.configure(SerializationConfig.Feature.USE_STATIC_TYPING, true); + assertEquals("{\"a\":\"a\"}", serializeAsString(m, new ValueWrapper())); + } + + public void testMapWithJsonValue() throws Exception + { + assertEquals("{\"a\":\"1\"}", new ObjectMapper().writeValueAsString(new MapBean())); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/ser/TestAnnotations.java b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestAnnotations.java new file mode 100644 index 0000000..2a5e12a --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestAnnotations.java
@@ -0,0 +1,267 @@ +package org.codehaus.jackson.map.ser; + +import org.codehaus.jackson.map.BaseMapTest; + +import java.io.*; +import java.util.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.annotate.*; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.JsonSerialize; + +/** + * This unit test suite tests use of Annotations for + * bean serialization. + */ +public class TestAnnotations + extends BaseMapTest +{ + /* + /********************************************************** + /* Helper classes + /********************************************************** + */ + + /// Class for testing {@link JsonProperty} annotations with getters + final static class SizeClassGetter + { + @JsonProperty public int size() { return 3; } + @JsonProperty("length") public int foobar() { return -17; } + // note: need not be public since there's annotation + @JsonProperty protected int value() { return 0; } + + // dummy method; not a getter signature + protected int getNotReally(int arg) { return 0; } + } + + // And additional testing to cover [JACKSON-64] + final static class SizeClassGetter2 + { + // Should still be considered property "x" + @JsonProperty protected int getX() { return 3; } + } + + // and some support for testing [JACKSON-120] + final static class SizeClassGetter3 + { + // Should be considered property "y" even tho non-public + @JsonSerialize protected int getY() { return 8; } + } + + + /** + * Class for testing {@link JsonSerializer} annotation + * for class itself. + */ + @JsonSerialize(using=BogusSerializer.class) + final static class ClassSerializer { + } + + /** + * Class for testing an active {@link JsonSerialize#using} annotation + * for a method + */ + final static class ClassMethodSerializer { + private int _x; + + public ClassMethodSerializer(int x) { _x = x; } + + @JsonSerialize(using=StringSerializer.class) + public int getX() { return _x; } + } + + /** + * Class for testing an inactive (one that will not have any effect) + * {@link JsonSerialize} annotation for a method + */ + final static class InactiveClassMethodSerializer { + private int _x; + + public InactiveClassMethodSerializer(int x) { _x = x; } + + // Basically, has no effect, hence gets serialized as number + @JsonSerialize(using=JsonSerializer.None.class) + public int getX() { return _x; } + } + + /** + * Class for verifying that getter information is inherited + * as expected via normal class inheritance + */ + static class BaseBean { + public int getX() { return 1; } + @SuppressWarnings("unused") + @JsonProperty("y") + private int getY() { return 2; } + } + + static class SubClassBean extends BaseBean { + public int getZ() { return 3; } + } + + // For [JACKSON-666] ("Feature of the Beast!") + @JsonPropertyOrder(alphabetic=true) + static class GettersWithoutSetters + { + public int d = 0; + + @JsonCreator + public GettersWithoutSetters(@JsonProperty("a") int a) { } + + // included, since there is a constructor property + public int getA() { return 3; } + + // not included, as there's nothing matching + public int getB() { return 4; } + + // include as there is setter + public int getC() { return 5; } + public void setC(int v) { } + + // and included, as there is a field + public int getD() { return 6; } + } + + // [JACKSON-806]: override 'need-setter' with explicit annotation + static class GettersWithoutSetters2 + { + @JsonProperty + public int getA() { return 123; } + } + + /* + /********************************************************** + /* Other helper classes + /********************************************************** + */ + + public final static class BogusSerializer extends JsonSerializer<Object> + { + @Override + public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + jgen.writeBoolean(true); + } + } + + private final static class StringSerializer extends JsonSerializer<Object> + { + @Override + public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + jgen.writeString("X"+value+"X"); + } + + } + + /* + /********************************************************** + /* Main tests + /********************************************************** + */ + + public void testSimpleGetter() throws Exception + { + ObjectMapper m = new ObjectMapper(); + Map<String,Object> result = writeAndMap(m, new SizeClassGetter()); + assertEquals(3, result.size()); + assertEquals(Integer.valueOf(3), result.get("size")); + assertEquals(Integer.valueOf(-17), result.get("length")); + assertEquals(Integer.valueOf(0), result.get("value")); + } + + public void testSimpleGetter2() throws Exception + { + ObjectMapper m = new ObjectMapper(); + Map<String,Object> result = writeAndMap(m, new SizeClassGetter2()); + assertEquals(1, result.size()); + assertEquals(Integer.valueOf(3), result.get("x")); + } + + // testing [JACKSON-120], implied getter + public void testSimpleGetter3() throws Exception + { + ObjectMapper m = new ObjectMapper(); + Map<String,Object> result = writeAndMap(m, new SizeClassGetter3()); + assertEquals(1, result.size()); + assertEquals(Integer.valueOf(8), result.get("y")); + } + + /** + * Let's also verify that inherited super-class getters are used + * as expected + */ + public void testGetterInheritance() throws Exception + { + ObjectMapper m = new ObjectMapper(); + Map<String,Object> result = writeAndMap(m, new SubClassBean()); + assertEquals(3, result.size()); + assertEquals(Integer.valueOf(1), result.get("x")); + assertEquals(Integer.valueOf(2), result.get("y")); + assertEquals(Integer.valueOf(3), result.get("z")); + } + + /** + * Unit test to verify that {@link JsonSerialize#using} annotation works + * when applied to a class + */ + public void testClassSerializer() throws Exception + { + ObjectMapper m = new ObjectMapper(); + StringWriter sw = new StringWriter(); + m.writeValue(sw, new ClassSerializer()); + assertEquals("true", sw.toString()); + } + + /** + * Unit test to verify that @JsonSerializer annotation works + * when applied to a Method + */ + public void testActiveMethodSerializer() throws Exception + { + ObjectMapper m = new ObjectMapper(); + StringWriter sw = new StringWriter(); + m.writeValue(sw, new ClassMethodSerializer(13)); + /* Here we will get wrapped as an object, since we have + * full object, just override a single property + */ + assertEquals("{\"x\":\"X13X\"}", sw.toString()); + } + + public void testInactiveMethodSerializer() throws Exception + { + ObjectMapper m = new ObjectMapper(); + StringWriter sw = new StringWriter(); + m.writeValue(sw, new InactiveClassMethodSerializer(8)); + /* Here we will get wrapped as an object, since we have + * full object, just override a single property + */ + assertEquals("{\"x\":8}", sw.toString()); + } + + public void testGettersWithoutSetters() throws Exception + { + ObjectMapper m = new ObjectMapper(); + GettersWithoutSetters bean = new GettersWithoutSetters(123); + assertFalse(m.isEnabled(SerializationConfig.Feature.REQUIRE_SETTERS_FOR_GETTERS)); + + // by default, all 4 found: + assertEquals("{\"a\":3,\"b\":4,\"c\":5,\"d\":6}", m.writeValueAsString(bean)); + + // but 3 if we require mutator: + m = new ObjectMapper(); + m.enable(SerializationConfig.Feature.REQUIRE_SETTERS_FOR_GETTERS); + assertEquals("{\"a\":3,\"c\":5,\"d\":6}", m.writeValueAsString(bean)); + } + + public void testGettersWithoutSettersOverride() throws Exception + { + GettersWithoutSetters2 bean = new GettersWithoutSetters2(); + ObjectMapper m = new ObjectMapper(); + m.enable(SerializationConfig.Feature.REQUIRE_SETTERS_FOR_GETTERS); + assertEquals("{\"a\":123}", m.writeValueAsString(bean)); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/ser/TestArraySerialization.java b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestArraySerialization.java new file mode 100644 index 0000000..928505d --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestArraySerialization.java
@@ -0,0 +1,105 @@ +package org.codehaus.jackson.map.ser; + +import org.codehaus.jackson.*; + +import main.BaseTest; + +import java.io.*; + +import org.codehaus.jackson.JsonFactory; +import org.codehaus.jackson.map.*; + +public class TestArraySerialization + extends BaseTest +{ + public void testLongStringArray() throws Exception + { + final int SIZE = 40000; + + StringBuilder sb = new StringBuilder(SIZE*2); + for (int i = 0; i < SIZE; ++i) { + sb.append((char) i); + } + String str = sb.toString(); + ObjectMapper mapper = new ObjectMapper(); + byte[] data = mapper.writeValueAsBytes(new String[] { "abc", str, null, str }); + JsonParser jp = mapper.getJsonFactory().createJsonParser(data); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + assertEquals("abc", jp.getText()); + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + String actual = jp.getText(); + assertEquals(str.length(), actual.length()); + assertEquals(str, actual); + assertToken(JsonToken.VALUE_NULL, jp.nextToken()); + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + assertEquals(str, jp.getText()); + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + assertNull(jp.nextToken()); + } + + public void testIntArray() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + StringWriter sw = new StringWriter(); + mapper.writeValue(sw, new int[] { 1, 2, 3, -7 }); + assertEquals("[1,2,3,-7]", sw.toString().trim()); + } + + public void testBigIntArray() throws Exception + { + final int SIZE = 99999; + ObjectMapper mapper = new ObjectMapper(); + int[] ints = new int[SIZE]; + for (int i = 0; i < ints.length; ++i) { + ints[i] = i; + } + + // Let's try couple of times, to ensure that state is handled + // correctly by ObjectMapper (wrt buffer recycling used + // with 'writeAsBytes()') + JsonFactory f = mapper.getJsonFactory(); + for (int round = 0; round < 3; ++round) { + byte[] data = mapper.writeValueAsBytes(ints); + JsonParser jp = f.createJsonParser(data); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + for (int i = 0; i < SIZE; ++i) { + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(i, jp.getIntValue()); + } + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + } + } + + public void testLongArray() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + StringWriter sw = new StringWriter(); + mapper.writeValue(sw, new long[] { Long.MIN_VALUE, 0, Long.MAX_VALUE }); + assertEquals("["+Long.MIN_VALUE+",0,"+Long.MAX_VALUE+"]", sw.toString().trim()); + } + + public void testStringArray() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + StringWriter sw = new StringWriter(); + mapper.writeValue(sw, new String[] { "a", "\"foo\"", null }); + assertEquals("[\"a\",\"\\\"foo\\\"\",null]", sw.toString().trim()); + } + + public void testDoubleArray() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + StringWriter sw = new StringWriter(); + mapper.writeValue(sw, new double[] { 1.01, 2.0, -7, Double.NaN, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY }); + assertEquals("[1.01,2.0,-7.0,\"NaN\",\"-Infinity\",\"Infinity\"]", sw.toString().trim()); + } + + public void testFloatArray() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + StringWriter sw = new StringWriter(); + mapper.writeValue(sw, new float[] { 1.01f, 2.0f, -7f, Float.NaN, Float.NEGATIVE_INFINITY, Float.POSITIVE_INFINITY }); + assertEquals("[1.01,2.0,-7.0,\"NaN\",\"-Infinity\",\"Infinity\"]", sw.toString().trim()); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/ser/TestAutoDetect.java b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestAutoDetect.java new file mode 100644 index 0000000..ee81e4c --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestAutoDetect.java
@@ -0,0 +1,127 @@ +package org.codehaus.jackson.map.ser; + +import org.codehaus.jackson.map.BaseMapTest; + +import java.util.*; + +import org.codehaus.jackson.annotate.*; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.introspect.VisibilityChecker; + +/** + * Unit tests for checking extended auto-detect configuration, + * in context of serialization + * + * @since 1.5 + */ +public class TestAutoDetect + extends BaseMapTest +{ + static class FieldBean + { + public String p1 = "public"; + protected String p2 = "protected"; + @SuppressWarnings("unused") + private String p3 = "private"; + } + + @JsonAutoDetect(fieldVisibility=JsonAutoDetect.Visibility.PROTECTED_AND_PUBLIC) + static class ProtFieldBean extends FieldBean { } + + static class MethodBean + { + public String getA() { return "a"; } + protected String getB() { return "b"; } + @SuppressWarnings("unused") + private String getC() { return "c"; } + } + + @JsonAutoDetect(getterVisibility=JsonAutoDetect.Visibility.PROTECTED_AND_PUBLIC) + static class ProtMethodBean extends MethodBean { } + + /* + /********************************************************* + /* Test methods + /********************************************************* + */ + + public void testDefaults() throws Exception + { + ObjectMapper m = new ObjectMapper(); + // by default, only public fields and getters are detected + assertEquals("{\"p1\":\"public\"}", + m.writeValueAsString(new FieldBean())); + assertEquals("{\"a\":\"a\"}", + m.writeValueAsString(new MethodBean())); + } + + public void testProtectedViaAnnotations() throws Exception + { + ObjectMapper m = new ObjectMapper(); + + Map<String,Object> result = writeAndMap(m, new ProtFieldBean()); + assertEquals(2, result.size()); + assertEquals("public", result.get("p1")); + assertEquals("protected", result.get("p2")); + assertNull(result.get("p3")); + + result = writeAndMap(m, new ProtMethodBean()); + assertEquals(2, result.size()); + assertEquals("a", result.get("a")); + assertEquals("b", result.get("b")); + assertNull(result.get("c")); + } + + public void testPrivateUsingGlobals() throws Exception + { + ObjectMapper m = new ObjectMapper(); + VisibilityChecker<?> vc = m.getVisibilityChecker(); + vc = vc.withFieldVisibility(JsonAutoDetect.Visibility.ANY); + m.setVisibilityChecker(vc); + + Map<String,Object> result = writeAndMap(m, new FieldBean()); + assertEquals(3, result.size()); + assertEquals("public", result.get("p1")); + assertEquals("protected", result.get("p2")); + assertEquals("private", result.get("p3")); + + m = new ObjectMapper(); + vc = m.getVisibilityChecker(); + vc = vc.withGetterVisibility(JsonAutoDetect.Visibility.ANY); + m.setVisibilityChecker(vc); + result = writeAndMap(m, new MethodBean()); + assertEquals(3, result.size()); + assertEquals("a", result.get("a")); + assertEquals("b", result.get("b")); + assertEquals("c", result.get("c")); + } + + // [JACKSON-621] + public void testBasicSetup() throws Exception + { + ObjectMapper m = new ObjectMapper(); + VisibilityChecker<?> vc = m.getVisibilityChecker(); + vc = vc.with(JsonAutoDetect.Visibility.ANY); + m.setVisibilityChecker(vc); + + Map<String,Object> result = writeAndMap(m, new FieldBean()); + assertEquals(3, result.size()); + assertEquals("public", result.get("p1")); + assertEquals("protected", result.get("p2")); + assertEquals("private", result.get("p3")); + } + + // [JACKSON-595] + public void testMapperShortcutMethods() throws Exception + { + ObjectMapper m = new ObjectMapper(); + m.setVisibility(JsonMethod.FIELD, JsonAutoDetect.Visibility.ANY); + + Map<String,Object> result = writeAndMap(m, new FieldBean()); + assertEquals(3, result.size()); + assertEquals("public", result.get("p1")); + assertEquals("protected", result.get("p2")); + assertEquals("private", result.get("p3")); + } + +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/ser/TestBeanSerializer.java b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestBeanSerializer.java new file mode 100644 index 0000000..353b2bb --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestBeanSerializer.java
@@ -0,0 +1,252 @@ +package org.codehaus.jackson.map.ser; + +import java.io.IOException; +import java.util.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.annotate.JsonIgnore; +import org.codehaus.jackson.annotate.JsonPropertyOrder; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.introspect.BasicBeanDescription; +import org.codehaus.jackson.map.module.SimpleModule; +import org.codehaus.jackson.type.JavaType; + +/** + * Unit tests for verifying that it is possible to configure + * construction of {@link BeanSerializer} instances. + * + * @since 1.7 + */ +public class TestBeanSerializer extends BaseMapTest +{ + /* + /******************************************************** + /* Helper types + /******************************************************** + */ + + static class ModuleImpl extends SimpleModule + { + protected BeanSerializerModifier modifier; + + public ModuleImpl(BeanSerializerModifier modifier) + { + super("test", Version.unknownVersion()); + this.modifier = modifier; + } + + @Override + public void setupModule(SetupContext context) + { + super.setupModule(context); + if (modifier != null) { + context.addBeanSerializerModifier(modifier); + } + } + } + + @JsonPropertyOrder({"b", "a"}) + static class Bean { + public String b = "b"; + public String a = "a"; + } + + static class RemovingModifier extends BeanSerializerModifier + { + private final String _removedProperty; + + public RemovingModifier(String remove) { _removedProperty = remove; } + + @Override + public List<BeanPropertyWriter> changeProperties(SerializationConfig config, BasicBeanDescription beanDesc, + List<BeanPropertyWriter> beanProperties) + { + Iterator<BeanPropertyWriter> it = beanProperties.iterator(); + while (it.hasNext()) { + BeanPropertyWriter bpw = it.next(); + if (bpw.getName().equals(_removedProperty)) { + it.remove(); + } + } + return beanProperties; + } + } + + static class ReorderingModifier extends BeanSerializerModifier + { + @Override + public List<BeanPropertyWriter> orderProperties(SerializationConfig config, BasicBeanDescription beanDesc, List<BeanPropertyWriter> beanProperties) + { + TreeMap<String,BeanPropertyWriter> props = new TreeMap<String,BeanPropertyWriter>(); + for (BeanPropertyWriter bpw : beanProperties) { + props.put(bpw.getName(), bpw); + } + return new ArrayList<BeanPropertyWriter>(props.values()); + } + } + + static class ReplacingModifier extends BeanSerializerModifier + { + private final JsonSerializer<?> _serializer; + + public ReplacingModifier(JsonSerializer<?> s) { _serializer = s; } + + @Override + public JsonSerializer<?> modifySerializer(SerializationConfig config, BasicBeanDescription beanDesc, + JsonSerializer<?> serializer) { + return _serializer; + } + } + + static class BuilderModifier extends BeanSerializerModifier + { + private final JsonSerializer<?> _serializer; + + public BuilderModifier(JsonSerializer<?> ser) { + _serializer = ser; + } + + @Override + public BeanSerializerBuilder updateBuilder(SerializationConfig config, + BasicBeanDescription beanDesc, BeanSerializerBuilder builder) { + return new BogusSerializerBuilder(builder, _serializer); + } + } + + static class BogusSerializerBuilder extends BeanSerializerBuilder + { + private final JsonSerializer<?> _serializer; + + public BogusSerializerBuilder(BeanSerializerBuilder src, + JsonSerializer<?> ser) { + super(src); + _serializer = ser; + } + + @Override + public JsonSerializer<?> build() { + return _serializer; + } + } + + static class BogusBeanSerializer extends JsonSerializer<Object> + { + private final int _value; + + public BogusBeanSerializer(int v) { _value = v; } + + @Override + public void serialize(Object value, JsonGenerator jgen, + SerializerProvider provider) throws IOException { + jgen.writeNumber(_value); + } + } + + // for [JACKSON-670] + + static class EmptyBean { + @JsonIgnore + public String name = "foo"; + } + + static class EmptyBeanModifier extends BeanSerializerModifier + { + @Override + public List<BeanPropertyWriter> changeProperties(SerializationConfig config, + BasicBeanDescription beanDesc, List<BeanPropertyWriter> beanProperties) + { + JavaType strType = config.constructType(String.class); + try { + beanProperties.add(new BeanPropertyWriter( + null, null, + "bogus", strType, + null, null, strType, + null, EmptyBean.class.getDeclaredField("name"), + false, null + )); + } catch (NoSuchFieldException e) { + throw new IllegalStateException(e.getMessage()); + } + return beanProperties; + } + } + + // For [JACKSON-694]: error message for conflicting getters sub-optimal + static class BeanWithConflict + { + public int getX() { return 3; } + public boolean isX() { return false; } + } + + /* + /******************************************************** + /* Unit tests: success + /******************************************************** + */ + + public void testPropertyRemoval() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.registerModule(new ModuleImpl(new RemovingModifier("a"))); + Bean bean = new Bean(); + assertEquals("{\"b\":\"b\"}", mapper.writeValueAsString(bean)); + } + + public void testPropertyReorder() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.registerModule(new ModuleImpl(new ReorderingModifier())); + Bean bean = new Bean(); + assertEquals("{\"a\":\"a\",\"b\":\"b\"}", mapper.writeValueAsString(bean)); + } + + public void testBuilderReplacement() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.registerModule(new ModuleImpl(new BuilderModifier(new BogusBeanSerializer(17)))); + Bean bean = new Bean(); + assertEquals("17", mapper.writeValueAsString(bean)); + } + public void testSerializerReplacement() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.registerModule(new ModuleImpl(new ReplacingModifier(new BogusBeanSerializer(123)))); + Bean bean = new Bean(); + assertEquals("123", mapper.writeValueAsString(bean)); + } + + // for [JACKSON-670] + public void testEmptyBean() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.registerModule(new SimpleModule("test", Version.unknownVersion()) { + @Override + public void setupModule(SetupContext context) + { + super.setupModule(context); + context.addBeanSerializerModifier(new EmptyBeanModifier()); + } + }); + String json = mapper.writeValueAsString(new EmptyBean()); + assertEquals("{\"bogus\":\"foo\"}", json); + } + + /* + /******************************************************** + /* Unit tests: failure handling + /******************************************************** + */ + + // for [JACKSON-694] + public void testFailWithDupProps() throws Exception + { + BeanWithConflict bean = new BeanWithConflict(); + ObjectMapper mapper = new ObjectMapper(); + try { + String json = mapper.writeValueAsString(bean); + fail("Should have failed due to conflicting accessor definitions; got JSON = "+json); + } catch (JsonProcessingException e) { + verifyException(e, "Conflicting getter definitions"); + } + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/ser/TestCollectionSerialization.java b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestCollectionSerialization.java new file mode 100644 index 0000000..77416b2 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestCollectionSerialization.java
@@ -0,0 +1,329 @@ +package org.codehaus.jackson.map.ser; + +import java.io.*; +import java.util.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.annotate.JsonProperty; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.JsonSerialize; + +public class TestCollectionSerialization + extends BaseMapTest +{ + /* + /********************************************************** + /* Helper classes + /********************************************************** + */ + + enum Key { A, B, C }; + + // Field-based simple bean with a single property, "values" + final static class CollectionBean + { + @JsonProperty // not required + public Collection<Object> values; + + public CollectionBean(Collection<Object> c) { values = c; } + } + + static class EnumMapBean + { + EnumMap<Key,String> _map; + + public EnumMapBean(EnumMap<Key,String> m) + { + _map = m; + } + + public EnumMap<Key,String> getMap() { return _map; } + } + + final static class IterableWrapper + implements Iterable<Integer> + { + List<Integer> _ints = new ArrayList<Integer>(); + + public IterableWrapper(int[] values) { + for (int i : values) { + _ints.add(Integer.valueOf(i)); + } + } + + @Override + public Iterator<Integer> iterator() { + return _ints.iterator(); + } + } + + /** + * Class needed for testing [JACKSON-220] + */ + @SuppressWarnings("serial") + @JsonSerialize(using=ListSerializer.class) + static class PseudoList extends ArrayList<String> + { + public PseudoList(String... values) { + super(Arrays.asList(values)); + } + } + + static class ListSerializer extends JsonSerializer<List<String>> + { + @Override + public void serialize(List<String> value, + JsonGenerator jgen, + SerializerProvider provider) + throws IOException + { + // just use standard List.toString(), output as JSON String + jgen.writeString(value.toString()); + } + } + + // for [JACKSON-254], suppression of empty collections + static class EmptyListBean { + public List<String> empty = new ArrayList<String>(); + } + + static class EmptyArrayBean { + public String[] empty = new String[0]; + } + + // [JACKSIN-689] + static class BeanWithIterable { + private final ArrayList<String> values = new ArrayList<String>(); + { + values.add("value"); + } + + public Iterable<String> getValues() { return values; } + } + + /* + /********************************************************** + /* Test methods + /********************************************************** + */ + + public void testCollections() + throws IOException + { + // Let's try different collections, arrays etc + final int entryLen = 98; + ObjectMapper mapper = new ObjectMapper(); + + for (int type = 0; type < 4; ++type) { + Object value; + + if (type == 0) { // first, array + int[] ints = new int[entryLen]; + for (int i = 0; i < entryLen; ++i) { + ints[i] = Integer.valueOf(i); + } + value = ints; + } else { + Collection<Integer> c; + + switch (type) { + case 1: + c = new LinkedList<Integer>(); + break; + case 2: + c = new TreeSet<Integer>(); // has to be ordered + break; + default: + c = new ArrayList<Integer>(); + break; + } + for (int i = 0; i < entryLen; ++i) { + c.add(Integer.valueOf(i)); + } + value = c; + } + StringWriter sw = new StringWriter(); + mapper.writeValue(sw, value); + + // and then need to verify: + JsonParser jp = new JsonFactory().createJsonParser(sw.toString()); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + for (int i = 0; i < entryLen; ++i) { + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(i, jp.getIntValue()); + } + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + } + } + + public void testBigCollection() + throws IOException + { + final int COUNT = 9999; + ArrayList<Integer> value = new ArrayList<Integer>(); + for (int i = 0; i <= COUNT; ++i) { + value.add(i); + } + ObjectMapper mapper = new ObjectMapper(); + // Let's test using 3 main variants... + for (int mode = 0; mode < 3; ++mode) { + JsonParser jp = null; + switch (mode) { + case 0: + { + byte[] data = mapper.writeValueAsBytes(value); + jp = new JsonFactory().createJsonParser(data); + } + break; + case 1: + { + StringWriter sw = new StringWriter(value.size()); + mapper.writeValue(sw, value); + jp = createParserUsingReader(sw.toString()); + } + break; + case 2: + { + String str = mapper.writeValueAsString(value); + jp = createParserUsingReader(str); + } + break; + } + + // and verify + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + for (int i = 0; i <= COUNT; ++i) { + assertEquals(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(i, jp.getIntValue()); + } + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + jp.close(); + } + } + + public void testEnumMap() + throws IOException + { + ObjectMapper mapper = new ObjectMapper(); + StringWriter sw = new StringWriter(); + EnumMap<Key,String> map = new EnumMap<Key,String>(Key.class); + map.put(Key.B, "xyz"); + map.put(Key.C, "abc"); + // assuming EnumMap uses enum entry order, which I think is true... + mapper.writeValue(sw, map); + assertEquals("{\"B\":\"xyz\",\"C\":\"abc\"}", sw.toString().trim()); + } + + public void testIterator() + throws IOException + { + ObjectMapper mapper = new ObjectMapper(); + StringWriter sw = new StringWriter(); + ArrayList<Integer> l = new ArrayList<Integer>(); + l.add(1); + l.add(-9); + l.add(0); + mapper.writeValue(sw, l.iterator()); + assertEquals("[1,-9,0]", sw.toString().trim()); + } + + public void testIterable() + throws IOException + { + ObjectMapper mapper = new ObjectMapper(); + StringWriter sw = new StringWriter(); + mapper.writeValue(sw, new IterableWrapper(new int[] { 1, 2, 3 })); + assertEquals("[1,2,3]", sw.toString().trim()); + } + + // Test that checks that empty collections are properly serialized + // when they are Bean properties + @SuppressWarnings("unchecked") + public void testEmptyBeanCollection() + throws IOException + { + Collection<Object> x = new ArrayList<Object>(); + x.add("foobar"); + CollectionBean cb = new CollectionBean(x); + ObjectMapper m = new ObjectMapper(); + Map<String,Object> result = writeAndMap(m, cb); + assertEquals(1, result.size()); + assertTrue(result.containsKey("values")); + Collection<Object> x2 = (Collection<Object>) result.get("values"); + assertNotNull(x2); + assertEquals(x, x2); + } + + public void testNullBeanCollection() + throws IOException + { + CollectionBean cb = new CollectionBean(null); + ObjectMapper m = new ObjectMapper(); + Map<String,Object> result = writeAndMap(m, cb); + assertEquals(1, result.size()); + assertTrue(result.containsKey("values")); + assertNull(result.get("values")); + } + + @SuppressWarnings("unchecked") + public void testEmptyBeanEnumMap() + throws IOException + { + EnumMap<Key,String> map = new EnumMap<Key,String>(Key.class); + EnumMapBean b = new EnumMapBean(map); + ObjectMapper m = new ObjectMapper(); + Map<String,Object> result = writeAndMap(m, b); + + assertEquals(1, result.size()); + assertTrue(result.containsKey("map")); + // we deserialized to untyped, not back to bean, so: + Map<Object,Object> map2 = (Map<Object,Object>) result.get("map"); + assertNotNull(map2); + assertEquals(0, map2.size()); + } + + // Should also be able to serialize null EnumMaps as expected + public void testNullBeanEnumMap() + throws IOException + { + EnumMapBean b = new EnumMapBean(null); + ObjectMapper m = new ObjectMapper(); + Map<String,Object> result = writeAndMap(m, b); + + assertEquals(1, result.size()); + assertTrue(result.containsKey("map")); + assertNull(result.get("map")); + } + + // Test [JACKSON-220] + public void testListSerializer() throws IOException + { + ObjectMapper m = new ObjectMapper(); + assertEquals("\"[ab, cd, ef]\"", m.writeValueAsString(new PseudoList("ab", "cd", "ef"))); + } + + // [JACKSON-254] + public void testEmptyListOrArray() throws IOException + { + // by default, empty lists serialized normally + EmptyListBean list = new EmptyListBean(); + EmptyArrayBean array = new EmptyArrayBean(); + ObjectMapper m = new ObjectMapper(); + assertTrue(m.getSerializationConfig().isEnabled(SerializationConfig.Feature.WRITE_EMPTY_JSON_ARRAYS)); + assertEquals("{\"empty\":[]}", m.writeValueAsString(list)); + assertEquals("{\"empty\":[]}", m.writeValueAsString(array)); + + // note: value of setting may be cached when constructing serializer, need a new instance + m = new ObjectMapper(); + m.configure(SerializationConfig.Feature.WRITE_EMPTY_JSON_ARRAYS, false); + assertEquals("{}", m.writeValueAsString(list)); + assertEquals("{}", m.writeValueAsString(array)); + } + + // [JACKSON-689] + public void testWithIterable() throws IOException + { + ObjectMapper m = new ObjectMapper(); + assertEquals("{\"values\":[\"value\"]}", m.writeValueAsString(new BeanWithIterable())); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/ser/TestConfig.java b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestConfig.java new file mode 100644 index 0000000..383c3b8 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestConfig.java
@@ -0,0 +1,189 @@ +package org.codehaus.jackson.map.ser; + +import java.util.*; + +import org.codehaus.jackson.annotate.*; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.JsonSerialize; + +/** + * Unit tests for checking handling of SerializationConfig. + */ +public class TestConfig + extends BaseMapTest +{ + /* + /********************************************************** + /* Helper beans + /********************************************************** + */ + + @SuppressWarnings("deprecation") + @JsonWriteNullProperties(false) + @JsonAutoDetect(JsonMethod.NONE) + final static class ConfigLegacy { } + + @JsonSerialize(include=JsonSerialize.Inclusion.NON_DEFAULT, + typing=JsonSerialize.Typing.STATIC) + @JsonAutoDetect(JsonMethod.NONE) + final static class Config { } + + final static class ConfigNone { } + + static class AnnoBean { + public int getX() { return 1; } + @SuppressWarnings("unused") @JsonProperty("y") + private int getY() { return 2; } + } + + /* + /********************************************************** + /* Main tests + /********************************************************** + */ + + @SuppressWarnings("deprecation") + public void testDefaults() + { + ObjectMapper m = new ObjectMapper(); + SerializationConfig cfg = m.getSerializationConfig(); + + // First, defaults: + assertTrue(cfg.isEnabled(SerializationConfig.Feature.USE_ANNOTATIONS)); + assertTrue(cfg.isEnabled(SerializationConfig.Feature.AUTO_DETECT_GETTERS)); + assertTrue(cfg.isEnabled(SerializationConfig.Feature.CAN_OVERRIDE_ACCESS_MODIFIERS)); + + assertTrue(cfg.isEnabled(SerializationConfig.Feature.WRITE_NULL_PROPERTIES)); + assertTrue(cfg.isEnabled(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS)); + + assertFalse(cfg.isEnabled(SerializationConfig.Feature.INDENT_OUTPUT)); + assertFalse(cfg.isEnabled(SerializationConfig.Feature.USE_STATIC_TYPING)); + + // since 1.3: + assertTrue(cfg.isEnabled(SerializationConfig.Feature.AUTO_DETECT_IS_GETTERS)); + // since 1.4 + + assertTrue(cfg.isEnabled(SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS)); + // since 1.5 + assertTrue(cfg.isEnabled(SerializationConfig.Feature.DEFAULT_VIEW_INCLUSION)); + + } + + public void testOverrideIntrospectors() + { + ObjectMapper m = new ObjectMapper(); + SerializationConfig cfg = m.getSerializationConfig(); + // and finally, ensure we could override introspectors + cfg = cfg.withClassIntrospector(null); // no way to verify tho + cfg = cfg.withAnnotationIntrospector(null); + assertNull(cfg.getAnnotationIntrospector()); + } + + public void testMisc() + { + ObjectMapper m = new ObjectMapper(); + m.setDateFormat(null); // just to execute the code path + assertNotNull(m.getSerializationConfig().toString()); // ditto + } + + @SuppressWarnings("deprecation") + public void testFromAnnotationsLegacy() + { + ObjectMapper m = new ObjectMapper(); + SerializationConfig cfg = m.getSerializationConfig(); + + /* then configure using annotations from the dummy object; only + * subset of features affected this way + */ + cfg.fromAnnotations(ConfigLegacy.class); + assertFalse(cfg.isEnabled(SerializationConfig.Feature.WRITE_NULL_PROPERTIES)); + + /* 08-Mar-2010, tatu: the way auto-detection is handled was changed; these + * tests are not correct any more: + assertFalse(cfg.isEnabled(SerializationConfig.Feature.AUTO_DETECT_GETTERS)); + assertFalse(cfg.isEnabled(SerializationConfig.Feature.AUTO_DETECT_IS_GETTERS)); + */ + } + + @SuppressWarnings("deprecation") + public void testFromAnnotations() + { + ObjectMapper m = new ObjectMapper(); + SerializationConfig cfg = m.getSerializationConfig(); + + // first without any annotations + cfg.fromAnnotations(ConfigNone.class); + assertTrue(cfg.isEnabled(SerializationConfig.Feature.AUTO_DETECT_GETTERS)); + assertTrue(cfg.isEnabled(SerializationConfig.Feature.AUTO_DETECT_IS_GETTERS)); + assertFalse(cfg.isEnabled(SerializationConfig.Feature.USE_STATIC_TYPING)); + + /* then configure using annotations from the dummy object; only + * subset of features affected this way + */ + cfg.fromAnnotations(Config.class); + assertEquals(JsonSerialize.Inclusion.NON_DEFAULT, cfg.getSerializationInclusion()); + assertTrue(cfg.isEnabled(SerializationConfig.Feature.USE_STATIC_TYPING)); + + /* 08-Mar-2010, tatu: the way auto-detection is handled was changed; these + * tests are not correct any more: + assertFalse(cfg.isEnabled(SerializationConfig.Feature.AUTO_DETECT_GETTERS)); + assertFalse(cfg.isEnabled(SerializationConfig.Feature.AUTO_DETECT_IS_GETTERS)); + */ + } + + public void testIndentation() throws Exception + { + ObjectMapper m = new ObjectMapper(); + m.configure(SerializationConfig.Feature.INDENT_OUTPUT, true); + Map<String,Integer> map = new HashMap<String,Integer>(); + map.put("a", Integer.valueOf(2)); + String result = serializeAsString(m, map).trim(); + // 02-Jun-2009, tatu: not really a clean way but... + String lf = System.getProperty("line.separator"); + assertEquals("{"+lf+" \"a\" : 2"+lf+"}", result); + } + + public void testAnnotationsDisabled() throws Exception + { + // first: verify that annotation introspection is enabled by default + ObjectMapper m = new ObjectMapper(); + assertTrue(m.getSerializationConfig().isEnabled(SerializationConfig.Feature.USE_ANNOTATIONS)); + Map<String,Object> result = writeAndMap(m, new AnnoBean()); + assertEquals(2, result.size()); + + m = new ObjectMapper(); + m.configure(SerializationConfig.Feature.USE_ANNOTATIONS, false); + result = writeAndMap(m, new AnnoBean()); + assertEquals(1, result.size()); + } + + /** + * Test for verifying working of [JACKSON-191] + * + * @since 1.4 + */ + public void testProviderConfig() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + assertEquals(0, mapper.getSerializerProvider().cachedSerializersCount()); + // and then should get one constructed for: + Map<String,Object> result = this.writeAndMap(mapper, new AnnoBean()); + assertEquals(2, result.size()); + assertEquals(Integer.valueOf(1), result.get("x")); + assertEquals(Integer.valueOf(2), result.get("y")); + + /* Note: it is 2 because we'll also get serializer for basic 'int', not + * just AnnoBean + */ + /* 12-Jan-2010, tatus: Actually, probably more, if and when we typing + * aspects are considered (depending on what is cached) + */ + int count = mapper.getSerializerProvider().cachedSerializersCount(); + if (count < 2) { + fail("Should have at least 2 cached serializers, got "+count); + } + mapper.getSerializerProvider().flushCachedSerializers(); + assertEquals(0, mapper.getSerializerProvider().cachedSerializersCount()); + } + +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/ser/TestCustomFactory.java b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestCustomFactory.java new file mode 100644 index 0000000..4fdaf37 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestCustomFactory.java
@@ -0,0 +1,145 @@ +package org.codehaus.jackson.map.ser; + +import java.io.*; +import java.util.Date; +import java.sql.Timestamp; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.*; + +public class TestCustomFactory + extends BaseMapTest +{ + /* + /********************************************************** + /* Helper types + /********************************************************** + */ + + static class DummySerializer<T> + extends JsonSerializer<T> + { + @Override + public void serialize(T value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonProcessingException + { + jgen.writeString("XXX"); + } + } + + interface BeanInterface { + public int foo(); + } + + static class BeanImpl implements BeanInterface { + @Override + public int foo() { return 13; } + } + + static class BeanSerializer + extends JsonSerializer<BeanInterface> + { + @Override + public void serialize(BeanInterface value, + JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonProcessingException + { + jgen.writeBoolean(true); + } + } + + // for [JACKSON-373] + interface BaseInterface { + public int getX(); + public void setX(int value); + } + + interface SubInterface extends BaseInterface { } + + class SubImpl implements SubInterface + { + protected int x; + @Override + public int getX() { return x; } + @Override + public void setX(int value) { x = value; } + } + + static class BaseInterfaceSerializer extends JsonSerializer<BaseInterface> + { + @Override + public void serialize(BaseInterface value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonProcessingException + { + jgen.writeBoolean(true); + } + } + + /* + /********************************************************** + /* Test methods + /********************************************************** + */ + + /** + * Simple test to verify specific mappings working + */ + public void testSpecificOverrideDate() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + CustomSerializerFactory sf = new CustomSerializerFactory(); + sf.addSpecificMapping(Date.class, new DummySerializer<Date>()); + mapper.setSerializerFactory(sf); + + String result = serializeAsString(mapper, new Date()); + assertEquals("\"XXX\"", result); + + // But also: sub-classes should NOT be affected. + result = serializeAsString(mapper, new Timestamp(0L)); + assertEquals("0", result); + } + + /** + * Test to verify generic mapping by using super-class + */ + public void testGenericOverrideDate() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + CustomSerializerFactory sf = new CustomSerializerFactory(); + + sf.addGenericMapping(Date.class, new DummySerializer<Date>()); + mapper.setSerializerFactory(sf); + + String result = serializeAsString(mapper, new Timestamp(0L)); + + assertEquals("\"XXX\"", result); + } + + // Unit test for [JACKSON-327] + public void testRegisterForInterface() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + CustomSerializerFactory sf = new CustomSerializerFactory(); + sf.addGenericMapping(BeanInterface.class, new BeanSerializer()); + mapper.setSerializerFactory(sf); + + ObjectWriter w = mapper.writerWithType(BeanInterface.class); + String result = w.writeValueAsString(new BeanImpl()); + + assertEquals("true", result); + } + + // Unit test for [JACKSON-373] + public void testRegisterForTransitiveInterface() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + CustomSerializerFactory sf = new CustomSerializerFactory(); + sf.addGenericMapping(BaseInterface.class, new BaseInterfaceSerializer()); + mapper.setSerializerFactory(sf); + + String result = mapper.writeValueAsString(new SubImpl()); + + assertEquals("true", result); + } + +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/ser/TestCustomSerializers.java b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestCustomSerializers.java new file mode 100644 index 0000000..45e7fe8 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestCustomSerializers.java
@@ -0,0 +1,79 @@ +package org.codehaus.jackson.map.ser; + +import java.io.IOException; +import java.io.StringWriter; +import java.util.*; + +import javax.xml.parsers.DocumentBuilderFactory; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.JsonSerialize; +import org.codehaus.jackson.map.ser.std.CollectionSerializer; +import org.w3c.dom.Element; + +/** + * Test for verifying [JACKSON-238] + * + * @author Pablo Lalloni <plalloni@gmail.com> + * @author tatu + */ +public class TestCustomSerializers + extends org.codehaus.jackson.map.BaseMapTest +{ + /* + /********************************************************** + /* Helper beans + /********************************************************** + */ + + static class ElementSerializer extends JsonSerializer<Element> + { + @Override + public void serialize(Element value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException { + jgen.writeString("element"); + } + } + + @JsonSerialize(using = ElementSerializer.class) + public static class ElementMixin {} + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + public void testCustomization() throws Exception + { + ObjectMapper objectMapper = new ObjectMapper(); + objectMapper.getSerializationConfig().addMixInAnnotations(Element.class, ElementMixin.class); + Element element = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument().createElement("el"); + StringWriter sw = new StringWriter(); + objectMapper.writeValue(sw, element); + assertEquals(sw.toString(), "\"element\""); + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + public void testCustomLists() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + CustomSerializerFactory sf = new CustomSerializerFactory(); + JsonSerializer<?> ser = new CollectionSerializer(null, false, null, null, null); + final JsonSerializer<Object> collectionSerializer = (JsonSerializer<Object>) ser; + + sf.addGenericMapping(Collection.class, new JsonSerializer<Collection>() { + @Override + public void serialize(Collection value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonProcessingException { + if (value.size() != 0) { + collectionSerializer.serialize(value, jgen, provider); + } else { + jgen.writeNull(); + } + } + }); + mapper.setSerializerFactory(sf); + assertEquals("null", mapper.writeValueAsString(new ArrayList<Object>())); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/ser/TestCyclicTypes.java b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestCyclicTypes.java new file mode 100644 index 0000000..4303855 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestCyclicTypes.java
@@ -0,0 +1,79 @@ +package org.codehaus.jackson.map.ser; + +import java.util.*; + +import org.codehaus.jackson.map.BaseMapTest; + +import org.codehaus.jackson.map.*; + +/** + * Simple unit tests to verify that it is possible to handle + * potentially cyclic structures, as long as object graph itself + * is not cyclic. This is the case for directed hierarchies like + * trees and DAGs. + */ +public class TestCyclicTypes + extends BaseMapTest +{ + /* + /********************************************************** + /* Helper bean classes + /********************************************************** + */ + + static class Bean + { + Bean _next; + final String _name; + + public Bean(Bean next, String name) { + _next = next; + _name = name; + } + + public Bean getNext() { return _next; } + public String getName() { return _name; } + + public void assignNext(Bean n) { _next = n; } + } + + /* + /********************************************************** + /* Types + /********************************************************** + */ + + public void testLinked() throws Exception + { + Bean last = new Bean(null, "last"); + Bean first = new Bean(last, "first"); + Map<String,Object> map = writeAndMap(new ObjectMapper(), first); + + assertEquals(2, map.size()); + assertEquals("first", map.get("name")); + + @SuppressWarnings("unchecked") + Map<String,Object> map2 = (Map<String,Object>) map.get("next"); + assertNotNull(map2); + assertEquals(2, map2.size()); + assertEquals("last", map2.get("name")); + assertNull(map2.get("next")); + } + + /** + * Test for verifying that [JACKSON-158] works as expected + */ + public void testSelfReference() throws Exception + { + Bean selfRef = new Bean(null, "self-refs"); + Bean first = new Bean(selfRef, "first"); + selfRef.assignNext(selfRef); + ObjectMapper m = new ObjectMapper(); + Bean[] wrapper = new Bean[] { first }; + try { + writeAndMap(m, wrapper); + } catch (JsonMappingException e) { + verifyException(e, "Direct self-reference leading to cycle"); + } + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/ser/TestDateSerialization.java b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestDateSerialization.java new file mode 100644 index 0000000..b057641 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestDateSerialization.java
@@ -0,0 +1,116 @@ +package org.codehaus.jackson.map.ser; + +import java.io.*; +import java.text.*; +import java.util.*; + +import org.codehaus.jackson.map.*; + +public class TestDateSerialization + extends BaseMapTest +{ + static class TimeZoneBean { + private TimeZone tz; + + public TimeZoneBean(String name) { + tz = TimeZone.getTimeZone(name); + } + + public TimeZone getTz() { return tz; } + } + + /* + /********************************************************** + /* Test methods + /********************************************************** + */ + + public void testDateNumeric() throws IOException + { + ObjectMapper mapper = new ObjectMapper(); + StringWriter sw = new StringWriter(); + // default is to output time stamps... + assertTrue(mapper.getSerializationConfig().isEnabled(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS)); + // shouldn't matter which offset we give... + mapper.writeValue(sw, new Date(199L)); + assertEquals("199", sw.toString()); + } + + public void testDateISO8601() throws IOException + { + ObjectMapper mapper = new ObjectMapper(); + StringWriter sw = new StringWriter(); + mapper.configure(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS, false); + // let's hit epoch start + mapper.writeValue(sw, new Date(0L)); + assertEquals("\"1970-01-01T00:00:00.000+0000\"", sw.toString()); + } + + public void testDateOther() throws IOException + { + ObjectMapper mapper = new ObjectMapper(); + DateFormat df = new SimpleDateFormat("yyyy-MM-dd'X'HH:mm:ss"); + df.setTimeZone(TimeZone.getTimeZone("PST")); + mapper.setDateFormat(df); + // let's hit epoch start, offset by a bit + assertEquals(quote("1969-12-31X16:00:00"), mapper.writeValueAsString(new Date(0L))); + } + + @SuppressWarnings("deprecation") + public void testSqlDate() throws IOException + { + ObjectMapper mapper = new ObjectMapper(); + // use date 1999-04-01 (note: months are 0-based, use constant) + java.sql.Date date = new java.sql.Date(99, Calendar.APRIL, 1); + assertEquals(quote("1999-04-01"), serializeAsString(mapper, date)); + } + + public void testTimeZone() throws IOException + { + ObjectMapper mapper = new ObjectMapper(); + TimeZone input = TimeZone.getTimeZone("PST"); + String json = mapper.writeValueAsString(input); + assertEquals(quote("PST"), json); + } + + // [JACKSON-663] + public void testTimeZoneInBean() throws IOException + { + ObjectMapper mapper = new ObjectMapper(); + String json = mapper.writeValueAsString(new TimeZoneBean("PST")); + assertEquals("{\"tz\":\"PST\"}", json); + } + + // [JACKSON-648]: (re)configuring via ObjectWriter + public void testDateUsingObjectWriter() throws IOException + { + DateFormat df = new SimpleDateFormat("yyyy-MM-dd'X'HH:mm:ss"); + df.setTimeZone(TimeZone.getTimeZone("PST")); + ObjectMapper mapper = new ObjectMapper(); + assertEquals(quote("1969-12-31X16:00:00"), + mapper.writer(df).writeValueAsString(new Date(0L))); + ObjectWriter w = mapper.writer((DateFormat)null); + assertEquals("0", w.writeValueAsString(new Date(0L))); + + w = w.withDateFormat(df); + assertEquals(quote("1969-12-31X16:00:00"), w.writeValueAsString(new Date(0L))); + w = w.withDateFormat(null); + assertEquals("0", w.writeValueAsString(new Date(0L))); + } + + // [JACKSON-606] + public void testDatesAsMapKeys() throws IOException + { + ObjectMapper mapper = new ObjectMapper(); + Map<Date,Integer> map = new HashMap<Date,Integer>(); + assertFalse(mapper.isEnabled(SerializationConfig.Feature.WRITE_DATE_KEYS_AS_TIMESTAMPS)); + map.put(new Date(0L), Integer.valueOf(1)); + // by default will serialize as ISO-8601 values... + assertEquals("{\"1970-01-01T00:00:00.000+0000\":1}", mapper.writeValueAsString(map)); + + // but can change to use timestamps too + mapper.configure(SerializationConfig.Feature.WRITE_DATE_KEYS_AS_TIMESTAMPS, true); + assertEquals("{\"0\":1}", mapper.writeValueAsString(map)); + } +} +
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/ser/TestEmptyClass.java b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestEmptyClass.java new file mode 100644 index 0000000..437f1c1 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestEmptyClass.java
@@ -0,0 +1,49 @@ +package org.codehaus.jackson.map.ser; + +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.*; + +public class TestEmptyClass + extends BaseMapTest +{ + static class Empty { } + + @JsonSerialize + static class EmptyWithAnno { } + + /** + * Test to check that [JACKSON-201] works if there is a recognized + * annotation (which indicates type is serializable) + */ + public void testEmptyWithAnnotations() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + // First: without annotations, should complain + try { + serializeAsString(mapper, new Empty()); + } catch (JsonMappingException e) { + verifyException(e, "No serializer found for class"); + } + + // But not if there is a recognized annotation + assertEquals("{}", serializeAsString(mapper, new EmptyWithAnno())); + + // Including class annotation through mix-ins + mapper = new ObjectMapper(); + mapper.getSerializationConfig().addMixInAnnotations(Empty.class, EmptyWithAnno.class); + assertEquals("{}", serializeAsString(mapper, new Empty())); + } + + /** + * Alternative it is possible to use a feature to allow + * serializing empty classes, too + */ + public void testEmptyWithFeature() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + // should be enabled by default + assertTrue(mapper.getSerializationConfig().isEnabled(SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS)); + mapper.configure(SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS, false); + assertEquals("{}", serializeAsString(mapper, new Empty())); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/ser/TestEnumSerialization.java b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestEnumSerialization.java new file mode 100644 index 0000000..c20897b --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestEnumSerialization.java
@@ -0,0 +1,272 @@ +package org.codehaus.jackson.map.ser; + +import java.io.*; +import java.util.*; + +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.annotate.JsonProperty; +import org.codehaus.jackson.annotate.JsonValue; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.JsonSerialize; +import org.codehaus.jackson.map.ser.std.ToStringSerializer; + +/** + * Unit tests for verifying serialization of simple basic non-structured + * types; primitives (and/or their wrappers), Strings. + */ +public class TestEnumSerialization + extends BaseMapTest +{ + /* + /********************************************************** + /* Helper enums + /********************************************************** + */ + + /** + * Test enumeration for verifying Enum serialization functionality. + */ + protected enum TestEnum { + A, B, C; + private TestEnum() { } + + @Override public String toString() { return name().toLowerCase(); } + } + + /** + * Alternative version that forces use of "toString-serializer". + */ + @JsonSerialize(using=ToStringSerializer.class) + protected enum AnnotatedTestEnum { + A2, B2, C2; + private AnnotatedTestEnum() { } + + @Override public String toString() { return name().toLowerCase(); } + } + + protected enum EnumWithJsonValue { + A("foo"), B("bar"); + private final String name; + private EnumWithJsonValue(String n) { + name = n; + } + @JsonValue + @Override + public String toString() { return name; } + } + + protected static interface ToStringMixin { + @Override + @JsonValue public String toString(); + } + + protected enum SerializableEnum implements JsonSerializableWithType + { + A, B, C; + + private SerializableEnum() { } + + @Override + public void serializeWithType(JsonGenerator jgen, SerializerProvider provider, TypeSerializer typeSer) + throws IOException, JsonProcessingException + { + serialize(jgen, provider); + } + + @Override + public void serialize(JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException + { + jgen.writeString("foo"); + } + } + + protected enum LowerCaseEnum { + A, B, C; + private LowerCaseEnum() { } + @Override + public String toString() { return name().toLowerCase(); } + } + + static class MapBean { + public Map<TestEnum,Integer> map = new HashMap<TestEnum,Integer>(); + + public void add(TestEnum key, int value) { + map.put(key, Integer.valueOf(value)); + } + } + + // [JACKSON-757] + static enum NOT_OK { + V1("v1"); + protected String key; + // any runtime-persistent annotation is fine + NOT_OK(@JsonProperty String key) { this.key = key; } + } + + static enum OK { + V1("v1"); + protected String key; + OK(String key) { this.key = key; } + } + + /* + /********************************************************** + /* Tests + /********************************************************** + */ + + public void testSimple() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + StringWriter sw = new StringWriter(); + mapper.writeValue(sw, TestEnum.B); + assertEquals("\"B\"", sw.toString()); + } + + public void testEnumSet() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + StringWriter sw = new StringWriter(); + EnumSet<TestEnum> value = EnumSet.of(TestEnum.B); + mapper.writeValue(sw, value); + assertEquals("[\"B\"]", sw.toString()); + } + + /** + * Whereas regular Enum serializer uses enum names, some users + * prefer calling toString() instead. So let's verify that + * this can be done using annotation for enum class. + */ + public void testEnumUsingToString() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + StringWriter sw = new StringWriter(); + mapper.writeValue(sw, AnnotatedTestEnum.C2); + assertEquals("\"c2\"", sw.toString()); + } + + /** + * Unit test that verifies that standard enum serialization + * can be overridden by using custom serializer factory + * to specify alternative global enum serializer. + */ + public void testEnumUsingCSFEnumOverride() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + CustomSerializerFactory sf = new CustomSerializerFactory(); + sf.setEnumSerializer(ToStringSerializer.instance); + mapper.setSerializerFactory(sf); + StringWriter sw = new StringWriter(); + mapper.writeValue(sw, TestEnum.B); + assertEquals("\"b\"", sw.toString()); + } + + /** + * Unit test that verifies that standard enum serialization + * can be overridden by using custom serializer factory + * to specify generic serializer for enum base class + */ + @SuppressWarnings("unchecked") + public void testEnumUsingCSFGenericMapping() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + CustomSerializerFactory sf = new CustomSerializerFactory(); + Class<?> enumCls = Enum.class; + sf.addGenericMapping((Class<Object>) enumCls, ToStringSerializer.instance); + mapper.setSerializerFactory(sf); + StringWriter sw = new StringWriter(); + mapper.writeValue(sw, TestEnum.A); + assertEquals("\"a\"", sw.toString()); + } + + // Test [JACKSON-214] + public void testSubclassedEnums() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + assertEquals("\"B\"", mapper.writeValueAsString(EnumWithSubClass.B)); + } + + // [JACKSON-193] + public void testEnumsWithJsonValue() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + assertEquals("\"bar\"", mapper.writeValueAsString(EnumWithJsonValue.B)); + } + + // also, for [JACKSON-193], needs to work via mix-ins + public void testEnumsWithJsonValueUsingMixin() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.getSerializationConfig().addMixInAnnotations(TestEnum.class, ToStringMixin.class); + assertEquals("\"b\"", mapper.writeValueAsString(TestEnum.B)); + } + + /** + * Test for ensuring that @JsonSerializable is used with Enum types as well + * as with any other types. + */ + public void testSerializableEnum() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + assertEquals("\"foo\"", mapper.writeValueAsString(SerializableEnum.A)); + } + + // [JACKSON-212] + public void testToStringEnum() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.configure(SerializationConfig.Feature.WRITE_ENUMS_USING_TO_STRING, true); + assertEquals("\"b\"", mapper.writeValueAsString(LowerCaseEnum.B)); + } + + // [JACKSON-212] + public void testToStringEnumWithEnumMap() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + EnumMap<LowerCaseEnum,String> m = new EnumMap<LowerCaseEnum,String>(LowerCaseEnum.class); + m.put(LowerCaseEnum.C, "value"); + mapper.configure(SerializationConfig.Feature.WRITE_ENUMS_USING_TO_STRING, true); + assertEquals("{\"c\":\"value\"}", mapper.writeValueAsString(m)); + } + + // [JACKSON-576] + public void testMapWithEnumKeys() throws Exception + { + MapBean bean = new MapBean(); + bean.add(TestEnum.B, 3); + String json = new ObjectMapper().writeValueAsString(bean); + assertEquals("{\"map\":{\"b\":3}}", json); + } + + // [JACKSON-684] + public void testAsIndex() throws Exception + { + // By default, serialize using name + ObjectMapper mapper = new ObjectMapper(); + assertFalse(mapper.isEnabled(SerializationConfig.Feature.WRITE_ENUMS_USING_INDEX)); + assertEquals(quote("B"), mapper.writeValueAsString(TestEnum.B)); + + // but we can change (dynamically, too!) it to be number-based + mapper.enable(SerializationConfig.Feature.WRITE_ENUMS_USING_INDEX); + assertEquals("1", mapper.writeValueAsString(TestEnum.B)); + } + + // [JACKSON-757] + public void testAnnotationsOnEnumCtor() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + assertEquals(quote("V1"), mapper.writeValueAsString(OK.V1)); + assertEquals(quote("V1"), mapper.writeValueAsString(NOT_OK.V1)); + assertEquals(quote("V2"), mapper.writeValueAsString(NOT_OK2.V2)); + } +} + + +// [JACKSON-757], non-inner enum +enum NOT_OK2 { + V2("v2"); + protected String key; + // any runtime-persistent annotation is fine + NOT_OK2(@JsonProperty String key) { this.key = key; } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/ser/TestExceptionHandling.java b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestExceptionHandling.java new file mode 100644 index 0000000..d331612 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestExceptionHandling.java
@@ -0,0 +1,154 @@ +package org.codehaus.jackson.map.ser; + +import main.BaseTest; + +import java.io.*; +import java.util.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.*; + +/** + * Unit test for verifying that exceptions are properly handled (caught, + * re-thrown or wrapped, depending) + * with Object serialization. + */ +public class TestExceptionHandling + extends BaseTest +{ + /* + ////////////////////////////////////////////// + // Helper classes + ////////////////////////////////////////////// + */ + + static class Bean { + // no methods, we'll use our custom serializer + } + + static class SerializerWithErrors + extends JsonSerializer<Bean> + { + @Override + public void serialize(Bean value, JsonGenerator jgen, SerializerProvider provider) + { + throw new IllegalArgumentException("test string"); + } + } + + /* + ////////////////////////////////////////////// + // Tests + ////////////////////////////////////////////// + */ + + /** + * Unit test that verifies that by default all exceptions except for + * JsonMappingException are caught and wrapped. + */ + public void testCatchAndRethrow() + throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + CustomSerializerFactory sf = new CustomSerializerFactory(); + sf.addSpecificMapping(Bean.class, new SerializerWithErrors()); + mapper.setSerializerFactory(sf); + try { + StringWriter sw = new StringWriter(); + /* And just to make things more interesting, let's create + * a nested data struct... + */ + Bean[] b = { new Bean() }; + List<Bean[]> l = new ArrayList<Bean[]>(); + l.add(b); + mapper.writeValue(sw, l); + fail("Should have gotten an exception"); + } catch (IOException e) { + // should contain original message somewhere + verifyException(e, "test string"); + Throwable root = e.getCause(); + assertNotNull(root); + + if (!(root instanceof IllegalArgumentException)) { + fail("Wrapped exception not IAE, but "+root.getClass()); + } + } + } + + /** + * Unit test for verifying that regular IOExceptions are not wrapped + * but are passed through as is. + */ + public void testExceptionWithSimpleMapper() + throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + try { + BrokenStringWriter sw = new BrokenStringWriter("TEST"); + mapper.writeValue(sw, createLongObject()); + fail("Should have gotten an exception"); + } catch (IOException e) { + verifyException(e, IOException.class, "TEST"); + } + } + + public void testExceptionWithMapperAndGenerator() + throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + JsonFactory f = new MappingJsonFactory(); + BrokenStringWriter sw = new BrokenStringWriter("TEST"); + JsonGenerator jg = f.createJsonGenerator(sw); + + try { + mapper.writeValue(jg, createLongObject()); + fail("Should have gotten an exception"); + } catch (IOException e) { + verifyException(e, IOException.class, "TEST"); + } + } + + public void testExceptionWithGeneratorMapping() + throws Exception + { + JsonFactory f = new MappingJsonFactory(); + JsonGenerator jg = f.createJsonGenerator(new BrokenStringWriter("TEST")); + try { + jg.writeObject(createLongObject()); + fail("Should have gotten an exception"); + } catch (Exception e) { + verifyException(e, IOException.class, "TEST"); + } + } + + /* + //////////////////////////////////////////////////// + // Helper methods + //////////////////////////////////////////////////// + */ + + void verifyException(Exception e, Class<?> expType, String expMsg) + throws Exception + { + if (e.getClass() != expType) { + fail("Expected exception of type "+expType.getName()+", got "+e.getClass().getName()); + } + if (expMsg != null) { + verifyException(e, expMsg); + } + } + + Object createLongObject() + { + List<Object> leaf = new ArrayList<Object>(); + for (int i = 0; i < 256; ++i) { + leaf.add(Integer.valueOf(i)); + } + List<Object> root = new ArrayList<Object>(256); + for (int i = 0; i < 256; ++i) { + root.add(leaf); + } + return root; + } +} +
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/ser/TestExceptionSerialization.java b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestExceptionSerialization.java new file mode 100644 index 0000000..b8b99be --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestExceptionSerialization.java
@@ -0,0 +1,37 @@ +package org.codehaus.jackson.map.ser; + +import org.codehaus.jackson.map.BaseMapTest; + +import java.util.*; + +import org.codehaus.jackson.map.*; + +/** + * Unit tests for verifying that simple exceptions can be serialized. + */ +public class TestExceptionSerialization + extends BaseMapTest +{ + /* + /////////////////////////////////////////////////// + // Tests + /////////////////////////////////////////////////// + */ + + public void testSimple() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + String TEST = "test exception"; + Map<String,Object> result = writeAndMap(mapper, new Exception(TEST)); + assertEquals(4, result.size()); + assertEquals(TEST, result.get("message")); + assertNull(result.get("cause")); + assertEquals(TEST, result.get("localizedMessage")); + + // hmmh. what should we get for stack traces? + Object traces = result.get("stackTrace"); + if (!(traces instanceof List<?>)) { + fail("Expected a List for exception member 'stackTrace', got: "+traces); + } + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/ser/TestFeatures.java b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestFeatures.java new file mode 100644 index 0000000..ecf2960 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestFeatures.java
@@ -0,0 +1,228 @@ +package org.codehaus.jackson.map.ser; + +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.map.BaseMapTest; + +import java.io.*; +import java.util.*; + +import org.codehaus.jackson.annotate.*; +import org.codehaus.jackson.map.*; + +/** + * Unit tests for checking whether JsonSerializerFactory.Feature + * configuration works + */ +public class TestFeatures + extends BaseMapTest +{ + /* + /********************************************************** + /* Helper classes + /********************************************************** + */ + + /** + * Class with one explicitly defined getter, one name-based + * auto-detectable getter. + */ + static class GetterClass + { + @JsonProperty("x") public int getX() { return -2; } + public int getY() { return 1; } + } + + /** + * Another test-class that explicitly disables auto-detection + */ + @JsonAutoDetect(JsonMethod.NONE) + static class DisabledGetterClass + { + @JsonProperty("x") public int getX() { return -2; } + public int getY() { return 1; } + } + + /** + * Another test-class that explicitly enables auto-detection + */ + @JsonAutoDetect(JsonMethod.GETTER) + static class EnabledGetterClass + { + @JsonProperty("x") public int getX() { return -2; } + public int getY() { return 1; } + + // not auto-detected, since "is getter" auto-detect disabled + public boolean isOk() { return true; } + } + + /** + * One more: only detect "isXxx", not "getXXX" + */ + @JsonAutoDetect(JsonMethod.IS_GETTER) + static class EnabledIsGetterClass + { + // Won't be auto-detected any more + public int getY() { return 1; } + + // but this will be + public boolean isOk() { return true; } + } + + static class CloseableBean implements Closeable + { + public int a = 3; + + protected boolean wasClosed = false; + + @Override + public void close() throws IOException { + wasClosed = true; + } + } + + /* + /********************************************************** + /* Test methods + /********************************************************** + */ + + public void testGlobalAutoDetection() throws IOException + { + // First: auto-detection enabled (default): + ObjectMapper m = new ObjectMapper(); + Map<String,Object> result = writeAndMap(m, new GetterClass()); + assertEquals(2, result.size()); + assertEquals(Integer.valueOf(-2), result.get("x")); + assertEquals(Integer.valueOf(1), result.get("y")); + + // Then auto-detection disabled. But note: we MUST create a new + // mapper, since old version of serializer may be cached by now + m = new ObjectMapper(); + m.configure(SerializationConfig.Feature.AUTO_DETECT_GETTERS, false); + result = writeAndMap(m, new GetterClass()); + assertEquals(1, result.size()); + assertTrue(result.containsKey("x")); + } + + public void testPerClassAutoDetection() throws IOException + { + // First: class-level auto-detection disabling + ObjectMapper m = new ObjectMapper(); + Map<String,Object> result = writeAndMap(m, new DisabledGetterClass()); + assertEquals(1, result.size()); + assertTrue(result.containsKey("x")); + + // And then class-level auto-detection enabling, should override defaults + m.configure(SerializationConfig.Feature.AUTO_DETECT_GETTERS, false); + result = writeAndMap(m, new EnabledGetterClass()); + assertEquals(2, result.size()); + assertTrue(result.containsKey("x")); + assertTrue(result.containsKey("y")); + } + + public void testPerClassAutoDetectionForIsGetter() throws IOException + { + ObjectMapper m = new ObjectMapper(); + // class level should override + m.configure(SerializationConfig.Feature.AUTO_DETECT_GETTERS, true); + m.configure(SerializationConfig.Feature.AUTO_DETECT_IS_GETTERS, false); + Map<String,Object> result = writeAndMap(m, new EnabledIsGetterClass()); + assertEquals(1, result.size()); + assertTrue(result.containsKey("ok")); + assertEquals(Boolean.TRUE, result.get("ok")); + } + + // Simple test verifying that chainable methods work ok... + public void testConfigChainability() + { + ObjectMapper m = new ObjectMapper(); + assertTrue(m.getDeserializationConfig().isEnabled(DeserializationConfig.Feature.AUTO_DETECT_SETTERS)); + assertTrue(m.getSerializationConfig().isEnabled(SerializationConfig.Feature.AUTO_DETECT_GETTERS)); + m.configure(DeserializationConfig.Feature.AUTO_DETECT_SETTERS, false).configure(SerializationConfig.Feature.AUTO_DETECT_GETTERS, false); + assertFalse(m.getDeserializationConfig().isEnabled(DeserializationConfig.Feature.AUTO_DETECT_SETTERS)); + assertFalse(m.getSerializationConfig().isEnabled(SerializationConfig.Feature.AUTO_DETECT_GETTERS)); + } + + // Test for [JACKSON-282] + public void testCloseCloseable() throws IOException + { + ObjectMapper m = new ObjectMapper(); + // default should be disabled: + CloseableBean bean = new CloseableBean(); + m.writeValueAsString(bean); + assertFalse(bean.wasClosed); + + // but can enable it: + m.configure(SerializationConfig.Feature.CLOSE_CLOSEABLE, true); + bean = new CloseableBean(); + m.writeValueAsString(bean); + assertTrue(bean.wasClosed); + + // also: let's ensure that ObjectWriter won't interfere with it + bean = new CloseableBean(); + m.writerWithType(CloseableBean.class).writeValueAsString(bean); + assertTrue(bean.wasClosed); + } + + // Test for [JACKSON-289] + public void testCharArrays() throws IOException + { + char[] chars = new char[] { 'a','b','c' }; + ObjectMapper m = new ObjectMapper(); + // default: serialize as Strings + assertEquals(quote("abc"), m.writeValueAsString(chars)); + + // new feature: serialize as JSON array: + m.configure(SerializationConfig.Feature.WRITE_CHAR_ARRAYS_AS_JSON_ARRAYS, true); + assertEquals("[\"a\",\"b\",\"c\"]", m.writeValueAsString(chars)); + } + + // Test for [JACKSON-401] + public void testFlushingAutomatic() throws IOException + { + ObjectMapper mapper = new ObjectMapper(); + assertTrue(mapper.getSerializationConfig().isEnabled(SerializationConfig.Feature.FLUSH_AFTER_WRITE_VALUE)); + // default is to flush after writeValue() + StringWriter sw = new StringWriter(); + JsonGenerator jgen = mapper.getJsonFactory().createJsonGenerator(sw); + mapper.writeValue(jgen, Integer.valueOf(13)); + assertEquals("13", sw.toString()); + jgen.close(); + + // ditto with ObjectWriter + sw = new StringWriter(); + jgen = mapper.getJsonFactory().createJsonGenerator(sw); + ObjectWriter ow = mapper.writer(); + ow.writeValue(jgen, Integer.valueOf(99)); + assertEquals("99", sw.toString()); + jgen.close(); + } + + // Test for [JACKSON-401] + public void testFlushingNotAutomatic() throws IOException + { + // but should not occur if configured otherwise + ObjectMapper mapper = new ObjectMapper(); + mapper.configure(SerializationConfig.Feature.FLUSH_AFTER_WRITE_VALUE, false); + StringWriter sw = new StringWriter(); + JsonGenerator jgen = mapper.getJsonFactory().createJsonGenerator(sw); + + mapper.writeValue(jgen, Integer.valueOf(13)); + // no flushing now: + assertEquals("", sw.toString()); + // except when actually flushing + jgen.flush(); + assertEquals("13", sw.toString()); + jgen.close(); + // Also, same should happen with ObjectWriter + sw = new StringWriter(); + jgen = mapper.getJsonFactory().createJsonGenerator(sw); + ObjectWriter ow = mapper.writer(); + ow.writeValue(jgen, Integer.valueOf(99)); + assertEquals("", sw.toString()); + // except when actually flushing + jgen.flush(); + assertEquals("99", sw.toString()); + jgen.close(); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/ser/TestFieldSerialization.java b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestFieldSerialization.java new file mode 100644 index 0000000..9ffc702 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestFieldSerialization.java
@@ -0,0 +1,215 @@ +package org.codehaus.jackson.map.ser; + +import org.codehaus.jackson.map.BaseMapTest; + +import java.util.*; + +import org.codehaus.jackson.annotate.*; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.*; + +/** + * Unit tests for verifying that field-backed properties can also be serialized + * (since version 1.1) as well as getter-accessible properties. + */ +public class TestFieldSerialization + extends BaseMapTest +{ + /* + /********************************************************** + /* Annotated helper classes + /********************************************************** + */ + + static class SimpleFieldBean + { + public int x, y; + + // not auto-detectable, not public + int z; + + // ignored, not detectable either + @JsonIgnore public int a; + } + + static class SimpleFieldBean2 + { + @JsonSerialize String[] values; + + // note: this annotation should not matter for serialization: + @JsonDeserialize int dummy; + } + + static class TransientBean + { + public int a; + // transients should not be included + public transient int b; + // or statics + public static int c; + } + + @JsonAutoDetect(JsonMethod.SETTER) + public class NoAutoDetectBean + { + // not auto-detectable any more + public int x; + + @JsonProperty("z") + public int _z; + } + + /** + * Let's test invalid bean too: can't have 2 logical properties + * with same name. + *<p> + * 21-Feb-2010, tatus: That is, not within same class. + * As per [JACKSON-226] it is acceptable to "override" + * field definitions in sub-classes. + */ + public static class DupFieldBean + { + @JsonProperty("foo") + public int _z; + + @SuppressWarnings("unused") + @JsonSerialize + private int foo; + } + + public static class DupFieldBean2 + { + public int z; + + @JsonProperty("z") + public int _z; + } + + public static class OkDupFieldBean + extends SimpleFieldBean + { + @JsonProperty("x") + protected int myX; + + @SuppressWarnings("hiding") + public int y; + + public OkDupFieldBean(int x, int y) { + this.myX = x; + this.y = y; + } + } + + /** + * It is ok to have a method-based and field-based property + * introspectable: only one should be serialized, and since + * methods have precedence, it should be the method one. + */ + public static class FieldAndMethodBean + { + @JsonProperty public int z; + + @JsonProperty("z") public int getZ() { return z+1; } + } + + /* + /********************************************************** + /* Main tests, success + /********************************************************** + */ + + public void testSimpleAutoDetect() throws Exception + { + SimpleFieldBean bean = new SimpleFieldBean(); + // let's set x, leave y as is + bean.x = 13; + ObjectMapper m = new ObjectMapper(); + Map<String,Object> result = writeAndMap(m, bean); + assertEquals(2, result.size()); + assertEquals(Integer.valueOf(13), result.get("x")); + assertEquals(Integer.valueOf(0), result.get("y")); + } + + @SuppressWarnings("unchecked") + public void testSimpleAnnotation() throws Exception + { + SimpleFieldBean2 bean = new SimpleFieldBean2(); + bean.values = new String[] { "a", "b" }; + ObjectMapper m = new ObjectMapper(); + Map<String,Object> result = writeAndMap(m, bean); + assertEquals(1, result.size()); + List<String> values = (List<String>) result.get("values"); + assertEquals(2, values.size()); + assertEquals("a", values.get(0)); + assertEquals("b", values.get(1)); + } + + public void testTransientAndStatic() throws Exception + { + TransientBean bean = new TransientBean(); + Map<String,Object> result = writeAndMap(bean); + assertEquals(1, result.size()); + assertEquals(Integer.valueOf(0), result.get("a")); + } + + public void testNoAutoDetect() throws Exception + { + NoAutoDetectBean bean = new NoAutoDetectBean(); + bean._z = -4; + ObjectMapper m = new ObjectMapper(); + Map<String,Object> result = writeAndMap(m, bean); + assertEquals(1, result.size()); + assertEquals(Integer.valueOf(-4), result.get("z")); + } + + /** + * Unit test that verifies that if both a field and a getter + * method exist for a logical property (which is allowed), + * getter has precendence over field. + */ + public void testMethodPrecedence() throws Exception + { + FieldAndMethodBean bean = new FieldAndMethodBean(); + bean.z = 9; + assertEquals(10, bean.getZ()); + assertEquals("{\"z\":10}", serializeAsString(bean)); + } + + /** + * Testing [JACKSON-226]: it is ok to have "field override", + * as long as there are no intra-class conflicts. + */ + public void testOkDupFields() throws Exception + { + OkDupFieldBean bean = new OkDupFieldBean(1, 2); + Map<String,Object> json = writeAndMap(new ObjectMapper(), bean); + assertEquals(2, json.size()); + assertEquals(Integer.valueOf(1), json.get("x")); + assertEquals(Integer.valueOf(2), json.get("y")); + } + + /* + /********************************************************** + /* Main tests, failure cases + /********************************************************** + */ + + public void testFailureDueToDups() throws Exception + { + try { + writeAndMap(new ObjectMapper(), new DupFieldBean()); + } catch (JsonMappingException e) { + verifyException(e, "Multiple fields representing"); + } + } + + public void testFailureDueToDupField() throws Exception + { + try { + writeAndMap(new ObjectMapper(), new DupFieldBean2()); + } catch (JsonMappingException e) { + verifyException(e, "Multiple fields representing"); + } + } +} +
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/ser/TestFiltering.java b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestFiltering.java new file mode 100644 index 0000000..48d9204 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestFiltering.java
@@ -0,0 +1,80 @@ +package org.codehaus.jackson.map.ser; + +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.JsonFilter; +import org.codehaus.jackson.map.ser.impl.*; + +/** + * Tests for verifying that bean property filtering (new with 1.7) + * works as expected. + * + * @since 1.7 + */ +public class TestFiltering extends BaseMapTest +{ + /* + /********************************************************** + /* Helper types + /********************************************************** + */ + + @JsonFilter("RootFilter") + static class Bean { + public String a = "a"; + public String b = "b"; + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + public void testSimpleInclusionFilter() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + FilterProvider prov = new SimpleFilterProvider().addFilter("RootFilter", + SimpleBeanPropertyFilter.filterOutAllExcept("a")); + assertEquals("{\"a\":\"a\"}", mapper.writer(prov).writeValueAsString(new Bean())); + + // [JACKSON-504]: also verify it works via mapper + mapper = new ObjectMapper(); + mapper.setFilters(prov); + assertEquals("{\"a\":\"a\"}", mapper.writeValueAsString(new Bean())); + } + + public void testSimpleExclusionFilter() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + FilterProvider prov = new SimpleFilterProvider().addFilter("RootFilter", + SimpleBeanPropertyFilter.serializeAllExcept("a")); + assertEquals("{\"b\":\"b\"}", mapper.writer(prov).writeValueAsString(new Bean())); + } + + // should handle missing case gracefully + public void testMissingFilter() throws Exception + { + // First: default behavior should be to throw an exception + ObjectMapper mapper = new ObjectMapper(); + try { + mapper.writeValueAsString(new Bean()); + fail("Should have failed without configured filter"); + } catch (JsonMappingException e) { // should be resolved to a MappingException (internally may be something else) + verifyException(e, "Can not resolve BeanPropertyFilter with id 'RootFilter'"); + } + + // but when changing behavior, should work difference + SimpleFilterProvider fp = new SimpleFilterProvider().setFailOnUnknownId(false); + mapper.setFilters(fp); + String json = mapper.writeValueAsString(new Bean()); + assertEquals("{\"a\":\"a\",\"b\":\"b\"}", json); + } + + // defaulting, as per [JACKSON-449] + public void testDefaultFilter() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + FilterProvider prov = new SimpleFilterProvider().setDefaultFilter(SimpleBeanPropertyFilter.filterOutAllExcept("b")); + assertEquals("{\"b\":\"b\"}", mapper.writer(prov).writeValueAsString(new Bean())); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/ser/TestGenericTypes.java b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestGenericTypes.java new file mode 100644 index 0000000..6cb0590 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestGenericTypes.java
@@ -0,0 +1,161 @@ +package org.codehaus.jackson.map.ser; + +import java.util.*; + +import org.codehaus.jackson.map.BaseMapTest; +import org.codehaus.jackson.map.ObjectMapper; + + +/** + * @since 1.7 + */ +public class TestGenericTypes extends BaseMapTest +{ + /* + /********************************************************** + /* Helper types + /********************************************************** + */ + + static class Account { + private Long id; + private String name; + + public Account(String name, Long id) { + this.id = id; + this.name = name; + } + + public String getName() { return name; } + public Long getId() { return id; } + } + + static class Key<T> { + private final T id; + + public Key(T id) { this.id = id; } + + public T getId() { return id; } + + public <V> Key<V> getParent() { return null; } + } + + static class Person1 { + private Long id; + private String name; + private Key<Account> account; + + public Person1(String name) { this.name = name; } + + public String getName() { + return name; + } + + public Key<Account> getAccount() { + return account; + } + + public Long getId() { + return id; + } + + public void setAccount(Key<Account> account) { + this.account = account; + } + } + + static class Person2 { + private Long id; + private String name; + private List<Key<Account>> accounts; + + public Person2(String name) { + this.name = name; + } + + public String getName() { return name; } + public List<Key<Account>> getAccounts() { return accounts; } + public Long getId() { return id; } + + public void setAccounts(List<Key<Account>> accounts) { + this.accounts = accounts; + } + } + + static class GenericBogusWrapper<T> { + public Element wrapped; + + public GenericBogusWrapper(T v) { wrapped = new Element(v); } + + class Element { + public T value; + + public Element(T v) { value = v; } + } + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + @SuppressWarnings("unchecked") + public void testIssue468a() throws Exception + { + Person1 p1 = new Person1("John"); + p1.setAccount(new Key<Account>(new Account("something", 42L))); + + // First: ensure we can serialize (pre 1.7 this failed) + ObjectMapper mapper = new ObjectMapper(); + String json = mapper.writeValueAsString(p1); + + // and then verify that results make sense + Map<String,Object> map = mapper.readValue(json, Map.class); + assertEquals("John", map.get("name")); + Object ob = map.get("account"); + assertNotNull(ob); + Map<String,Object> acct = (Map<String,Object>) ob; + Object idOb = acct.get("id"); + assertNotNull(idOb); + Map<String,Object> key = (Map<String,Object>) idOb; + assertEquals("something", key.get("name")); + assertEquals(Integer.valueOf(42), key.get("id")); + } + + @SuppressWarnings("unchecked") + public void testIssue468b() throws Exception + { + Person2 p2 = new Person2("John"); + List<Key<Account>> accounts = new ArrayList<Key<Account>>(); + accounts.add(new Key<Account>(new Account("a", 42L))); + accounts.add(new Key<Account>(new Account("b", 43L))); + accounts.add(new Key<Account>(new Account("c", 44L))); + p2.setAccounts(accounts); + + // serialize without error: + ObjectMapper mapper = new ObjectMapper(); + String json = mapper.writeValueAsString(p2); + + // then verify output + Map<String,Object> map = mapper.readValue(json, Map.class); + assertEquals("John", map.get("name")); + Object ob = map.get("accounts"); + assertNotNull(ob); + List<?> acctList = (List<?>) ob; + assertEquals(3, acctList.size()); + // ... might want to verify more, but for now that should suffice + } + + /** + * Issue [JACKSON-572] is about unbound type variables, usually resulting + * from inner classes of generic classes (like Sets). + */ + public void testUnboundIssue572() throws Exception + { + GenericBogusWrapper<Integer> list = new GenericBogusWrapper<Integer>(Integer.valueOf(7)); + String json = new ObjectMapper().writeValueAsString(list); + assertEquals("{\"wrapped\":{\"value\":7}}", json); + } +} +
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/ser/TestIgnoreProperties.java b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestIgnoreProperties.java new file mode 100644 index 0000000..62430fc --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestIgnoreProperties.java
@@ -0,0 +1,63 @@ +package org.codehaus.jackson.map.ser; + +import java.util.*; + +import org.codehaus.jackson.annotate.*; +import org.codehaus.jackson.map.*; + +public class TestIgnoreProperties + extends BaseMapTest +{ + /* + **************************************************************** + * Helper classes + **************************************************************** + */ + + @JsonIgnoreProperties({"b", "c"}) + static class IgnoreSome + { + public int a = 3; + public String b = "x"; + + public int getC() { return -6; } + public String getD() { return "abc"; } + } + + @SuppressWarnings("serial") + @JsonIgnoreProperties({"@class"}) + static class MyMap extends HashMap<String,String> { } + + /* + **************************************************************** + * Unit tests + **************************************************************** + */ + + public void testExplicitIgnoralWithBean() throws Exception + { + IgnoreSome value = new IgnoreSome(); + Map<String,Object> result = writeAndMap(value); + assertEquals(2, result.size()); + // verify that specified fields are ignored + assertFalse(result.containsKey("b")); + assertFalse(result.containsKey("c")); + // and that others are not + assertEquals(Integer.valueOf(value.a), result.get("a")); + assertEquals(value.getD(), result.get("d")); + } + + public void testExplicitIgnoralWithMap() throws Exception + { + // test simulating need to filter out metadata like class name + MyMap value = new MyMap(); + value.put("a", "b"); + value.put("@class", MyMap.class.getName()); + Map<String,Object> result = writeAndMap(value); + assertEquals(1, result.size()); + // verify that specified field is ignored + assertFalse(result.containsKey("@class")); + // and that others are not + assertEquals(value.get("a"), result.get("a")); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/ser/TestJSONP.java b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestJSONP.java new file mode 100644 index 0000000..19b9cb1 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestJSONP.java
@@ -0,0 +1,54 @@ +package org.codehaus.jackson.map.ser; + +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.type.TypeFactory; +import org.codehaus.jackson.map.util.JSONPObject; +import org.codehaus.jackson.type.JavaType; + +public class TestJSONP + extends BaseMapTest +{ + static class Base { + public String a; + } + static class Impl extends Base { + public String b; + + public Impl(String a, String b) { + this.a = a; + this.b = b; + } + } + + public void testSimpleScalars() throws Exception + { + ObjectMapper m = new ObjectMapper(); + assertEquals("callback(\"abc\")", + serializeAsString(m, new JSONPObject("callback", "abc"))); + assertEquals("calc(123)", + serializeAsString(m, new JSONPObject("calc", Integer.valueOf(123)))); + assertEquals("dummy(null)", + serializeAsString(m, new JSONPObject("dummy", null))); + } + + public void testSimpleBean() throws Exception + { + ObjectMapper m = new ObjectMapper(); + assertEquals("xxx({\"a\":\"123\",\"b\":\"456\"})", + serializeAsString(m, new JSONPObject("xxx", + new Impl("123", "456")))); + } + + /** + * Test to ensure that it is possible to force a static type for wrapped + * value. + */ + public void testWithType() throws Exception + { + ObjectMapper m = new ObjectMapper(); + Object ob = new Impl("abc", "def"); + JavaType type = TypeFactory.defaultInstance().uncheckedSimpleType(Base.class); + assertEquals("do({\"a\":\"abc\"})", + serializeAsString(m, new JSONPObject("do", ob, type))); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/ser/TestJacksonTypes.java b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestJacksonTypes.java new file mode 100644 index 0000000..1c9ed6d --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestJacksonTypes.java
@@ -0,0 +1,50 @@ +package org.codehaus.jackson.map.ser; + +import java.io.*; +import java.util.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.util.TokenBuffer; + +/** + * Unit tests for those Jackson types we want to ensure can be serialized. + */ +public class TestJacksonTypes + extends BaseMapTest +{ + public void testLocation() throws IOException + { + JsonLocation loc = new JsonLocation(new File("/tmp/test.json"), + -1, 100, 13); + ObjectMapper mapper = new ObjectMapper(); + Map<String,Object> result = writeAndMap(mapper, loc); + assertEquals(5, result.size()); + assertEquals("/tmp/test.json", result.get("sourceRef")); + assertEquals(Integer.valueOf(-1), result.get("charOffset")); + assertEquals(Integer.valueOf(-1), result.get("byteOffset")); + assertEquals(Integer.valueOf(100), result.get("lineNr")); + assertEquals(Integer.valueOf(13), result.get("columnNr")); + + } + + /** + * Verify that {@link TokenBuffer} can be properly serialized + * automatically, using the "standard" JSON sample document + * + * @since 1.5 + */ + public void testTokenBuffer() throws Exception + { + // First, copy events from known good source (StringReader) + JsonParser jp = createParserUsingReader(SAMPLE_DOC_JSON_SPEC); + TokenBuffer tb = new TokenBuffer(null); + while (jp.nextToken() != null) { + tb.copyCurrentEvent(jp); + } + // Then serialize as String + String str = serializeAsString(tb); + // and verify it looks ok + verifyJsonSpecSampleDoc(createParserUsingReader(str), true); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/ser/TestJdkTypes.java b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestJdkTypes.java new file mode 100644 index 0000000..4739fc5 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestJdkTypes.java
@@ -0,0 +1,79 @@ +package org.codehaus.jackson.map.ser; + +import java.io.*; +import java.net.InetAddress; +import java.nio.charset.Charset; +import java.util.*; +import java.util.regex.Pattern; + +import org.codehaus.jackson.map.*; + +/** + * Unit tests for JDK types not covered by other tests (i.e. things + * that are not Enums, Collections, Maps, or standard Date/Time types) + */ +public class TestJdkTypes + extends org.codehaus.jackson.map.BaseMapTest +{ + /** + * Unit test related to [JACKSON-155] + */ + public void testFile() throws IOException + { + /* Not sure if this gets translated differently on Windows, Mac? + * It'd be hard to make truly portable test tho... + */ + File f = new File("/tmp/foo.txt"); + String str = serializeAsString(new ObjectMapper(), f); + assertEquals("\""+f.getAbsolutePath()+"\"", str); + } + + public void testRegexps() throws IOException + { + final String PATTERN_STR = "\\s+([a-b]+)\\w?"; + Pattern p = Pattern.compile(PATTERN_STR); + Map<String,Object> input = new HashMap<String,Object>(); + input.put("p", p); + Map<String,Object> result = writeAndMap(input); + assertEquals(p.pattern(), result.get("p")); + } + + public void testCurrency() throws IOException + { + Currency usd = Currency.getInstance("USD"); + assertEquals(quote("USD"), new ObjectMapper().writeValueAsString(usd)); + } + + // @since 1.7 + public void testLocale() throws IOException + { + ObjectMapper mapper = new ObjectMapper(); + assertEquals(quote("en"), mapper.writeValueAsString(new Locale("en"))); + assertEquals(quote("es_ES"), mapper.writeValueAsString(new Locale("es", "ES"))); + assertEquals(quote("fi_FI_savo"), mapper.writeValueAsString(new Locale("FI", "fi", "savo"))); + } + + // [JACKSON-484] + public void testInetAddress() throws IOException + { + ObjectMapper mapper = new ObjectMapper(); + assertEquals(quote("127.0.0.1"), mapper.writeValueAsString(InetAddress.getByName("127.0.0.1"))); + assertEquals(quote("ning.com"), mapper.writeValueAsString(InetAddress.getByName("ning.com"))); + } + + // [JACKSON-597] + public void testClass() throws IOException + { + ObjectMapper mapper = new ObjectMapper(); + assertEquals(quote("java.lang.String"), mapper.writeValueAsString(String.class)); + assertEquals(quote("int"), mapper.writeValueAsString(Integer.TYPE)); + assertEquals(quote("boolean"), mapper.writeValueAsString(Boolean.TYPE)); + assertEquals(quote("void"), mapper.writeValueAsString(Void.TYPE)); + } + + // [JACKSON-789] + public void testCharset() throws IOException { + ObjectMapper mapper = new ObjectMapper(); + assertEquals(quote("UTF-8"), mapper.writeValueAsString(Charset.forName("UTF-8"))); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/ser/TestJsonSerialize3.java b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestJsonSerialize3.java new file mode 100644 index 0000000..ba90223 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestJsonSerialize3.java
@@ -0,0 +1,43 @@ +package org.codehaus.jackson.map.ser; + +import java.io.IOException; +import java.util.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.JsonSerialize; + +public class TestJsonSerialize3 extends BaseMapTest +{ + // [JACKSON-829] + static class FooToBarSerializer extends JsonSerializer<String> { + @Override + public void serialize(String value, JsonGenerator jgen, SerializerProvider provider) + throws IOException { + if ("foo".equals(value)) { + jgen.writeString("bar"); + } else { + jgen.writeString(value); + } + } + } + + static class MyObject { + @JsonSerialize(contentUsing = FooToBarSerializer.class) + List<String> list; + } + /* + /********************************************************** + /* Test methods + /********************************************************** + */ + + public void testCustomContentSerializer() throws Exception + { + ObjectMapper m = new ObjectMapper(); + MyObject object = new MyObject(); + object.list = Arrays.asList("foo"); + String json = m.writeValueAsString(object); + assertEquals("{\"list\":[\"bar\"]}", json); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/ser/TestMapSerialization.java b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestMapSerialization.java new file mode 100644 index 0000000..4f1d3c2 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestMapSerialization.java
@@ -0,0 +1,114 @@ +package org.codehaus.jackson.map.ser; + +import java.io.*; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.JsonSerialize; + +@SuppressWarnings("serial") +public class TestMapSerialization + extends BaseMapTest +{ + /* + /********************************************************** + /* Helper classes + /********************************************************** + */ + + /** + * Class needed for testing [JACKSON-220] + */ + @JsonSerialize(using=MapSerializer.class) + static class PseudoMap extends LinkedHashMap<String,String> + { + public PseudoMap(String... values) { + for (int i = 0, len = values.length; i < len; i += 2) { + put(values[i], values[i+1]); + } + } + } + + static class MapSerializer extends JsonSerializer<Map<String,String>> + { + @Override + public void serialize(Map<String,String> value, + JsonGenerator jgen, + SerializerProvider provider) + throws IOException + { + // just use standard Map.toString(), output as JSON String + jgen.writeString(value.toString()); + } + } + + // For [JACKSON-574] + static class DefaultKeySerializer extends JsonSerializer<Object> + { + @Override + public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider) throws IOException + { + jgen.writeFieldName("DEFAULT:"+value); + } + } + + /* + /********************************************************** + /* Test methods + /********************************************************** + */ + + // Test [JACKSON-220] + public void testMapSerializer() throws IOException + { + ObjectMapper m = new ObjectMapper(); + assertEquals("\"{a=b, c=d}\"", m.writeValueAsString(new PseudoMap("a", "b", "c", "d"))); + } + + // Test [JACKSON-314] + public void testMapNullSerialization() throws IOException + { + ObjectMapper m = new ObjectMapper(); + Map<String,String> map = new HashMap<String,String>(); + map.put("a", null); + // by default, should output null-valued entries: + assertEquals("{\"a\":null}", m.writeValueAsString(map)); + // but not if explicitly asked not to (note: config value is dynamic here) + m.configure(SerializationConfig.Feature.WRITE_NULL_MAP_VALUES, false); + assertEquals("{}", m.writeValueAsString(map)); + } + + // [JACKSON-499], problems with map entries, values + public void testMapKeyValueSerialization() throws IOException + { + ObjectMapper m = new ObjectMapper(); + Map<String,String> map = new HashMap<String,String>(); + map.put("a", "b"); + assertEquals("[\"a\"]", m.writeValueAsString(map.keySet())); + assertEquals("[\"b\"]", m.writeValueAsString(map.values())); + + // TreeMap has similar inner class(es): + map = new TreeMap<String,String>(); + map.put("c", "d"); + assertEquals("[\"c\"]", m.writeValueAsString(map.keySet())); + assertEquals("[\"d\"]", m.writeValueAsString(map.values())); + + // and for [JACKSON-533], same for concurrent maps + map = new ConcurrentHashMap<String,String>(); + map.put("e", "f"); + assertEquals("[\"e\"]", m.writeValueAsString(map.keySet())); + assertEquals("[\"f\"]", m.writeValueAsString(map.values())); + } + + // For [JACKSON-574] + public void testDefaultKeySerializer() throws IOException + { + ObjectMapper m = new ObjectMapper(); + m.getSerializerProvider().setDefaultKeySerializer(new DefaultKeySerializer()); + Map<String,String> map = new HashMap<String,String>(); + map.put("a", "b"); + assertEquals("{\"DEFAULT:a\":\"b\"}", m.writeValueAsString(map)); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/ser/TestNullProperties.java b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestNullProperties.java new file mode 100644 index 0000000..ba5eab6 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestNullProperties.java
@@ -0,0 +1,208 @@ +package org.codehaus.jackson.map.ser; + +import org.codehaus.jackson.map.BaseMapTest; + +import java.io.IOException; +import java.util.*; + +import org.codehaus.jackson.annotate.*; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.JsonSerialize; + +/** + * Unit tests for checking that alternative settings for + * {@link JsonSerialize#include} annotation property work + * as expected. + */ +@SuppressWarnings("deprecation") +public class TestNullProperties + extends BaseMapTest +{ + /* + /********************************************************** + /* Helper beans + /********************************************************** + */ + + static class SimpleBean + { + public String getA() { return "a"; } + public String getB() { return null; } + } + + @JsonWriteNullProperties(false) + static class LegacyNoNullsBean + { + public String getA() { return "a"; } + public String getB() { return null; } + } + + static class LegacyMethodBean + { + @JsonWriteNullProperties(false) + public String getB() { return null; } + } + + static class LegacyFieldBean + { + @JsonWriteNullProperties(false) + public String b; + } + + @JsonSerialize(include=JsonSerialize.Inclusion.ALWAYS) // just to ensure default + static class NoNullsBean + { + @JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) + public String getA() { return null; } + + public String getB() { return null; } + } + + @JsonSerialize(include=JsonSerialize.Inclusion.NON_DEFAULT) + static class NonDefaultBean + { + String _a = "a", _b = "b"; + + NonDefaultBean() { } + + public String getA() { return _a; } + public String getB() { return _b; } + } + + static class MixedBean + { + String _a = "a", _b = "b"; + + MixedBean() { } + + @JsonSerialize(include=JsonSerialize.Inclusion.NON_DEFAULT) + public String getA() { return _a; } + + @JsonSerialize(include=JsonSerialize.Inclusion.NON_NULL) + public String getB() { return _b; } + } + + // to ensure that default values work for collections as well + static class ListBean { + @JsonSerialize(include=JsonSerialize.Inclusion.NON_DEFAULT) + public List<String> strings = new ArrayList<String>(); + } + + @JsonSerialize(include=JsonSerialize.Inclusion.NON_DEFAULT) + static class ArrayBean { + public int[] ints = new int[] { 1, 2 }; + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + public void testGlobal() throws IOException + { + ObjectMapper m = new ObjectMapper(); + assertTrue(m.getSerializationConfig().isEnabled(SerializationConfig.Feature.WRITE_NULL_PROPERTIES)); + Map<String,Object> result = writeAndMap(m, new SimpleBean()); + assertEquals(2, result.size()); + assertEquals("a", result.get("a")); + assertNull(result.get("b")); + assertTrue(result.containsKey("b")); + + /* Important: MUST create a new ObjectMapper, will otherwise + * cache old serializer + */ + m = new ObjectMapper(); + m.configure(SerializationConfig.Feature.WRITE_NULL_PROPERTIES, false); + result = writeAndMap(m, new SimpleBean()); + assertEquals(1, result.size()); + assertEquals("a", result.get("a")); + assertNull(result.get("b")); + assertFalse(result.containsKey("b")); + } + + public void testNonNullByClass() throws IOException + { + ObjectMapper m = new ObjectMapper(); + Map<String,Object> result = writeAndMap(m, new NoNullsBean()); + assertEquals(1, result.size()); + assertFalse(result.containsKey("a")); + assertNull(result.get("a")); + assertTrue(result.containsKey("b")); + assertNull(result.get("b")); + } + + public void testNonDefaultByClass() throws IOException + { + ObjectMapper m = new ObjectMapper(); + NonDefaultBean bean = new NonDefaultBean(); + // need to change one of defaults + bean._a = "notA"; + Map<String,Object> result = writeAndMap(m, bean); + assertEquals(1, result.size()); + assertTrue(result.containsKey("a")); + assertEquals("notA", result.get("a")); + assertFalse(result.containsKey("b")); + assertNull(result.get("b")); + } + + public void testMixedMethod() throws IOException + { + ObjectMapper m = new ObjectMapper(); + + MixedBean bean = new MixedBean(); + bean._a = "xyz"; + bean._b = null; + Map<String,Object> result = writeAndMap(m, bean); + assertEquals(1, result.size()); + assertEquals("xyz", result.get("a")); + assertFalse(result.containsKey("b")); + + bean._a = "a"; + bean._b = "b"; + result = writeAndMap(m, bean); + assertEquals(1, result.size()); + assertEquals("b", result.get("b")); + assertFalse(result.containsKey("a")); + } + + public void testDefaultForEmptyList() throws IOException + { + ObjectMapper m = new ObjectMapper(); + assertEquals("{}", m.writeValueAsString(new ListBean())); + } + + // // // Tests for deprecated legacy annotations: + + public void testByClassLegacy() throws IOException + { + ObjectMapper m = new ObjectMapper(); + assertTrue(m.getSerializationConfig().isEnabled(SerializationConfig.Feature.WRITE_NULL_PROPERTIES)); + Map<String,Object> result = writeAndMap(m, new LegacyNoNullsBean()); + assertEquals(1, result.size()); + assertEquals("a", result.get("a")); + assertNull(result.get("b")); + assertFalse(result.containsKey("b")); + } + + public void testByMethodLegacy() throws IOException + { + ObjectMapper m = new ObjectMapper(); + Map<String,Object> result = writeAndMap(m, new LegacyMethodBean()); + assertEquals(0, result.size()); + } + + public void testByFieldLegacy() throws IOException + { + ObjectMapper m = new ObjectMapper(); + Map<String,Object> result = writeAndMap(m, new LegacyFieldBean()); + assertEquals(0, result.size()); + } + + // [JACKSON-531]: make NON_DEFAULT work for arrays too + public void testNonEmptyDefaultArray() throws IOException + { + ObjectMapper m = new ObjectMapper(); + assertEquals("{}", m.writeValueAsString(new ArrayBean())); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/ser/TestNullSerialization.java b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestNullSerialization.java new file mode 100644 index 0000000..4a3ca98 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestNullSerialization.java
@@ -0,0 +1,57 @@ +package org.codehaus.jackson.map.ser; + +import java.io.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.JsonSerialize.Inclusion; +import org.codehaus.jackson.map.introspect.JacksonAnnotationIntrospector; + +public class TestNullSerialization + extends BaseMapTest +{ + static class NullSerializer extends JsonSerializer<Object> + { + @Override + public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonProcessingException + { + jgen.writeString("foobar"); + } + } + + static class NullBean<T> { + public T value = null; + + public NullBean(T v) { value = v; } + } + + /* + /********************************************************** + /* Test methods + /********************************************************** + */ + + public void testSimple() throws Exception + { + assertEquals("null", new ObjectMapper().writeValueAsString(null)); + } + + public void testCustom() throws Exception + { + StdSerializerProvider sp = new StdSerializerProvider(); + sp.setNullValueSerializer(new NullSerializer()); + ObjectMapper m = new ObjectMapper(); + m.setSerializerProvider(sp); + assertEquals("\"foobar\"", m.writeValueAsString(null)); + } + + public void testDefaultNonNull() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.setAnnotationIntrospector(new JacksonAnnotationIntrospector()); + mapper.setSerializationInclusion(Inclusion.NON_NULL); + assertEquals("{\"value\":\"abc\"}", mapper.writeValueAsString(new NullBean<String>("abc"))); + assertEquals("{}", mapper.writeValueAsString(new NullBean<String>(null))); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/ser/TestObjectWriter.java b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestObjectWriter.java new file mode 100644 index 0000000..7dd0c7c --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestObjectWriter.java
@@ -0,0 +1,34 @@ +package org.codehaus.jackson.map.ser; + +import java.util.*; + +import org.codehaus.jackson.map.*; + +/** + * Unit tests for checking features added to {@link ObjectWriter}, such + * as adding of explicit pretty printer. + * + * @since 1.6 + */ +public class TestObjectWriter + extends BaseMapTest +{ + public void testPrettyPrinter() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + ObjectWriter writer = mapper.writer(); + HashMap<String, Integer> data = new HashMap<String,Integer>(); + data.put("a", 1); + + // default: no indentation + assertEquals("{\"a\":1}", writer.writeValueAsString(data)); + + // and then with standard + writer = writer.withDefaultPrettyPrinter(); + assertEquals("{\n \"a\" : 1\n}", writer.writeValueAsString(data)); + + // and finally, again without indentation + writer = writer.withPrettyPrinter(null); + assertEquals("{\"a\":1}", writer.writeValueAsString(data)); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/ser/TestRootType.java b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestRootType.java new file mode 100644 index 0000000..9a1416f --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestRootType.java
@@ -0,0 +1,188 @@ +package org.codehaus.jackson.map.ser; + +import java.io.StringWriter; +import java.util.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.annotate.JsonTypeInfo; +import org.codehaus.jackson.annotate.JsonTypeInfo.As; +import org.codehaus.jackson.annotate.JsonTypeInfo.Id; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.JsonRootName; +import org.codehaus.jackson.map.type.TypeFactory; +import org.codehaus.jackson.type.JavaType; + +/** + * Unit tests for verifying functioning of [JACKSON-195], ability to + * force specific root type for serialization (super type of value) + * + * @author tatu + * @since 1.5 + */ +public class TestRootType + extends BaseMapTest +{ + /* + /********************************************************** + /* Annotated helper classes + /********************************************************** + */ + + interface BaseInterface { + int getB(); + } + + static class BaseType + implements BaseInterface + { + public String a = "a"; + + @Override + public int getB() { return 3; } + } + + static class SubType extends BaseType { + public String a2 = "x"; + + public boolean getB2() { return true; } + } + + @JsonTypeInfo(use=Id.NAME, include=As.PROPERTY, property="beanClass") + public abstract static class BaseClass398 { } + + public static class TestClass398 extends BaseClass398 { + public String property = "aa"; + } + + @JsonRootName("root") + static class WithRootName { + public int a = 3; + } + + /* + /********************************************************** + /* Main tests + /********************************************************** + */ + + @SuppressWarnings("unchecked") + public void testSuperClass() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + SubType bean = new SubType(); + + // first, test with dynamically detected type + Map<String,Object> result = writeAndMap(mapper, bean); + assertEquals(4, result.size()); + assertEquals("a", result.get("a")); + assertEquals(Integer.valueOf(3), result.get("b")); + assertEquals("x", result.get("a2")); + assertEquals(Boolean.TRUE, result.get("b2")); + + // and then using specified typed writer + ObjectWriter w = mapper.writerWithType(BaseType.class); + String json = w.writeValueAsString(bean); + result = (Map<String,Object>)mapper.readValue(json, Map.class); + assertEquals(2, result.size()); + assertEquals("a", result.get("a")); + assertEquals(Integer.valueOf(3), result.get("b")); + } + + public void testSuperInterface() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + SubType bean = new SubType(); + + // let's constrain by interface: + ObjectWriter w = mapper.writerWithType(BaseInterface.class); + String json = w.writeValueAsString(bean); + @SuppressWarnings("unchecked") + Map<String,Object> result = mapper.readValue(json, Map.class); + assertEquals(1, result.size()); + assertEquals(Integer.valueOf(3), result.get("b")); + } + + public void testInArray() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + // must force static typing, otherwise won't matter a lot + mapper.configure(SerializationConfig.Feature.USE_STATIC_TYPING, true); + SubType[] ob = new SubType[] { new SubType() }; + String json = mapper.writerWithType(BaseInterface[].class).writeValueAsString(ob); + // should propagate interface type through due to root declaration; static typing + assertEquals("[{\"b\":3}]", json); + } + + /** + * Unit test to ensure that proper exception is thrown if declared + * root type is not compatible with given value instance. + */ + public void testIncompatibleRootType() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + SubType bean = new SubType(); + + // and then let's try using incompatible type + ObjectWriter w = mapper.writerWithType(HashMap.class); + try { + w.writeValueAsString(bean); + fail("Should have failed due to incompatible type"); + } catch (JsonProcessingException e) { + verifyException(e, "Incompatible types"); + } + } + + /** + * Unit test to verify [JACKSON-398] + */ + public void testJackson398() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + JavaType collectionType = TypeFactory.defaultInstance().constructCollectionType(ArrayList.class, BaseClass398.class); + List<TestClass398> typedList = new ArrayList<TestClass398>(); + typedList.add(new TestClass398()); + + final String EXP = "[{\"beanClass\":\"TestRootType$TestClass398\",\"property\":\"aa\"}]"; + + // First simplest way: + String json = mapper.writerWithType(collectionType).writeValueAsString(typedList); + assertEquals(EXP, json); + + StringWriter out = new StringWriter(); + JsonFactory f = new JsonFactory(); + mapper.writerWithType(collectionType).writeValue(f.createJsonGenerator(out), typedList); + + assertEquals(EXP, out.toString()); + } + + // Test to verify [JACKSON-163] + public void testRootWrapping() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.configure(SerializationConfig.Feature.WRAP_ROOT_VALUE, true); + String json = mapper.writeValueAsString(new StringWrapper("abc")); + assertEquals("{\"StringWrapper\":{\"str\":\"abc\"}}", json); + } + + /** + * Test to verify that there is support for specifying root type as primitive, + * even if wrapper value is passed (there is no way to pass primitive values as + * Objects); this to support frameworks that may pass unprocessed + * {@link java.lang.reflect.Type} from field or method. + */ + public void testIssue456WrapperPart() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + assertEquals("123", mapper.writerWithType(Integer.TYPE).writeValueAsString(Integer.valueOf(123))); + assertEquals("456", mapper.writerWithType(Long.TYPE).writeValueAsString(Long.valueOf(456L))); + } + + // [JACKSON-630] also, allow annotation to define root name + public void testRootNameAnnotation() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.configure(SerializationConfig.Feature.WRAP_ROOT_VALUE, true); + String json = mapper.writeValueAsString(new WithRootName()); + assertEquals("{\"root\":{\"a\":3}}", json); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/ser/TestSerializationOrder.java b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestSerializationOrder.java new file mode 100644 index 0000000..bf23ba5 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestSerializationOrder.java
@@ -0,0 +1,120 @@ +package org.codehaus.jackson.map.ser; + +import org.codehaus.jackson.map.BaseMapTest; + +import org.codehaus.jackson.annotate.*; +import org.codehaus.jackson.map.*; + +/** + * Unit tests for verifying that constraints on ordering of serialized + * properties are held. + */ +public class TestSerializationOrder + extends BaseMapTest +{ + /* + /********************************************* + /* Annotated helper classes + /********************************************* + */ + + static class BeanWithCreator + { + public int a; + public int b; + public int c; + + @JsonCreator public BeanWithCreator(@JsonProperty("c") int c, @JsonProperty("a") int a) { + this.a = a; + this.c = c; + } + } + + @JsonPropertyOrder({"c", "a", "b"}) + static class BeanWithOrder + { + public int d, b, a, c; + + public BeanWithOrder(int a, int b, int c, int d) { + this.a = a; + this.b = b; + this.c = c; + this.d = d; + } + } + + @JsonPropertyOrder(value={"d"}, alphabetic=true) + static class SubBeanWithOrder extends BeanWithOrder + { + public SubBeanWithOrder(int a, int b, int c, int d) { + super(a, b, c, d); + } + } + + @JsonPropertyOrder({"b", "a", + // note: including non-existant properties is fine (has no effect, but not an error) + "foobar", + "c" + }) + static class OrderMixIn { } + + @JsonPropertyOrder(value={"a","b","x","z"}) + static class BeanFor268 { // testing [JACKSON-268] + @JsonProperty("a") public String xA = "a"; + @JsonProperty("z") public String aZ = "z"; + @JsonProperty("b") public String xB() { return "b"; } + @JsonProperty("x") public String aX() { return "x"; } + } + + static class BeanFor459 { + public int d = 4; + public int c = 3; + public int b = 2; + public int a = 1; + } + + /* + /********************************************* + /* Unit tests + /********************************************* + */ + + // Test for [JACKSON-170] + public void testImplicitOrderByCreator() throws Exception + { + assertEquals("{\"c\":1,\"a\":2,\"b\":0}", serializeAsString(new BeanWithCreator(1, 2))); + } + + public void testExplicitOrder() throws Exception + { + assertEquals("{\"c\":3,\"a\":1,\"b\":2,\"d\":4}", serializeAsString(new BeanWithOrder(1, 2, 3, 4))); + } + + public void testAlphabeticOrder() throws Exception + { + assertEquals("{\"d\":4,\"a\":1,\"b\":2,\"c\":3}", serializeAsString(new SubBeanWithOrder(1, 2, 3, 4))); + } + + + public void testOrderWithMixins() throws Exception + { + ObjectMapper m = new ObjectMapper(); + m.getSerializationConfig().addMixInAnnotations(BeanWithOrder.class, OrderMixIn.class); + assertEquals("{\"b\":2,\"a\":1,\"c\":3,\"d\":4}", serializeAsString(m, new BeanWithOrder(1, 2, 3, 4))); + } + + // Test for [JACKSON-268] + public void testOrderWrt268() throws Exception + { + assertEquals("{\"a\":\"a\",\"b\":\"b\",\"x\":\"x\",\"z\":\"z\"}", + serializeAsString(new BeanFor268())); + } + + // Test for [JACKSON-459] + public void testOrderWithFeature() throws Exception + { + ObjectMapper m = new ObjectMapper(); + m.configure(SerializationConfig.Feature.SORT_PROPERTIES_ALPHABETICALLY, true); + assertEquals("{\"a\":1,\"b\":2,\"c\":3,\"d\":4}", serializeAsString(m, new BeanFor459())); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/ser/TestSerializerProvider.java b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestSerializerProvider.java new file mode 100644 index 0000000..1e66dce --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestSerializerProvider.java
@@ -0,0 +1,32 @@ +package org.codehaus.jackson.map.ser; + +import org.codehaus.jackson.map.*; + +public class TestSerializerProvider + extends org.codehaus.jackson.map.BaseMapTest +{ + static class MyBean { + public int getX() { return 3; } + } + + public void testFindExplicit() throws JsonMappingException + { + ObjectMapper mapper = new ObjectMapper(); + SerializationConfig config = mapper.getSerializationConfig(); + SerializerFactory f = new BeanSerializerFactory(null); + StdSerializerProvider prov = new StdSerializerProvider().createInstance(config, f); + + // Should have working default key and null key serializers + assertNotNull(prov.findKeySerializer(null, null)); + assertNotNull(prov.getNullKeySerializer()); + // as well as 'unknown type' one (throws exception) + assertNotNull(prov.getUnknownTypeSerializer(getClass())); + + assertTrue(prov.hasSerializerFor(config, String.class, f)); + // call twice to verify it'll be cached (second code path) + assertTrue(prov.hasSerializerFor(config, String.class, f)); + + assertTrue(prov.hasSerializerFor(config, MyBean.class, f)); + assertTrue(prov.hasSerializerFor(config, MyBean.class, f)); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/ser/TestSimpleAtomicTypes.java b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestSimpleAtomicTypes.java new file mode 100644 index 0000000..9415c28 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestSimpleAtomicTypes.java
@@ -0,0 +1,41 @@ +package org.codehaus.jackson.map.ser; + +import java.util.concurrent.atomic.*; + +import org.codehaus.jackson.map.BaseMapTest; +import org.codehaus.jackson.map.ObjectMapper; + +/** + * Unit tests for verifying serialization of simple basic non-structured + * types; primitives (and/or their wrappers), Strings. + */ +public class TestSimpleAtomicTypes + extends BaseMapTest +{ + public void testAtomicBoolean() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + assertEquals("true", serializeAsString(mapper, new AtomicBoolean(true))); + assertEquals("false", serializeAsString(mapper, new AtomicBoolean(false))); + } + + public void testAtomicInteger() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + assertEquals("1", serializeAsString(mapper, new AtomicInteger(1))); + assertEquals("-9", serializeAsString(mapper, new AtomicInteger(-9))); + } + + public void testAtomicLong() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + assertEquals("0", serializeAsString(mapper, new AtomicLong(0))); + } + + public void testAtomicReference() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + String[] strs = new String[] { "abc" }; + assertEquals("[\"abc\"]", serializeAsString(mapper, new AtomicReference<String[]>(strs))); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/ser/TestSimpleTypes.java b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestSimpleTypes.java new file mode 100644 index 0000000..9881757 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestSimpleTypes.java
@@ -0,0 +1,119 @@ +package org.codehaus.jackson.map.ser; + +import java.math.BigInteger; + +import org.codehaus.jackson.map.BaseMapTest; +import org.codehaus.jackson.map.ObjectMapper; + +import static org.junit.Assert.*; + +/** + * Unit tests for verifying serialization of simple basic non-structured + * types; primitives (and/or their wrappers), Strings. + */ +public class TestSimpleTypes + extends BaseMapTest +{ + public void testBoolean() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + assertEquals("true", serializeAsString(mapper, Boolean.TRUE)); + assertEquals("false", serializeAsString(mapper, Boolean.FALSE)); + } + + public void testBooleanArray() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + assertEquals("[true,false]", serializeAsString(mapper, new boolean[] { true, false} )); + assertEquals("[true,false]", serializeAsString(mapper, new Boolean[] { Boolean.TRUE, Boolean.FALSE} )); + } + + public void testByteArray() throws Exception + { + byte[] data = { 1, 17, -3, 127, -128 }; + Byte[] data2 = new Byte[data.length]; + for (int i = 0; i < data.length; ++i) { + data2[i] = data[i]; // auto-boxing + } + ObjectMapper mapper = new ObjectMapper(); + // For this we need to deserialize, to get base64 codec + String str1 = serializeAsString(mapper, data); + String str2 = serializeAsString(mapper, data2); + assertArrayEquals(data, mapper.readValue(str1, byte[].class)); + assertArrayEquals(data2, mapper.readValue(str2, Byte[].class)); + } + + public void testShortArray() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + assertEquals("[0,1]", serializeAsString(mapper, new short[] { 0, 1 })); + assertEquals("[2,3]", serializeAsString(mapper, new Short[] { 2, 3 })); + } + + public void testIntArray() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + assertEquals("[0,-3]", serializeAsString(mapper, new int[] { 0, -3 })); + assertEquals("[13,9]", serializeAsString(mapper, new Integer[] { 13, 9 })); + } + + /* Note: dealing with floating-point values is tricky; not sure if + * we can really use equality tests here... JDK does have decent + * conversions though, to retain accuracy and round-trippability. + * But still... + */ + public void testFloat() throws Exception + { + double[] values = new double[] { + 0.0, 1.0, 0.1, -37.01, 999.99, 0.3, 33.3, Double.NaN, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY + }; + ObjectMapper mapper = new ObjectMapper(); + + for (double d : values) { + float f = (float) d; + String expected = String.valueOf(f); + if (Float.isNaN(f) || Float.isInfinite(f)) { + expected = "\""+expected+"\""; + } + assertEquals(expected,serializeAsString(mapper, Float.valueOf(f))); + } + } + + public void testDouble() throws Exception + { + double[] values = new double[] { + 0.0, 1.0, 0.1, -37.01, 999.99, 0.3, 33.3, Double.NaN, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY + }; + ObjectMapper mapper = new ObjectMapper(); + + for (double d : values) { + String expected = String.valueOf(d); + if (Double.isNaN(d) || Double.isInfinite(d)) { + expected = "\""+d+"\""; + } + assertEquals(expected,serializeAsString(mapper, Double.valueOf(d))); + } + } + + public void testBigInteger() throws Exception + { + BigInteger[] values = new BigInteger[] { + BigInteger.ONE, BigInteger.TEN, BigInteger.ZERO, + BigInteger.valueOf(1234567890L), + new BigInteger("123456789012345678901234568"), + new BigInteger("-1250000124326904597090347547457") + }; + ObjectMapper mapper = new ObjectMapper(); + + for (BigInteger value : values) { + String expected = value.toString(); + assertEquals(expected,serializeAsString(mapper, value)); + } + } + + public void testClass() throws Exception + { + String result = serializeAsString(java.util.List.class); + assertEquals("\"java.util.List\"", result); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/ser/TestStatics.java b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestStatics.java new file mode 100644 index 0000000..358caa4 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestStatics.java
@@ -0,0 +1,64 @@ +package org.codehaus.jackson.map.ser; + +import org.codehaus.jackson.map.BaseMapTest; + +import java.util.*; + +import org.codehaus.jackson.annotate.*; +import org.codehaus.jackson.map.*; + +/** + * This unit test suite verifies that static fields and methods are + * ignored wrt serialization + */ +public class TestStatics + extends BaseMapTest +{ + /* + /********************************************************** + /* Annotated helper classes + /********************************************************** + */ + + final static class FieldBean + { + public int x = 1; + + public static int y = 2; + + // not even @JsonProperty should make statics usable... + @JsonProperty public static int z = 3; + } + + final static class GetterBean + { + public int getX() { return 3; } + + public static int getA() { return -3; } + + // not even @JsonProperty should make statics usable... + @JsonProperty public static int getFoo() { return 123; } + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + public void testStaticFields() throws Exception + { + ObjectMapper m = new ObjectMapper(); + Map<String,Object> result = writeAndMap(m, new FieldBean()); + assertEquals(1, result.size()); + assertEquals(Integer.valueOf(1), result.get("x")); + } + + public void testStaticMethods() throws Exception + { + ObjectMapper m = new ObjectMapper(); + Map<String,Object> result = writeAndMap(m, new GetterBean()); + assertEquals(1, result.size()); + assertEquals(Integer.valueOf(3), result.get("x")); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/ser/TestTreeSerialization.java b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestTreeSerialization.java new file mode 100644 index 0000000..c44c8ff --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestTreeSerialization.java
@@ -0,0 +1,112 @@ +package org.codehaus.jackson.map.ser; + +import org.codehaus.jackson.map.BaseMapTest; + +import java.io.*; +import java.util.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.node.*; + +/** + * This unit test suite tries to verify that JsonNode-based trees + * can be serialized as expected + */ +public class TestTreeSerialization + extends BaseMapTest +{ + final static class Bean { + public String getX() { return "y"; } + public int getY() { return 13; } + } + + @SuppressWarnings("unchecked") + public void testSimpleViaObjectMapper() + throws IOException + { + ObjectMapper mapper = new ObjectMapper(); + // also need tree mapper to construct tree to serialize + ObjectNode n = mapper.getNodeFactory().objectNode(); + n.put("number", 15); + n.put("string", "abc"); + ObjectNode n2 = n.putObject("ob"); + n2.putArray("arr"); + StringWriter sw = new StringWriter(); + JsonGenerator jg = mapper.getJsonFactory().createJsonGenerator(sw); + mapper.writeTree(jg, n); + + Map<String,Object> result = (Map<String,Object>) mapper.readValue(sw.toString(), Map.class); + + assertEquals(3, result.size()); + assertEquals("abc", result.get("string")); + assertEquals(Integer.valueOf(15), result.get("number")); + Map<String,Object> ob = (Map<String,Object>) result.get("ob"); + assertEquals(1, ob.size()); + List<Object> list = (List<Object>) ob.get("arr"); + assertEquals(0, list.size()); + } + + /** + * Simple test to verify that POJONodes (JsonNode wrapper around + * any old Java object) work with serialization + */ + @SuppressWarnings("unchecked") + public void testPOJOString() + throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + // also need tree mapper to construct tree to serialize + ObjectNode n = mapper.getNodeFactory().objectNode(); + n.put("pojo", mapper.getNodeFactory().POJONode("abc")); + StringWriter sw = new StringWriter(); + JsonGenerator jg = mapper.getJsonFactory().createJsonGenerator(sw); + mapper.writeTree(jg, n); + Map<String,Object> result = (Map<String,Object>) mapper.readValue(sw.toString(), Map.class); + assertEquals(1, result.size()); + assertEquals("abc", result.get("pojo")); + } + + @SuppressWarnings("unchecked") + public void testPOJOIntArray() + throws IOException + { + ObjectMapper mapper = new ObjectMapper(); + ObjectNode n = mapper.getNodeFactory().objectNode(); + n.put("pojo", mapper.getNodeFactory().POJONode(new int[] { 1, 2, 3 })); + StringWriter sw = new StringWriter(); + JsonGenerator jg = mapper.getJsonFactory().createJsonGenerator(sw); + mapper.writeTree(jg, n); + + Map<String,Object> result = (Map<String,Object>) mapper.readValue(sw.toString(), Map.class); + + assertEquals(1, result.size()); + // int array becomes a list when mapped to general Object: + List<Object> list = (List<Object>) result.get("pojo"); + assertEquals(3, list.size()); + for (int i = 0; i < 3; ++i) { + assertEquals(Integer.valueOf(i+1), list.get(i)); + } + } + + @SuppressWarnings("unchecked") + public void testPOJOBean() + throws IOException + { + ObjectMapper mapper = new ObjectMapper(); + // also need tree mapper to construct tree to serialize + ObjectNode n = mapper.getNodeFactory().objectNode(); + n.put("pojo", mapper.getNodeFactory().POJONode(new Bean())); + StringWriter sw = new StringWriter(); + JsonGenerator jg = mapper.getJsonFactory().createJsonGenerator(sw); + mapper.writeTree(jg, n); + + Map<String,Object> result = (Map<String,Object>) mapper.readValue(sw.toString(), Map.class); + + assertEquals(1, result.size()); + Map<String,Object> bean = (Map<String,Object>) result.get("pojo"); + assertEquals(2, bean.size()); + assertEquals("y", bean.get("x")); + assertEquals(Integer.valueOf(13), bean.get("y")); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/ser/TestViews.java b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestViews.java new file mode 100644 index 0000000..c9aaf04 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestViews.java
@@ -0,0 +1,169 @@ +package org.codehaus.jackson.map.ser; + +import org.codehaus.jackson.map.BaseMapTest; + +import java.io.*; +import java.util.*; + +import org.codehaus.jackson.annotate.*; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.JsonView; + +/** + * Unit tests for verifying JSON view functionality: ability to declaratively + * suppress subset of properties from being serialized. + */ +public class TestViews + extends BaseMapTest +{ + /* + /********************************************************** + /* Helper types + /********************************************************** + */ + + // Classes that represent views + static class ViewA { } + static class ViewAA extends ViewA { } + static class ViewB { } + static class ViewBB extends ViewB { } + + static class Bean + { + @JsonView(ViewA.class) + public String a = "1"; + + @JsonView({ViewAA.class, ViewB.class}) + public String aa = "2"; + + @JsonView(ViewB.class) + public String getB() { return "3"; } + } + + /** + * Bean with mix of explicitly annotated + * properties, and implicit ones that may or may + * not be included in views. + */ + static class MixedBean + { + @JsonView(ViewA.class) + public String a = "1"; + + public String getB() { return "2"; } + } + + /** + * As indicated by [JACKSON-261], @JsonView should imply + * that associated element (method, field) is to be considered + * a property + */ + static class ImplicitBean { + @SuppressWarnings("unused") + @JsonView(ViewA.class) + private int a = 1; + } + + static class VisibilityBean { + @JsonProperty protected String id = "id"; + + @JsonView(ViewA.class) + public String value = "x"; + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + @SuppressWarnings("unchecked") + public void testSimple() throws IOException + { + StringWriter sw = new StringWriter(); + ObjectMapper mapper = new ObjectMapper(); + // Ok, first, using no view whatsoever; all 3 + Bean bean = new Bean(); + Map<String,Object> map = writeAndMap(mapper, bean); + assertEquals(3, map.size()); + + // Then with "ViewA", just one property + sw = new StringWriter(); + mapper.writerWithView(ViewA.class).writeValue(sw, bean); + map = mapper.readValue(sw.toString(), Map.class); + assertEquals(1, map.size()); + assertEquals("1", map.get("a")); + + // "ViewAA", 2 properties + sw = new StringWriter(); + mapper.writerWithView(ViewAA.class).writeValue(sw, bean); + map = mapper.readValue(sw.toString(), Map.class); + assertEquals(2, map.size()); + assertEquals("1", map.get("a")); + assertEquals("2", map.get("aa")); + + // "ViewB", 2 prop2 + String json = mapper.writerWithView(ViewB.class).writeValueAsString(bean); + map = mapper.readValue(json, Map.class); + assertEquals(2, map.size()); + assertEquals("2", map.get("aa")); + assertEquals("3", map.get("b")); + + // and "ViewBB", 2 as well + json = mapper.writerWithView(ViewBB.class).writeValueAsString(bean); + map = mapper.readValue(json, Map.class); + assertEquals(2, map.size()); + assertEquals("2", map.get("aa")); + assertEquals("3", map.get("b")); + } + + /** + * Unit test to verify implementation of [JACKSON-232], to + * allow "opt-in" handling for JSON Views: that is, that + * default for properties is to exclude unless included in + * a view. + */ + @SuppressWarnings("unchecked") + public void testDefaultExclusion() throws IOException + { + MixedBean bean = new MixedBean(); + StringWriter sw = new StringWriter(); + + ObjectMapper mapper = new ObjectMapper(); + // default setting: both fields will get included + mapper.writerWithView(ViewA.class).writeValue(sw, bean); + Map<String,Object> map = mapper.readValue(sw.toString(), Map.class); + assertEquals(2, map.size()); + assertEquals("1", map.get("a")); + assertEquals("2", map.get("b")); + + // but can also change (but not necessarily on the fly...) + mapper = new ObjectMapper(); + mapper.configure(SerializationConfig.Feature.DEFAULT_VIEW_INCLUSION, false); + // with this setting, only explicit inclusions count: + String json = mapper.writerWithView(ViewA.class).writeValueAsString(bean); + map = mapper.readValue(json, Map.class); + assertEquals(1, map.size()); + assertEquals("1", map.get("a")); + assertNull(map.get("b")); + } + + /** + * As per [JACKSON-261], @JsonView annotation should imply that associated + * method/field does indicate a property. + */ + public void testImplicitAutoDetection() throws Exception + { + assertEquals("{\"a\":1}", serializeAsString(new ImplicitBean())); + } + + public void testVisibility() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + VisibilityBean bean = new VisibilityBean(); + // Without view setting, should only see "id" + String json = mapper.writerWithView(Object.class).writeValueAsString(bean); + //json = mapper.writeValueAsString(bean); + assertEquals("{\"id\":\"id\"}", json); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/ser/TestViews2.java b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestViews2.java new file mode 100644 index 0000000..1ef30ac --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/ser/TestViews2.java
@@ -0,0 +1,165 @@ +package org.codehaus.jackson.map.ser; + +import java.io.*; + +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.*; + +public class TestViews2 extends BaseMapTest +{ + + /* + /************************************************************************ + /* Tests + /************************************************************************ + */ + + public void testDataBindingUsage( ) throws Exception + { + ObjectMapper objectMapper = createObjectMapper( null ); + String result = serializeWithObjectMapper(new ComplexTestData( ), Views.View.class, objectMapper ); + assertEquals(-1, result.indexOf( "nameHidden" )); + } + + public void testDataBindingUsageWithoutView( ) throws Exception + { + ObjectMapper objectMapper = createObjectMapper( null ); + String json = serializeWithObjectMapper(new ComplexTestData( ), null, objectMapper); + assertTrue(json.indexOf( "nameHidden" ) > 0); + } + + /* + /************************************************************************ + /* Helper methods + /************************************************************************ + */ + + @SuppressWarnings("deprecation") + private ObjectMapper createObjectMapper(Class<?> viewClass) + { + ObjectMapper objectMapper = new ObjectMapper( ); + objectMapper.configure( SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS, false ); + objectMapper.getSerializationConfig( ).setSerializationInclusion(JsonSerialize.Inclusion.NON_NULL ); + objectMapper.configure( SerializationConfig.Feature.DEFAULT_VIEW_INCLUSION, false ); +// objectMapper.getSerializationConfig( ).disable( SerializationConfig.Feature.DEFAULT_VIEW_INCLUSION ); +// objectMapper.getSerializationConfig( ).setSerializationView( viewClass ); + return objectMapper; + } + + + @SuppressWarnings("deprecation") + private String serializeWithObjectMapper(Object object, Class<? extends Views.View> view, ObjectMapper objectMapper ) + throws IOException + { + objectMapper.getSerializationConfig( ).setSerializationView( view ); + return objectMapper.writeValueAsString(object ); + } + + /* + /************************************************************************ + /* Helper classes + /************************************************************************ + */ + + static class Views + { + public interface View { } + public interface ExtendedView extends View { } + } + + static class ComplexTestData + { + String nameNull = null; + + String nameComplex = "complexValue"; + + String nameComplexHidden = "nameComplexHiddenValue"; + + SimpleTestData testData = new SimpleTestData( ); + + SimpleTestData[] testDataArray = new SimpleTestData[] { new SimpleTestData( ), null }; + + @JsonView( Views.View.class ) + public String getNameNull() + { + return nameNull; + } + + public void setNameNull( String nameNull ) + { + this.nameNull = nameNull; + } + + @JsonView( Views.View.class ) + public String getNameComplex() + { + return nameComplex; + } + + public void setNameComplex( String nameComplex ) + { + this.nameComplex = nameComplex; + } + + public String getNameComplexHidden() + { + return nameComplexHidden; + } + + public void setNameComplexHidden( String nameComplexHidden ) + { + this.nameComplexHidden = nameComplexHidden; + } + + @JsonView( Views.View.class ) + public SimpleTestData getTestData() + { + return testData; + } + + public void setTestData( SimpleTestData testData ) + { + this.testData = testData; + } + + @JsonView( Views.View.class ) + public SimpleTestData[] getTestDataArray() + { + return testDataArray; + } + + public void setTestDataArray( SimpleTestData[] testDataArray ) + { + this.testDataArray = testDataArray; + } + } + + static class SimpleTestData + { + String name = "shown"; + + String nameHidden = "hidden"; + + @JsonView( Views.View.class ) + public String getName() + { + return name; + } + + public void setName( String name ) + { + this.name = name; + } + + public String getNameHidden( ) + { + return nameHidden; + } + + public void setNameHidden( String nameHidden ) + { + this.nameHidden = nameHidden; + } + } + +} \ No newline at end of file
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/struct/TestUnwrapping.java b/1.9.10/src/test/org/codehaus/jackson/map/struct/TestUnwrapping.java new file mode 100644 index 0000000..fbcf0e4 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/struct/TestUnwrapping.java
@@ -0,0 +1,150 @@ +package org.codehaus.jackson.map.struct; + +import org.codehaus.jackson.annotate.*; +import org.codehaus.jackson.map.*; + +/** + * Unit tests for verifying [JACKSON-132] implementation. + */ +public class TestUnwrapping extends BaseMapTest +{ + static class Unwrapping { + public String name; + @JsonUnwrapped + public Location location; + + public Unwrapping() { } + public Unwrapping(String str, int x, int y) { + name = str; + location = new Location(x, y); + } + } + + static class UnwrappingWithCreator { + public String name; + + @JsonUnwrapped + public Location location; + + @JsonCreator + public UnwrappingWithCreator(@JsonProperty("name") String n) { + name = n; + } + } + + static class Location { + public int x; + public int y; + + public Location() { } + public Location(int x, int y) { + this.x = x; + this.y = y; + } + } + + // Class with two unwrapped properties + static class TwoUnwrappedProperties { + @JsonUnwrapped + public Location location; + @JsonUnwrapped + public Name name; + + public TwoUnwrappedProperties() { } + } + + static class Name { + public String first, last; + } + + static class DeepUnwrapping + { + @JsonUnwrapped + public Unwrapping unwrapped; + + public DeepUnwrapping() { } + public DeepUnwrapping(String str, int x, int y) { + unwrapped = new Unwrapping(str, x, y); + } + } + + /* + /********************************************************** + /* Tests, serialization + /********************************************************** + */ + + public void testSimpleUnwrappingSerialize() throws Exception + { + ObjectMapper m = new ObjectMapper(); + assertEquals("{\"name\":\"Tatu\",\"x\":1,\"y\":2}", + m.writeValueAsString(new Unwrapping("Tatu", 1, 2))); + } + + public void testDeepUnwrappingSerialize() throws Exception + { + ObjectMapper m = new ObjectMapper(); + assertEquals("{\"name\":\"Tatu\",\"x\":1,\"y\":2}", + m.writeValueAsString(new DeepUnwrapping("Tatu", 1, 2))); + } + + /* + /********************************************************** + /* Tests, deserialization + /********************************************************** + */ + + public void testSimpleUnwrappedDeserialize() throws Exception + { + ObjectMapper m = new ObjectMapper(); + Unwrapping bean = m.readValue("{\"name\":\"Tatu\",\"y\":7,\"x\":-13}", + Unwrapping.class); + assertEquals("Tatu", bean.name); + Location loc = bean.location; + assertNotNull(loc); + assertEquals(-13, loc.x); + assertEquals(7, loc.y); + } + + public void testDoubleUnwrapping() throws Exception + { + ObjectMapper m = new ObjectMapper(); + TwoUnwrappedProperties bean = m.readValue("{\"first\":\"Joe\",\"y\":7,\"last\":\"Smith\",\"x\":-13}", + TwoUnwrappedProperties.class); + Location loc = bean.location; + assertNotNull(loc); + assertEquals(-13, loc.x); + assertEquals(7, loc.y); + Name name = bean.name; + assertNotNull(name); + assertEquals("Joe", name.first); + assertEquals("Smith", name.last); + } + + public void testDeepUnwrapping() throws Exception + { + ObjectMapper m = new ObjectMapper(); + DeepUnwrapping bean = m.readValue("{\"x\":3,\"name\":\"Bob\",\"y\":27}", + DeepUnwrapping.class); + Unwrapping uw = bean.unwrapped; + assertNotNull(uw); + assertEquals("Bob", uw.name); + Location loc = uw.location; + assertNotNull(loc); + assertEquals(3, loc.x); + assertEquals(27, loc.y); + } + + public void testUnwrappedDeserializeWithCreator() throws Exception + { + ObjectMapper m = new ObjectMapper(); + UnwrappingWithCreator bean = m.readValue("{\"x\":1,\"y\":2,\"name\":\"Tatu\"}", + UnwrappingWithCreator.class); + assertEquals("Tatu", bean.name); + Location loc = bean.location; + assertNotNull(loc); + assertEquals(1, loc.x); + assertEquals(2, loc.y); + } + +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/tree/TestTreeDeserialization.java b/1.9.10/src/test/org/codehaus/jackson/map/tree/TestTreeDeserialization.java new file mode 100644 index 0000000..96bab1d --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/tree/TestTreeDeserialization.java
@@ -0,0 +1,82 @@ +package org.codehaus.jackson.map.tree; + +import org.codehaus.jackson.map.BaseMapTest; + +import java.io.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.node.*; + +/** + * This unit test suite tries to verify that JsonNode-based trees + * can be deserialized as expected. + */ +public class TestTreeDeserialization + extends BaseMapTest +{ + final static class Bean { + int _x; + JsonNode _node; + + public void setX(int x) { _x = x; } + public void setNode(JsonNode n) { _node = n; } + } + + /** + * This test checks that is possible to mix "regular" Java objects + * and JsonNode. + */ + public void testMixed() throws IOException + { + ObjectMapper om = new ObjectMapper(); + String JSON = "{\"node\" : { \"a\" : 3 }, \"x\" : 9 }"; + Bean bean = om.readValue(JSON, Bean.class); + + assertEquals(9, bean._x); + JsonNode n = bean._node; + assertNotNull(n); + assertEquals(1, n.size()); + ObjectNode on = (ObjectNode) n; + assertEquals(3, on.get("a").getIntValue()); + } + + /// Verifying [JACKSON-143] + public void testArrayNodeEquality() + { + ArrayNode n1 = new ArrayNode(null); + ArrayNode n2 = new ArrayNode(null); + + assertTrue(n1.equals(n2)); + assertTrue(n2.equals(n1)); + + n1.add(TextNode.valueOf("Test")); + + assertFalse(n1.equals(n2)); + assertFalse(n2.equals(n1)); + + n2.add(TextNode.valueOf("Test")); + + assertTrue(n1.equals(n2)); + assertTrue(n2.equals(n1)); + } + + public void testObjectNodeEquality() + { + ObjectNode n1 = new ObjectNode(null); + ObjectNode n2 = new ObjectNode(null); + + assertTrue(n1.equals(n2)); + assertTrue(n2.equals(n1)); + + n1.put("x", TextNode.valueOf("Test")); + + assertFalse(n1.equals(n2)); + assertFalse(n2.equals(n1)); + + n2.put("x", TextNode.valueOf("Test")); + + assertTrue(n1.equals(n2)); + assertTrue(n2.equals(n1)); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/tree/TestTreeMapperDeserializer.java b/1.9.10/src/test/org/codehaus/jackson/map/tree/TestTreeMapperDeserializer.java new file mode 100644 index 0000000..3780a06 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/tree/TestTreeMapperDeserializer.java
@@ -0,0 +1,440 @@ +package org.codehaus.jackson.map.tree; + +import main.BaseTest; + +import java.io.*; +import java.math.BigDecimal; +import java.util.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.node.*; + +/** + * This unit test suite tries to verify that ObjectMapper + * can properly parse JSON and bind contents into appropriate + * JsonNode instances. + */ +public class TestTreeMapperDeserializer + extends BaseTest +{ + public void testSimple() + throws Exception + { + final String JSON = SAMPLE_DOC_JSON_SPEC; + + ObjectMapper mapper = new ObjectMapper(); + + for (int type = 0; type < 2; ++type) { + JsonNode result; + + if (type == 0) { + result = mapper.readTree(new StringReader(JSON)); + } else { + result = mapper.readTree(JSON); + } + + assertType(result, ObjectNode.class); + assertEquals(1, result.size()); + assertTrue(result.isObject()); + + ObjectNode main = (ObjectNode) result; + assertEquals("Image", main.getFieldNames().next()); + JsonNode ob = main.getElements().next(); + assertType(ob, ObjectNode.class); + ObjectNode imageMap = (ObjectNode) ob; + + assertEquals(5, imageMap.size()); + ob = imageMap.get("Width"); + assertTrue(ob.isIntegralNumber()); + assertFalse(ob.isFloatingPointNumber()); + assertEquals(SAMPLE_SPEC_VALUE_WIDTH, ob.getIntValue()); + ob = imageMap.get("Height"); + assertTrue(ob.isIntegralNumber()); + assertEquals(SAMPLE_SPEC_VALUE_HEIGHT, ob.getIntValue()); + + ob = imageMap.get("Title"); + assertTrue(ob.isTextual()); + assertEquals(SAMPLE_SPEC_VALUE_TITLE, ob.getTextValue()); + + ob = imageMap.get("Thumbnail"); + assertType(ob, ObjectNode.class); + ObjectNode tn = (ObjectNode) ob; + ob = tn.get("Url"); + assertTrue(ob.isTextual()); + assertEquals(SAMPLE_SPEC_VALUE_TN_URL, ob.getTextValue()); + ob = tn.get("Height"); + assertTrue(ob.isIntegralNumber()); + assertEquals(SAMPLE_SPEC_VALUE_TN_HEIGHT, ob.getIntValue()); + ob = tn.get("Width"); + assertTrue(ob.isTextual()); + assertEquals(SAMPLE_SPEC_VALUE_TN_WIDTH, ob.getTextValue()); + + ob = imageMap.get("IDs"); + assertTrue(ob.isArray()); + ArrayNode idList = (ArrayNode) ob; + assertEquals(4, idList.size()); + assertEquals(4, calcLength(idList.getElements())); + assertEquals(4, calcLength(idList.iterator())); + { + int[] values = new int[] { + SAMPLE_SPEC_VALUE_TN_ID1, + SAMPLE_SPEC_VALUE_TN_ID2, + SAMPLE_SPEC_VALUE_TN_ID3, + SAMPLE_SPEC_VALUE_TN_ID4 + }; + for (int i = 0; i < values.length; ++i) { + assertEquals(values[i], idList.get(i).getIntValue()); + } + int i = 0; + for (JsonNode n : idList) { + assertEquals(values[i], n.getIntValue()); + ++i; + } + } + } + } + + public void testBoolean() + throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + JsonNode result = mapper.readTree("true\n"); + assertFalse(result.isNull()); + assertFalse(result.isNumber()); + assertFalse(result.isTextual()); + assertTrue(result.isBoolean()); + assertType(result, BooleanNode.class); + assertTrue(result.getBooleanValue()); + assertEquals("true", result.asText()); + assertFalse(result.isMissingNode()); + + // also, equality should work ok + assertEquals(result, BooleanNode.valueOf(true)); + assertEquals(result, BooleanNode.getTrue()); + } + + public void testDouble() + throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + double value = 3.04; + JsonNode result = mapper.readTree(String.valueOf(value)); + assertTrue(result.isNumber()); + assertFalse(result.isNull()); + assertType(result, DoubleNode.class); + assertTrue(result.isFloatingPointNumber()); + assertTrue(result.isDouble()); + assertFalse(result.isInt()); + assertFalse(result.isLong()); + assertFalse(result.isIntegralNumber()); + assertFalse(result.isTextual()); + assertFalse(result.isMissingNode()); + + assertEquals(value, result.getDoubleValue()); + assertEquals(value, result.getNumberValue().doubleValue()); + assertEquals((int) value, result.getIntValue()); + assertEquals((long) value, result.getLongValue()); + assertEquals(String.valueOf(value), result.asText()); + + // also, equality should work ok + assertEquals(result, DoubleNode.valueOf(value)); + } + + public void testInt() + throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + int value = -90184; + JsonNode result = mapper.readTree(String.valueOf(value)); + assertTrue(result.isNumber()); + assertTrue(result.isIntegralNumber()); + assertTrue(result.isInt()); + assertType(result, IntNode.class); + assertFalse(result.isLong()); + assertFalse(result.isFloatingPointNumber()); + assertFalse(result.isDouble()); + assertFalse(result.isNull()); + assertFalse(result.isTextual()); + assertFalse(result.isMissingNode()); + + assertEquals(value, result.getNumberValue().intValue()); + assertEquals(value, result.getIntValue()); + assertEquals(String.valueOf(value), result.asText()); + assertEquals((double) value, result.getDoubleValue()); + assertEquals((long) value, result.getLongValue()); + + // also, equality should work ok + assertEquals(result, IntNode.valueOf(value)); + } + + public void testLong() + throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + // need to use something being 32-bit value space + long value = 12345678L << 32; + JsonNode result = mapper.readTree(String.valueOf(value)); + assertTrue(result.isNumber()); + assertTrue(result.isIntegralNumber()); + assertTrue(result.isLong()); + assertType(result, LongNode.class); + assertFalse(result.isInt()); + assertFalse(result.isFloatingPointNumber()); + assertFalse(result.isDouble()); + assertFalse(result.isNull()); + assertFalse(result.isTextual()); + assertFalse(result.isMissingNode()); + + assertEquals(value, result.getNumberValue().longValue()); + assertEquals(value, result.getLongValue()); + assertEquals(String.valueOf(value), result.asText()); + assertEquals((double) value, result.getDoubleValue()); + + // also, equality should work ok + assertEquals(result, LongNode.valueOf(value)); + } + + public void testNull() + throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + JsonNode result = mapper.readTree(" null "); + // should not get java null, but NullNode... + assertNotNull(result); + assertTrue(result.isNull()); + assertFalse(result.isNumber()); + assertFalse(result.isTextual()); + assertEquals("null", result.asText()); + + // also, equality should work ok + assertEquals(result, NullNode.instance); + } + + public void testDecimalNode() + throws Exception + { + // no "natural" way to get it, must construct + BigDecimal value = new BigDecimal("0.1"); + JsonNode result = DecimalNode.valueOf(value); + + assertFalse(result.isArray()); + assertFalse(result.isObject()); + assertTrue(result.isNumber()); + assertFalse(result.isIntegralNumber()); + assertFalse(result.isLong()); + assertType(result, DecimalNode.class); + assertFalse(result.isInt()); + assertTrue(result.isFloatingPointNumber()); + assertTrue(result.isBigDecimal()); + assertFalse(result.isDouble()); + assertFalse(result.isNull()); + assertFalse(result.isTextual()); + assertFalse(result.isMissingNode()); + + assertEquals(value, result.getNumberValue()); + assertEquals(value.toString(), result.asText()); + + // also, equality should work ok + assertEquals(result, DecimalNode.valueOf(value)); + } + + public void testSimpleArray() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + ArrayNode result = mapper.createArrayNode(); + + assertTrue(result.isArray()); + assertType(result, ArrayNode.class); + + assertFalse(result.isObject()); + assertFalse(result.isNumber()); + assertFalse(result.isNull()); + assertFalse(result.isTextual()); + + // and let's add stuff... + result.add(false); + result.insertNull(0); + + // should be equal to itself no matter what + assertEquals(result, result); + assertFalse(result.equals(null)); // but not to null + + // plus see that we can access stuff + assertEquals(NullNode.instance, result.path(0)); + assertEquals(NullNode.instance, result.get(0)); + assertEquals(BooleanNode.FALSE, result.path(1)); + assertEquals(BooleanNode.FALSE, result.get(1)); + assertEquals(2, result.size()); + + assertNull(result.get(-1)); + assertNull(result.get(2)); + JsonNode missing = result.path(2); + assertTrue(missing.isMissingNode()); + assertTrue(result.path(-100).isMissingNode()); + + // then construct and compare + ArrayNode array2 = mapper.createArrayNode(); + array2.addNull(); + array2.add(false); + assertEquals(result, array2); + + // plus remove entries + JsonNode rm1 = array2.remove(0); + assertEquals(NullNode.instance, rm1); + assertEquals(1, array2.size()); + assertEquals(BooleanNode.FALSE, array2.get(0)); + assertFalse(result.equals(array2)); + + JsonNode rm2 = array2.remove(0); + assertEquals(BooleanNode.FALSE, rm2); + assertEquals(0, array2.size()); + } + + /** + * Type mappers should be able to gracefully deal with end of + * input. + */ + public void testEOF() throws Exception + { + String JSON = + "{ \"key\": [ { \"a\" : { \"name\": \"foo\", \"type\": 1\n" + +"}, \"type\": 3, \"url\": \"http://www.google.com\" } ],\n" + +"\"name\": \"xyz\", \"type\": 1, \"url\" : null }\n " + ; + JsonFactory jf = new JsonFactory(); + ObjectMapper mapper = new ObjectMapper(); + JsonParser jp = jf.createJsonParser(new StringReader(JSON)); + JsonNode result = mapper.readTree(jp); + + assertTrue(result.isObject()); + assertEquals(4, result.size()); + + assertNull(mapper.readTree(jp)); + } + + public void testMultiple() throws Exception + { + String JSON = "12 \"string\" [ 1, 2, 3 ]"; + JsonFactory jf = new JsonFactory(); + ObjectMapper mapper = new ObjectMapper(); + JsonParser jp = jf.createJsonParser(new StringReader(JSON)); + JsonNode result = mapper.readTree(jp); + + assertTrue(result.isIntegralNumber()); + assertTrue(result.isInt()); + assertFalse(result.isTextual()); + assertEquals(12, result.getIntValue()); + + result = mapper.readTree(jp); + assertTrue(result.isTextual()); + assertFalse(result.isIntegralNumber()); + assertFalse(result.isInt()); + assertEquals("string", result.getTextValue()); + + result = mapper.readTree(jp); + assertTrue(result.isArray()); + assertEquals(3, result.size()); + + assertNull(mapper.readTree(jp)); + } + + /** + * Let's also verify behavior of "MissingNode" -- one needs to be able + * to traverse such bogus nodes with appropriate methods. + */ + @SuppressWarnings("unused") + public void testMissingNode() + throws Exception + { + String JSON = "[ { }, [ ] ]"; + ObjectMapper mapper = new ObjectMapper(); + JsonNode result = mapper.readTree(new StringReader(JSON)); + + assertTrue(result.isContainerNode()); + assertTrue(result.isArray()); + assertEquals(2, result.size()); + + int count = 0; + for (JsonNode node : result) { + ++count; + } + assertEquals(2, count); + + Iterator<JsonNode> it = result.iterator(); + + JsonNode onode = it.next(); + assertTrue(onode.isContainerNode()); + assertTrue(onode.isObject()); + assertEquals(0, onode.size()); + assertFalse(onode.isMissingNode()); // real node + assertNull(onode.getTextValue()); + + // how about dereferencing? + assertNull(onode.get(0)); + JsonNode dummyNode = onode.path(0); + assertNotNull(dummyNode); + assertTrue(dummyNode.isMissingNode()); + assertNull(dummyNode.get(3)); + assertNull(dummyNode.get("whatever")); + JsonNode dummyNode2 = dummyNode.path(98); + assertNotNull(dummyNode2); + assertTrue(dummyNode2.isMissingNode()); + JsonNode dummyNode3 = dummyNode.path("field"); + assertNotNull(dummyNode3); + assertTrue(dummyNode3.isMissingNode()); + + // and same for the array node + + JsonNode anode = it.next(); + assertTrue(anode.isContainerNode()); + assertTrue(anode.isArray()); + assertFalse(anode.isMissingNode()); // real node + assertEquals(0, anode.size()); + + assertNull(anode.get(0)); + dummyNode = anode.path(0); + assertNotNull(dummyNode); + assertTrue(dummyNode.isMissingNode()); + assertNull(dummyNode.get(0)); + assertNull(dummyNode.get("myfield")); + dummyNode2 = dummyNode.path(98); + assertNotNull(dummyNode2); + assertTrue(dummyNode2.isMissingNode()); + dummyNode3 = dummyNode.path("f"); + assertNotNull(dummyNode3); + assertTrue(dummyNode3.isMissingNode()); + } + + public void testArray() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + final String JSON = "[[[-0.027512,51.503221],[-0.008497,51.503221],[-0.008497,51.509744],[-0.027512,51.509744]]]"; + + JsonNode n = mapper.readTree(JSON); + assertNotNull(n); + assertTrue(n.isArray()); + ArrayNode an = (ArrayNode) n; + assertEquals(1, an.size()); + ArrayNode an2 = (ArrayNode) n.get(0); + assertTrue(an2.isArray()); + assertEquals(4, an2.size()); + } + + /* + /********************************************** + /* Helper methods + /********************************************** + */ + + private int calcLength(Iterator<JsonNode> it) + { + int count = 0; + while (it.hasNext()) { + it.next(); + ++count; + } + return count; + } +} +
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/tree/TestTreeMapperMaps.java b/1.9.10/src/test/org/codehaus/jackson/map/tree/TestTreeMapperMaps.java new file mode 100644 index 0000000..6097447 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/tree/TestTreeMapperMaps.java
@@ -0,0 +1,77 @@ +package org.codehaus.jackson.map.tree; + +import main.BaseTest; + +import java.util.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.node.*; + +/** + * Unit tests to verify that Json Objects map property to Map-like + * ObjectNodes. + */ +public class TestTreeMapperMaps + extends BaseTest +{ + public void testSimpleObject() throws Exception + { + String JSON = "{ \"key\" : 1, \"b\" : \"x\" }"; + ObjectMapper mapper = new ObjectMapper(); + JsonNode root = mapper.readTree(JSON); + + // basic properties first: + assertFalse(root.isValueNode()); + assertTrue(root.isContainerNode()); + assertFalse(root.isArray()); + assertTrue(root.isObject()); + assertEquals(2, root.size()); + + // Related to [JACKSON-50]: + Iterator<JsonNode> it = root.iterator(); + assertNotNull(it); + assertTrue(it.hasNext()); + JsonNode n = it.next(); + assertNotNull(n); + assertEquals(IntNode.valueOf(1), n); + + assertTrue(it.hasNext()); + n = it.next(); + assertNotNull(n); + assertEquals(TextNode.valueOf("x"), n); + + assertFalse(it.hasNext()); + + // Ok, then, let's traverse via extended interface + ObjectNode obNode = (ObjectNode) root; + Iterator<Map.Entry<String,JsonNode>> fit = obNode.getFields(); + // we also know that LinkedHashMap is used, i.e. order preserved + assertTrue(fit.hasNext()); + Map.Entry<String,JsonNode> en = fit.next(); + assertEquals("key", en.getKey()); + assertEquals(IntNode.valueOf(1), en.getValue()); + + assertTrue(fit.hasNext()); + en = fit.next(); + assertEquals("b", en.getKey()); + assertEquals(TextNode.valueOf("x"), en.getValue()); + + // Plus: we should be able to modify the node via iterator too: + fit.remove(); + assertEquals(1, obNode.size()); + assertEquals(IntNode.valueOf(1), root.get("key")); + assertNull(root.get("b")); + } + + public void testSimplePath() throws Exception + { + JsonNode root = new ObjectMapper().readTree("{ \"results\" : { \"a\" : 3 } }"); + assertTrue(root.isObject()); + JsonNode rnode = root.path("results"); + assertNotNull(rnode); + assertTrue(rnode.isObject()); + assertEquals(3, rnode.path("a").getIntValue()); + } + +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/tree/TestTreeMapperSerializer.java b/1.9.10/src/test/org/codehaus/jackson/map/tree/TestTreeMapperSerializer.java new file mode 100644 index 0000000..84bcf2e --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/tree/TestTreeMapperSerializer.java
@@ -0,0 +1,224 @@ +package org.codehaus.jackson.map.tree; + +import main.BaseTest; +import static org.junit.Assert.*; + +import java.io.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.node.*; + +/** + * This unit test suite tries to verify that the trees ObjectMapper + * constructs can be serialized properly. + */ +public class TestTreeMapperSerializer + extends BaseTest +{ + final static String FIELD1 = "first"; + final static String FIELD2 = "Second?"; + final static String FIELD3 = "foo'n \"bar\""; + final static String FIELD4 = "4"; + + final static String TEXT1 = "Some text & \"stuff\""; + final static String TEXT2 = "Some more text:\twith\nlinefeeds and all!"; + + final static double DOUBLE_VALUE = 9.25; + + public void testFromArray() + throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + ArrayNode root = mapper.createArrayNode(); + root.add(TEXT1); + root.add(3); + ObjectNode obj = root.addObject(); + obj.put(FIELD1, true); + obj.putArray(FIELD2); + root.add(false); + + /* Ok, ready... let's serialize using one of two alternate + * methods: first preferred (using generator) + * (there are 2 variants here too) + */ + for (int i = 0; i < 2; ++i) { + StringWriter sw = new StringWriter(); + if (i == 0) { + JsonGenerator gen = new JsonFactory().createJsonGenerator(sw); + root.serialize(gen, null); + gen.close(); + } else { + mapper.writeValue(sw, root); + } + verifyFromArray(sw.toString()); + } + + // And then convenient but less efficient alternative: + verifyFromArray(root.toString()); + } + + public void testFromMap() + throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + ObjectNode root = mapper.createObjectNode(); + root.put(FIELD4, TEXT2); + root.put(FIELD3, -1); + root.putArray(FIELD2); + root.put(FIELD1, DOUBLE_VALUE); + + /* Let's serialize using one of two alternate methods: + * first preferred (using generator) + * (there are 2 variants here too) + */ + for (int i = 0; i < 2; ++i) { + StringWriter sw = new StringWriter(); + if (i == 0) { + JsonGenerator gen = new JsonFactory().createJsonGenerator(sw); + root.serialize(gen, null); + gen.close(); + } else { + mapper.writeValue(sw, root); + } + verifyFromMap(sw.toString()); + } + + // And then convenient but less efficient alternative: + verifyFromMap(root.toString()); + } + + /** + * Unit test to check for regression of [JACKSON-18]. + */ + public void testSmallNumbers() + throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + ArrayNode root = mapper.createArrayNode(); + for (int i = -20; i <= 20; ++i) { + JsonNode n = root.numberNode(i); + root.add(n); + // Hmmh. Not sure why toString() won't be triggered otherwise... + assertEquals(String.valueOf(i), n.toString()); + } + + // Loop over 2 different serialization methods + for (int type = 0; type < 2; ++type) { + StringWriter sw = new StringWriter(); + if (type == 0) { + JsonGenerator gen = new JsonFactory().createJsonGenerator(sw); + root.serialize(gen, null); + gen.close(); + } else { + mapper.writeValue(sw, root); + } + + String doc = sw.toString(); + JsonParser jp = new JsonFactory().createJsonParser(new StringReader(doc)); + + assertEquals(JsonToken.START_ARRAY, jp.nextToken()); + for (int i = -20; i <= 20; ++i) { + assertEquals(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(i, jp.getIntValue()); + assertEquals(""+i, jp.getText()); + } + assertEquals(JsonToken.END_ARRAY, jp.nextToken()); + jp.close(); + } + } + + public void testNull() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + StringWriter sw = new StringWriter(); + mapper.writeValue(sw, NullNode.instance); + assertEquals("null", sw.toString()); + } + + public void testBinary() + throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + final int LENGTH = 13045; + byte[] data = new byte[LENGTH]; + for (int i = 0; i < LENGTH; ++i) { + data[i] = (byte) i; + } + StringWriter sw = new StringWriter(); + mapper.writeValue(sw, BinaryNode.valueOf(data)); + + JsonParser jp = new JsonFactory().createJsonParser(sw.toString()); + // note: can't determine it's binary from json alone: + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + assertArrayEquals(data, jp.getBinaryValue()); + jp.close(); + } + + /* + /////////////////////////////////////////////////////////////// + // Internal methods + /////////////////////////////////////////////////////////////// + */ + + private void verifyFromArray(String input) + throws Exception + { + JsonParser jp = new JsonFactory().createJsonParser(new StringReader(input)); + + assertEquals(JsonToken.START_ARRAY, jp.nextToken()); + + assertEquals(JsonToken.VALUE_STRING, jp.nextToken()); + assertEquals(TEXT1, getAndVerifyText(jp)); + + assertEquals(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(3, jp.getIntValue()); + + assertEquals(JsonToken.START_OBJECT, jp.nextToken()); + assertEquals(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals(FIELD1, getAndVerifyText(jp)); + + assertEquals(JsonToken.VALUE_TRUE, jp.nextToken()); + assertEquals(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals(FIELD2, getAndVerifyText(jp)); + + assertEquals(JsonToken.START_ARRAY, jp.nextToken()); + assertEquals(JsonToken.END_ARRAY, jp.nextToken()); + assertEquals(JsonToken.END_OBJECT, jp.nextToken()); + + assertEquals(JsonToken.VALUE_FALSE, jp.nextToken()); + + assertEquals(JsonToken.END_ARRAY, jp.nextToken()); + assertNull(jp.nextToken()); + } + + private void verifyFromMap(String input) + throws Exception + { + JsonParser jp = new JsonFactory().createJsonParser(new StringReader(input)); + assertEquals(JsonToken.START_OBJECT, jp.nextToken()); + assertEquals(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals(FIELD4, getAndVerifyText(jp)); + assertEquals(JsonToken.VALUE_STRING, jp.nextToken()); + assertEquals(TEXT2, getAndVerifyText(jp)); + + assertEquals(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals(FIELD3, getAndVerifyText(jp)); + assertEquals(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(-1, jp.getIntValue()); + + assertEquals(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals(FIELD2, getAndVerifyText(jp)); + assertEquals(JsonToken.START_ARRAY, jp.nextToken()); + assertEquals(JsonToken.END_ARRAY, jp.nextToken()); + + assertEquals(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals(FIELD1, getAndVerifyText(jp)); + assertEquals(JsonToken.VALUE_NUMBER_FLOAT, jp.nextToken()); + assertEquals(DOUBLE_VALUE, jp.getDoubleValue()); + + assertEquals(JsonToken.END_OBJECT, jp.nextToken()); + + assertNull(jp.nextToken()); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/type/TestAnnotatedClass.java b/1.9.10/src/test/org/codehaus/jackson/map/type/TestAnnotatedClass.java new file mode 100644 index 0000000..77d2f6b --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/type/TestAnnotatedClass.java
@@ -0,0 +1,146 @@ +package org.codehaus.jackson.map.type; + +import java.util.*; + +import org.codehaus.jackson.map.BaseMapTest; +import org.codehaus.jackson.map.introspect.AnnotatedClass; +import org.codehaus.jackson.map.introspect.AnnotatedField; +import org.codehaus.jackson.map.introspect.AnnotatedMethod; +import org.codehaus.jackson.map.introspect.BasicClassIntrospector; +import org.codehaus.jackson.map.introspect.JacksonAnnotationIntrospector; + +import org.codehaus.jackson.annotate.*; + +/** + * Unit test for verifying that {@link AnnotatedClass} + * works as expected. + */ +public class TestAnnotatedClass + extends BaseMapTest +{ + /* + /********************************************************** + /* Annotated helper classes + /********************************************************** + */ + + static class BaseClass + { + public int foo; + + public BaseClass(int x, int y) { } + + @JsonProperty public int x() { return 3; } + } + + static class SubClass extends BaseClass + { + public SubClass() { this(1); } + public SubClass(int x) { super(x, 2); } + + public int y() { return 3; } + } + + static abstract class GenericBase<T extends Number> + { + public abstract void setX(T value); + } + + static class NumberBean + extends GenericBase<Integer> + { + @Override + public void setX(Integer value) { } + } + + /** + * Test class for checking that field introspection + * works as expected + */ + static class FieldBean + { + // static, not to be included: + public static boolean DUMMY; + + // not public, no annotations, shouldn't be included + @SuppressWarnings("unused") + private long bar; + + @SuppressWarnings("unused") + @JsonProperty + private String props; + } + + /* + /********************************************************** + /* Test methods + /********************************************************** + */ + + @SuppressWarnings("deprecation") + public void testSimple() + { + // null -> no mix-in annotations + AnnotatedClass ac = AnnotatedClass.construct(SubClass.class, new JacksonAnnotationIntrospector(), null); + ac.resolveMemberMethods(BasicClassIntrospector.DEFAULT_GETTER_FILTER); + ac.resolveCreators(true); + ac.resolveFields(); + + assertNotNull(ac.getDefaultConstructor()); + assertEquals(1, ac.getConstructors().size()); + assertEquals(0, ac.getStaticMethods().size()); + assertEquals(2, ac.getMemberMethodCount()); + for (AnnotatedMethod am : ac.memberMethods()) { + String name = am.getName(); + if ("y".equals(name)) { + assertEquals(0, am.getAnnotationCount()); + } else if ("x".equals(name)) { + assertEquals(1, am.getAnnotationCount()); + assertNotNull(am.getAnnotation(JsonProperty.class)); + } else { + fail("Unexpected method: "+name); + } + } + assertEquals(1, ac.getFieldCount()); + assertEquals("foo", ac.fields().iterator().next().getName()); + } + + /** + * Another simple test to verify that the (concrete) type information + * from a sub-class is used instead of abstract one from superclass. + */ + @SuppressWarnings("deprecation") + public void testGenericsWithSetter() + { + // null -> no mix-in annotations + AnnotatedClass ac = AnnotatedClass.construct(NumberBean.class, new JacksonAnnotationIntrospector(), null); + ac.resolveMemberMethods(BasicClassIntrospector.DEFAULT_SETTER_FILTER); + assertEquals(1, ac.getMemberMethodCount()); + + Iterator<AnnotatedMethod> it = ac.memberMethods().iterator(); + AnnotatedMethod am = it.next(); + + assertEquals("setX", am.getName()); + // should be one from sub-class + assertEquals(NumberBean.class, am.getDeclaringClass()); + assertEquals(Integer.class, am.getParameterClass(0)); + } + + public void testFieldIntrospection() + { + // null -> no mix-in annotations + AnnotatedClass ac = AnnotatedClass.construct(FieldBean.class, new JacksonAnnotationIntrospector(), null); + ac.resolveFields(); + /* 14-Jul-2009, tatu: AnnotatedClass does remove forcibly ignored + * entries, but will still contain non-public fields too (earlier + * versions didn't, but filtering was moved to a later point) + */ + assertEquals(2, ac.getFieldCount()); + for (AnnotatedField f : ac.fields()) { + String fname = f.getName(); + if (!"bar".equals(fname) && !"props".equals(fname)) { + fail("Unexpected field name '"+fname+"'"); + } + } + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/type/TestTypeFactory.java b/1.9.10/src/test/org/codehaus/jackson/map/type/TestTypeFactory.java new file mode 100644 index 0000000..b57dd1e --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/type/TestTypeFactory.java
@@ -0,0 +1,508 @@ +package org.codehaus.jackson.map.type; + +import java.lang.reflect.Field; +import java.util.*; +import java.util.concurrent.atomic.AtomicReference; + +import main.BaseTest; + +import org.codehaus.jackson.map.ObjectMapper; +import org.codehaus.jackson.type.JavaType; +import org.codehaus.jackson.type.TypeReference; + +/** + * Simple tests to verify that the {@link TypeFactory} constructs + * type information as expected. + */ +public class TestTypeFactory + extends BaseTest +{ + /* + /********************************************************** + /* Helper types + /********************************************************** + */ + + enum EnumForCanonical { YES, NO; } + + static class SingleArgGeneric<X> { } + + abstract static class MyMap extends IntermediateMap<String,Long> { } + abstract static class IntermediateMap<K,V> implements Map<K,V> { } + + abstract static class MyList extends IntermediateList<Long> { } + abstract static class IntermediateList<E> implements List<E> { } + + @SuppressWarnings("serial") + static class GenericList<T> extends ArrayList<T> { } + + interface MapInterface extends Cloneable, IntermediateInterfaceMap<String> { } + interface IntermediateInterfaceMap<FOO> extends Map<FOO, Integer> { } + + @SuppressWarnings("serial") + static class MyStringIntMap extends MyStringXMap<Integer> { } + @SuppressWarnings("serial") + static class MyStringXMap<V> extends HashMap<String,V> { } + + // And one more, now with obfuscated type names; essentially it's just Map<Int,Long> + static abstract class IntLongMap extends XLongMap<Integer> { } + // trick here is that V now refers to key type, not value type + static abstract class XLongMap<V> extends XXMap<V,Long> { } + static abstract class XXMap<K,V> implements Map<K,V> { } + + static class SneakyBean { + public IntLongMap intMap; + public MyList longList; + } + + static class SneakyBean2 { + // self-reference; should be resolved as "Comparable<Object>" + public <T extends Comparable<T>> T getFoobar() { return null; } + } + + @SuppressWarnings("serial") + public static class LongValuedMap<K> extends HashMap<K, Long> { } + + static class StringLongMapBean { + public LongValuedMap<String> value; + } + + static class StringListBean { + public GenericList<String> value; + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + public void testSimpleTypes() + { + Class<?>[] classes = new Class<?>[] { + boolean.class, byte.class, char.class, + short.class, int.class, long.class, + float.class, double.class, + + Boolean.class, Byte.class, Character.class, + Short.class, Integer.class, Long.class, + Float.class, Double.class, + + String.class, + Object.class, + + Calendar.class, + Date.class, + }; + + TypeFactory tf = TypeFactory.defaultInstance(); + for (Class<?> clz : classes) { + assertSame(clz, tf.constructType(clz).getRawClass()); + assertSame(clz, tf.constructType(clz).getRawClass()); + } + } + + public void testArrays() + { + Class<?>[] classes = new Class<?>[] { + boolean[].class, byte[].class, char[].class, + short[].class, int[].class, long[].class, + float[].class, double[].class, + + String[].class, Object[].class, + Calendar[].class, + }; + + TypeFactory tf = TypeFactory.defaultInstance(); + for (Class<?> clz : classes) { + assertSame(clz, tf.constructType(clz).getRawClass()); + Class<?> elemType = clz.getComponentType(); + assertSame(clz, tf.constructArrayType(elemType).getRawClass()); + } + } + + public void testCollections() + { + // Ok, first: let's test what happens when we pass 'raw' Collection: + TypeFactory tf = TypeFactory.defaultInstance(); + JavaType t = tf.constructType(ArrayList.class); + assertEquals(CollectionType.class, t.getClass()); + assertSame(ArrayList.class, t.getRawClass()); + + // And then the proper way + t = tf.constructType(new TypeReference<ArrayList<String>>() { }); + assertEquals(CollectionType.class, t.getClass()); + assertSame(ArrayList.class, t.getRawClass()); + + JavaType elemType = ((CollectionType) t).getContentType(); + assertNotNull(elemType); + assertSame(SimpleType.class, elemType.getClass()); + assertSame(String.class, elemType.getRawClass()); + + // And alternate method too + t = tf.constructCollectionType(ArrayList.class, String.class); + assertEquals(CollectionType.class, t.getClass()); + assertSame(String.class, ((CollectionType) t).getContentType().getRawClass()); + } + + public void testMaps() + { + TypeFactory tf = TypeFactory.defaultInstance(); + // Ok, first: let's test what happens when we pass 'raw' Map: + JavaType t = tf.constructType(HashMap.class); + assertEquals(MapType.class, t.getClass()); + assertSame(HashMap.class, t.getRawClass()); + + // Then explicit construction + t = tf.constructMapType(TreeMap.class, String.class, Integer.class); + assertEquals(MapType.class, t.getClass()); + assertSame(String.class, ((MapType) t).getKeyType().getRawClass()); + assertSame(Integer.class, ((MapType) t).getContentType().getRawClass()); + + // And then with TypeReference + t = tf.constructType(new TypeReference<HashMap<String,Integer>>() { }); + assertEquals(MapType.class, t.getClass()); + assertSame(HashMap.class, t.getRawClass()); + MapType mt = (MapType) t; + assertEquals(tf.constructType(String.class), mt.getKeyType()); + assertEquals(tf.constructType(Integer.class), mt.getContentType()); + + t = tf.constructType(new TypeReference<LongValuedMap<Boolean>>() { }); + assertEquals(MapType.class, t.getClass()); + assertSame(LongValuedMap.class, t.getRawClass()); + mt = (MapType) t; + assertEquals(tf.constructType(Boolean.class), mt.getKeyType()); + assertEquals(tf.constructType(Long.class), mt.getContentType()); + } + + public void testIterator() + { + TypeFactory tf = TypeFactory.defaultInstance(); + JavaType t = tf.constructType(new TypeReference<Iterator<String>>() { }); + assertEquals(SimpleType.class, t.getClass()); + assertSame(Iterator.class, t.getRawClass()); + assertEquals(1, t.containedTypeCount()); + assertEquals(tf.constructType(String.class), t.containedType(0)); + assertNull(t.containedType(1)); + } + + /** + * Test for verifying that parametric types can be constructed + * programmatically + * + * @since 1.5 + */ + public void testParametricTypes() + { + TypeFactory tf = TypeFactory.defaultInstance(); + // first, simple class based + JavaType t = tf.constructParametricType(ArrayList.class, String.class); // ArrayList<String> + assertEquals(CollectionType.class, t.getClass()); + JavaType strC = tf.constructType(String.class); + assertEquals(1, t.containedTypeCount()); + assertEquals(strC, t.containedType(0)); + assertNull(t.containedType(1)); + + // Then using JavaType + JavaType t2 = tf.constructParametricType(Map.class, strC, t); // Map<String,ArrayList<String>> + // should actually produce a MapType + assertEquals(MapType.class, t2.getClass()); + assertEquals(2, t2.containedTypeCount()); + assertEquals(strC, t2.containedType(0)); + assertEquals(t, t2.containedType(1)); + assertNull(t2.containedType(2)); + + // and then custom generic type as well + JavaType custom = tf.constructParametricType(SingleArgGeneric.class, String.class); + assertEquals(SimpleType.class, custom.getClass()); + assertEquals(1, custom.containedTypeCount()); + assertEquals(strC, custom.containedType(0)); + assertNull(custom.containedType(1)); + // should also be able to access variable name: + assertEquals("X", custom.containedTypeName(0)); + + // And finally, ensure that we can't create invalid combinations + try { + // Maps must take 2 type parameters, not just one + tf.constructParametricType(Map.class, strC); + } catch (IllegalArgumentException e) { + verifyException(e, "Need exactly 2 parameter types for Map types"); + } + + try { + // Type only accepts one type param + tf.constructParametricType(SingleArgGeneric.class, strC, strC); + } catch (IllegalArgumentException e) { + verifyException(e, "expected 1 parameters, was given 2"); + } + } + + /** + * Test for checking that canonical name handling works ok + * + * @since 1.5 + */ + public void testCanonicalNames() + { + TypeFactory tf = TypeFactory.defaultInstance(); + JavaType t = tf.constructType(java.util.Calendar.class); + String can = t.toCanonical(); + assertEquals("java.util.Calendar", can); + assertEquals(t, TypeFactory.fromCanonical(can)); + + // Generic maps and collections will default to Object.class if type-erased + t = tf.constructType(java.util.ArrayList.class); + can = t.toCanonical(); + assertEquals("java.util.ArrayList<java.lang.Object>", can); + assertEquals(t, TypeFactory.fromCanonical(can)); + + t = tf.constructType(java.util.TreeMap.class); + can = t.toCanonical(); + assertEquals("java.util.TreeMap<java.lang.Object,java.lang.Object>", can); + assertEquals(t, TypeFactory.fromCanonical(can)); + + // And then EnumMap (actual use case for us) + t = tf.constructMapType(EnumMap.class, EnumForCanonical.class, String.class); + can = t.toCanonical(); + assertEquals("java.util.EnumMap<org.codehaus.jackson.map.type.TestTypeFactory$EnumForCanonical,java.lang.String>", + can); + assertEquals(t, TypeFactory.fromCanonical(can)); + + } + + /* + /********************************************************** + /* Unit tests: low-level inheritance resolution + /********************************************************** + */ + + /** + * @since 1.6 + */ + public void testSuperTypeDetectionClass() + { + TypeFactory tf = TypeFactory.defaultInstance(); + HierarchicType sub = tf._findSuperTypeChain(MyStringIntMap.class, HashMap.class); + assertNotNull(sub); + assertEquals(2, _countSupers(sub)); + assertSame(MyStringIntMap.class, sub.getRawClass()); + HierarchicType sup = sub.getSuperType(); + assertSame(MyStringXMap.class, sup.getRawClass()); + HierarchicType sup2 = sup.getSuperType(); + assertSame(HashMap.class, sup2.getRawClass()); + assertNull(sup2.getSuperType()); + } + + /** + * @since 1.6 + */ + public void testSuperTypeDetectionInterface() + { + // List first + TypeFactory tf = TypeFactory.defaultInstance(); + HierarchicType sub = tf._findSuperTypeChain(MyList.class, List.class); + assertNotNull(sub); + assertEquals(2, _countSupers(sub)); + assertSame(MyList.class, sub.getRawClass()); + HierarchicType sup = sub.getSuperType(); + assertSame(IntermediateList.class, sup.getRawClass()); + HierarchicType sup2 = sup.getSuperType(); + assertSame(List.class, sup2.getRawClass()); + assertNull(sup2.getSuperType()); + + // Then Map + sub = tf._findSuperTypeChain(MyMap.class, Map.class); + assertNotNull(sub); + assertEquals(2, _countSupers(sub)); + assertSame(MyMap.class, sub.getRawClass()); + sup = sub.getSuperType(); + assertSame(IntermediateMap.class, sup.getRawClass()); + sup2 = sup.getSuperType(); + assertSame(Map.class, sup2.getRawClass()); + assertNull(sup2.getSuperType()); + } + + /** + * @since 1.6 + */ + public void testAtomicArrayRefParameterDetection() + { + TypeFactory tf = TypeFactory.defaultInstance(); + JavaType type = tf.constructType(new TypeReference<AtomicReference<long[]>>() { }); + HierarchicType sub = tf._findSuperTypeChain(type.getRawClass(), AtomicReference.class); + assertNotNull(sub); + assertEquals(0, _countSupers(sub)); + assertTrue(AtomicReference.class.isAssignableFrom(type.getRawClass())); + assertNull(sub.getSuperType()); + } + + private int _countSupers(HierarchicType t) + { + int depth = 0; + for (HierarchicType sup = t.getSuperType(); sup != null; sup = sup.getSuperType()) { + ++depth; + } + return depth; + } + + /* + /********************************************************** + /* Unit tests: map/collection type parameter resolution + /********************************************************** + */ + + /** + * @since 1.6 + */ + public void testMapTypesSimple() + { + TypeFactory tf = TypeFactory.defaultInstance(); + JavaType type = tf.constructType(new TypeReference<Map<String,Boolean>>() { }); + MapType mapType = (MapType) type; + assertEquals(tf.constructType(String.class), mapType.getKeyType()); + assertEquals(tf.constructType(Boolean.class), mapType.getContentType()); + } + + /** + * @since 1.6 + */ + public void testMapTypesRaw() + { + TypeFactory tf = TypeFactory.defaultInstance(); + JavaType type = tf.constructType(HashMap.class); + MapType mapType = (MapType) type; + assertEquals(tf.constructType(Object.class), mapType.getKeyType()); + assertEquals(tf.constructType(Object.class), mapType.getContentType()); + } + + /** + * @since 1.6 + */ + public void testMapTypesAdvanced() + { + TypeFactory tf = TypeFactory.defaultInstance(); + JavaType type = tf.constructType(MyMap.class); + MapType mapType = (MapType) type; + assertEquals(tf.constructType(String.class), mapType.getKeyType()); + assertEquals(tf.constructType(Long.class), mapType.getContentType()); + + type = tf.constructType(MapInterface.class); + mapType = (MapType) type; + assertEquals(tf.constructType(String.class), mapType.getKeyType()); + assertEquals(tf.constructType(Integer.class), mapType.getContentType()); + + type = tf.constructType(MyStringIntMap.class); + mapType = (MapType) type; + assertEquals(tf.constructType(String.class), mapType.getKeyType()); + assertEquals(tf.constructType(Integer.class), mapType.getContentType()); + } + + /** + * Specific test to verify that complicate name mangling schemes + * do not fool type resolver + * + * @since 1.6 + */ + public void testMapTypesSneaky() + { + TypeFactory tf = TypeFactory.defaultInstance(); + JavaType type = tf.constructType(IntLongMap.class); + MapType mapType = (MapType) type; + assertEquals(tf.constructType(Integer.class), mapType.getKeyType()); + assertEquals(tf.constructType(Long.class), mapType.getContentType()); + } + + /** + * Plus sneaky types may be found via introspection as well. + * + * @since 1.7 + */ + public void testSneakyFieldTypes() throws Exception + { + TypeFactory tf = TypeFactory.defaultInstance(); + Field field = SneakyBean.class.getDeclaredField("intMap"); + JavaType type = tf.constructType(field.getGenericType()); + assertTrue(type instanceof MapType); + MapType mapType = (MapType) type; + assertEquals(tf.constructType(Integer.class), mapType.getKeyType()); + assertEquals(tf.constructType(Long.class), mapType.getContentType()); + + field = SneakyBean.class.getDeclaredField("longList"); + type = tf.constructType(field.getGenericType()); + assertTrue(type instanceof CollectionType); + CollectionType collectionType = (CollectionType) type; + assertEquals(tf.constructType(Long.class), collectionType.getContentType()); + } + + /** + * Looks like type handling actually differs for properties, too. + * + * @since 1.7 + */ + public void testSneakyBeanProperties() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + StringLongMapBean bean = mapper.readValue("{\"value\":{\"a\":123}}", StringLongMapBean.class); + assertNotNull(bean); + Map<String,Long> map = bean.value; + assertEquals(1, map.size()); + assertEquals(Long.valueOf(123), map.get("a")); + + StringListBean bean2 = mapper.readValue("{\"value\":[\"...\"]}", StringListBean.class); + assertNotNull(bean2); + List<String> list = bean2.value; + assertSame(GenericList.class, list.getClass()); + assertEquals(1, list.size()); + assertEquals("...", list.get(0)); + } + + public void testAtomicArrayRefParameters() + { + TypeFactory tf = TypeFactory.defaultInstance(); + JavaType type = tf.constructType(new TypeReference<AtomicReference<long[]>>() { }); + JavaType[] params = tf.findTypeParameters(type, AtomicReference.class); + assertNotNull(params); + assertEquals(1, params.length); + assertEquals(tf.constructType(long[].class), params[0]); + } + + public void testSneakySelfRefs() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + String json = mapper.writeValueAsString(new SneakyBean2()); + assertEquals("{\"foobar\":null}", json); + } + + /* + /********************************************************** + /* Unit tests: construction of "raw" types + /********************************************************** + */ + + public void testRawCollections() + { + TypeFactory tf = TypeFactory.defaultInstance(); + JavaType type = tf.constructRawCollectionType(ArrayList.class); + assertTrue(type.isContainerType()); + assertEquals(TypeFactory.unknownType(), type.getContentType()); + + type = tf.constructRawCollectionLikeType(String.class); // class doesn't really matter + assertTrue(type.isCollectionLikeType()); + assertEquals(TypeFactory.unknownType(), type.getContentType()); + } + + public void testRawMaps() + { + TypeFactory tf = TypeFactory.defaultInstance(); + JavaType type = tf.constructRawMapType(HashMap.class); + assertTrue(type.isContainerType()); + assertEquals(TypeFactory.unknownType(), type.getKeyType()); + assertEquals(TypeFactory.unknownType(), type.getContentType()); + + type = tf.constructRawMapLikeType(String.class); // class doesn't really matter + assertTrue(type.isMapLikeType()); + assertEquals(TypeFactory.unknownType(), type.getKeyType()); + assertEquals(TypeFactory.unknownType(), type.getContentType()); + } +} +
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/type/TestTypeResolution.java b/1.9.10/src/test/org/codehaus/jackson/map/type/TestTypeResolution.java new file mode 100644 index 0000000..71a564d --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/type/TestTypeResolution.java
@@ -0,0 +1,46 @@ +package org.codehaus.jackson.map.type; + +import java.util.*; + +import org.codehaus.jackson.type.JavaType; +import org.codehaus.jackson.type.TypeReference; + +import main.BaseTest; + +@SuppressWarnings("serial") +public class TestTypeResolution extends BaseTest +{ + public static class LongValuedMap<K> extends HashMap<K, Long> { } + + static class GenericList<X> extends ArrayList<X> { } + static class GenericList2<Y> extends GenericList<Y> { } + + static class LongList extends GenericList2<Long> { } + static class MyLongList<T> extends LongList { } + + public void testMaps() + { + TypeFactory tf = TypeFactory.defaultInstance(); + JavaType t = tf.constructType(new TypeReference<LongValuedMap<String>>() { }); + MapType type = (MapType) t; + assertSame(LongValuedMap.class, type.getRawClass()); + assertEquals(tf.constructType(String.class), type.getKeyType()); + assertEquals(tf.constructType(Long.class), type.getContentType()); + } + + public void testList() + { + JavaType t; + + TypeFactory tf = TypeFactory.defaultInstance(); + t = tf.constructType(new TypeReference<MyLongList<Integer>>() {}); + CollectionType type = (CollectionType) t; + assertSame(MyLongList.class, type.getRawClass()); + assertEquals(tf.constructType(Long.class), type.getContentType()); + + t = tf.constructType(LongList.class); + type = (CollectionType) t; + assertSame(LongList.class, type.getRawClass()); + assertEquals(tf.constructType(Long.class), type.getContentType()); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/util/ISO8601DateFormatTest.java b/1.9.10/src/test/org/codehaus/jackson/map/util/ISO8601DateFormatTest.java new file mode 100644 index 0000000..6aa51ac --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/util/ISO8601DateFormatTest.java
@@ -0,0 +1,41 @@ +package org.codehaus.jackson.map.util; + +import java.text.DateFormat; +import java.util.*; + +import org.codehaus.jackson.map.BaseMapTest; + +/** + * @see ISO8601DateFormat + */ +public class ISO8601DateFormatTest extends BaseMapTest +{ + private ISO8601DateFormat df; + private Date date; + + @Override + public void setUp() + { + Calendar cal = new GregorianCalendar(2007, 8 - 1, 13, 19, 51, 23); + cal.setTimeZone(TimeZone.getTimeZone("GMT")); + cal.set(Calendar.MILLISECOND, 0); + date = cal.getTime(); + df = new ISO8601DateFormat(); + } + + public void testFormat() { + String result = df.format(date); + assertEquals("2007-08-13T19:51:23Z", result); + } + + public void testParse() throws Exception { + Date result = df.parse("2007-08-13T19:51:23Z"); + assertEquals(date, result); + } + + public void testCloneObject() throws Exception { + DateFormat clone = (DateFormat)df.clone(); + assertSame(df, clone); + } + +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/util/ISO8601UtilsTest.java b/1.9.10/src/test/org/codehaus/jackson/map/util/ISO8601UtilsTest.java new file mode 100644 index 0000000..b2a5e32 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/util/ISO8601UtilsTest.java
@@ -0,0 +1,59 @@ +package org.codehaus.jackson.map.util; + +import java.util.*; + +import org.codehaus.jackson.map.BaseMapTest; + +/** + * @see ISO8601Utils + */ +public class ISO8601UtilsTest extends BaseMapTest +{ + private Date date; + private Date dateZeroMillis; + + @Override + public void setUp() + { + Calendar cal = new GregorianCalendar(2007, 8 - 1, 13, 19, 51, 23); + cal.setTimeZone(TimeZone.getTimeZone("GMT")); + cal.set(Calendar.MILLISECOND, 789); + date = cal.getTime(); + cal.set(Calendar.MILLISECOND, 0); + dateZeroMillis = cal.getTime(); + } + + public void testFormat() { + String result = ISO8601Utils.format(date); + assertEquals("2007-08-13T19:51:23Z", result); + } + + public void testFormatMillis() { + String result = ISO8601Utils.format(date, true); + assertEquals("2007-08-13T19:51:23.789Z", result); + + result = ISO8601Utils.format(date, false); + assertEquals("2007-08-13T19:51:23Z", result); + } + + public void testFormatTimeZone() { + String result = ISO8601Utils.format(date, false, TimeZone.getTimeZone("GMT+02:00")); + assertEquals("2007-08-13T21:51:23+02:00", result); + result = ISO8601Utils.format(date, true, TimeZone.getTimeZone("GMT+02:00")); + assertEquals("2007-08-13T21:51:23.789+02:00", result); + result = ISO8601Utils.format(date, true, TimeZone.getTimeZone("GMT")); + assertEquals("2007-08-13T19:51:23.789Z", result); + } + + public void testParse() { + Date d = ISO8601Utils.parse("2007-08-13T19:51:23.789Z"); + assertEquals(date, d); + + d = ISO8601Utils.parse("2007-08-13T19:51:23Z"); + assertEquals(dateZeroMillis, d); + + d = ISO8601Utils.parse("2007-08-13T21:51:23.789+02:00"); + assertEquals(date, d); + } + +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/map/util/TestClassUtil.java b/1.9.10/src/test/org/codehaus/jackson/map/util/TestClassUtil.java new file mode 100644 index 0000000..04df8bc --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/map/util/TestClassUtil.java
@@ -0,0 +1,139 @@ +package org.codehaus.jackson.map.util; + +import java.util.*; + +import static org.junit.Assert.*; + +import org.codehaus.jackson.map.BaseMapTest; +import org.codehaus.jackson.map.util.ClassUtil; + +public class TestClassUtil + extends BaseMapTest +{ + /* + /********************************************************** + /* Test classes, enums + /********************************************************** + */ + + /* Test classes and interfaces needed for testing class util + * methods + */ + static abstract class BaseClass implements Comparable<BaseClass>, + BaseInt + { + BaseClass(String str) { } + } + + interface BaseInt { } + + interface SubInt extends BaseInt { } + + enum TestEnum { A; } + + abstract class InnerNonStatic { } + + static class Inner { + protected Inner() { + throw new IllegalStateException("test"); + } + } + + static abstract class SubClass + extends BaseClass + implements SubInt { + SubClass() { super("x"); } + } + + /* + /********************************************************** + /* Test methods + /********************************************************** + */ + + public void testSuperTypes() + { + Collection<Class<?>> result = ClassUtil.findSuperTypes(SubClass.class, null); + Class<?>[] classes = result.toArray(new Class<?>[result.size()]); + Class<?>[] exp = new Class[] { + SubInt.class, BaseInt.class, + BaseClass.class, + Comparable.class + }; + assertArrayEquals(exp, classes); + } + + public void testSuperInterfaces() + { + Collection<Class<?>> result = ClassUtil.findSuperTypes(SubInt.class, null); + Class<?>[] classes = result.toArray(new Class<?>[result.size()]); + Class<?>[] exp = new Class[] { + BaseInt.class + }; + assertArrayEquals(exp, classes); + } + + public void testIsConcrete() + { + assertTrue(ClassUtil.isConcrete(getClass())); + assertFalse(ClassUtil.isConcrete(BaseClass.class)); + assertFalse(ClassUtil.isConcrete(BaseInt.class)); + } + + public void testCanBeABeanType() + { + assertEquals("annotation", ClassUtil.canBeABeanType(java.lang.annotation.Retention.class)); + assertEquals("array", ClassUtil.canBeABeanType(String[].class)); + assertEquals("enum", ClassUtil.canBeABeanType(TestEnum.class)); + assertEquals("primitive", ClassUtil.canBeABeanType(Integer.TYPE)); + assertNull(ClassUtil.canBeABeanType(Integer.class)); + + assertEquals("non-static member class", ClassUtil.isLocalType(InnerNonStatic.class, false)); + assertNull(ClassUtil.isLocalType(Integer.class, false)); + } + + public void testExceptionHelpers() + { + RuntimeException e = new RuntimeException("test"); + RuntimeException wrapper = new RuntimeException(e); + + assertSame(e, ClassUtil.getRootCause(wrapper)); + + try { + ClassUtil.throwAsIAE(e); + fail("Shouldn't get this far"); + } catch (RuntimeException e2) { + assertSame(e, e2); + } + + try { + ClassUtil.unwrapAndThrowAsIAE(wrapper); + fail("Shouldn't get this far"); + } catch (RuntimeException e2) { + assertSame(e, e2); + } + } + + public void testFailedCreateInstance() + { + try { + ClassUtil.createInstance(BaseClass.class, true); + } catch (IllegalArgumentException e) { + verifyException(e, "has no default"); + } + + try { + // false means ctor would need to be public + ClassUtil.createInstance(Inner.class, false); + } catch (IllegalArgumentException e) { + verifyException(e, "is not accessible"); + } + + // and finally, check that we'll get expected exception... + try { + ClassUtil.createInstance(Inner.class, true); + } catch (IllegalStateException e) { + verifyException(e, "test"); + } + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/mrbean/TestAbstractClasses.java b/1.9.10/src/test/org/codehaus/jackson/mrbean/TestAbstractClasses.java new file mode 100644 index 0000000..29c45c6 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/mrbean/TestAbstractClasses.java
@@ -0,0 +1,43 @@ +package org.codehaus.jackson.mrbean; + +import org.codehaus.jackson.map.BaseMapTest; +import org.codehaus.jackson.map.ObjectMapper; + +public class TestAbstractClasses + extends BaseMapTest +{ + /* + /********************************************************** + /* Test classes, enums + /********************************************************** + */ + + public abstract static class Bean + { + int y; + + protected Bean() { } + + public abstract String getX(); + + public String getFoo() { return "Foo!"; } + public void setY(int value) { y = value; } + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + public void testSimpleInteface() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.registerModule(new MrBeanModule()); + Bean bean = mapper.readValue("{ \"x\" : \"abc\", \"y\" : 13 }", Bean.class); + assertNotNull(bean); + assertEquals("abc", bean.getX()); + assertEquals(13, bean.y); + assertEquals("Foo!", bean.getFoo()); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/mrbean/TestGenericTypes.java b/1.9.10/src/test/org/codehaus/jackson/mrbean/TestGenericTypes.java new file mode 100644 index 0000000..577440c --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/mrbean/TestGenericTypes.java
@@ -0,0 +1,47 @@ +package org.codehaus.jackson.mrbean; + +import java.util.*; + +import org.codehaus.jackson.map.BaseMapTest; +import org.codehaus.jackson.map.ObjectMapper; + +public class TestGenericTypes + extends BaseMapTest +{ + /* + /********************************************************** + /* Test classes, enums + /********************************************************** + */ + + public interface ListBean { + public List<LeafBean> getLeaves(); + } + + public static class LeafBean { + public String value; + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + /** + * Test simple leaf-level bean with 2 implied _beanProperties + */ + public void testSimpleInteface() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.registerModule(new MrBeanModule()); + ListBean bean = mapper.readValue("{\"leaves\":[{\"value\":\"foo\"}] }", ListBean.class); + assertNotNull(bean); + List<LeafBean> leaves = bean.getLeaves(); + assertNotNull(leaves); + assertEquals(1, leaves.size()); + Object ob = leaves.get(0); + assertSame(LeafBean.class, ob.getClass()); + assertEquals("foo", leaves.get(0).value); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/mrbean/TestSimpleMaterializedInterfaces.java b/1.9.10/src/test/org/codehaus/jackson/mrbean/TestSimpleMaterializedInterfaces.java new file mode 100644 index 0000000..d69b13b --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/mrbean/TestSimpleMaterializedInterfaces.java
@@ -0,0 +1,209 @@ +package org.codehaus.jackson.mrbean; + +import static org.junit.Assert.assertArrayEquals; + +import org.codehaus.jackson.map.BaseMapTest; +import org.codehaus.jackson.map.DeserializationConfig; +import org.codehaus.jackson.map.JsonMappingException; +import org.codehaus.jackson.map.ObjectMapper; +import org.codehaus.jackson.mrbean.AbstractTypeMaterializer; + +public class TestSimpleMaterializedInterfaces + extends BaseMapTest +{ + /* + /********************************************************** + /* Test classes, enums + /********************************************************** + */ + + public interface Bean { + public int getX(); + public String getA(); + } + + public interface BeanWithY extends Bean + { + public int getY(); + } + + public interface PartialBean { + public boolean isOk(); + // and then non-getter/setter one: + public int foobar(); + } + + public interface BeanHolder { + public Bean getBean(); + } + + // then invalid one; conflicting setter/getter types + public interface InvalidBean { + public int getX(); + public void setX(String value); + } + + public interface ArrayBean { + public int[] getValues(); + public String[] getWords(); + public void setWords(String[] words); + } + + // how about non-public classes? + interface NonPublicBean { + public abstract int getX(); + } + + /* + /********************************************************** + /* Unit tests, low level + /********************************************************** + */ + + /** + * First test verifies that bean builder works as expected + */ + public void testLowLevelMaterializer() throws Exception + { + AbstractTypeMaterializer mat = new AbstractTypeMaterializer(); + DeserializationConfig config = new ObjectMapper().getDeserializationConfig(); + Class<?> impl = mat.materializeClass(config, Bean.class); + assertNotNull(impl); + assertTrue(Bean.class.isAssignableFrom(impl)); + // also, let's instantiate to make sure: + Object ob = impl.newInstance(); + // and just for good measure do actual cast + Bean bean = (Bean) ob; + // call something to ensure generation worked... + assertNull(bean.getA()); + + // Also: let's verify that we can handle dup calls: + Class<?> impl2 = mat.materializeClass(config, Bean.class); + assertNotNull(impl2); + assertSame(impl, impl2); + } + + public void testLowLevelMaterializerFailOnIncompatible() throws Exception + { + AbstractTypeMaterializer mat = new AbstractTypeMaterializer(); + DeserializationConfig config = new ObjectMapper().getDeserializationConfig(); + try { + mat.materializeClass(config, InvalidBean.class); + fail("Expected exception for incompatible property types"); + } catch (IllegalArgumentException e) { + verifyException(e, "incompatible types"); + } + } + + public void testLowLevelMaterializerFailOnUnrecognized() throws Exception + { + AbstractTypeMaterializer mat = new AbstractTypeMaterializer(); + // by default early failure is disabled, enable: + mat.enable(AbstractTypeMaterializer.Feature.FAIL_ON_UNMATERIALIZED_METHOD); + DeserializationConfig config = new ObjectMapper().getDeserializationConfig(); + try { + mat.materializeClass(config, PartialBean.class); + fail("Expected exception for unrecognized method"); + } catch (IllegalArgumentException e) { + verifyException(e, "Unrecognized abstract method 'foobar'"); + } + } + + /* + /********************************************************** + /* Unit tests, higher level + /********************************************************** + */ + + /** + * Test simple leaf-level bean with 2 implied _beanProperties + */ + public void testSimpleInteface() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.registerModule(new MrBeanModule()); + Bean bean = mapper.readValue("{\"a\":\"value\",\"x\":123 }", Bean.class); + assertNotNull(bean); + assertEquals("value", bean.getA()); + assertEquals(123, bean.getX()); + } + + /** + * Then one bean holding a reference to another (leaf-level) bean + */ + public void testBeanHolder() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.registerModule(new MrBeanModule()); + BeanHolder holder = mapper.readValue("{\"bean\":{\"a\":\"b\",\"x\":-4 }}", BeanHolder.class); + assertNotNull(holder); + Bean bean = holder.getBean(); + assertNotNull(bean); + assertEquals("b", bean.getA()); + assertEquals(-4, bean.getX()); + } + + public void testArrayInterface() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.registerModule(new MrBeanModule()); + ArrayBean bean = mapper.readValue("{\"values\":[1,2,3], \"words\": [ \"cool\", \"beans\" ] }", + ArrayBean.class); + assertNotNull(bean); + assertArrayEquals(new int[] { 1, 2, 3} , bean.getValues()); + assertArrayEquals(new String[] { "cool", "beans" } , bean.getWords()); + } + + public void testSubInterface() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.registerModule(new MrBeanModule()); + BeanWithY bean = mapper.readValue("{\"a\":\"b\",\"x\":1, \"y\":2 }", BeanWithY.class); + assertNotNull(bean); + assertEquals("b", bean.getA()); + assertEquals(1, bean.getX()); + assertEquals(2, bean.getY()); + } + + /* + /********************************************************** + /* Unit tests, higher level, error handling + /********************************************************** + */ + + /** + * Test to verify that materializer will by default create exception-throwing methods + * for "unknown" abstract methods + */ + public void testPartialBean() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + AbstractTypeMaterializer mat = new AbstractTypeMaterializer(); + // ensure that we will only get deferred error methods + mat.disable(AbstractTypeMaterializer.Feature.FAIL_ON_UNMATERIALIZED_METHOD); + mapper.registerModule(new MrBeanModule(mat)); + PartialBean bean = mapper.readValue("{\"ok\":true}", PartialBean.class); + assertNotNull(bean); + assertTrue(bean.isOk()); + // and then exception + try { + bean.foobar(); + } catch (UnsupportedOperationException e) { + verifyException(e, "Unimplemented method 'foobar'"); + } + } + + // As per [JACKSON-683]: fail gracefully if super type not public + public void testNonPublic() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + mapper.registerModule(new MrBeanModule()); + try { + mapper.readValue("{\"x\":3}", NonPublicBean.class); + fail("Should have thrown an exception"); + } catch (JsonMappingException e) { + verifyException(e, "is not public"); + } + } + +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/node/TestArrayNode.java b/1.9.10/src/test/org/codehaus/jackson/node/TestArrayNode.java new file mode 100644 index 0000000..8ee80fb --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/node/TestArrayNode.java
@@ -0,0 +1,156 @@ +package org.codehaus.jackson.node; + +import java.io.*; +import java.util.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.*; + +/** + * Additional tests for {@link ArrayNode} container class. + */ +public class TestArrayNode + extends BaseMapTest +{ + public void testBasics() throws IOException + { + ArrayNode n = new ArrayNode(JsonNodeFactory.instance); + assertStandardEquals(n); + assertFalse(n.getElements().hasNext()); + assertFalse(n.getFieldNames().hasNext()); + TextNode text = TextNode.valueOf("x"); + n.add(text); + assertEquals(1, n.size()); + assertFalse(0 == n.hashCode()); + assertTrue(n.getElements().hasNext()); + // no field names for arrays + assertFalse(n.getFieldNames().hasNext()); + assertNull(n.get("x")); // not used with arrays + assertTrue(n.path("x").isMissingNode()); + assertSame(text, n.get(0)); + + // single element, so: + assertFalse(n.has("field")); + assertTrue(n.has(0)); + assertFalse(n.has(1)); + + // add null node too + n.add((JsonNode) null); + assertEquals(2, n.size()); + assertTrue(n.get(1).isNull()); + // change to text + n.set(1, text); + assertSame(text, n.get(1)); + n.set(0, null); + assertTrue(n.get(0).isNull()); + + // and finally, clear it all + ArrayNode n2 = new ArrayNode(JsonNodeFactory.instance); + n2.add("foobar"); + assertFalse(n.equals(n2)); + n.addAll(n2); + assertEquals(3, n.size()); + + assertFalse(n.get(0).isTextual()); + assertNotNull(n.remove(0)); + assertEquals(2, n.size()); + assertTrue(n.get(0).isTextual()); + + ArrayList<JsonNode> nodes = new ArrayList<JsonNode>(); + nodes.add(text); + n.addAll(nodes); + assertEquals(3, n.size()); + assertNull(n.get(10000)); + assertNull(n.remove(-4)); + + TextNode text2 = TextNode.valueOf("b"); + n.insert(0, text2); + assertEquals(4, n.size()); + assertSame(text2, n.get(0)); + + assertNotNull(n.addArray()); + assertEquals(5, n.size()); + n.addPOJO("foo"); + assertEquals(6, n.size()); + + // Try serializing it for fun, too... + JsonGenerator jg = new MappingJsonFactory().createJsonGenerator(new StringWriter()); + n.serialize(jg, null); + + n.removeAll(); + assertEquals(0, n.size()); + } + + public void testAdds() + { + ArrayNode n = new ArrayNode(JsonNodeFactory.instance); + assertNotNull(n.addArray()); + assertNotNull(n.addObject()); + n.addPOJO("foobar"); + n.add(1); + n.add(1L); + n.add(0.5); + n.add(0.5f); + assertEquals(7, n.size()); + + assertNotNull(n.insertArray(0)); + assertNotNull(n.insertObject(0)); + n.insertPOJO(2, "xxx"); + assertEquals(10, n.size()); + } + + /** + * Test to verify [JACKSON-227] + */ + public void testNullChecking() + { + ArrayNode a1 = JsonNodeFactory.instance.arrayNode(); + ArrayNode a2 = JsonNodeFactory.instance.arrayNode(); + // used to throw NPE before fix: + a1.addAll(a2); + assertEquals(0, a1.size()); + assertEquals(0, a2.size()); + + a2.addAll(a1); + assertEquals(0, a1.size()); + assertEquals(0, a2.size()); + } + + /** + * Another test to verify [JACKSON-227]... + */ + public void testNullChecking2() + { + ObjectMapper mapper = new ObjectMapper(); + ArrayNode src = mapper.createArrayNode(); + ArrayNode dest = mapper.createArrayNode(); + src.add("element"); + dest.addAll(src); + } + + public void testParser() throws Exception + { + ArrayNode n = new ArrayNode(JsonNodeFactory.instance); + n.add(123); + TreeTraversingParser p = new TreeTraversingParser(n, null); + p.setCodec(null); + assertNull(p.getCodec()); + assertNotNull(p.getParsingContext()); + assertNotNull(p.getTokenLocation()); + assertNotNull(p.getCurrentLocation()); + assertNull(p.getEmbeddedObject()); + assertNull(p.currentNode()); + + //assertNull(p.getNumberType()); + + assertToken(JsonToken.START_ARRAY, p.nextToken()); + p.skipChildren(); + assertToken(JsonToken.END_ARRAY, p.getCurrentToken()); + p.close(); + + p = new TreeTraversingParser(n, null); + p.nextToken(); + assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); + assertEquals(JsonParser.NumberType.INT, p.getNumberType()); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/node/TestConversions.java b/1.9.10/src/test/org/codehaus/jackson/node/TestConversions.java new file mode 100644 index 0000000..c2f1414 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/node/TestConversions.java
@@ -0,0 +1,198 @@ +package org.codehaus.jackson.node; + +import java.io.IOException; + +import static org.junit.Assert.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.JsonDeserialize; +import org.codehaus.jackson.util.TokenBuffer; +import org.junit.Assert; + +/** + * Unit tests for verifying functionality of {@link JsonNode} methods that + * convert values to other types + * + * @since 1.7 + */ +public class TestConversions extends BaseMapTest +{ + static class Root { + public Leaf leaf; + } + + static class Leaf { + public int value; + } + + // MixIn for [JACKSON-554] + @JsonDeserialize(using = LeafDeserializer.class) + public static class LeafMixIn + { + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + public void testAsInt() throws Exception + { + assertEquals(9, IntNode.valueOf(9).asInt()); + assertEquals(7, LongNode.valueOf(7L).asInt()); + assertEquals(13, new TextNode("13").asInt()); + assertEquals(0, new TextNode("foobar").asInt()); + assertEquals(27, new TextNode("foobar").asInt(27)); + assertEquals(1, BooleanNode.TRUE.asInt()); + } + + public void testAsBoolean() throws Exception + { + assertEquals(false, BooleanNode.FALSE.asBoolean()); + assertEquals(true, BooleanNode.TRUE.asBoolean()); + assertEquals(false, IntNode.valueOf(0).asBoolean()); + assertEquals(true, IntNode.valueOf(1).asBoolean()); + assertEquals(false, LongNode.valueOf(0).asBoolean()); + assertEquals(true, LongNode.valueOf(-34L).asBoolean()); + assertEquals(true, new TextNode("true").asBoolean()); + assertEquals(false, new TextNode("false").asBoolean()); + assertEquals(false, new TextNode("barf").asBoolean()); + assertEquals(true, new TextNode("barf").asBoolean(true)); + + assertEquals(true, new POJONode(Boolean.TRUE).asBoolean()); + } + + // Deserializer to trigger the problem described in [JACKSON-554] + public static class LeafDeserializer extends JsonDeserializer<Leaf> + { + @Override + public Leaf deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + JsonNode tree = jp.readValueAsTree(); + Leaf leaf = new Leaf(); + leaf.value = tree.get("value").getIntValue(); + return leaf; + } + } + + // Test for [JACKSON-554] + public void testTreeToValue() throws Exception + { + String JSON = "{\"leaf\":{\"value\":13}}"; + ObjectMapper mapper = new ObjectMapper(); + mapper.getDeserializationConfig().addMixInAnnotations(Leaf.class, LeafMixIn.class); + JsonNode root = mapper.readTree(JSON); + // Ok, try converting to bean using two mechanisms + Root r1 = mapper.treeToValue(root, Root.class); + assertNotNull(r1); + assertEquals(13, r1.leaf.value); + Root r2 = mapper.readValue(root, Root.class); + assertEquals(13, r2.leaf.value); + } + + // Test for [JACKSON-631] + public void testBase64Text() throws Exception + { + // let's actually iterate over sets of encoding modes, lengths + + final int[] LENS = { 1, 2, 3, 4, 7, 9, 32, 33, 34, 35 }; + final Base64Variant[] VARIANTS = { + Base64Variants.MIME, + Base64Variants.MIME_NO_LINEFEEDS, + Base64Variants.MODIFIED_FOR_URL, + Base64Variants.PEM + }; + + for (int len : LENS) { + byte[] input = new byte[len]; + for (int i = 0; i < input.length; ++i) { + input[i] = (byte) i; + } + for (Base64Variant variant : VARIANTS) { + TextNode n = new TextNode(variant.encode(input)); + byte[] data = null; + try { + data = n.getBinaryValue(variant); + } catch (Exception e) { + throw new IOException("Failed (variant "+variant+", data length "+len+"): "+e.getMessage(), e); + } + assertNotNull(data); + assertArrayEquals(data, input); + } + } + } + + static class Issue709Bean { + public byte[] data; + } + + /** + * Simple test to verify that byte[] values can be handled properly when + * converting, as long as there is metadata (from POJO definitions). + */ + public void testIssue709() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + byte[] inputData = new byte[] { 1, 2, 3 }; + ObjectNode node = mapper.createObjectNode(); + node.put("data", inputData); + Issue709Bean result = mapper.readValue(node, Issue709Bean.class); + String json = mapper.writeValueAsString(node); + Issue709Bean resultFromString = mapper.readValue(json, Issue709Bean.class); + Issue709Bean resultFromConvert = mapper.convertValue(node, Issue709Bean.class); + + // all methods should work equally well: + Assert.assertArrayEquals(inputData, resultFromString.data); + Assert.assertArrayEquals(inputData, resultFromConvert.data); + Assert.assertArrayEquals(inputData, result.data); + } + + public void testBinaryData() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + TokenBuffer buf = new TokenBuffer(mapper); + buf.writeObject(new byte[3]); + JsonNode node = mapper.readTree(buf.asParser()); +// assertTrue(node.isBinary()); + byte[] data = node.getBinaryValue(); + assertNotNull(data); + assertEquals(3, data.length); + } + + private final Object MARKER = new Object(); + + public void testEmbeddedObjectInArray() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + TokenBuffer buf = new TokenBuffer(mapper); + buf.writeStartArray(); + buf.writeObject(MARKER); + buf.writeEndArray(); + JsonNode node = mapper.readTree(buf.asParser()); + assertTrue(node.isArray()); + assertEquals(1, node.size()); + JsonNode n = node.get(0); + assertTrue(n.isPojo()); + assertSame(MARKER, ((POJONode) n).getPojo()); + } + + public void testEmbeddedObjectInObject() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + TokenBuffer buf = new TokenBuffer(mapper); + buf.writeStartObject(); + buf.writeFieldName("pojo"); + buf.writeObject(MARKER); + buf.writeEndObject(); + JsonNode node = mapper.readTree(buf.asParser()); + assertTrue(node.isObject()); + assertEquals(1, node.size()); + JsonNode n = node.get("pojo"); + assertTrue(n.isPojo()); + assertSame(MARKER, ((POJONode) n).getPojo()); + } +} +
diff --git a/1.9.10/src/test/org/codehaus/jackson/node/TestFindMethods.java b/1.9.10/src/test/org/codehaus/jackson/node/TestFindMethods.java new file mode 100644 index 0000000..5e1c0e2 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/node/TestFindMethods.java
@@ -0,0 +1,72 @@ +package org.codehaus.jackson.node; + +import java.util.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.BaseMapTest; +import org.codehaus.jackson.map.ObjectMapper; + +public class TestFindMethods + extends BaseMapTest +{ + public void testNonMatching() throws Exception + { + JsonNode root = _buildTree(); + + assertNull(root.findValue("boogaboo")); + assertNull(root.findParent("boogaboo")); + JsonNode n = root.findPath("boogaboo"); + assertNotNull(n); + assertTrue(n.isMissingNode()); + + assertTrue(root.findValues("boogaboo").isEmpty()); + assertTrue(root.findParents("boogaboo").isEmpty()); + } + + public void testMatchingSingle() throws Exception + { + JsonNode root = _buildTree(); + + JsonNode node = root.findValue("b"); + assertNotNull(node); + assertEquals(3, node.getIntValue()); + node = root.findParent("b"); + assertNotNull(node); + assertTrue(node.isObject()); + assertEquals(1, ((ObjectNode) node).size()); + assertEquals(3, node.path("b").getIntValue()); + } + + public void testMatchingMultiple() throws Exception + { + JsonNode root = _buildTree(); + + List<JsonNode> nodes = root.findValues("value"); + assertEquals(2, nodes.size()); + // here we count on nodes being returned in order; true with Jackson: + assertEquals(3, nodes.get(0).getIntValue()); + assertEquals(42, nodes.get(1).getIntValue()); + + nodes = root.findParents("value"); + assertEquals(2, nodes.size()); + // should only return JSON Object nodes: + assertTrue(nodes.get(0).isObject()); + assertTrue(nodes.get(1).isObject()); + assertEquals(3, nodes.get(0).path("value").getIntValue()); + assertEquals(42, nodes.get(1).path("value").getIntValue()); + + // and finally, convenience conversion method + List<String> values = root.findValuesAsText("value"); + assertEquals(2, values.size()); + assertEquals("3", values.get(0)); + assertEquals("42", values.get(1)); + } + + private JsonNode _buildTree() throws Exception + { + final String SAMPLE = "{ \"a\" : { \"value\" : 3 }," + +"\"array\" : [ { \"b\" : 3 }, {\"value\" : 42}, { \"other\" : true } ]" + +"}"; + return new ObjectMapper().readTree(SAMPLE); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/node/TestJsonNode.java b/1.9.10/src/test/org/codehaus/jackson/node/TestJsonNode.java new file mode 100644 index 0000000..b91c403 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/node/TestJsonNode.java
@@ -0,0 +1,262 @@ +package org.codehaus.jackson.node; + +import java.math.BigInteger; +import java.math.BigDecimal; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.*; + +/** + * Basic tests for {@link JsonNode} base class and some features + * of implementation classes + */ +public class TestJsonNode + extends BaseMapTest +{ + public void testBasicsWithNullNode() throws Exception + { + // Let's use something that doesn't add much beyond JsonNode base + NullNode n = NullNode.instance; + + // basic properties + assertFalse(n.isContainerNode()); + assertFalse(n.isBigDecimal()); + assertFalse(n.isBigInteger()); + assertFalse(n.isBinary()); + assertFalse(n.isBoolean()); + assertFalse(n.isPojo()); + assertFalse(n.isMissingNode()); + + // fallback accessors + assertFalse(n.getBooleanValue()); + assertNull(n.getNumberValue()); + assertEquals(0, n.getIntValue()); + assertEquals(0L, n.getLongValue()); + assertEquals(BigDecimal.ZERO, n.getDecimalValue()); + assertEquals(BigInteger.ZERO, n.getBigIntegerValue()); + + assertEquals(0, n.size()); + assertFalse(n.getElements().hasNext()); + assertFalse(n.getFieldNames().hasNext()); + // path is never null; but does point to missing node + assertNotNull(n.path("xyz")); + assertTrue(n.path("xyz").isMissingNode()); + + assertFalse(n.has("field")); + assertFalse(n.has(3)); + + // 1.6: + assertNodeNumbers(n, 0, 0.0); + } + + public void testText() + { + assertNull(TextNode.valueOf(null)); + TextNode empty = TextNode.valueOf(""); + assertStandardEquals(empty); + assertSame(TextNode.EMPTY_STRING_NODE, empty); + + // 1.6: + assertNodeNumbers(TextNode.valueOf("-3"), -3, -3.0); + assertNodeNumbers(TextNode.valueOf("17.75"), 17, 17.75); + + // [JACKSON-587] + long value = 127353264013893L; + TextNode n = TextNode.valueOf(String.valueOf(value)); + assertEquals(value, n.asLong()); + + // and then with non-numeric input + assertNodeNumbersForNonNumeric(TextNode.valueOf("foobar")); + + } + + public void testBoolean() + { + BooleanNode f = BooleanNode.getFalse(); + assertNotNull(f); + assertTrue(f.isBoolean()); + assertSame(f, BooleanNode.valueOf(false)); + assertStandardEquals(f); + assertFalse(f.getBooleanValue()); + assertEquals("false", f.asText()); + assertEquals(JsonToken.VALUE_FALSE, f.asToken()); + + // and ditto for true + BooleanNode t = BooleanNode.getTrue(); + assertNotNull(t); + assertTrue(t.isBoolean()); + assertSame(t, BooleanNode.valueOf(true)); + assertStandardEquals(t); + assertTrue(t.getBooleanValue()); + assertEquals("true", t.asText()); + assertEquals(JsonToken.VALUE_TRUE, t.asToken()); + + // 1.6: + assertNodeNumbers(f, 0, 0.0); + assertNodeNumbers(t, 1, 1.0); + } + + public void testInt() + { + IntNode n = IntNode.valueOf(1); + assertStandardEquals(n); + assertTrue(0 != n.hashCode()); + assertEquals(JsonToken.VALUE_NUMBER_INT, n.asToken()); + assertEquals(JsonParser.NumberType.INT, n.getNumberType()); + assertEquals(1, n.getIntValue()); + assertEquals(1L, n.getLongValue()); + assertEquals(BigDecimal.ONE, n.getDecimalValue()); + assertEquals(BigInteger.ONE, n.getBigIntegerValue()); + assertEquals("1", n.asText()); + + // 1.6: + assertNodeNumbers(n, 1, 1.0); + } + + public void testLong() + { + LongNode n = LongNode.valueOf(1L); + assertStandardEquals(n); + assertTrue(0 != n.hashCode()); + assertEquals(JsonToken.VALUE_NUMBER_INT, n.asToken()); + assertEquals(JsonParser.NumberType.LONG, n.getNumberType()); + assertEquals(1, n.getIntValue()); + assertEquals(1L, n.getLongValue()); + assertEquals(BigDecimal.ONE, n.getDecimalValue()); + assertEquals(BigInteger.ONE, n.getBigIntegerValue()); + assertEquals("1", n.asText()); + + // 1.6: + assertNodeNumbers(n, 1, 1.0); + } + + public void testDouble() + { + DoubleNode n = DoubleNode.valueOf(0.25); + assertStandardEquals(n); + assertTrue(0 != n.hashCode()); + assertEquals(JsonToken.VALUE_NUMBER_FLOAT, n.asToken()); + assertEquals(JsonParser.NumberType.DOUBLE, n.getNumberType()); + assertEquals(0, n.getIntValue()); + assertEquals(0.25, n.getDoubleValue()); + assertNotNull(n.getDecimalValue()); + assertEquals(BigInteger.ZERO, n.getBigIntegerValue()); + assertEquals("0.25", n.asText()); + + // 1.6: + assertNodeNumbers(DoubleNode.valueOf(4.5), 4, 4.5); + } + + public void testDecimalNode() throws Exception + { + DecimalNode n = DecimalNode.valueOf(BigDecimal.ONE); + assertStandardEquals(n); + assertTrue(n.equals(new DecimalNode(BigDecimal.ONE))); + assertEquals(JsonToken.VALUE_NUMBER_FLOAT, n.asToken()); + assertEquals(JsonParser.NumberType.BIG_DECIMAL, n.getNumberType()); + assertTrue(n.isNumber()); + assertFalse(n.isIntegralNumber()); + assertTrue(n.isBigDecimal()); + assertEquals(BigDecimal.ONE, n.getNumberValue()); + assertEquals(1, n.getIntValue()); + assertEquals(1L, n.getLongValue()); + assertEquals(BigDecimal.ONE, n.getDecimalValue()); + assertEquals("1", n.asText()); + + // 1.6: + assertNodeNumbers(n, 1, 1.0); + } + + public void testBigIntegerNode() throws Exception + { + BigIntegerNode n = BigIntegerNode.valueOf(BigInteger.ONE); + assertStandardEquals(n); + assertTrue(n.equals(new BigIntegerNode(BigInteger.ONE))); + assertEquals(JsonToken.VALUE_NUMBER_INT, n.asToken()); + assertEquals(JsonParser.NumberType.BIG_INTEGER, n.getNumberType()); + assertTrue(n.isNumber()); + assertTrue(n.isIntegralNumber()); + assertTrue(n.isBigInteger()); + assertEquals(BigInteger.ONE, n.getNumberValue()); + assertEquals(1, n.getIntValue()); + assertEquals(1L, n.getLongValue()); + assertEquals(BigInteger.ONE, n.getBigIntegerValue()); + assertEquals("1", n.asText()); + + // 1.6: + assertNodeNumbers(n, 1, 1.0); + + BigInteger maxLong = BigInteger.valueOf(Long.MAX_VALUE); + + n = BigIntegerNode.valueOf(maxLong); + assertEquals(Long.MAX_VALUE, n.getLongValue()); + + ObjectMapper mapper = new ObjectMapper(); + JsonNode n2 = mapper.readTree(maxLong.toString()); + assertEquals(Long.MAX_VALUE, n2.getLongValue()); + + // then over long limit: + BigInteger beyondLong = maxLong.shiftLeft(2); // 4x max long + n2 = mapper.readTree(beyondLong.toString()); + assertEquals(beyondLong, n2.getBigIntegerValue()); + } + + public void testBinary() throws Exception + { + assertNull(BinaryNode.valueOf(null)); + assertNull(BinaryNode.valueOf(null, 0, 0)); + + BinaryNode empty = BinaryNode.valueOf(new byte[1], 0, 0); + assertSame(BinaryNode.EMPTY_BINARY_NODE, empty); + assertStandardEquals(empty); + + byte[] data = new byte[3]; + data[1] = (byte) 3; + BinaryNode n = BinaryNode.valueOf(data, 1, 1); + data[2] = (byte) 3; + BinaryNode n2 = BinaryNode.valueOf(data, 2, 1); + assertTrue(n.equals(n2)); + assertEquals("\"Aw==\"", n.toString()); + + assertEquals("AAMD", new BinaryNode(data).asText()); + + // 1.6: + assertNodeNumbersForNonNumeric(n); + } + + public void testPOJO() + { + POJONode n = new POJONode("x"); // not really a pojo but that's ok + assertStandardEquals(n); + assertEquals(n, new POJONode("x")); + assertEquals("x", n.asText()); + // not sure if this is what it'll remain as but: + assertEquals("x", n.toString()); + + assertEquals(new POJONode(null), new POJONode(null)); + + // 1.6: + // default; non-numeric + assertNodeNumbersForNonNumeric(n); + // but if wrapping actual number, use it + assertNodeNumbers(new POJONode(Integer.valueOf(123)), 123, 123.0); + } + + public void testMissing() + { + MissingNode n = MissingNode.getInstance(); + assertEquals(JsonToken.NOT_AVAILABLE, n.asToken()); + assertEquals("", n.asText()); + assertStandardEquals(n); + assertEquals("", n.toString()); + + // missing acts same as null, so: + assertNodeNumbersForNonNumeric(n); + + // [JACKSON-823] + assertEquals(4, n.asInt(4)); + assertEquals(5L, n.asLong(5)); + assertEquals(0.25, n.asDouble(0.25)); + assertTrue(n.asBoolean(true)); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/node/TestNodeFactoryConfig.java b/1.9.10/src/test/org/codehaus/jackson/node/TestNodeFactoryConfig.java new file mode 100644 index 0000000..5d1a7b2 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/node/TestNodeFactoryConfig.java
@@ -0,0 +1,70 @@ +package org.codehaus.jackson.node; + +import org.codehaus.jackson.map.BaseMapTest; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.*; + +/** + * Unit tests for ensuring that it is possible to override default + * {@link JsonNodeFactory} when doing data binding + */ +public class TestNodeFactoryConfig + extends BaseMapTest +{ + /* + /********************************************************** + /* Test classes + /********************************************************** + */ + + /** + * Test factory that just replaces JSON Object node with + * custom version + */ + static class MyNodeFactory + extends JsonNodeFactory + { + @Override + public ObjectNode objectNode() { return new MyObjectNode(this); } + + } + + static class MyObjectNode + extends ObjectNode + { + public MyObjectNode(JsonNodeFactory f) { + super(f); + } + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + /** + * Verifying [JACKSON-321] + */ + public void testWithObjectMapper() throws Exception + { + ObjectMapper m = new ObjectMapper(); + m.setNodeFactory(new MyNodeFactory()); + JsonNode n = m.readTree("{ \"a\":3 }"); + assertNotNull(n); + assertSame(MyObjectNode.class, n.getClass()); + } + + /** + * Verifying [JACKSON-321] + */ + public void testWithObjectReader() throws Exception + { + ObjectMapper m = new ObjectMapper(); + ObjectReader reader = m.reader(new MyNodeFactory()); + JsonNode n = reader.readTree("{ \"a\":3 }"); + assertNotNull(n); + assertSame(MyObjectNode.class, n.getClass()); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/node/TestObjectNode.java b/1.9.10/src/test/org/codehaus/jackson/node/TestObjectNode.java new file mode 100644 index 0000000..86784ef --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/node/TestObjectNode.java
@@ -0,0 +1,163 @@ +package org.codehaus.jackson.node; + +import java.math.BigDecimal; +import java.util.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.*; + +/** + * Additional tests for {@link ObjectNode} container class. + */ +public class TestObjectNode + extends BaseMapTest +{ + public void testBasics() + { + ObjectNode n = new ObjectNode(JsonNodeFactory.instance); + assertStandardEquals(n); + + assertFalse(n.getElements().hasNext()); + assertFalse(n.getFields().hasNext()); + assertFalse(n.getFieldNames().hasNext()); + assertNull(n.get("a")); + assertTrue(n.path("a").isMissingNode()); + + TextNode text = TextNode.valueOf("x"); + n.put("a", text); + assertEquals(1, n.size()); + assertTrue(n.getElements().hasNext()); + assertTrue(n.getFields().hasNext()); + assertTrue(n.getFieldNames().hasNext()); + assertSame(text, n.get("a")); + assertSame(text, n.path("a")); + assertNull(n.get("b")); + assertNull(n.get(0)); // not used with objects + + assertFalse(n.has(0)); + assertTrue(n.has("a")); + assertFalse(n.has("b")); + + ObjectNode n2 = new ObjectNode(JsonNodeFactory.instance); + n2.put("b", 13); + assertFalse(n.equals(n2)); + n.putAll(n2); + assertEquals(2, n.size()); + n.put("null", (JsonNode)null); + assertEquals(3, n.size()); + // should replace, not add + n.put("null", "notReallNull"); + assertEquals(3, n.size()); + assertNotNull(n.remove("null")); + assertEquals(2, n.size()); + + Map<String,JsonNode> nodes = new HashMap<String,JsonNode>(); + nodes.put("d", text); + n.putAll(nodes); + assertEquals(3, n.size()); + + n.removeAll(); + assertEquals(0, n.size()); + } + + /** + * Verify null handling + */ + public void testNullChecking() + { + ObjectNode o1 = JsonNodeFactory.instance.objectNode(); + ObjectNode o2 = JsonNodeFactory.instance.objectNode(); + // used to throw NPE before fix: + o1.putAll(o2); + assertEquals(0, o1.size()); + assertEquals(0, o2.size()); + + // also: nulls should be converted to NullNodes... + o1.put("x", (ObjectNode) null); + JsonNode n = o1.get("x"); + assertNotNull(n); + assertSame(n, NullNode.instance); + + o1.put("str", (String) null); + n = o1.get("str"); + assertNotNull(n); + assertSame(n, NullNode.instance); + + o1.put("d", (BigDecimal) null); + n = o1.get("d"); + assertNotNull(n); + assertSame(n, NullNode.instance); + } + + /** + * Another test to verify [JACKSON-227]... + */ + public void testNullChecking2() + { + ObjectMapper mapper = new ObjectMapper(); + ObjectNode src = mapper.createObjectNode(); + ObjectNode dest = mapper.createObjectNode(); + src.put("a", "b"); + dest.putAll(src); + } + + public void testRemove() + { + ObjectMapper mapper = new ObjectMapper(); + ObjectNode ob = mapper.createObjectNode(); + ob.put("a", "a"); + ob.put("b", "b"); + ob.put("c", "c"); + assertEquals(3, ob.size()); + assertSame(ob, ob.remove(Arrays.asList("a", "c"))); + assertEquals(1, ob.size()); + assertEquals("b", ob.get("b").getTextValue()); + } + + public void testRetain() + { + ObjectMapper mapper = new ObjectMapper(); + ObjectNode ob = mapper.createObjectNode(); + ob.put("a", "a"); + ob.put("b", "b"); + ob.put("c", "c"); + assertEquals(3, ob.size()); + assertSame(ob, ob.retain("a", "c")); + assertEquals(2, ob.size()); + assertEquals("a", ob.get("a").getTextValue()); + assertNull(ob.get("b")); + assertEquals("c", ob.get("c").getTextValue()); + } + + // @since 1.8 + public void testValidWith() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + ObjectNode root = mapper.createObjectNode(); + assertEquals("{}", mapper.writeValueAsString(root)); + JsonNode child = root.with("prop"); + assertTrue(child instanceof ObjectNode); + assertEquals("{\"prop\":{}}", mapper.writeValueAsString(root)); + } + + public void testInvalidWith() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + JsonNode root = mapper.createArrayNode(); + try { // should not work for non-ObjectNode nodes: + root.with("prop"); + fail("Expected exception"); + } catch (UnsupportedOperationException e) { + verifyException(e, "not of type ObjectNode"); + } + // also: should fail of we already have non-object property + ObjectNode root2 = mapper.createObjectNode(); + root2.put("prop", 13); + try { // should not work for non-ObjectNode nodes: + root2.with("prop"); + fail("Expected exception"); + } catch (UnsupportedOperationException e) { + verifyException(e, "has value that is not"); + } + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/node/TestTreeTraversingParser.java b/1.9.10/src/test/org/codehaus/jackson/node/TestTreeTraversingParser.java new file mode 100644 index 0000000..f134b0a --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/node/TestTreeTraversingParser.java
@@ -0,0 +1,268 @@ +package org.codehaus.jackson.node; + +import java.util.*; + +import static org.junit.Assert.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.annotate.JsonIgnoreProperties; +import org.codehaus.jackson.map.*; + +public class TestTreeTraversingParser + extends BaseMapTest +{ + static class Person { + public String name; + public int magicNumber; + public List<String> kids; + } + + // Helper class for [JACKSON-370] + @JsonIgnoreProperties(ignoreUnknown=true) + public static class Jackson370Bean { + public Inner inner; + } + + public static class Inner { + public String value; + } + + /* + /********************************************************** + /* Test methods + /********************************************************** + */ + + public void testSimple() throws Exception + { + // For convenience, parse tree from JSON first + final String JSON = + "{ \"a\" : 123, \"list\" : [ 12.25, null, true, { }, [ ] ] }"; + ObjectMapper m = new ObjectMapper(); + JsonNode tree = m.readTree(JSON); + JsonParser jp = tree.traverse(); + + assertNull(jp.getCurrentToken()); + assertNull(jp.getCurrentName()); + + assertToken(JsonToken.START_OBJECT, jp.nextToken()); + assertNull(jp.getCurrentName()); + assertEquals("Expected START_OBJECT", JsonToken.START_OBJECT.asString(), jp.getText()); + + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals("a", jp.getCurrentName()); + assertEquals("a", jp.getText()); + + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals("a", jp.getCurrentName()); + assertEquals(123, jp.getIntValue()); + assertEquals("123", jp.getText()); + + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals("list", jp.getCurrentName()); + assertEquals("list", jp.getText()); + + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + assertEquals("list", jp.getCurrentName()); + assertEquals(JsonToken.START_ARRAY.asString(), jp.getText()); + + assertToken(JsonToken.VALUE_NUMBER_FLOAT, jp.nextToken()); + assertNull(jp.getCurrentName()); + assertEquals(12.25, jp.getDoubleValue()); + assertEquals("12.25", jp.getText()); + + assertToken(JsonToken.VALUE_NULL, jp.nextToken()); + assertNull(jp.getCurrentName()); + assertEquals(JsonToken.VALUE_NULL.asString(), jp.getText()); + + assertToken(JsonToken.VALUE_TRUE, jp.nextToken()); + assertNull(jp.getCurrentName()); + assertTrue(jp.getBooleanValue()); + assertEquals(JsonToken.VALUE_TRUE.asString(), jp.getText()); + + assertToken(JsonToken.START_OBJECT, jp.nextToken()); + assertNull(jp.getCurrentName()); + assertToken(JsonToken.END_OBJECT, jp.nextToken()); + assertNull(jp.getCurrentName()); + + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + assertNull(jp.getCurrentName()); + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + assertNull(jp.getCurrentName()); + + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + + assertToken(JsonToken.END_OBJECT, jp.nextToken()); + assertNull(jp.getCurrentName()); + + assertNull(jp.nextToken()); + + jp.close(); + assertTrue(jp.isClosed()); + } + + public void testArray() throws Exception + { + // For convenience, parse tree from JSON first + ObjectMapper m = new ObjectMapper(); + + JsonParser jp = m.readTree("[]").traverse(); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + jp.close(); + + jp = m.readTree("[[]]").traverse(); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + jp.close(); + + jp = m.readTree("[[ 12.1 ]]").traverse(); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + assertToken(JsonToken.VALUE_NUMBER_FLOAT, jp.nextToken()); + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + jp.close(); + } + + public void testNested() throws Exception + { + // For convenience, parse tree from JSON first + final String JSON = + "{\"coordinates\":[[[-3,\n1],[179.859681,51.175092]]]}" + ; + ObjectMapper m = new ObjectMapper(); + JsonNode tree = m.readTree(JSON); + JsonParser jp = tree.traverse(); + assertToken(JsonToken.START_OBJECT, jp.nextToken()); + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + assertToken(JsonToken.VALUE_NUMBER_FLOAT, jp.nextToken()); + assertToken(JsonToken.VALUE_NUMBER_FLOAT, jp.nextToken()); + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + + assertToken(JsonToken.END_OBJECT, jp.nextToken()); + } + + /** + * Unit test that verifies that we can (re)parse sample document + * from JSON specification. + */ + public void testSpecDoc() throws Exception + { + ObjectMapper m = new ObjectMapper(); + JsonNode tree = m.readTree(SAMPLE_DOC_JSON_SPEC); + JsonParser jp = tree.traverse(); + + verifyJsonSpecSampleDoc(jp, true); + } + + public void testBinaryPojo() throws Exception + { + byte[] inputBinary = new byte[] { 1, 2, 100 }; + POJONode n = new POJONode(inputBinary); + JsonParser jp = n.traverse(); + + assertNull(jp.getCurrentToken()); + assertToken(JsonToken.VALUE_EMBEDDED_OBJECT, jp.nextToken()); + byte[] data = jp.getBinaryValue(); + assertNotNull(data); + assertArrayEquals(inputBinary, data); + Object pojo = jp.getEmbeddedObject(); + assertSame(data, pojo); + } + + public void testBinaryNode() throws Exception + { + byte[] inputBinary = new byte[] { 0, -5 }; + BinaryNode n = new BinaryNode(inputBinary); + JsonParser jp = n.traverse(); + + assertNull(jp.getCurrentToken()); + // exposed as POJO... not as VALUE_STRING + assertToken(JsonToken.VALUE_EMBEDDED_OBJECT, jp.nextToken()); + byte[] data = jp.getBinaryValue(); + assertNotNull(data); + assertArrayEquals(inputBinary, data); + + // but as importantly, can be viewed as base64 encoded thing: + assertEquals("APs=", jp.getText()); + + assertNull(jp.nextToken()); + } + + public void testTextAsBinary() throws Exception + { + TextNode n = new TextNode(" APs=\n"); + JsonParser jp = n.traverse(); + assertNull(jp.getCurrentToken()); + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + byte[] data = jp.getBinaryValue(); + assertNotNull(data); + assertArrayEquals(new byte[] { 0, -5 }, data); + + assertNull(jp.nextToken()); + jp.close(); + assertTrue(jp.isClosed()); + + // Also: let's verify we get an exception for garbage... + n = new TextNode("?!??"); + jp = n.traverse(); + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + try { + jp.getBinaryValue(); + } catch (JsonParseException e) { + verifyException(e, "Illegal character"); + } + } + + /** + * Very simple test case to verify that tree-to-POJO + * conversion works ok + */ + public void testDataBind() throws Exception + { + ObjectMapper m = new ObjectMapper(); + JsonNode tree = m.readTree + ("{ \"name\" : \"Tatu\", \n" + +"\"magicNumber\" : 42," + +"\"kids\" : [ \"Leo\", \"Lila\", \"Leia\" ] \n" + +"}"); + Person tatu = m.treeToValue(tree, Person.class); + assertNotNull(tatu); + assertEquals(42, tatu.magicNumber); + assertEquals("Tatu", tatu.name); + assertNotNull(tatu.kids); + assertEquals(3, tatu.kids.size()); + assertEquals("Leo", tatu.kids.get(0)); + assertEquals("Lila", tatu.kids.get(1)); + assertEquals("Leia", tatu.kids.get(2)); + } + + // [JACKSON-370] + public void testSkipChildrenWrt370() throws Exception + { + ObjectMapper o = new ObjectMapper(); + ObjectNode n = o.createObjectNode(); + n.putObject("inner").put("value", "test"); + n.putObject("unknown").putNull("inner"); + Jackson370Bean obj = o.readValue(n.traverse(), Jackson370Bean.class); + assertNotNull(obj.inner); + assertEquals("test", obj.inner.value); + } +} +
diff --git a/1.9.10/src/test/org/codehaus/jackson/schema/TestGenerateJsonSchema.java b/1.9.10/src/test/org/codehaus/jackson/schema/TestGenerateJsonSchema.java new file mode 100644 index 0000000..19fff5f --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/schema/TestGenerateJsonSchema.java
@@ -0,0 +1,166 @@ +package org.codehaus.jackson.schema; + +import java.util.*; + +import org.codehaus.jackson.map.ObjectMapper; +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.node.ObjectNode; + +/** + * @author Ryan Heaton + */ +public class TestGenerateJsonSchema + extends org.codehaus.jackson.map.BaseMapTest +{ + /* + /********************************************************** + /* Helper classes + /********************************************************** + */ + + public static class SimpleBean + { + private int property1; + private String property2; + private String[] property3; + private Collection<Float> property4; + + public int getProperty1() + { + return property1; + } + + public void setProperty1(int property1) + { + this.property1 = property1; + } + + public String getProperty2() + { + return property2; + } + + public void setProperty2(String property2) + { + this.property2 = property2; + } + + public String[] getProperty3() + { + return property3; + } + + public void setProperty3(String[] property3) + { + this.property3 = property3; + } + + public Collection<Float> getProperty4() + { + return property4; + } + + public void setProperty4(Collection<Float> property4) + { + this.property4 = property4; + } + } + + public class TrivialBean { + public String name; + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + /** + * tests generating json-schema stuff. + */ + public void testGeneratingJsonSchema() + throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + JsonSchema jsonSchema = mapper.generateJsonSchema(SimpleBean.class); + assertNotNull(jsonSchema); + + // test basic equality, and that equals() handles null, other obs + assertTrue(jsonSchema.equals(jsonSchema)); + assertFalse(jsonSchema.equals(null)); + assertFalse(jsonSchema.equals("foo")); + + // other basic things + assertNotNull(jsonSchema.toString()); + assertNotNull(JsonSchema.getDefaultSchemaNode()); + + ObjectNode root = jsonSchema.getSchemaNode(); + assertEquals("object", root.get("type").asText()); + assertEquals(false, root.path("required").getBooleanValue()); + JsonNode propertiesSchema = root.get("properties"); + assertNotNull(propertiesSchema); + JsonNode property1Schema = propertiesSchema.get("property1"); + assertNotNull(property1Schema); + assertEquals("integer", property1Schema.get("type").asText()); + assertEquals(false, property1Schema.path("required").getBooleanValue()); + JsonNode property2Schema = propertiesSchema.get("property2"); + assertNotNull(property2Schema); + assertEquals("string", property2Schema.get("type").asText()); + assertEquals(false, property2Schema.path("required").getBooleanValue()); + JsonNode property3Schema = propertiesSchema.get("property3"); + assertNotNull(property3Schema); + assertEquals("array", property3Schema.get("type").asText()); + assertEquals(false, property3Schema.path("required").getBooleanValue()); + assertEquals("string", property3Schema.get("items").get("type").asText()); + JsonNode property4Schema = propertiesSchema.get("property4"); + assertNotNull(property4Schema); + assertEquals("array", property4Schema.get("type").asText()); + assertEquals(false, property4Schema.path("required").getBooleanValue()); + assertEquals("number", property4Schema.get("items").get("type").asText()); + } + + /** + * Additional unit test for verifying that schema object itself + * can be properly serialized + * + * @since 1.2 + */ + public void testSchemaSerialization() + throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + JsonSchema jsonSchema = mapper.generateJsonSchema(SimpleBean.class); + Map<String,Object> result = writeAndMap(mapper, jsonSchema); + assertNotNull(result); + // no need to check out full structure, just basics... + assertEquals("object", result.get("type")); + // only add 'required' if it is true... + assertNull(result.get("required")); + assertNotNull(result.get("properties")); + } + + public void testInvalidCall() + throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + // not ok to pass null + try { + mapper.generateJsonSchema(null); + } catch (IllegalArgumentException iae) { } + } + + /** + * Test for [JACKSON-454] + */ + public void testThatObjectsHaveNoItems() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + JsonSchema jsonSchema = mapper.generateJsonSchema(TrivialBean.class); + String json = jsonSchema.toString().replaceAll("\"", "'"); + // can we count on ordering being stable? I think this is true with current ObjectNode impl + // as perh [JACKSON-563]; 'required' is only included if true + assertEquals("{'type':'object','properties':{'name':{'type':'string'}}}", + json); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/schema/TestReadJsonSchema.java b/1.9.10/src/test/org/codehaus/jackson/schema/TestReadJsonSchema.java new file mode 100644 index 0000000..c3ea3a9 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/schema/TestReadJsonSchema.java
@@ -0,0 +1,60 @@ +package org.codehaus.jackson.schema; + +import java.util.*; + +import org.codehaus.jackson.map.*; + +/** + * Trivial test to ensure {@link JsonSchema} can be also deserialized + */ +public class TestReadJsonSchema + extends org.codehaus.jackson.map.BaseMapTest +{ + enum SchemaEnum { YES, NO; } + + static class Schemable { + public String name; + public char[] nameBuffer; + + // We'll include tons of stuff, just to force generation of schema + public boolean[] states; + public byte[] binaryData; + public short[] shorts; + public int[] ints; + public long[] longs; + + public float[] floats; + public double[] doubles; + + public Object[] objects; + public JsonSerializableWithType someSerializable; + + public Iterable<Object> iterableOhYeahBaby; + + public List<String> extra; + public ArrayList<String> extra2; + public Iterator<String[]> extra3; + + public Map<String,Double> sizes; + public EnumMap<SchemaEnum,List<String>> whatever; + + SchemaEnum testEnum; + public EnumSet<SchemaEnum> testEnums; + } + + /** + * Verifies that a simple schema that is serialized can be + * deserialized back to equal schema instance + */ + public void testDeserializeSimple() throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + JsonSchema schema = mapper.generateJsonSchema(Schemable.class); + assertNotNull(schema); + + String schemaStr = mapper.writeValueAsString(schema); + assertNotNull(schemaStr); + JsonSchema result = mapper.readValue(schemaStr, JsonSchema.class); + assertEquals("Trying to read from '"+schemaStr+"'", schema, result); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/smile/SmileTestBase.java b/1.9.10/src/test/org/codehaus/jackson/smile/SmileTestBase.java new file mode 100644 index 0000000..cc0e870 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/smile/SmileTestBase.java
@@ -0,0 +1,112 @@ +package org.codehaus.jackson.smile; + +import java.io.*; + +import org.junit.Assert; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.ObjectMapper; + +abstract class SmileTestBase + extends main.BaseTest +{ + protected ObjectMapper smileMapper() { + return smileMapper(false); + } + + protected ObjectMapper smileMapper(boolean requireHeader) { + return smileMapper(requireHeader, false, false); + } + + protected ObjectMapper smileMapper(boolean requireHeader, + boolean writeHeader, boolean writeEndMarker) + { + return new ObjectMapper(smileFactory(requireHeader, writeHeader, writeEndMarker)); + } + + protected SmileParser _smileParser(byte[] input) throws IOException { + return _smileParser(input, false); + } + + protected SmileParser _smileParser(InputStream input) throws IOException { + return _smileParser(input, false); + } + + protected SmileParser _smileParser(byte[] input, boolean requireHeader) throws IOException + { + SmileFactory f = smileFactory(requireHeader, false, false); + return _smileParser(f, input); + } + + protected SmileParser _smileParser(InputStream input, boolean requireHeader) throws IOException + { + SmileFactory f = smileFactory(requireHeader, false, false); + return _smileParser(f, input); + } + + protected SmileParser _smileParser(SmileFactory f, byte[] input) + throws IOException + { + return f.createJsonParser(input); + } + + protected SmileParser _smileParser(SmileFactory f, InputStream input) + throws IOException + { + return f.createJsonParser(input); + } + + protected SmileFactory smileFactory(boolean requireHeader, + boolean writeHeader, boolean writeEndMarker) + { + SmileFactory f = new SmileFactory(); + f.configure(SmileParser.Feature.REQUIRE_HEADER, requireHeader); + f.configure(SmileGenerator.Feature.WRITE_HEADER, writeHeader); + f.configure(SmileGenerator.Feature.WRITE_END_MARKER, writeEndMarker); + return f; + } + + protected byte[] _smileDoc(String json) throws IOException + { + return _smileDoc(json, true); + } + + protected byte[] _smileDoc(String json, boolean writeHeader) throws IOException + { + return _smileDoc(new SmileFactory(), json, writeHeader); + } + + protected byte[] _smileDoc(SmileFactory smileFactory, String json, boolean writeHeader) throws IOException + { + JsonFactory jf = new JsonFactory(); + JsonParser jp = jf.createJsonParser(json); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + JsonGenerator jg = smileGenerator(out, writeHeader); + + while (jp.nextToken() != null) { + jg.copyCurrentEvent(jp); + } + jp.close(); + jg.close(); + return out.toByteArray(); + } + + protected SmileGenerator smileGenerator(ByteArrayOutputStream result, boolean addHeader) + throws IOException + { + return smileGenerator(new SmileFactory(), result, addHeader); + } + + protected SmileGenerator smileGenerator(SmileFactory f, + ByteArrayOutputStream result, boolean addHeader) + throws IOException + { + f.configure(SmileGenerator.Feature.WRITE_HEADER, addHeader); + return f.createJsonGenerator(result, null); + } + + protected void _verifyBytes(byte[] actBytes, byte... expBytes) + { + Assert.assertArrayEquals(expBytes, actBytes); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/smile/TestGeneratorWithRawUtf8.java b/1.9.10/src/test/org/codehaus/jackson/smile/TestGeneratorWithRawUtf8.java new file mode 100644 index 0000000..2e77853 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/smile/TestGeneratorWithRawUtf8.java
@@ -0,0 +1,222 @@ +package org.codehaus.jackson.smile; + +import static org.junit.Assert.assertArrayEquals; + +import java.io.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +import org.codehaus.jackson.*; + +/** + * Test similar to {@link org.codehaus.jackson.main.TestRawStringWriting}, + * to verify handling of "raw String value" write methods that by-pass + * most encoding steps, for potential higher output speed (in cases where + * input naturally comes as UTF-8 encoded byte arrays). + * + * @since 1.7 + */ +public class TestGeneratorWithRawUtf8 extends SmileTestBase +{ + public void testUtf8RawStrings() throws Exception + { + // Let's create set of Strings to output; no ctrl chars as we do raw + List<byte[]> strings = generateStrings(new Random(28), 750000, false); + ByteArrayOutputStream out = new ByteArrayOutputStream(16000); + SmileFactory jf = new SmileFactory(); + JsonGenerator jgen = jf.createJsonGenerator(out, JsonEncoding.UTF8); + jgen.writeStartArray(); + for (byte[] str : strings) { + jgen.writeRawUTF8String(str, 0, str.length); + } + jgen.writeEndArray(); + jgen.close(); + byte[] json = out.toByteArray(); + + // Ok: let's verify that stuff was written out ok + JsonParser jp = jf.createJsonParser(json); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + for (byte[] inputBytes : strings) { + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + String string = jp.getText(); + byte[] outputBytes = string.getBytes("UTF-8"); + assertEquals(inputBytes.length, outputBytes.length); + assertArrayEquals(inputBytes, outputBytes); + } + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + } + + /** + * Unit test for "JsonGenerator.writeUTF8String()", which needs + * to handle escaping properly + */ + public void testUtf8StringsWithEscaping() throws Exception + { + // Let's create set of Strings to output; do include control chars too: + List<byte[]> strings = generateStrings(new Random(28), 720000, true); + ByteArrayOutputStream out = new ByteArrayOutputStream(16000); + SmileFactory jf = new SmileFactory(); + JsonGenerator jgen = jf.createJsonGenerator(out, JsonEncoding.UTF8); + jgen.writeStartArray(); + for (byte[] str : strings) { + jgen.writeUTF8String(str, 0, str.length); + } + jgen.writeEndArray(); + jgen.close(); + byte[] json = out.toByteArray(); + + // Ok: let's verify that stuff was written out ok + JsonParser jp = jf.createJsonParser(json); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + for (byte[] inputBytes : strings) { + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + String string = jp.getText(); + byte[] outputBytes = string.getBytes("UTF-8"); + assertEquals(inputBytes.length, outputBytes.length); + assertArrayEquals(inputBytes, outputBytes); + } + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + } + + /** + * Test to point out an issue with "raw" UTF-8 encoding + * + * @author David Yu + */ + public void testIssue492() throws Exception + { + doTestIssue492(false); + doTestIssue492(true); + } + + /* + /********************************************************** + /* Helper methods + /********************************************************** + */ + + private void doTestIssue492(boolean asUtf8String) throws Exception + { + SmileFactory factory = new SmileFactory(); + + ByteArrayOutputStream out = new ByteArrayOutputStream(); + SmileGenerator generator = factory.createJsonGenerator(out); + + generator.writeStartObject(); + + generator.writeFieldName("name"); + + if(asUtf8String) + { + byte[] text = "PojoFoo".getBytes("ASCII"); + generator.writeUTF8String(text, 0, text.length); + } + else + { + generator.writeString("PojoFoo"); + } + + generator.writeFieldName("collection"); + + generator.writeStartObject(); + + generator.writeFieldName("v"); + + generator.writeStartArray(); + + if(asUtf8String) + { + byte[] text = "1".getBytes("ASCII"); + generator.writeUTF8String(text, 0, text.length); + } + else + { + generator.writeString("1"); + } + + generator.writeEndArray(); + + generator.writeEndObject(); + + generator.writeEndObject(); + + generator.close(); + + byte[] data = out.toByteArray(); + + ByteArrayInputStream in = new ByteArrayInputStream(data); + SmileParser parser = factory.createJsonParser(in); + + assertToken(parser.nextToken(), JsonToken.START_OBJECT); + + assertToken(parser.nextToken(), JsonToken.FIELD_NAME); + assertEquals(parser.getCurrentName(), "name"); + assertToken(parser.nextToken(), JsonToken.VALUE_STRING); + assertEquals(parser.getText(), "PojoFoo"); + + assertToken(parser.nextToken(), JsonToken.FIELD_NAME); + assertEquals(parser.getCurrentName(), "collection"); + assertToken(parser.nextToken(), JsonToken.START_OBJECT); + + assertToken(parser.nextToken(), JsonToken.FIELD_NAME); + assertEquals("Should have property with name 'v'", parser.getCurrentName(), "v"); + assertToken(parser.nextToken(), JsonToken.START_ARRAY); + + assertToken(parser.nextToken(), JsonToken.VALUE_STRING); + assertEquals("Should get String value '1'", parser.getText(), "1"); + + assertToken(parser.nextToken(), JsonToken.END_ARRAY); + assertToken(parser.nextToken(), JsonToken.END_OBJECT); + + + assertToken(parser.nextToken(), JsonToken.END_OBJECT); + parser.close(); + } + + private List<byte[]> generateStrings(Random rnd, int totalLength, boolean includeCtrlChars) + throws IOException + { + ArrayList<byte[]> strings = new ArrayList<byte[]>(); + do { + int len = 2; + int bits = rnd.nextInt(14); + while (--bits >= 0) { + len += len; + } + len = 1 + ((len + len) / 3); + String str = generateString(rnd, len, includeCtrlChars); + byte[] bytes = str.getBytes("UTF-8"); + strings.add(bytes); + totalLength -= bytes.length; + } while (totalLength > 0); + return strings; + } + + private String generateString(Random rnd, int length, boolean includeCtrlChars) + { + StringBuilder sb = new StringBuilder(length); + do { + int i; + switch (rnd.nextInt(3)) { + case 0: // 3 byte one + i = 2048 + rnd.nextInt(16383); + break; + case 1: // 2 byte + i = 128 + rnd.nextInt(1024); + break; + default: // ASCII + i = rnd.nextInt(192); + if (!includeCtrlChars) { + i += 32; + // but also need to avoid backslash, double-quote + if (i == '\\' || i == '"') { + i = '@'; // just arbitrary choice + } + } + } + sb.append((char) i); + } while (sb.length() < length); + return sb.toString(); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/smile/TestGeneratorWithSerializedString.java b/1.9.10/src/test/org/codehaus/jackson/smile/TestGeneratorWithSerializedString.java new file mode 100644 index 0000000..4c85e67 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/smile/TestGeneratorWithSerializedString.java
@@ -0,0 +1,86 @@ +package org.codehaus.jackson.smile; + +import java.io.ByteArrayOutputStream; + +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.JsonToken; +import org.codehaus.jackson.io.SerializedString; + +public class TestGeneratorWithSerializedString extends SmileTestBase +{ + final static String NAME_WITH_QUOTES = "\"name\""; + final static String NAME_WITH_LATIN1 = "P\u00f6ll\u00f6"; + + private final SerializedString quotedName = new SerializedString(NAME_WITH_QUOTES); + private final SerializedString latin1Name = new SerializedString(NAME_WITH_LATIN1); + + public void testSimple() throws Exception + { + SmileFactory sf = new SmileFactory(); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + JsonGenerator jgen = sf.createJsonGenerator(out); + _writeSimple(jgen); + jgen.close(); + byte[] smileB = out.toByteArray(); + _verifySimple(sf.createJsonParser(smileB)); + } + + /* + /********************************************************** + /* Helper methods + /********************************************************** + */ + + private void _writeSimple(JsonGenerator jgen) throws Exception + { + // Let's just write array of 2 objects + jgen.writeStartArray(); + + jgen.writeStartObject(); + jgen.writeFieldName(quotedName); + jgen.writeString("a"); + jgen.writeFieldName(latin1Name); + jgen.writeString("b"); + jgen.writeEndObject(); + + jgen.writeStartObject(); + jgen.writeFieldName(latin1Name); + jgen.writeString("c"); + jgen.writeFieldName(quotedName); + jgen.writeString("d"); + jgen.writeEndObject(); + + jgen.writeEndArray(); + } + + private void _verifySimple(JsonParser jp) throws Exception + { + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + + assertToken(JsonToken.START_OBJECT, jp.nextToken()); + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals(NAME_WITH_QUOTES, jp.getText()); + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + assertEquals("a", jp.getText()); + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals(NAME_WITH_LATIN1, jp.getText()); + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + assertEquals("b", jp.getText()); + assertToken(JsonToken.END_OBJECT, jp.nextToken()); + + assertToken(JsonToken.START_OBJECT, jp.nextToken()); + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals(NAME_WITH_LATIN1, jp.getText()); + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + assertEquals("c", jp.getText()); + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals(NAME_WITH_QUOTES, jp.getText()); + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + assertEquals("d", jp.getText()); + assertToken(JsonToken.END_OBJECT, jp.nextToken()); + + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + assertNull(jp.nextToken()); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/smile/TestMapper.java b/1.9.10/src/test/org/codehaus/jackson/smile/TestMapper.java new file mode 100644 index 0000000..5f67456 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/smile/TestMapper.java
@@ -0,0 +1,28 @@ +package org.codehaus.jackson.smile; + +import java.io.IOException; + +import org.codehaus.jackson.map.ObjectMapper; +import org.junit.Assert; + +public class TestMapper extends SmileTestBase +{ + static class BytesBean { + public byte[] bytes; + + public BytesBean() { } + public BytesBean(byte[] b) { bytes = b; } + } + + // [JACKSON-733] + public void testBinary() throws IOException + { + byte[] input = new byte[] { 1, 2, 3, -1, 8, 0, 42 }; + ObjectMapper mapper = smileMapper(); + byte[] smile = mapper.writeValueAsBytes(new BytesBean(input)); + BytesBean result = mapper.readValue(smile, BytesBean.class); + + assertNotNull(result.bytes); + Assert.assertArrayEquals(input, result.bytes); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/smile/TestSmileAsTree.java b/1.9.10/src/test/org/codehaus/jackson/smile/TestSmileAsTree.java new file mode 100644 index 0000000..8745c9b --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/smile/TestSmileAsTree.java
@@ -0,0 +1,36 @@ +package org.codehaus.jackson.smile; + +import org.junit.Assert; + +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.node.*; + +public class TestSmileAsTree extends SmileTestBase +{ + public void testSimple() throws Exception + { + // create the serialized JSON with byte array + ObjectMapper mapper = new ObjectMapper(new SmileFactory()); + + ObjectNode top1 = mapper.createObjectNode(); + ObjectNode foo1 = top1.putObject("foo"); + foo1.put("bar", "baz"); + final String TEXT = "Caf\u00e9 1\u20ac"; + final byte[] TEXT_BYTES = TEXT.getBytes("UTF-8"); + foo1.put("dat", TEXT_BYTES); + + byte[] doc = mapper.writeValueAsBytes(top1); + // now, deserialize + JsonNode top2 = mapper.readValue(doc, JsonNode.class); + JsonNode foo2 = top2.get("foo"); + assertEquals("baz", foo2.get("bar").getTextValue()); + + JsonNode datNode = foo2.get("dat"); + if (!datNode.isBinary()) { + fail("Expected binary node; got "+datNode.getClass().getName()); + } + byte[] bytes = datNode.getBinaryValue(); + Assert.assertArrayEquals(TEXT_BYTES, bytes); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/smile/TestSmileDetection.java b/1.9.10/src/test/org/codehaus/jackson/smile/TestSmileDetection.java new file mode 100644 index 0000000..7da8d7b --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/smile/TestSmileDetection.java
@@ -0,0 +1,148 @@ +package org.codehaus.jackson.smile; + +import java.io.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.format.DataFormatDetector; +import org.codehaus.jackson.format.DataFormatMatcher; +import org.codehaus.jackson.format.MatchStrength; + +public class TestSmileDetection extends SmileTestBase +{ + + public void testSimpleObjectWithHeader() throws IOException + { + SmileFactory f = new SmileFactory(); + DataFormatDetector detector = new DataFormatDetector(f); + byte[] doc = _smileDoc("{\"a\":3}", true); + DataFormatMatcher matcher = detector.findFormat(doc); + // should have match + assertTrue(matcher.hasMatch()); + assertEquals("Smile", matcher.getMatchedFormatName()); + assertSame(f, matcher.getMatch()); + // with header, should be full match + assertEquals(MatchStrength.FULL_MATCH, matcher.getMatchStrength()); + // and so: + JsonParser jp = matcher.createParserWithMatch(); + assertToken(JsonToken.START_OBJECT, jp.nextToken()); + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals("a", jp.getCurrentName()); + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(3, jp.getIntValue()); + assertToken(JsonToken.END_OBJECT, jp.nextToken()); + assertNull(jp.nextToken()); + jp.close(); + } + + public void testSimpleObjectWithoutHeader() throws IOException + { + SmileFactory f = new SmileFactory(); + DataFormatDetector detector = new DataFormatDetector(f); + f.disable(SmileParser.Feature.REQUIRE_HEADER); + byte[] doc = _smileDoc("{\"abc\":false}", false); + DataFormatMatcher matcher = detector.findFormat(doc); + assertTrue(matcher.hasMatch()); + assertEquals("Smile", matcher.getMatchedFormatName()); + assertSame(f, matcher.getMatch()); + assertEquals(MatchStrength.SOLID_MATCH, matcher.getMatchStrength()); + JsonParser jp = matcher.createParserWithMatch(); + assertToken(JsonToken.START_OBJECT, jp.nextToken()); + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals("abc", jp.getCurrentName()); + assertToken(JsonToken.VALUE_FALSE, jp.nextToken()); + assertToken(JsonToken.END_OBJECT, jp.nextToken()); + assertNull(jp.nextToken()); + jp.close(); + } + + public void testSimpleArrayWithHeader() throws IOException + { + SmileFactory f = new SmileFactory(); + DataFormatDetector detector = new DataFormatDetector(f); + byte[] doc = _smileDoc("[ true, 7 ]", true); + DataFormatMatcher matcher = detector.findFormat(doc); + // should have match + assertTrue(matcher.hasMatch()); + assertEquals("Smile", matcher.getMatchedFormatName()); + assertSame(f, matcher.getMatch()); + // with header, should be full match + assertEquals(MatchStrength.FULL_MATCH, matcher.getMatchStrength()); + JsonParser jp = matcher.createParserWithMatch(); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + assertToken(JsonToken.VALUE_TRUE, jp.nextToken()); + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(7, jp.getIntValue()); + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + assertNull(jp.nextToken()); + jp.close(); + } + + public void testSimpleArrayWithoutHeader() throws IOException + { + SmileFactory f = new SmileFactory(); + f.disable(SmileParser.Feature.REQUIRE_HEADER); + DataFormatDetector detector = new DataFormatDetector(f); + byte[] doc = _smileDoc("[ -13 ]", false); + DataFormatMatcher matcher = detector.findFormat(doc); + assertTrue(matcher.hasMatch()); + assertEquals("Smile", matcher.getMatchedFormatName()); + assertSame(f, matcher.getMatch()); + assertEquals(MatchStrength.SOLID_MATCH, matcher.getMatchStrength()); + JsonParser jp = matcher.createParserWithMatch(); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + assertNull(jp.nextToken()); + jp.close(); + } + + /* + /********************************************************** + /* Simple negative tests + /********************************************************** + */ + + /* + * Also let's ensure no match is found if data doesn't support it... + * Let's use 0xFD since it can not be included (except in raw binary; + * use of which requires header to be present) + */ + public void testSimpleInvalid() throws Exception + { + DataFormatDetector detector = new DataFormatDetector(new SmileFactory()); + byte FD = (byte) 0xFD; + byte[] DOC = new byte[] { FD, FD, FD, FD }; + DataFormatMatcher matcher = detector.findFormat(new ByteArrayInputStream(DOC)); + assertFalse(matcher.hasMatch()); + assertEquals(MatchStrength.INCONCLUSIVE, matcher.getMatchStrength()); + assertNull(matcher.createParserWithMatch()); + } + + /* + /********************************************************** + /* Fallback tests to ensure Smile is found even against JSON + /********************************************************** + */ + + public void testSmileVsJson() throws IOException + { + SmileFactory f = new SmileFactory(); + f.disable(SmileParser.Feature.REQUIRE_HEADER); + DataFormatDetector detector = new DataFormatDetector(new JsonFactory(), f); + // to make it bit trickier, leave out header + byte[] doc = _smileDoc("[ \"abc\" ]", false); + DataFormatMatcher matcher = detector.findFormat(doc); + assertTrue(matcher.hasMatch()); + assertEquals("Smile", matcher.getMatchedFormatName()); + assertSame(f, matcher.getMatch()); + // without header, just solid + assertEquals(MatchStrength.SOLID_MATCH, matcher.getMatchStrength()); + JsonParser jp = matcher.createParserWithMatch(); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + assertNull(jp.nextToken()); + jp.close(); + } + +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/smile/TestSmileDocBoundary.java b/1.9.10/src/test/org/codehaus/jackson/smile/TestSmileDocBoundary.java new file mode 100644 index 0000000..293fb98 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/smile/TestSmileDocBoundary.java
@@ -0,0 +1,105 @@ +package org.codehaus.jackson.smile; + +import java.io.*; + +import org.codehaus.jackson.JsonToken; + +/** + * Unit tests for verifying that multiple document output and document + * boundaries and/or header mark handling works as expected + */ +public class TestSmileDocBoundary + extends SmileTestBase +{ + public void testNoHeadersNoEndMarker() throws Exception + { + _verifyMultiDoc(false, false); + } + + public void testHeadersNoEndMarker() throws Exception + { + _verifyMultiDoc(true, false); + } + + public void testEndMarkerNoHeader() throws Exception + { + _verifyMultiDoc(false, true); + } + + public void testHeaderAndEndMarker() throws Exception + { + _verifyMultiDoc(true, true); + } + + public void testExtraHeader() throws Exception + { + // also; sprinkling headers can be used to segment document + for (boolean addHeader : new boolean[] { false, true }) { + SmileFactory f = smileFactory(false, false, false); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + SmileGenerator jg = f.createJsonGenerator(out); + jg.writeNumber(1); + if (addHeader) jg.writeHeader(); + jg.writeNumber(2); + if (addHeader) jg.writeHeader(); + jg.writeNumber(3); + jg.close(); + + SmileParser jp = f.createJsonParser(out.toByteArray()); + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(1, jp.getIntValue()); + if (addHeader) { + assertNull(jp.nextToken()); + } + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(2, jp.getIntValue()); + if (addHeader) { + assertNull(jp.nextToken()); + } + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(3, jp.getIntValue()); + assertNull(jp.nextToken()); + jg.close(); + } + } + + /* + /********************************************************** + /* Helper methods + /********************************************************** + */ + + protected void _verifyMultiDoc(boolean addHeader, boolean addEndMarker) throws Exception + { + SmileFactory f = smileFactory(false, addHeader, addEndMarker); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + SmileGenerator jg = f.createJsonGenerator(out); + // First doc, JSON Object + jg.writeStartObject(); + jg.writeEndObject(); + jg.close(); + // and second, array + jg = f.createJsonGenerator(out); + jg.writeStartArray(); + jg.writeEndArray(); + jg.close(); + + // and read it back + SmileParser jp = f.createJsonParser(out.toByteArray()); + assertToken(JsonToken.START_OBJECT, jp.nextToken()); + assertToken(JsonToken.END_OBJECT, jp.nextToken()); + + // now: if one of header or end marker (or, both) enabled, should get null here: + if (addHeader || addEndMarker) { + assertNull(jp.nextToken()); + } + + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + + // end + assertNull(jp.nextToken()); + // and no more: + assertNull(jp.nextToken()); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/smile/TestSmileFeatures.java b/1.9.10/src/test/org/codehaus/jackson/smile/TestSmileFeatures.java new file mode 100644 index 0000000..100196c --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/smile/TestSmileFeatures.java
@@ -0,0 +1,36 @@ +package org.codehaus.jackson.smile; + +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.smile.SmileFactory; + +public class TestSmileFeatures + extends SmileTestBase +{ + /* + /********************************************************** + /* Helper types + /********************************************************** + */ + + static class Bean { + public int value; + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + // Let's ensure indentation doesn't break anything (should be NOP) + public void testIndent() throws Exception + { + ObjectMapper mapper = new ObjectMapper(new SmileFactory()); + mapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, true); + Bean bean = new Bean(); + bean.value = 42; + + byte[] smile = mapper.writeValueAsBytes(bean); + Bean result = mapper.readValue(smile, 0, smile.length, Bean.class); + assertEquals(42, result.value); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/smile/TestSmileGenerator.java b/1.9.10/src/test/org/codehaus/jackson/smile/TestSmileGenerator.java new file mode 100644 index 0000000..01cedd1 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/smile/TestSmileGenerator.java
@@ -0,0 +1,196 @@ +package org.codehaus.jackson.smile; + +import java.io.*; + +import static org.codehaus.jackson.smile.SmileConstants.*; + +public class TestSmileGenerator + extends SmileTestBase +{ + /** + * Test for verifying handling of 'true', 'false' and 'null' literals + */ + public void testSimpleLiterals() throws Exception + { + // false, no header (or frame marker) + ByteArrayOutputStream out = new ByteArrayOutputStream(); + SmileGenerator gen = smileGenerator(out, false); + gen.writeBoolean(true); + gen.close(); + _verifyBytes(out.toByteArray(), SmileConstants.TOKEN_LITERAL_TRUE); + + // false, no header or frame marker + out = new ByteArrayOutputStream(); + gen = smileGenerator(out, false); + gen.writeBoolean(false); + gen.close(); + _verifyBytes(out.toByteArray(), SmileConstants.TOKEN_LITERAL_FALSE); + + // null, no header or frame marker + out = new ByteArrayOutputStream(); + gen = smileGenerator(out, false); + gen.writeNull(); + gen.close(); + _verifyBytes(out.toByteArray(), SmileConstants.TOKEN_LITERAL_NULL); + + // And then with some other combinations: + // true, but with header + out = new ByteArrayOutputStream(); + gen = smileGenerator(out, true); + gen.writeBoolean(true); + gen.close(); + + // note: version, and 'check shared names', but not 'check shared strings' or 'raw binary' + int b4 = HEADER_BYTE_4 | SmileConstants.HEADER_BIT_HAS_SHARED_NAMES; + + _verifyBytes(out.toByteArray(), + HEADER_BYTE_1, HEADER_BYTE_2, HEADER_BYTE_3, (byte) b4, + SmileConstants.TOKEN_LITERAL_TRUE); + + // null, with header and end marker + out = new ByteArrayOutputStream(); + gen = smileGenerator(out, true); + gen.enable(SmileGenerator.Feature.WRITE_END_MARKER); + gen.writeNull(); + gen.close(); + _verifyBytes(out.toByteArray(), + HEADER_BYTE_1, HEADER_BYTE_2, HEADER_BYTE_3, (byte) b4, + TOKEN_LITERAL_NULL, BYTE_MARKER_END_OF_CONTENT); + } + + public void testSimpleArray() throws Exception + { + // First: empty array (2 bytes) + ByteArrayOutputStream out = new ByteArrayOutputStream(); + SmileGenerator gen = smileGenerator(out, false); + gen.writeStartArray(); + gen.writeEndArray(); + gen.close(); + _verifyBytes(out.toByteArray(), SmileConstants.TOKEN_LITERAL_START_ARRAY, + SmileConstants.TOKEN_LITERAL_END_ARRAY); + + // then simple array with 3 literals + out = new ByteArrayOutputStream(); + gen = smileGenerator(out, false); + gen.writeStartArray(); + gen.writeBoolean(true); + gen.writeNull(); + gen.writeBoolean(false); + gen.writeEndArray(); + gen.close(); + assertEquals(5, out.toByteArray().length); + + // and then array containing another array and short String + out = new ByteArrayOutputStream(); + gen = smileGenerator(out, false); + gen.writeStartArray(); + gen.writeStartArray(); + gen.writeEndArray(); + gen.writeString("12"); + gen.writeEndArray(); + gen.close(); + // 4 bytes for start/end arrays; 3 bytes for short ascii string + assertEquals(7, out.toByteArray().length); + } + + public void testShortAscii() throws Exception + { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + SmileGenerator gen = smileGenerator(out, false); + gen.writeString("abc"); + gen.close(); + _verifyBytes(out.toByteArray(), (byte)0x42, (byte) 'a', (byte) 'b', (byte) 'c'); + } + + + public void testTrivialObject() throws Exception + { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + SmileGenerator gen = smileGenerator(out, false); + gen.writeStartObject(); + gen.writeNumberField("a", 6); + gen.writeEndObject(); + gen.close(); + _verifyBytes(out.toByteArray(), SmileConstants.TOKEN_LITERAL_START_OBJECT, + (byte) 0x80, (byte) 'a', (byte) (0xC0 + SmileUtil.zigzagEncode(6)), + SmileConstants.TOKEN_LITERAL_END_OBJECT); + } + + public void test2FieldObject() throws Exception + { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + SmileGenerator gen = smileGenerator(out, false); + gen.writeStartObject(); + gen.writeNumberField("a", 1); + gen.writeNumberField("b", 2); + gen.writeEndObject(); + gen.close(); + _verifyBytes(out.toByteArray(), SmileConstants.TOKEN_LITERAL_START_OBJECT, + (byte) 0x80, (byte) 'a', (byte) (0xC0 + SmileUtil.zigzagEncode(1)), + (byte) 0x80, (byte) 'b', (byte) (0xC0 + SmileUtil.zigzagEncode(2)), + SmileConstants.TOKEN_LITERAL_END_OBJECT); + } + + public void testAnotherObject() throws Exception + { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + SmileGenerator gen = smileGenerator(out, false); + gen.writeStartObject(); + gen.writeNumberField("a", 8); + gen.writeFieldName("b"); + gen.writeStartArray(); + gen.writeBoolean(true); + gen.writeEndArray(); + gen.writeFieldName("c"); + gen.writeStartObject(); + gen.writeEndObject(); + + gen.writeFieldName("d"); + gen.writeStartObject(); + gen.writeFieldName("3"); + gen.writeNull(); + gen.writeEndObject(); + + gen.writeEndObject(); + gen.close(); + assertEquals(21, out.toByteArray().length); + } + + /** + * Test to verify that + */ + public void testSharedStrings() throws Exception + { + // first, no sharing, 2 separate Strings + final String VALUE = "abcde12345"; + byte[] data = writeRepeatedString(false, VALUE); + int BASE_LEN = 28; + assertEquals(BASE_LEN, data.length); + data = writeRepeatedString(true, VALUE); + if (data.length >= BASE_LEN) { // should be less + fail("Expected shared String length to be < "+BASE_LEN+", was "+data.length); + } + } + + /* + /********************************************************** + /* Helper methods + /********************************************************** + */ + + private byte[] writeRepeatedString(boolean shared, String value) throws Exception + { + SmileFactory f = new SmileFactory(); + // need header to enable shared string values + f.configure(SmileGenerator.Feature.WRITE_HEADER, true); + f.configure(SmileGenerator.Feature.CHECK_SHARED_STRING_VALUES, shared); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + SmileGenerator gen = f.createJsonGenerator(out); + gen.writeStartArray(); + gen.writeString(value); + gen.writeString(value); + gen.writeEndArray(); + gen.close(); + return out.toByteArray(); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/smile/TestSmileGeneratorBufferRecycle.java b/1.9.10/src/test/org/codehaus/jackson/smile/TestSmileGeneratorBufferRecycle.java new file mode 100644 index 0000000..3a2d68a --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/smile/TestSmileGeneratorBufferRecycle.java
@@ -0,0 +1,76 @@ +package org.codehaus.jackson.smile; + +import java.io.*; +import java.util.*; + +import org.codehaus.jackson.*; + +/* Test based on kimchy's issue (see https://gist.github.com/853232); + * exhibits an issue with buffer recycling. + * + * @since 1.8 + */ +public class TestSmileGeneratorBufferRecycle extends SmileTestBase +{ + public void testMaps() throws Exception + { + SmileFactory factory = new SmileFactory(); + + Map<?,?> props1 = buildMap("", 65); + Map<?,?> props2 = buildMap("", 1); + + writeMapAndParse(factory, props1); + writeMapAndParse(factory, props2); + writeMapAndParse(factory, props1); + writeMapAndParse(factory, props2); + } + + /* + /********************************************************** + /* Helper methods + /********************************************************** + */ + + private static void writeMapAndParse(SmileFactory factory, Map<?,?> map) throws Exception { + ByteArrayOutputStream os = new ByteArrayOutputStream(); + + // generate + JsonGenerator generator = factory.createJsonGenerator(os); + writeMap(generator, map); + generator.close(); + + // parse + JsonParser parser = factory.createJsonParser(os.toByteArray()); + while (parser.nextToken() != null) { + + } + } + + private static Map<?,?> buildMap(String prefix, int size) { + HashMap<String,String> props = new HashMap<String, String>(); + for (int it = 0; it < size; it++) { + String key = prefix + "prop_" + it; + props.put(key, "a"); + } + return props; + } + + + // A sample utility to write a map + + public static void writeMap(JsonGenerator gen, Map<?,?> map) throws IOException { + gen.writeStartObject(); + + for (Map.Entry<?,?> entry : map.entrySet()) { + gen.writeFieldName((String) entry.getKey()); + Object value = entry.getValue(); + if (value == null) { + gen.writeNull(); + } else { + gen.writeString(value.toString()); + } + } + + gen.writeEndObject(); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/smile/TestSmileGeneratorLongStrings.java b/1.9.10/src/test/org/codehaus/jackson/smile/TestSmileGeneratorLongStrings.java new file mode 100644 index 0000000..5477a44 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/smile/TestSmileGeneratorLongStrings.java
@@ -0,0 +1,91 @@ +package org.codehaus.jackson.smile; + +import java.io.*; +import java.util.*; + +import org.codehaus.jackson.*; + +public class TestSmileGeneratorLongStrings extends SmileTestBase +{ + final static int DOC_LEN = 2000000; // 2 meg test doc + + public void testLongWithMultiBytes() throws Exception + { + SmileFactory f = new SmileFactory(); + ArrayList<String> strings = new ArrayList<String>(); + Random rnd = new Random(123); + + ByteArrayOutputStream out = new ByteArrayOutputStream(DOC_LEN); + SmileGenerator gen = f.createJsonGenerator(out); + gen.writeStartArray(); + + // Let's create 1M doc, first using Strings + while (out.size() < (DOC_LEN - 10000)) { + String str = generateString(5000, rnd); + strings.add(str); + gen.writeString(str); + } + gen.writeEndArray(); + gen.close(); + // Written ok; let's try parsing then + _verifyStrings(f, out.toByteArray(), strings); + + // Then same with char[] + out = new ByteArrayOutputStream(DOC_LEN); + gen = f.createJsonGenerator(out); + gen.writeStartArray(); + + // Let's create 1M doc, first using Strings + for (int i = 0, len = strings.size(); i < len; ++i) { + char[] ch = strings.get(i).toCharArray(); + gen.writeString(ch, 0, ch.length); + } + gen.writeEndArray(); + gen.close(); + _verifyStrings(f, out.toByteArray(), strings); + } + + /* + /********************************************************** + /* Helper methods + /********************************************************** + */ + + protected String generateString(int length, Random rnd) throws Exception + { + StringBuilder sw = new StringBuilder(length+10); + do { + // First, add 7 ascii characters + int num = 4 + (rnd.nextInt() & 7); + while (--num >= 0) { + sw.append((char) ('A' + num)); + } + // Then a unicode char of 2, 3 or 4 bytes long + switch (rnd.nextInt() % 3) { + case 0: + sw.append((char) (256 + rnd.nextInt() & 511)); + break; + case 1: + sw.append((char) (2048 + rnd.nextInt() & 4095)); + break; + default: + sw.append((char) (65536 + rnd.nextInt() & 0x3FFF)); + break; + } + } while (sw.length() < length); + return sw.toString(); + } + + private void _verifyStrings(JsonFactory f, byte[] input, List<String> strings) + throws IOException + { + JsonParser jp = f.createJsonParser(input); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + for (int i = 0, len = strings.size(); i < len; ++i) { + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + assertEquals(strings.get(i), jp.getText()); + } + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + jp.close(); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/smile/TestSmileGeneratorNumbers.java b/1.9.10/src/test/org/codehaus/jackson/smile/TestSmileGeneratorNumbers.java new file mode 100644 index 0000000..babfb52 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/smile/TestSmileGeneratorNumbers.java
@@ -0,0 +1,128 @@ +package org.codehaus.jackson.smile; + +import java.io.ByteArrayOutputStream; + +public class TestSmileGeneratorNumbers + extends SmileTestBase +{ + public void testSmallInts() throws Exception + { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + SmileGenerator gen = smileGenerator(out, false); + gen.writeNumber(3); + gen.close(); + _verifyBytes(out.toByteArray(), (byte) (0xC0 + SmileUtil.zigzagEncode(3))); + + out = new ByteArrayOutputStream(); + gen = smileGenerator(out, false); + gen.writeNumber(0); + gen.close(); + _verifyBytes(out.toByteArray(), (byte) (0xC0 + SmileUtil.zigzagEncode(0))); + + out = new ByteArrayOutputStream(); + gen = smileGenerator(out, false); + gen.writeNumber(-6); + gen.close(); + _verifyBytes(out.toByteArray(), (byte) (0xC0 + SmileUtil.zigzagEncode(-6))); + + out = new ByteArrayOutputStream(); + gen = smileGenerator(out, false); + gen.writeNumber(15); + gen.close(); + _verifyBytes(out.toByteArray(), (byte) (0xC0 + SmileUtil.zigzagEncode(15))); + + out = new ByteArrayOutputStream(); + gen = smileGenerator(out, false); + gen.writeNumber(-16); + gen.close(); + _verifyBytes(out.toByteArray(), (byte) (0xC0 + SmileUtil.zigzagEncode(-16))); + } + + public void testOtherInts() throws Exception + { + // beyond tiny ints, 6-bit values take 2 bytes + ByteArrayOutputStream out = new ByteArrayOutputStream(); + SmileGenerator gen = smileGenerator(out, false); + gen.writeNumber(16); + gen.close(); + assertEquals(2, out.toByteArray().length); + + out = new ByteArrayOutputStream(); + gen = smileGenerator(out, false); + gen.writeNumber(-17); + gen.close(); + assertEquals(2, out.toByteArray().length); + + // and up to 13-bit values take 3 bytes + out = new ByteArrayOutputStream(); + gen = smileGenerator(out, false); + gen.writeNumber(0xFFF); + gen.close(); + assertEquals(3, out.toByteArray().length); + + out = new ByteArrayOutputStream(); + gen = smileGenerator(out, false); + gen.writeNumber(-4096); + gen.close(); + assertEquals(3, out.toByteArray().length); + + // up to 20, 4 bytes... and so forth + out = new ByteArrayOutputStream(); + gen = smileGenerator(out, false); + gen.writeNumber(0x1000); + gen.close(); + assertEquals(4, out.toByteArray().length); + + out = new ByteArrayOutputStream(); + gen = smileGenerator(out, false); + gen.writeNumber(500000); + gen.close(); + assertEquals(4, out.toByteArray().length); + + out = new ByteArrayOutputStream(); + gen = smileGenerator(out, false); + gen.writeNumber(Integer.MAX_VALUE); + gen.close(); + assertEquals(6, out.toByteArray().length); + + out = new ByteArrayOutputStream(); + gen = smileGenerator(out, false); + gen.writeNumber(Integer.MIN_VALUE); + gen.close(); + assertEquals(6, out.toByteArray().length); + + // up to longest ones, taking 11 bytes + out = new ByteArrayOutputStream(); + gen = smileGenerator(out, false); + gen.writeNumber(Long.MAX_VALUE); + gen.close(); + assertEquals(11, out.toByteArray().length); + + out = new ByteArrayOutputStream(); + gen = smileGenerator(out, false); + gen.writeNumber(Long.MIN_VALUE); + gen.close(); + assertEquals(11, out.toByteArray().length); + } + + public void testFloats() throws Exception + { + // float length is fixed, 6 bytes + ByteArrayOutputStream out = new ByteArrayOutputStream(); + SmileGenerator gen = smileGenerator(out, false); + gen.writeNumber(0.125f); + gen.close(); + assertEquals(6, out.toByteArray().length); + } + + public void testDoubles() throws Exception + { + // double length is fixed, 11 bytes + ByteArrayOutputStream out = new ByteArrayOutputStream(); + SmileGenerator gen = smileGenerator(out, false); + gen.writeNumber(0.125); + gen.close(); + assertEquals(11, out.toByteArray().length); + } + +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/smile/TestSmileGeneratorSymbols.java b/1.9.10/src/test/org/codehaus/jackson/smile/TestSmileGeneratorSymbols.java new file mode 100644 index 0000000..2cfd21e --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/smile/TestSmileGeneratorSymbols.java
@@ -0,0 +1,129 @@ +package org.codehaus.jackson.smile; + +import java.io.ByteArrayOutputStream; + +import org.codehaus.jackson.*; + +public class TestSmileGeneratorSymbols extends SmileTestBase +{ + /** + * Simple test to verify that second reference will not output new String, but + * rather references one output earlier. + */ + public void testSharedNameSimple() throws Exception + { + // false, no header (or frame marker) + ByteArrayOutputStream out = new ByteArrayOutputStream(); + SmileGenerator gen = smileGenerator(out, false); + gen.writeStartArray(); + gen.writeStartObject(); + gen.writeNumberField("abc", 1); + gen.writeEndObject(); + gen.writeStartObject(); + gen.writeNumberField("abc", 2); + gen.writeEndObject(); + gen.writeEndArray(); + gen.close(); + byte[] result = out.toByteArray(); + assertEquals(13, result.length); + } + + // same as above, but with name >= 64 characters + public void testSharedNameSimpleLong() throws Exception + { + String digits = "01234567899"; + + // Base is 76 chars; loop over couple of shorter ones too + + final String LONG_NAME = "a"+digits+"b"+digits+"c"+digits+"d"+digits+"e"+digits+"f"+digits+"ABCD"; + + for (int i = 0; i < 4; ++i) { + int strLen = LONG_NAME.length() - i; + String field = LONG_NAME.substring(0, strLen); + // false, no header (or frame marker) + ByteArrayOutputStream out = new ByteArrayOutputStream(); + SmileGenerator gen = smileGenerator(out, false); + gen.writeStartArray(); + gen.writeStartObject(); + gen.writeNumberField(field, 1); + gen.writeEndObject(); + gen.writeStartObject(); + gen.writeNumberField(field, 2); + gen.writeEndObject(); + gen.writeEndArray(); + gen.close(); + byte[] result = out.toByteArray(); + assertEquals(11 + field.length(), result.length); + + // better also parse it back... + JsonParser parser = _smileParser(result); + assertToken(JsonToken.START_ARRAY, parser.nextToken()); + + assertToken(JsonToken.START_OBJECT, parser.nextToken()); + assertToken(JsonToken.FIELD_NAME, parser.nextToken()); + assertEquals(field, parser.getCurrentName()); + assertToken(JsonToken.VALUE_NUMBER_INT, parser.nextToken()); + assertEquals(1, parser.getIntValue()); + assertToken(JsonToken.END_OBJECT, parser.nextToken()); + + assertToken(JsonToken.START_OBJECT, parser.nextToken()); + assertToken(JsonToken.FIELD_NAME, parser.nextToken()); + assertEquals(field, parser.getCurrentName()); + assertToken(JsonToken.VALUE_NUMBER_INT, parser.nextToken()); + assertEquals(2, parser.getIntValue()); + assertToken(JsonToken.END_OBJECT, parser.nextToken()); + + assertToken(JsonToken.END_ARRAY, parser.nextToken()); + } + } + + public void testLongNamesNonShared() throws Exception + { + _testLongNames(false); + } + + public void testLongNamesShared() throws Exception + { + _testLongNames(true); + } + + /* + /********************************************************** + /* Secondary methods + /********************************************************** + */ + + // For issue [JACKSON-552] + public void _testLongNames(boolean shareNames) throws Exception + { + // 68 bytes long (on boundary) + final String FIELD_NAME = "dossier.domaine.supportsDeclaratifsForES.SupportDeclaratif.reference"; + final String VALUE = "11111"; + + SmileFactory factory = new SmileFactory(); + factory.configure(SmileGenerator.Feature.CHECK_SHARED_NAMES, shareNames); + + ByteArrayOutputStream os = new ByteArrayOutputStream(); + JsonGenerator gen = factory.createJsonGenerator(os); + gen.writeStartObject(); + gen.writeObjectFieldStart("query"); + gen.writeStringField(FIELD_NAME, VALUE); + gen.writeEndObject(); + gen.writeEndObject(); + gen.close(); + + JsonParser parser = factory.createJsonParser(os.toByteArray()); + assertNull(parser.getCurrentToken()); + assertToken(JsonToken.START_OBJECT, parser.nextToken()); + assertToken(JsonToken.FIELD_NAME, parser.nextToken()); + assertEquals("query", parser.getCurrentName()); + assertToken(JsonToken.START_OBJECT, parser.nextToken()); + assertToken(JsonToken.FIELD_NAME, parser.nextToken()); + assertEquals(FIELD_NAME, parser.getCurrentName()); + assertToken(JsonToken.VALUE_STRING, parser.nextToken()); + assertEquals(VALUE, parser.getText()); + assertToken(JsonToken.END_OBJECT, parser.nextToken()); + assertToken(JsonToken.END_OBJECT, parser.nextToken()); + } + +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/smile/TestSmileParser.java b/1.9.10/src/test/org/codehaus/jackson/smile/TestSmileParser.java new file mode 100644 index 0000000..16247d9 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/smile/TestSmileParser.java
@@ -0,0 +1,404 @@ +package org.codehaus.jackson.smile; + +import java.io.*; + +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.JsonToken; + +public class TestSmileParser + extends SmileTestBase +{ + // Unit tests for verifying that if header/signature is required, + // lacking it is fatal + public void testMandatoryHeader() throws IOException + { + // first test failing case + byte[] data = _smileDoc("[ null ]", false); + try { + _smileParser(data, true); + fail("Should have gotten exception for missing header"); + } catch (Exception e) { + verifyException(e, "does not start with Smile format header"); + } + + // and then test passing one + SmileParser p = _smileParser(data, false); + assertToken(JsonToken.START_ARRAY, p.nextToken()); + assertToken(JsonToken.VALUE_NULL, p.nextToken()); + assertToken(JsonToken.END_ARRAY, p.nextToken()); + assertNull(p.nextToken()); + } + + public void testSimple() throws IOException + { + byte[] data = _smileDoc("[ true, null, false ]"); + SmileParser p = _smileParser(data); + assertNull(p.getCurrentToken()); + assertToken(JsonToken.START_ARRAY, p.nextToken()); + assertToken(JsonToken.VALUE_TRUE, p.nextToken()); + assertToken(JsonToken.VALUE_NULL, p.nextToken()); + assertToken(JsonToken.VALUE_FALSE, p.nextToken()); + assertToken(JsonToken.END_ARRAY, p.nextToken()); + assertNull(p.nextToken()); + p.close(); + } + + public void testArrayWithString() throws IOException + { + byte[] data = _smileDoc("[ \"abc\" ]"); + SmileParser p = _smileParser(data); + assertNull(p.getCurrentToken()); + assertToken(JsonToken.START_ARRAY, p.nextToken()); + assertToken(JsonToken.VALUE_STRING, p.nextToken()); + assertEquals("abc", p.getText()); + assertEquals(0, p.getTextOffset()); + assertEquals(3, p.getTextLength()); + assertToken(JsonToken.END_ARRAY, p.nextToken()); + p.close(); + } + + public void testEmptyStrings() throws IOException + { + // first, empty key + byte[] data = _smileDoc("{ \"\":true }"); + SmileParser p = _smileParser(data); + assertNull(p.getCurrentToken()); + assertToken(JsonToken.START_OBJECT, p.nextToken()); + assertToken(JsonToken.FIELD_NAME, p.nextToken()); + assertEquals("", p.getCurrentName()); + assertToken(JsonToken.VALUE_TRUE, p.nextToken()); + assertToken(JsonToken.END_OBJECT, p.nextToken()); + assertNull(p.nextToken()); + p.close(); + + // then empty value + data = _smileDoc("{ \"abc\":\"\" }"); + p = _smileParser(data); + assertNull(p.getCurrentToken()); + assertToken(JsonToken.START_OBJECT, p.nextToken()); + assertToken(JsonToken.FIELD_NAME, p.nextToken()); + assertEquals("abc", p.getCurrentName()); + assertToken(JsonToken.VALUE_STRING, p.nextToken()); + assertEquals("", p.getText()); + assertToken(JsonToken.END_OBJECT, p.nextToken()); + assertNull(p.nextToken()); + p.close(); + + // and combinations + data = _smileDoc("{ \"\":\"\", \"\":\"\" }"); + p = _smileParser(data); + assertNull(p.getCurrentToken()); + assertToken(JsonToken.START_OBJECT, p.nextToken()); + assertToken(JsonToken.FIELD_NAME, p.nextToken()); + assertEquals("", p.getCurrentName()); + assertToken(JsonToken.VALUE_STRING, p.nextToken()); + assertEquals("", p.getText()); + assertToken(JsonToken.FIELD_NAME, p.nextToken()); + assertEquals("", p.getCurrentName()); + assertToken(JsonToken.VALUE_STRING, p.nextToken()); + assertEquals("", p.getText()); + assertToken(JsonToken.END_OBJECT, p.nextToken()); + assertNull(p.nextToken()); + p.close(); + } + + // Test for ASCII String values longer than 64 bytes; separate + // since handling differs + public void testLongAsciiString() throws IOException + { + final String DIGITS = "1234567890"; + String LONG = DIGITS + DIGITS + DIGITS + DIGITS; + LONG = LONG + LONG + LONG + LONG; + byte[] data = _smileDoc(quote(LONG)); + + SmileParser p = _smileParser(data); + assertNull(p.getCurrentToken()); + assertToken(JsonToken.VALUE_STRING, p.nextToken()); + assertEquals(LONG, p.getText()); + assertNull(p.nextToken()); + } + + //Test for non-ASCII String values longer than 64 bytes; separate + // since handling differs + public void testLongUnicodeString() throws IOException + { + final String DIGITS = "1234567890"; + final String UNIC = "\u00F06"; // o with umlauts + String LONG = DIGITS + UNIC + DIGITS + UNIC + UNIC + DIGITS + DIGITS; + LONG = LONG + LONG + LONG; + byte[] data = _smileDoc(quote(LONG)); + + SmileParser p = _smileParser(data); + assertNull(p.getCurrentToken()); + assertToken(JsonToken.VALUE_STRING, p.nextToken()); + assertEquals(LONG, p.getText()); + assertNull(p.nextToken()); + } + + public void testTrivialObject() throws IOException + { + byte[] data = _smileDoc("{\"abc\":13}"); + SmileParser p = _smileParser(data); + assertNull(p.getCurrentToken()); + + assertToken(JsonToken.START_OBJECT, p.nextToken()); + assertToken(JsonToken.FIELD_NAME, p.nextToken()); + assertEquals("abc", p.getCurrentName()); + assertEquals("abc", p.getText()); + assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); + assertEquals(13, p.getIntValue()); + assertToken(JsonToken.END_OBJECT, p.nextToken()); + } + + public void testSimpleObject() throws IOException + { + byte[] data = _smileDoc("{\"a\":8, \"b\" : [ true ], \"c\" : { }, \"d\":{\"e\":null}}"); + SmileParser p = _smileParser(data); + assertNull(p.getCurrentToken()); + assertToken(JsonToken.START_OBJECT, p.nextToken()); + + assertToken(JsonToken.FIELD_NAME, p.nextToken()); + assertEquals("a", p.getCurrentName()); + assertEquals("a", p.getText()); + assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); + assertEquals(8, p.getIntValue()); + + assertToken(JsonToken.FIELD_NAME, p.nextToken()); + assertEquals("b", p.getCurrentName()); + assertToken(JsonToken.START_ARRAY, p.nextToken()); + assertToken(JsonToken.VALUE_TRUE, p.nextToken()); + assertToken(JsonToken.END_ARRAY, p.nextToken()); + + assertToken(JsonToken.FIELD_NAME, p.nextToken()); + assertEquals("c", p.getCurrentName()); + assertToken(JsonToken.START_OBJECT, p.nextToken()); + assertToken(JsonToken.END_OBJECT, p.nextToken()); + + assertToken(JsonToken.FIELD_NAME, p.nextToken()); + assertEquals("d", p.getCurrentName()); + + assertToken(JsonToken.START_OBJECT, p.nextToken()); + assertToken(JsonToken.FIELD_NAME, p.nextToken()); + assertEquals("e", p.getCurrentName()); + assertToken(JsonToken.VALUE_NULL, p.nextToken()); + assertToken(JsonToken.END_OBJECT, p.nextToken()); + + assertToken(JsonToken.END_OBJECT, p.nextToken()); + p.close(); + } + + public void testNestedObject() throws IOException + { + byte[] data = _smileDoc("[{\"a\":{\"b\":[1]}}]"); + SmileParser p = _smileParser(data); + assertNull(p.getCurrentToken()); + assertToken(JsonToken.START_ARRAY, p.nextToken()); + assertToken(JsonToken.START_OBJECT, p.nextToken()); + assertToken(JsonToken.FIELD_NAME, p.nextToken()); // a + assertEquals("a", p.getCurrentName()); + assertToken(JsonToken.START_OBJECT, p.nextToken()); + assertToken(JsonToken.FIELD_NAME, p.nextToken()); // b + assertEquals("b", p.getCurrentName()); + assertToken(JsonToken.START_ARRAY, p.nextToken()); + assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); + assertToken(JsonToken.END_ARRAY, p.nextToken()); + assertToken(JsonToken.END_OBJECT, p.nextToken()); + assertToken(JsonToken.END_OBJECT, p.nextToken()); + assertToken(JsonToken.END_ARRAY, p.nextToken()); + assertNull(p.nextToken()); + } + + public void testJsonSampleDoc() throws IOException + { + byte[] data = _smileDoc(SAMPLE_DOC_JSON_SPEC); + verifyJsonSpecSampleDoc(_smileParser(data), true); + } + + public void testUnicodeStringValues() throws IOException + { + String uc = "\u00f6stl. v. Greenwich \u3333?"; + byte[] data = _smileDoc("[" +quote(uc)+"]"); + + // First, just skipping + SmileParser p = _smileParser(data); + assertToken(JsonToken.START_ARRAY, p.nextToken()); + assertToken(JsonToken.VALUE_STRING, p.nextToken()); + assertToken(JsonToken.END_ARRAY, p.nextToken()); + assertNull(p.nextToken()); + p.close(); + + // Then accessing data + p = _smileParser(data); + assertToken(JsonToken.START_ARRAY, p.nextToken()); + assertToken(JsonToken.VALUE_STRING, p.nextToken()); + assertEquals(uc, p.getText()); + assertToken(JsonToken.END_ARRAY, p.nextToken()); + assertNull(p.nextToken()); + p.close(); + + // and then let's create longer text segment as well + StringBuilder sb = new StringBuilder(); + while (sb.length() < 200) { + sb.append(uc); + } + final String longer = sb.toString(); + data = _smileDoc("["+quote(longer)+"]"); + + // Ok once again, first skipping, then accessing + p = _smileParser(data); + assertToken(JsonToken.START_ARRAY, p.nextToken()); + assertToken(JsonToken.VALUE_STRING, p.nextToken()); + assertToken(JsonToken.END_ARRAY, p.nextToken()); + assertNull(p.nextToken()); + p.close(); + + p = _smileParser(data); + assertToken(JsonToken.START_ARRAY, p.nextToken()); + assertToken(JsonToken.VALUE_STRING, p.nextToken()); + assertEquals(longer, p.getText()); + assertToken(JsonToken.END_ARRAY, p.nextToken()); + assertNull(p.nextToken()); + p.close(); + } + + public void testUnicodePropertyNames() throws IOException + { + String uc = "\u00f6stl. v. Greenwich \u3333"; + byte[] data = _smileDoc("{" +quote(uc)+":true}"); + + // First, just skipping + SmileParser p = _smileParser(data); + assertToken(JsonToken.START_OBJECT, p.nextToken()); + assertToken(JsonToken.FIELD_NAME, p.nextToken()); + assertToken(JsonToken.VALUE_TRUE, p.nextToken()); + assertToken(JsonToken.END_OBJECT, p.nextToken()); + assertNull(p.nextToken()); + p.close(); + + // Then accessing data + p = _smileParser(data); + assertToken(JsonToken.START_OBJECT, p.nextToken()); + assertToken(JsonToken.FIELD_NAME, p.nextToken()); + assertEquals(uc, p.getCurrentName()); + assertToken(JsonToken.VALUE_TRUE, p.nextToken()); + assertToken(JsonToken.END_OBJECT, p.nextToken()); + assertNull(p.nextToken()); + p.close(); + } + + // Simple test to verify that byte 0 is not used (an implementation + // might mistakenly consider it a string value reference) + public void testInvalidByte() throws IOException + { + byte[] data = new byte[] { SmileConstants.TOKEN_LITERAL_START_ARRAY, + (byte) SmileConstants.TOKEN_PREFIX_SHARED_STRING_SHORT, + (byte) SmileConstants.TOKEN_LITERAL_END_ARRAY + }; + SmileParser p = _smileParser(data); + assertToken(JsonToken.START_ARRAY, p.nextToken()); + // And now should get an error + try { + JsonToken t = p.nextToken(); + fail("Expected parse error, got: "+t); + } catch (IOException e) { + verifyException(e, "Invalid token byte 0x00"); + } + } + + // [JACKSON-629] + public void testNameBoundary() throws IOException + { + SmileFactory f = smileFactory(true, true, false); + // let's create 3 meg docs + final int LEN = 3 * 1000 * 1000; + final String FIELD = "field01"; // important: 7 chars + + for (int offset = 0; offset < 12; ++offset) { + ByteArrayOutputStream bytes = new ByteArrayOutputStream(LEN); + // To trigger boundary condition, need to shuffle stuff around a bit... + for (int i = 0; i < offset; ++i) { + bytes.write(0); + } + + // force back-refs off, easier to trigger problem + f.configure(SmileGenerator.Feature.CHECK_SHARED_NAMES, false); + SmileGenerator gen = f.createJsonGenerator(bytes); + + int count = 0; + do { + gen.writeStartObject(); + // importa + gen.writeNumberField(FIELD, count % 17); + gen.writeEndObject(); + ++count; + } while (bytes.size() < (LEN - 100)); + gen.close(); + + // and then read back + byte[] json = bytes.toByteArray(); + SmileParser jp = f.createJsonParser(new ByteArrayInputStream(json, offset, json.length-offset)); + int i = 0; + + while (i < count) { + assertToken(JsonToken.START_OBJECT, jp.nextToken()); + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals(FIELD, jp.getCurrentName()); + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals((i % 17), jp.getIntValue()); + assertToken(JsonToken.END_OBJECT, jp.nextToken()); + ++i; + } + // and should be done now + assertNull(jp.nextToken()); + jp.close(); + } + } + + // [JACKSON-640]: Problem with getTextCharacters/Offset/Length + public void testCharacters() throws IOException + { + // ensure we are using both back-ref types + SmileFactory sf = new SmileFactory(); + sf.configure(SmileGenerator.Feature.CHECK_SHARED_NAMES, true); + sf.configure(SmileGenerator.Feature.CHECK_SHARED_STRING_VALUES, true); + ByteArrayOutputStream bytes = new ByteArrayOutputStream(100); + + JsonGenerator jgen = sf.createJsonGenerator(bytes); + jgen.writeStartArray(); + jgen.writeStartObject(); + jgen.writeStringField("key", "value"); + jgen.writeEndObject(); + jgen.writeStartObject(); + jgen.writeStringField("key", "value"); + jgen.writeEndObject(); + jgen.writeEndArray(); + jgen.close(); + + SmileParser p = _smileParser(bytes.toByteArray()); + + assertToken(JsonToken.START_ARRAY, p.nextToken()); + String str; + + assertToken(JsonToken.START_OBJECT, p.nextToken()); + assertToken(JsonToken.FIELD_NAME, p.nextToken()); + str = new String(p.getTextCharacters(), p.getTextOffset(), p.getTextLength()); + assertEquals("key", str); + assertToken(JsonToken.VALUE_STRING, p.nextToken()); + str = new String(p.getTextCharacters(), p.getTextOffset(), p.getTextLength()); + assertEquals("value", str); + assertToken(JsonToken.END_OBJECT, p.nextToken()); + + assertToken(JsonToken.START_OBJECT, p.nextToken()); + assertToken(JsonToken.FIELD_NAME, p.nextToken()); + str = new String(p.getTextCharacters(), p.getTextOffset(), p.getTextLength()); + assertEquals("key", str); + assertToken(JsonToken.VALUE_STRING, p.nextToken()); + str = new String(p.getTextCharacters(), p.getTextOffset(), p.getTextLength()); + assertEquals("value", str); + assertToken(JsonToken.END_OBJECT, p.nextToken()); + + assertToken(JsonToken.END_ARRAY, p.nextToken()); + assertNull(p.nextToken()); + p.close(); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/smile/TestSmileParserBinary.java b/1.9.10/src/test/org/codehaus/jackson/smile/TestSmileParserBinary.java new file mode 100644 index 0000000..a94252f --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/smile/TestSmileParserBinary.java
@@ -0,0 +1,170 @@ +package org.codehaus.jackson.smile; + +import java.io.*; + +import static org.junit.Assert.*; + +import org.codehaus.jackson.JsonToken; + +public class TestSmileParserBinary + extends SmileTestBase +{ + final static int[] SIZES = new int[] { + 1, 2, 3, 4, 5, 6, + 7, 8, 12, + 100, 350, 1900, 6000, 19000, 65000, + 139000 + }; + + public void testRawAsArray() throws IOException + { + _testBinaryAsArray(true); + } + + public void test7BitAsArray() throws IOException + { + _testBinaryAsArray(false); + } + + // Added based on [JACKSON-376] + public void testRawAsObject() throws IOException + { + _testBinaryAsObject(true); + } + + // Added based on [JACKSON-376] + public void test7BitAsObject() throws IOException + { + _testBinaryAsObject(false); + } + + public void testRawAsRootValue() throws IOException + { + _testBinaryAsRoot(true); + } + + public void test7BitAsRootValue() throws IOException + { + _testBinaryAsRoot(false); + } + + /* + /********************************************************** + /* Helper methods + /********************************************************** + */ + + private void _testBinaryAsRoot(boolean raw) throws IOException + { + SmileFactory f = new SmileFactory(); + f.configure(SmileGenerator.Feature.ENCODE_BINARY_AS_7BIT, !raw); + for (int size : SIZES) { + byte[] data = _generateData(size); + ByteArrayOutputStream bo = new ByteArrayOutputStream(size+10); + SmileGenerator g = f.createJsonGenerator(bo); + g.writeBinary(data); + g.close(); + byte[] smile = bo.toByteArray(); + + // and verify + SmileParser p = f.createJsonParser(smile); + assertToken(JsonToken.VALUE_EMBEDDED_OBJECT, p.nextToken()); + byte[] result = p.getBinaryValue(); + assertArrayEquals(data, result); + assertNull(p.nextToken()); + p.close(); + + // and second time around, skipping + p = f.createJsonParser(smile); + assertToken(JsonToken.VALUE_EMBEDDED_OBJECT, p.nextToken()); + assertNull(p.nextToken()); + p.close(); + } + } + + private void _testBinaryAsArray(boolean raw) throws IOException + { + SmileFactory f = new SmileFactory(); + f.configure(SmileGenerator.Feature.ENCODE_BINARY_AS_7BIT, !raw); + for (int size : SIZES) { + byte[] data = _generateData(size); + ByteArrayOutputStream bo = new ByteArrayOutputStream(size+10); + SmileGenerator g = f.createJsonGenerator(bo); + g.writeStartArray(); + g.writeBinary(data); + g.writeNumber(1); // just to verify there's no overrun + g.writeEndArray(); + g.close(); + byte[] smile = bo.toByteArray(); + + // and verify + SmileParser p = f.createJsonParser(smile); + assertToken(JsonToken.START_ARRAY, p.nextToken()); + assertToken(JsonToken.VALUE_EMBEDDED_OBJECT, p.nextToken()); + byte[] result = p.getBinaryValue(); + assertArrayEquals(data, result); + assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); + assertEquals(1, p.getIntValue()); + assertToken(JsonToken.END_ARRAY, p.nextToken()); + assertNull(p.nextToken()); + p.close(); + + // and second time around, skipping + p = f.createJsonParser(smile); + assertToken(JsonToken.START_ARRAY, p.nextToken()); + assertToken(JsonToken.VALUE_EMBEDDED_OBJECT, p.nextToken()); + assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); + assertToken(JsonToken.END_ARRAY, p.nextToken()); + assertNull(p.nextToken()); + p.close(); + } + } + + private void _testBinaryAsObject(boolean raw) throws IOException + { + SmileFactory f = new SmileFactory(); + f.configure(SmileGenerator.Feature.ENCODE_BINARY_AS_7BIT, !raw); + for (int size : SIZES) { + byte[] data = _generateData(size); + ByteArrayOutputStream bo = new ByteArrayOutputStream(size+10); + SmileGenerator g = f.createJsonGenerator(bo); + g.writeStartObject(); + g.writeFieldName("binary"); + g.writeBinary(data); + g.writeEndObject(); + g.close(); + byte[] smile = bo.toByteArray(); + + // and verify + SmileParser p = f.createJsonParser(smile); + assertToken(JsonToken.START_OBJECT, p.nextToken()); + + assertToken(JsonToken.FIELD_NAME, p.nextToken()); + assertEquals("binary", p.getCurrentName()); + assertToken(JsonToken.VALUE_EMBEDDED_OBJECT, p.nextToken()); + byte[] result = p.getBinaryValue(); + assertArrayEquals(data, result); + assertToken(JsonToken.END_OBJECT, p.nextToken()); + assertNull(p.nextToken()); + p.close(); + + // and second time around, skipping + p = f.createJsonParser(smile); + assertToken(JsonToken.START_OBJECT, p.nextToken()); + assertToken(JsonToken.FIELD_NAME, p.nextToken()); + assertToken(JsonToken.VALUE_EMBEDDED_OBJECT, p.nextToken()); + assertToken(JsonToken.END_OBJECT, p.nextToken()); + assertNull(p.nextToken()); + p.close(); + } + } + + private byte[] _generateData(int size) + { + byte[] result = new byte[size]; + for (int i = 0; i < size; ++i) { + result[i] = (byte) (i % 255); + } + return result; + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/smile/TestSmileParserLocation.java b/1.9.10/src/test/org/codehaus/jackson/smile/TestSmileParserLocation.java new file mode 100644 index 0000000..299e905 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/smile/TestSmileParserLocation.java
@@ -0,0 +1,62 @@ +package org.codehaus.jackson.smile; + +import java.io.IOException; + +import org.codehaus.jackson.JsonLocation; +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.JsonToken; + +public class TestSmileParserLocation + extends SmileTestBase +{ + /** + * Basic unit test to verify that [JACKSON-] has been resolved. + */ + public void testSimpleOffsets() throws IOException + { + byte[] data = _smileDoc("[ true, null, false, 511 ]", true); // true -> write header + + JsonParser p = _smileParser(data); + assertNull(p.getCurrentToken()); + JsonLocation loc = p.getCurrentLocation(); + assertNotNull(loc); + // first: -1 for "not known", for character-based stuff + assertEquals(-1, loc.getCharOffset()); + // except that with 1.9.7 and above, we also consider column to be same as offset, for convenience + assertEquals(4, loc.getColumnNr()); + assertEquals(-1, loc.getLineNr()); + // but first 4 bytes are for header + assertEquals(4, loc.getByteOffset()); + + // array marker is a single byte, so: + assertToken(JsonToken.START_ARRAY, p.nextToken()); + assertEquals(5, p.getCurrentLocation().getByteOffset()); + assertEquals(4, p.getTokenLocation().getByteOffset()); + + // same for true and others except for last int + assertToken(JsonToken.VALUE_TRUE, p.nextToken()); + assertEquals(6, p.getCurrentLocation().getByteOffset()); + assertEquals(5, p.getTokenLocation().getByteOffset()); + + assertToken(JsonToken.VALUE_NULL, p.nextToken()); + assertEquals(7, p.getCurrentLocation().getByteOffset()); + assertEquals(6, p.getTokenLocation().getByteOffset()); + + assertToken(JsonToken.VALUE_FALSE, p.nextToken()); + assertEquals(8, p.getCurrentLocation().getByteOffset()); + assertEquals(7, p.getTokenLocation().getByteOffset()); + + // 0x1FF takes 3 bytes (type byte, 7/6 bit segments) + assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); + assertEquals(511, p.getIntValue()); + assertEquals(11, p.getCurrentLocation().getByteOffset()); + assertEquals(8, p.getTokenLocation().getByteOffset()); + + assertToken(JsonToken.END_ARRAY, p.nextToken()); + assertEquals(12, p.getCurrentLocation().getByteOffset()); + assertEquals(11, p.getTokenLocation().getByteOffset()); + + assertNull(p.nextToken()); + p.close(); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/smile/TestSmileParserNames.java b/1.9.10/src/test/org/codehaus/jackson/smile/TestSmileParserNames.java new file mode 100644 index 0000000..d26aaab --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/smile/TestSmileParserNames.java
@@ -0,0 +1,66 @@ +package org.codehaus.jackson.smile; + +import java.io.*; +import java.util.Random; + +import org.codehaus.jackson.*; + +public class TestSmileParserNames extends SmileTestBase +{ + public void testLongNames() throws IOException + { + _testWithName(generateName(5000)); + } + + public void testJsonBinForLargeObjects() throws Exception + { + StringBuilder nameBuf = new StringBuilder("longString"); + int minLength = 9000; + for (int i = 1; nameBuf.length() < minLength; ++i) { + nameBuf.append("." + i); + } + String name = nameBuf.toString(); + _testWithName(name); + } + + /* + /********************************************************** + /* Helper methods + /********************************************************** + */ + + private void _testWithName(String name) throws IOException + { + byte[] data = _smileDoc("{"+quote(name)+":13}"); + // important: MUST use InputStream to enforce buffer boundaries! + SmileParser p = _smileParser(new ByteArrayInputStream(data)); + assertNull(p.getCurrentToken()); + assertToken(JsonToken.START_OBJECT, p.nextToken()); + assertToken(JsonToken.FIELD_NAME, p.nextToken()); + assertEquals(name, p.getCurrentName()); + assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); + assertEquals(13, p.getIntValue()); + assertEquals(name, p.getCurrentName()); + assertToken(JsonToken.END_OBJECT, p.nextToken()); + assertNull(p.nextToken()); + p.close(); + } + + + private String generateName(int minLen) + { + StringBuilder sb = new StringBuilder(); + Random rnd = new Random(123); + while (sb.length() < minLen) { + int ch = rnd.nextInt(96); + if (ch < 32) { // ascii (single byte) + sb.append((char) (48 + ch)); + } else if (ch < 64) { // 2 byte + sb.append((char) (128 + ch)); + } else { // 3 byte + sb.append((char) (4000 + ch)); + } + } + return sb.toString(); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/smile/TestSmileParserNumbers.java b/1.9.10/src/test/org/codehaus/jackson/smile/TestSmileParserNumbers.java new file mode 100644 index 0000000..d7f38cf --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/smile/TestSmileParserNumbers.java
@@ -0,0 +1,301 @@ +package org.codehaus.jackson.smile; + +import java.io.*; +import java.math.BigDecimal; +import java.math.BigInteger; + +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.JsonToken; + +public class TestSmileParserNumbers + extends SmileTestBase +{ + public void testIntsMedium() throws IOException + { + byte[] data = _smileDoc("255"); + SmileParser p = _smileParser(data); + assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); + assertEquals(255, p.getIntValue()); + assertEquals("255", p.getText()); + + data = _smileDoc("-999"); + p = _smileParser(data); + assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); + assertEquals(JsonParser.NumberType.INT, p.getNumberType()); + assertEquals(-999, p.getIntValue()); + assertEquals("-999", p.getText()); + + data = _smileDoc("123456789"); + p = _smileParser(data); + assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); + assertEquals(JsonParser.NumberType.INT, p.getNumberType()); + assertEquals(123456789, p.getIntValue()); + } + + public void testMinMaxInts() throws IOException + { + byte[] data = _smileDoc(String.valueOf(Integer.MAX_VALUE)); + SmileParser p = _smileParser(data); + assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); + assertEquals(JsonParser.NumberType.INT, p.getNumberType()); + assertEquals(Integer.MAX_VALUE, p.getIntValue()); + + data = _smileDoc(String.valueOf(Integer.MIN_VALUE)); + p = _smileParser(data); + assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); + assertEquals(JsonParser.NumberType.INT, p.getNumberType()); + assertEquals(Integer.MIN_VALUE, p.getIntValue()); + } + + public void testIntsInObjectSkipping() throws IOException + { + byte[] data = _smileDoc("{\"a\":200,\"b\":200}"); + SmileParser p = _smileParser(data); + assertToken(JsonToken.START_OBJECT, p.nextToken()); + assertToken(JsonToken.FIELD_NAME, p.nextToken()); + assertEquals("a", p.getCurrentName()); + assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); + // let's NOT access value, forcing skipping + assertToken(JsonToken.FIELD_NAME, p.nextToken()); + assertEquals("b", p.getCurrentName()); + assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); + // let's NOT access value, forcing skipping + assertToken(JsonToken.END_OBJECT, p.nextToken()); + } + + public void testBorderLongs() throws IOException + { + long l = (long) Integer.MIN_VALUE - 1L; + byte[] data = _smileDoc(String.valueOf(l), false); + assertEquals(6, data.length); + SmileParser p = _smileParser(data); + assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); + assertEquals(JsonParser.NumberType.LONG, p.getNumberType()); + assertEquals(l, p.getLongValue()); + + l = 1L + (long) Integer.MAX_VALUE; + data = _smileDoc(String.valueOf(l), false); + assertEquals(6, data.length); + p = _smileParser(data); + assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); + assertEquals(JsonParser.NumberType.LONG, p.getNumberType()); + assertEquals(l, p.getLongValue()); + } + + public void testLongs() throws IOException + { + long l = Long.MAX_VALUE; + byte[] data = _smileDoc(String.valueOf(l)); + SmileParser p = _smileParser(data); + assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); + assertEquals(JsonParser.NumberType.LONG, p.getNumberType()); + assertEquals(l, p.getLongValue()); + assertEquals(String.valueOf(l), p.getText()); + + l = Long.MIN_VALUE; + data = _smileDoc(String.valueOf(l)); + p = _smileParser(data); + assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); + assertEquals(JsonParser.NumberType.LONG, p.getNumberType()); + assertEquals(l, p.getLongValue()); + assertEquals(String.valueOf(l), p.getText()); + } + + public void testArrayWithInts() throws IOException + { + byte[] data = _smileDoc("[ 1, 0, -1, 255, -999, " + +Integer.MIN_VALUE+","+Integer.MAX_VALUE+"," + +Long.MIN_VALUE+", "+Long.MAX_VALUE+" ]"); + SmileParser p = _smileParser(data); + assertNull(p.getCurrentToken()); + assertToken(JsonToken.START_ARRAY, p.nextToken()); + + assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); + assertEquals(1, p.getIntValue()); + assertEquals(JsonParser.NumberType.INT, p.getNumberType()); + assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); + assertEquals(0, p.getIntValue()); + assertEquals(JsonParser.NumberType.INT, p.getNumberType()); + assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); + assertEquals(-1, p.getIntValue()); + assertEquals(JsonParser.NumberType.INT, p.getNumberType()); + + assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); + assertEquals(255, p.getIntValue()); + assertEquals(JsonParser.NumberType.INT, p.getNumberType()); + assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); + assertEquals(-999, p.getIntValue()); + assertEquals(JsonParser.NumberType.INT, p.getNumberType()); + + assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); + assertEquals(JsonParser.NumberType.INT, p.getNumberType()); + assertEquals(Integer.MIN_VALUE, p.getIntValue()); + assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); + assertEquals(Integer.MAX_VALUE, p.getIntValue()); + assertEquals(JsonParser.NumberType.INT, p.getNumberType()); + + assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); + assertEquals(JsonParser.NumberType.LONG, p.getNumberType()); + assertEquals(Long.MIN_VALUE, p.getLongValue()); + assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); + assertEquals(Long.MAX_VALUE, p.getLongValue()); + assertEquals(JsonParser.NumberType.LONG, p.getNumberType()); + + assertToken(JsonToken.END_ARRAY, p.nextToken()); + p.close(); + } + + public void testFloats() throws IOException + { + ByteArrayOutputStream bo = new ByteArrayOutputStream(); + SmileGenerator g = smileGenerator(bo, false); + float value = 0.37f; + g.writeNumber(value); + g.close(); + byte[] data = bo.toByteArray(); + assertEquals(6, data.length); + + SmileParser p = _smileParser(data); + assertToken(JsonToken.VALUE_NUMBER_FLOAT, p.nextToken()); + assertEquals(JsonParser.NumberType.FLOAT, p.getNumberType()); + assertEquals(value, p.getFloatValue()); + } + + public void testDoubles() throws IOException + { + ByteArrayOutputStream bo = new ByteArrayOutputStream(); + SmileGenerator g = smileGenerator(bo, false); + double value = -12.0986; + g.writeNumber(value); + g.close(); + byte[] data = bo.toByteArray(); + assertEquals(11, data.length); + + SmileParser p = _smileParser(data); + assertToken(JsonToken.VALUE_NUMBER_FLOAT, p.nextToken()); + assertEquals(JsonParser.NumberType.DOUBLE, p.getNumberType()); + assertEquals(value, p.getDoubleValue()); + } + + public void testArrayWithDoubles() throws IOException + { + ByteArrayOutputStream bo = new ByteArrayOutputStream(); + SmileGenerator g = smileGenerator(bo, false); + g.writeStartArray(); + g.writeNumber(0.1f); + g.writeNumber(0.333); + g.writeEndArray(); + g.close(); + byte[] data = bo.toByteArray(); + assertEquals(19, data.length); + + SmileParser p = _smileParser(data); + assertToken(JsonToken.START_ARRAY, p.nextToken()); + assertToken(JsonToken.VALUE_NUMBER_FLOAT, p.nextToken()); + assertEquals(JsonParser.NumberType.FLOAT, p.getNumberType()); + assertEquals(0.1f, p.getFloatValue()); + assertToken(JsonToken.VALUE_NUMBER_FLOAT, p.nextToken()); + assertEquals(JsonParser.NumberType.DOUBLE, p.getNumberType()); + assertEquals(0.333, p.getDoubleValue()); + assertToken(JsonToken.END_ARRAY, p.nextToken()); + } + + public void testObjectWithDoubles() throws IOException + { + ByteArrayOutputStream bo = new ByteArrayOutputStream(); + SmileGenerator g = smileGenerator(bo, false); + g.writeStartObject(); + g.writeNumberField("x", 0.5); + g.writeNumberField("y", 0.01338); + g.writeEndObject(); + g.close(); + + byte[] data = bo.toByteArray(); + + // first let's just skip + SmileParser p = _smileParser(data); + assertToken(JsonToken.START_OBJECT, p.nextToken()); + assertToken(JsonToken.FIELD_NAME, p.nextToken()); + assertToken(JsonToken.VALUE_NUMBER_FLOAT, p.nextToken()); + assertToken(JsonToken.FIELD_NAME, p.nextToken()); + assertToken(JsonToken.VALUE_NUMBER_FLOAT, p.nextToken()); + assertToken(JsonToken.END_OBJECT, p.nextToken()); + p.close(); + + // and then check data too (skip codepath distinct) + p = _smileParser(data); + assertToken(JsonToken.START_OBJECT, p.nextToken()); + assertToken(JsonToken.FIELD_NAME, p.nextToken()); + assertEquals("x", p.getText()); + assertToken(JsonToken.VALUE_NUMBER_FLOAT, p.nextToken()); + assertEquals(0.5, p.getDoubleValue()); + assertToken(JsonToken.FIELD_NAME, p.nextToken()); + assertEquals("y", p.getText()); + assertToken(JsonToken.VALUE_NUMBER_FLOAT, p.nextToken()); + assertEquals(0.01338, p.getDoubleValue()); + assertToken(JsonToken.END_OBJECT, p.nextToken()); + p.close(); + } + + public void testBigInteger() throws IOException + { + ByteArrayOutputStream bo = new ByteArrayOutputStream(); + BigInteger in = new BigInteger(String.valueOf(Long.MIN_VALUE)+"0012575934"); + SmileGenerator g = smileGenerator(bo, false); + g.writeNumber(in); + g.close(); + byte[] data = bo.toByteArray(); + SmileParser p = _smileParser(data); + assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); + assertEquals(JsonParser.NumberType.BIG_INTEGER, p.getNumberType()); + assertEquals(BigInteger.class, p.getNumberValue().getClass()); + assertEquals(in, p.getBigIntegerValue()); + p.close(); + + // second test; verify skipping works + bo = new ByteArrayOutputStream(); + g = smileGenerator(bo, false); + g.writeStartArray(); + g.writeNumber(in); + g.writeEndArray(); + g.close(); + data = bo.toByteArray(); + p = _smileParser(data); + assertToken(JsonToken.START_ARRAY, p.nextToken()); + assertToken(JsonToken.VALUE_NUMBER_INT, p.nextToken()); + assertToken(JsonToken.END_ARRAY, p.nextToken()); + assertNull(p.nextToken()); + p.close(); + } + + public void testBigDecimal() throws IOException + { + ByteArrayOutputStream bo = new ByteArrayOutputStream(); + BigDecimal in = new BigDecimal("32599.00001"); + SmileGenerator g = smileGenerator(bo, false); + g.writeNumber(in); + g.close(); + byte[] data = bo.toByteArray(); + SmileParser p = _smileParser(data); + assertToken(JsonToken.VALUE_NUMBER_FLOAT, p.nextToken()); + assertEquals(JsonParser.NumberType.BIG_DECIMAL, p.getNumberType()); + assertEquals(BigDecimal.class, p.getNumberValue().getClass()); + assertEquals(in, p.getDecimalValue()); + p.close(); + + // second test; verify skipping works + bo = new ByteArrayOutputStream(); + g = smileGenerator(bo, false); + g.writeStartArray(); + g.writeNumber(in); + g.writeEndArray(); + g.close(); + data = bo.toByteArray(); + p = _smileParser(data); + assertToken(JsonToken.START_ARRAY, p.nextToken()); + assertToken(JsonToken.VALUE_NUMBER_FLOAT, p.nextToken()); + assertToken(JsonToken.END_ARRAY, p.nextToken()); + assertNull(p.nextToken()); + p.close(); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/smile/TestSmileParserSymbolHandling.java b/1.9.10/src/test/org/codehaus/jackson/smile/TestSmileParserSymbolHandling.java new file mode 100644 index 0000000..e5f0e92 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/smile/TestSmileParserSymbolHandling.java
@@ -0,0 +1,560 @@ +package org.codehaus.jackson.smile; + +import java.io.*; +import java.util.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.ObjectMapper; +import org.codehaus.jackson.sym.BytesToNameCanonicalizer; + +/** + * Unit tests for verifying that symbol handling works as planned, including + * efficient reuse of names encountered during parsing. + */ +public class TestSmileParserSymbolHandling + extends SmileTestBase +{ + /* + /********************************************************** + /* Helper types, constants + /********************************************************** + */ + + private final static String[] SHARED_SYMBOLS = new String[] { + "g", "J", "v", "B", "S", "JAVA", + "h", "J", "LARGE", + "JAVA", "J", "SMALL" + }; + + static class MediaItem + { + public Content content; + public Image[] images; + } + + public enum Size { SMALL, LARGE; } + public enum Player { JAVA, FLASH; } + + static class Image + { + public String uri; + public String title; + public int width; + public int height; + public Size size; + + public Image() { } + public Image(String uri, String title, int w, int h, Size s) + { + this.uri = uri; + this.title = title; + width = w; + height = h; + size = s; + } + } + + static class Content + { + public Player player; + public String uri; + public String title; + public int width; + public int height; + public String format; + public long duration; + public long size; + public int bitrate; + public String[] persons; + public String copyright; + } + + /* + /********************************************************** + /* Unit tests + /********************************************************** + */ + + public void testSimple() throws IOException + { + final String STR1 = "a"; + + byte[] data = _smileDoc("{ "+quote(STR1)+":1, \"foobar\":2, \"longername\":3 }"); + SmileFactory f = new SmileFactory(); + SmileParser p = _smileParser(f, data); + final BytesToNameCanonicalizer symbols1 = p._symbols; + assertEquals(0, symbols1.size()); + + assertEquals(JsonToken.START_OBJECT, p.nextToken()); + assertEquals(JsonToken.FIELD_NAME, p.nextToken()); + // field names are interned: + assertSame(STR1, p.getCurrentName()); + assertEquals(1, symbols1.size()); + assertEquals(JsonToken.VALUE_NUMBER_INT, p.nextToken()); + assertEquals(JsonToken.FIELD_NAME, p.nextToken()); + assertSame("foobar", p.getCurrentName()); + assertEquals(2, symbols1.size()); + assertEquals(JsonToken.VALUE_NUMBER_INT, p.nextToken()); + assertEquals(JsonToken.FIELD_NAME, p.nextToken()); + assertSame("longername", p.getCurrentName()); + assertEquals(3, symbols1.size()); + assertEquals(JsonToken.VALUE_NUMBER_INT, p.nextToken()); + assertEquals(JsonToken.END_OBJECT, p.nextToken()); + assertNull(p.nextToken()); + assertEquals(3, symbols1.size()); + p.close(); + + // but let's verify that symbol table gets reused properly + p = _smileParser(f, data); + BytesToNameCanonicalizer symbols2 = p._symbols; + // symbol tables are not reused, but contents are: + assertNotSame(symbols1, symbols2); + assertEquals(3, symbols2.size()); + + assertEquals(JsonToken.START_OBJECT, p.nextToken()); + assertEquals(JsonToken.FIELD_NAME, p.nextToken()); + // field names are interned: + assertSame(STR1, p.getCurrentName()); + assertEquals(3, symbols2.size()); + assertEquals(JsonToken.VALUE_NUMBER_INT, p.nextToken()); + assertEquals(JsonToken.FIELD_NAME, p.nextToken()); + assertSame("foobar", p.getCurrentName()); + assertEquals(3, symbols2.size()); + assertEquals(JsonToken.VALUE_NUMBER_INT, p.nextToken()); + assertEquals(JsonToken.FIELD_NAME, p.nextToken()); + assertSame("longername", p.getCurrentName()); + assertEquals(3, symbols2.size()); + assertEquals(JsonToken.VALUE_NUMBER_INT, p.nextToken()); + assertEquals(JsonToken.END_OBJECT, p.nextToken()); + assertNull(p.nextToken()); + assertEquals(3, symbols2.size()); + p.close(); + + assertEquals(3, symbols2.size()); + p.close(); + } + + public void testSharedNames() throws IOException + { + final int COUNT = 19000; + + SmileFactory f = new SmileFactory(); + f.configure(SmileGenerator.Feature.WRITE_HEADER, false); + f.configure(SmileGenerator.Feature.CHECK_SHARED_NAMES, true); + ByteArrayOutputStream out = new ByteArrayOutputStream(4000); + JsonGenerator gen = f.createJsonGenerator(out); + gen.writeStartArray(); + Random rnd = new Random(COUNT); + for (int i = 0; i < COUNT; ++i) { + gen.writeStartObject(); + int nr = rnd.nextInt() % 1200; + gen.writeNumberField("f"+nr, nr); + gen.writeEndObject(); + } + gen.writeEndArray(); + gen.close(); + byte[] json = out.toByteArray(); + + // And verify + f.configure(SmileParser.Feature.REQUIRE_HEADER, false); + JsonParser jp = f.createJsonParser(json); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + rnd = new Random(COUNT); + for (int i = 0; i < COUNT; ++i) { + assertToken(JsonToken.START_OBJECT, jp.nextToken()); + int nr = rnd.nextInt() % 1200; + String name = "f"+nr; + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals(name, jp.getCurrentName()); + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(nr, jp.getIntValue()); + assertToken(JsonToken.END_OBJECT, jp.nextToken()); + + } + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + } + + public void testSharedStrings() throws IOException + { + final int count = 19000; + byte[] baseline = writeStringValues(false, count); + assertEquals(763589, baseline.length); + verifyStringValues(baseline, count); + + // and then shared; should be much smaller + byte[] shared = writeStringValues(true, count); + if (shared.length >= baseline.length) { + fail("Expected shared String length < "+baseline.length+", was "+shared.length); + } + verifyStringValues(shared, count); + } + + public void testSharedStringsInArrays() throws IOException + { + SmileFactory f = new SmileFactory(); + f.configure(SmileGenerator.Feature.CHECK_SHARED_STRING_VALUES, true); + + ByteArrayOutputStream out = new ByteArrayOutputStream(4000); + JsonGenerator gen = f.createJsonGenerator(out); + gen.writeStartArray(); + for (String value : SHARED_SYMBOLS) { + gen.writeString(value); + } + gen.writeEndArray(); + gen.close(); + + byte[] smile = out.toByteArray(); + + JsonParser jp = f.createJsonParser(smile); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + for (String value : SHARED_SYMBOLS) { + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + assertEquals(value, jp.getText()); + } + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + } + + public void testSharedStringsInObject() throws IOException + { + SmileFactory f = new SmileFactory(); + f.configure(SmileGenerator.Feature.CHECK_SHARED_STRING_VALUES, true); + ByteArrayOutputStream out = new ByteArrayOutputStream(4000); + JsonGenerator gen = f.createJsonGenerator(out); + gen.writeStartObject(); + for (int i = 0; i < SHARED_SYMBOLS.length; ++i) { + gen.writeFieldName("a"+i); + gen.writeString(SHARED_SYMBOLS[i]); + } + gen.writeEndObject(); + gen.close(); + + byte[] smile = out.toByteArray(); + + JsonParser jp = f.createJsonParser(smile); + assertToken(JsonToken.START_OBJECT, jp.nextToken()); + for (int i = 0; i < SHARED_SYMBOLS.length; ++i) { + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals("a"+i, jp.getCurrentName()); + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + assertEquals(SHARED_SYMBOLS[i], jp.getText()); + } + assertToken(JsonToken.END_OBJECT, jp.nextToken()); + } + + public void testSharedStringsMixed() throws IOException + { + SmileFactory f = new SmileFactory(); + f.configure(SmileGenerator.Feature.CHECK_SHARED_STRING_VALUES, true); + + ByteArrayOutputStream out = new ByteArrayOutputStream(4000); + JsonGenerator gen = f.createJsonGenerator(out); + gen.writeStartObject(); + + gen.writeFieldName("media"); + gen.writeStartObject(); + + gen.writeStringField("uri", "g"); + gen.writeStringField("title", "J"); + gen.writeNumberField("width", 640); + gen.writeStringField("format", "v"); + gen.writeFieldName("persons"); + gen.writeStartArray(); + gen.writeString("B"); + gen.writeString("S"); + gen.writeEndArray(); + gen.writeStringField("player", "JAVA"); + gen.writeStringField("copyright", "NONE"); + + gen.writeEndObject(); // media + + gen.writeFieldName("images"); + gen.writeStartArray(); + + // 3 instances of identical entries + for (int i = 0; i < 3; ++i) { + gen.writeStartObject(); + gen.writeStringField("uri", "h"); + gen.writeStringField("title", "J"); + gen.writeNumberField("width", 1024); + gen.writeNumberField("height", 768); + gen.writeEndObject(); + } + gen.writeEndArray(); + + gen.writeEndObject(); + gen.close(); + + byte[] smile = out.toByteArray(); + + JsonParser jp = f.createJsonParser(smile); + assertToken(JsonToken.START_OBJECT, jp.nextToken()); + + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals("media", jp.getCurrentName()); + + assertToken(JsonToken.START_OBJECT, jp.nextToken()); + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals("uri", jp.getCurrentName()); + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + assertEquals("g", jp.getText()); + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals("title", jp.getCurrentName()); + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + assertEquals("J", jp.getText()); + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals("width", jp.getCurrentName()); + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(640, jp.getIntValue()); + + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals("format", jp.getCurrentName()); + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + assertEquals("v", jp.getText()); + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals("persons", jp.getCurrentName()); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + assertEquals("B", jp.getText()); + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + assertEquals("S", jp.getText()); + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals("player", jp.getCurrentName()); + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + assertEquals("JAVA", jp.getText()); + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals("copyright", jp.getCurrentName()); + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + assertEquals("NONE", jp.getText()); + + assertToken(JsonToken.END_OBJECT, jp.nextToken()); // media + + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals("images", jp.getCurrentName()); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + + // 3 instances of identical entries: + for (int i = 0; i < 3; ++i) { + assertToken(JsonToken.START_OBJECT, jp.nextToken()); + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals("uri", jp.getCurrentName()); + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + assertEquals("h", jp.getText()); + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals("title", jp.getCurrentName()); + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + assertEquals("J", jp.getText()); + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals("width", jp.getCurrentName()); + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(1024, jp.getIntValue()); + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals("height", jp.getCurrentName()); + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(768, jp.getIntValue()); + assertToken(JsonToken.END_OBJECT, jp.nextToken()); + } + + assertToken(JsonToken.END_ARRAY, jp.nextToken()); // images + + assertToken(JsonToken.END_OBJECT, jp.nextToken()); + } + + public void testDataBindingAndShared() throws IOException + { + SmileFactory f = new SmileFactory(); + f.configure(SmileGenerator.Feature.CHECK_SHARED_STRING_VALUES, true); + MediaItem item = new MediaItem(); + Content c = new Content(); + c.uri = "g"; + c.title = "J"; + c.width = 640; + c.height = 480; + c.format = "v"; + c.duration = 18000000L; + c.size = 58982400L; + c.bitrate = 262144; + c.persons = new String[] { "B", "S" }; + c.player = Player.JAVA; + c.copyright = "NONE"; + item.content = c; + item.images = new Image[] { + new Image("h", "J", 1024, 768, Size.LARGE), + new Image("h", "J", 320, 240, Size.LARGE) + }; + + // Ok: let's just do quick comparison (yes/no)... + ObjectMapper plain = new ObjectMapper(); + ObjectMapper smiley = new ObjectMapper(f); + String exp = plain.writeValueAsString(item); + byte[] smile = smiley.writeValueAsBytes(item); + MediaItem result = smiley.readValue(smile, 0, smile.length, MediaItem.class); + String actual = plain.writeValueAsString(result); + assertEquals(exp, actual); + } + + /** + * Reproducing [JACKSON-561] (and [JACKSON-562]) + */ + public void testIssue562() throws IOException + { + JsonFactory factory = new SmileFactory(); + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + JsonGenerator gen = factory.createJsonGenerator(bos); + gen.writeStartObject(); + gen.writeFieldName("z_aaaabbbbccccddddee"); + gen.writeString("end"); + gen.writeFieldName("a_aaaabbbbccccddddee"); + gen.writeString("start"); + gen.writeEndObject(); + gen.close(); + + JsonParser parser = factory.createJsonParser(bos.toByteArray()); + assertToken(JsonToken.START_OBJECT, parser.nextToken()); + + assertToken(JsonToken.FIELD_NAME, parser.nextToken()); + assertEquals("z_aaaabbbbccccddddee", parser.getCurrentName()); + assertToken(JsonToken.VALUE_STRING, parser.nextToken()); + assertEquals("end", parser.getText()); + + // This one fails... + assertToken(JsonToken.FIELD_NAME, parser.nextToken()); + assertEquals("a_aaaabbbbccccddddee", parser.getCurrentName()); + assertToken(JsonToken.VALUE_STRING, parser.nextToken()); + assertEquals("start", parser.getText()); + + assertToken(JsonToken.END_OBJECT, parser.nextToken()); + } + + /** + * Verification that [JACKSON-564] was fixed. + */ + public void testIssue564() throws Exception + { + JsonFactory factory = new SmileFactory(); + + ByteArrayOutputStream bos1 = new ByteArrayOutputStream(); + JsonGenerator generator = factory.createJsonGenerator(bos1); + generator.writeStartObject(); + generator.writeFieldName("query"); + generator.writeStartObject(); + generator.writeFieldName("term"); + generator.writeStartObject(); + generator.writeStringField("doc.payload.test_record_main.string_not_analyzed__s", "foo"); + generator.writeEndObject(); + generator.writeEndObject(); + generator.writeEndObject(); + generator.close(); + + JsonParser parser = factory.createJsonParser(bos1.toByteArray()); + JsonToken token = parser.nextToken(); + assertToken(JsonToken.START_OBJECT, token); + token = parser.nextToken(); + assertToken(JsonToken.FIELD_NAME, token); + assertEquals("query", parser.getCurrentName()); + token = parser.nextToken(); + assertToken(JsonToken.START_OBJECT, token); + token = parser.nextToken(); + assertToken(JsonToken.FIELD_NAME, token); + assertEquals("term", parser.getCurrentName()); + token = parser.nextToken(); + assertToken(JsonToken.START_OBJECT, token); + token = parser.nextToken(); + assertToken(JsonToken.FIELD_NAME, token); + assertEquals("doc.payload.test_record_main.string_not_analyzed__s", parser.getCurrentName()); + token = parser.nextToken(); + assertToken(JsonToken.VALUE_STRING, token); + assertEquals("foo", parser.getText()); + parser.close(); + + ByteArrayOutputStream bos2 = new ByteArrayOutputStream(); + generator = factory.createJsonGenerator(bos2); + generator.writeStartObject(); + generator.writeFieldName("query"); + generator.writeStartObject(); + generator.writeFieldName("term"); + generator.writeStartObject(); + // note the difference here, teh field is analyzed2 and not analyzed as in the first doc, as well + // as having a different value, though don't think it matters + generator.writeStringField("doc.payload.test_record_main.string_not_analyzed2__s", "bar"); + generator.writeEndObject(); + generator.writeEndObject(); + generator.writeEndObject(); + generator.close(); + + parser = factory.createJsonParser(bos2.toByteArray()); + token = parser.nextToken(); + assertToken(JsonToken.START_OBJECT, token); + token = parser.nextToken(); + assertToken(JsonToken.FIELD_NAME, token); + assertEquals("query", parser.getCurrentName()); + token = parser.nextToken(); + assertToken(JsonToken.START_OBJECT, token); + token = parser.nextToken(); + assertToken(JsonToken.FIELD_NAME, token); + assertEquals("term", parser.getCurrentName()); + token = parser.nextToken(); + assertToken(JsonToken.START_OBJECT, token); + token = parser.nextToken(); + assertToken(JsonToken.FIELD_NAME, token); + // here we fail..., seems to be a problem with field caching factory level??? + // since we get the field name of the previous (bos1) document field value (withou the 2) + assertEquals("doc.payload.test_record_main.string_not_analyzed2__s", parser.getCurrentName()); + token = parser.nextToken(); + assertToken(JsonToken.VALUE_STRING, token); + assertEquals("bar", parser.getText()); + + parser.close(); + } + + /* + /********************************************************** + /* Helper methods + /********************************************************** + */ + + private final String CHARS_40 = "0123456789012345678901234567890123456789"; + + private byte[] writeStringValues(boolean enableSharing, int COUNT) throws IOException + { + SmileFactory f = new SmileFactory(); + f.configure(SmileGenerator.Feature.WRITE_HEADER, true); + f.configure(SmileGenerator.Feature.CHECK_SHARED_STRING_VALUES, enableSharing); + ByteArrayOutputStream out = new ByteArrayOutputStream(4000); + JsonGenerator gen = f.createJsonGenerator(out); + gen.writeStartArray(); + Random rnd = new Random(COUNT); + for (int i = 0; i < COUNT; ++i) { + gen.writeString(generateString(rnd.nextInt())); + } + gen.writeEndArray(); + gen.close(); + return out.toByteArray(); + } + + private void verifyStringValues(byte[] json, int COUNT) throws IOException + { + SmileFactory f = new SmileFactory(); + JsonParser jp = f.createJsonParser(json); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + Random rnd = new Random(COUNT); + for (int i = 0; i < COUNT; ++i) { + String str = generateString(rnd.nextInt()); + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + assertEquals(str, jp.getText()); + } + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + } + + private String generateString(int rawNr) + { + int nr = rawNr % 1100; + // Actually, let's try longer ones too + String str = "some kind of String value we use"+nr; + if (nr > 900) { + str += CHARS_40; + } + return str; + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/smile/TestSmileParserUnicode.java b/1.9.10/src/test/org/codehaus/jackson/smile/TestSmileParserUnicode.java new file mode 100644 index 0000000..b73ad3d --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/smile/TestSmileParserUnicode.java
@@ -0,0 +1,27 @@ +package org.codehaus.jackson.smile; + +import java.io.IOException; + +import org.codehaus.jackson.JsonToken; + +public class TestSmileParserUnicode extends SmileTestBase +{ + // [Issue-2]: probs with Surrogate handling + public void testLongUnicodeWithSurrogates() throws IOException + { + final String SURROGATE_CHARS = "\ud834\udd1e"; + StringBuilder sb = new StringBuilder(300); + while (sb.length() < 300) { + sb.append(SURROGATE_CHARS); + } + final String TEXT = sb.toString(); + byte[] data = _smileDoc(quote(TEXT)); + + SmileParser p = _smileParser(data); + assertNull(p.getCurrentToken()); + assertToken(JsonToken.VALUE_STRING, p.nextToken()); + assertEquals(TEXT, p.getText()); + assertNull(p.nextToken()); + } + +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/smile/TestSmileUtil.java b/1.9.10/src/test/org/codehaus/jackson/smile/TestSmileUtil.java new file mode 100644 index 0000000..289c988 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/smile/TestSmileUtil.java
@@ -0,0 +1,43 @@ +package org.codehaus.jackson.smile; + +public class TestSmileUtil + extends main.BaseTest +{ + /** + * Verification of helper methods used to handle with zigzag encoding + */ + public void testZigZagInt() + { + // simple encode + assertEquals(0, SmileUtil.zigzagEncode(0)); + assertEquals(1, SmileUtil.zigzagEncode(-1)); + assertEquals(2, SmileUtil.zigzagEncode(1)); + assertEquals(0xFFFFFFFF, SmileUtil.zigzagEncode(Integer.MIN_VALUE)); + assertEquals(0xFFFFFFFE, SmileUtil.zigzagEncode(Integer.MAX_VALUE)); + + // simple decode + assertEquals(0, SmileUtil.zigzagDecode(0)); + assertEquals(-1, SmileUtil.zigzagDecode(1)); + assertEquals(1, SmileUtil.zigzagDecode(2)); + assertEquals(0x7fffFFFF, SmileUtil.zigzagDecode(0xFFFFFFFE)); + assertEquals(Integer.MIN_VALUE, SmileUtil.zigzagDecode(0xFFFFFFFF)); + + // round-trip + assertEquals(Integer.MIN_VALUE, SmileUtil.zigzagDecode(SmileUtil.zigzagEncode(Integer.MIN_VALUE))); + assertEquals(Integer.MAX_VALUE, SmileUtil.zigzagDecode(SmileUtil.zigzagEncode(Integer.MAX_VALUE))); + } + + public void testZigZagLong() + { + assertEquals(0L, SmileUtil.zigzagEncode(0L)); + assertEquals(-1L, SmileUtil.zigzagEncode(Long.MIN_VALUE)); + assertEquals(-2L, SmileUtil.zigzagEncode(Long.MAX_VALUE)); + + assertEquals(Long.MAX_VALUE, SmileUtil.zigzagDecode(-2L)); + assertEquals(Long.MIN_VALUE, SmileUtil.zigzagDecode(-1L)); + + // round-trip + assertEquals(Long.MIN_VALUE, SmileUtil.zigzagDecode(SmileUtil.zigzagEncode(Long.MIN_VALUE))); + assertEquals(Long.MAX_VALUE, SmileUtil.zigzagDecode(SmileUtil.zigzagEncode(Long.MAX_VALUE))); +} +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/sym/TestSymbolTables.java b/1.9.10/src/test/org/codehaus/jackson/sym/TestSymbolTables.java new file mode 100644 index 0000000..8b8b4e5 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/sym/TestSymbolTables.java
@@ -0,0 +1,145 @@ +package org.codehaus.jackson.sym; + +import java.io.IOException; + +public class TestSymbolTables extends main.BaseTest +{ + // 11 3-char snippets that hash to 0xFFFF (with default JDK hashCode() calc), + // and which can be combined as + // sequences, like, say, 11x11x11 (1331) 9-character thingies + final static String[] CHAR_COLLISION_SNIPPETS = { + /* + // with MULT of 31, seed 0, we'd get: + "@~}", "@^", "A_}", "A`^", + "Aa?", "B@}", "BA^", "BB?", + "C!}", "C\"^", "C#?" + */ + + "*!\u0804", "*\"\u07E3", "*#\u07C2", "*$\u07A1", "*%\u0780", "*&\u075F", + "*'\u073E", "*(\u071D", "*)\u06FC", "**\u06DB" + + // With MULT of 33, seed of 0: + + }; + final static String[] CHAR_COLLISIONS; + static { + final int len = CHAR_COLLISION_SNIPPETS.length; + CHAR_COLLISIONS = new String[len*len*len]; + int ix = 0; + for (int i1 = 0; i1 < len; ++i1) { + for (int i2 = 0; i2 < len; ++i2) { + for (int i3 = 0; i3 < len; ++i3) { + CHAR_COLLISIONS[ix++] = CHAR_COLLISION_SNIPPETS[i1] + +CHAR_COLLISION_SNIPPETS[i2] + CHAR_COLLISION_SNIPPETS[i3]; + } + } + } + } + + /** + * Test to see what happens with pre-computed collisions; should + * get an exception. + */ + public void testCharBasedCollisions() + { + CharsToNameCanonicalizer sym = CharsToNameCanonicalizer.createRoot(); + + // first, verify that we'd get a few collisions... + try { + int firstHash = 0; + for (String str : CHAR_COLLISIONS) { + int hash = sym.calcHash(str); + if (firstHash == 0) { + firstHash = hash; + } else { + assertEquals(firstHash, hash); + } + sym.findSymbol(str.toCharArray(), 0, str.length(), hash); + } + fail("Should have thrown exception"); + } catch (IllegalStateException e) { + verifyException(e, "exceeds maximum"); + // should fail right after addition: + assertEquals(CharsToNameCanonicalizer.MAX_COLL_CHAIN_LENGTH+1, sym.maxCollisionLength()); + assertEquals(CharsToNameCanonicalizer.MAX_COLL_CHAIN_LENGTH+1, sym.collisionCount()); + // one "non-colliding" entry (head of collision chain), thus: + assertEquals(CharsToNameCanonicalizer.MAX_COLL_CHAIN_LENGTH+2, sym.size()); + } + } + + // Test for verifying stability of hashCode, wrt collisions, using + // synthetic field name generation and character-based input + public void testSyntheticWithChars() + { + // pass seed, to keep results consistent: + CharsToNameCanonicalizer symbols = CharsToNameCanonicalizer.createRoot(1); + final int COUNT = 6000; + for (int i = 0; i < COUNT; ++i) { + String id = fieldNameFor(i); + char[] ch = id.toCharArray(); + symbols.findSymbol(ch, 0, ch.length, symbols.calcHash(id)); + } + + assertEquals(8192, symbols.bucketCount()); + assertEquals(COUNT, symbols.size()); + +//System.out.printf("Char stuff: collisions %d, max-coll %d\n", symbols.collisionCount(), symbols.maxCollisionLength()); + + // original hashCode calc gave very high rate (3567), but with shuffling comes down a bit + assertEquals(1401, symbols.collisionCount()); + // esp. with collisions; first got about 30 + assertEquals(4, symbols.maxCollisionLength()); + } + + // Test for verifying stability of hashCode, wrt collisions, using + // synthetic field name generation and byte-based input (UTF-8) + public void testSyntheticWithBytes() throws IOException + { + // pass seed, to keep results consistent: + BytesToNameCanonicalizer symbols = BytesToNameCanonicalizer.createRoot(1) + .makeChild(true, true); + final int COUNT = 6000; + for (int i = 0; i < COUNT; ++i) { + String id = fieldNameFor(i); + int[] quads = BytesToNameCanonicalizer.calcQuads(id.getBytes("UTF-8")); + symbols.addName(id, quads, quads.length); + } + assertEquals(COUNT, symbols.size()); + assertEquals(8192, symbols.bucketCount()); + +//System.out.printf("Byte stuff: collisions %d, max-coll %d\n", symbols.collisionCount(), symbols.maxCollisionLength()); + + // Fewer collisions than with chars, but still quite a few + assertEquals(1700, symbols.collisionCount()); + // but not super long collision chains: + assertEquals(10, symbols.maxCollisionLength()); + } + + protected void fieldNameFor(StringBuilder sb, int index) + { + /* let's do something like "f1.1" to exercise different + * field names (important for byte-based codec) + * Other name shuffling done mostly just for fun... :) + */ + sb.append("f"); + sb.append(index); + if (index > 50) { + sb.append('.'); + if (index > 200) { + sb.append(index); + if (index > 4000) { // and some even longer symbols... + sb.append(".").append(index); + } + } else { + sb.append(index >> 3); // divide by 8 + } + } + } + + protected String fieldNameFor(int index) + { + StringBuilder sb = new StringBuilder(16); + fieldNameFor(sb, index); + return sb.toString(); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/type/TestJavaType.java b/1.9.10/src/test/org/codehaus/jackson/type/TestJavaType.java new file mode 100644 index 0000000..3fcaecc --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/type/TestJavaType.java
@@ -0,0 +1,166 @@ +package org.codehaus.jackson.type; + +import java.util.*; + +import main.BaseTest; + +import org.codehaus.jackson.map.type.*; + +/** + * Simple tests to verify that {@link JavaType} types work to + * some degree + */ +public class TestJavaType + extends BaseTest +{ + static class BaseType { } + + static class SubType extends BaseType { } + + /* + /********************************************************** + /* Test methods + /********************************************************** + */ + + public void testSimpleClass() + { + TypeFactory tf = TypeFactory.defaultInstance(); + JavaType baseType = tf.constructType(BaseType.class); + assertSame(BaseType.class, baseType.getRawClass()); + assertTrue(baseType.hasRawClass(BaseType.class)); + + assertFalse(baseType.isArrayType()); + assertFalse(baseType.isContainerType()); + assertFalse(baseType.isEnumType()); + assertFalse(baseType.isInterface()); + assertFalse(baseType.isPrimitive()); + + assertNull(baseType.getContentType()); + assertNull(baseType.getValueHandler()); + + /* both narrow and widen just return type itself (exact, not just + * equal) + * (also note that widen/narrow wouldn't work on basic simple + * class type otherwise) + */ + assertSame(baseType, baseType.narrowBy(BaseType.class)); + assertSame(baseType, baseType.widenBy(BaseType.class)); + + // Also: no narrowing for simple types (but should there be?) + try { + baseType.narrowBy(SubType.class); + } catch (IllegalArgumentException e) { + verifyException(e, "should never be called"); + } + + // Also, let's try assigning bogus handler + /* + baseType.setValueHandler("xyz"); // untyped + assertEquals("xyz", baseType.getValueHandler()); + // illegal to re-set + try { + baseType.setValueHandler("foobar"); + fail("Shouldn't allow re-setting value handler"); + } catch (IllegalStateException iae) { + verifyException(iae, "Trying to reset"); + } + */ + } + + public void testMapType() + { + TypeFactory tf = TypeFactory.defaultInstance(); + JavaType keyT = tf.constructType(String.class); + JavaType baseT = tf.constructType(BaseType.class); + + MapType mapT = MapType.construct(Map.class, keyT, baseT); + assertNotNull(mapT); + assertTrue(mapT.isContainerType()); + + // NOPs: + assertSame(mapT, mapT.narrowContentsBy(BaseType.class)); + assertSame(mapT, mapT.narrowKey(String.class)); + + assertTrue(mapT.equals(mapT)); + assertFalse(mapT.equals(null)); + assertFalse(mapT.equals("xyz")); + + MapType mapT2 = MapType.construct(HashMap.class, keyT, baseT); + assertFalse(mapT.equals(mapT2)); + + // Also, must use map type constructor, not simple... + try { + SimpleType.construct(HashMap.class); + } catch (IllegalArgumentException e) { + verifyException(e, "for a Map"); + } + } + + public void testArrayType() + { + TypeFactory tf = TypeFactory.defaultInstance(); + JavaType arrayT = ArrayType.construct(tf.constructType(String.class), null, null); + assertNotNull(arrayT); + assertTrue(arrayT.isContainerType()); + + // NOPs: + assertSame(arrayT, arrayT.narrowContentsBy(String.class)); + + assertNotNull(arrayT.toString()); + + assertTrue(arrayT.equals(arrayT)); + assertFalse(arrayT.equals(null)); + assertFalse(arrayT.equals("xyz")); + + assertTrue(arrayT.equals(ArrayType.construct(tf.constructType(String.class), null, null))); + assertFalse(arrayT.equals(ArrayType.construct(tf.constructType(Integer.class), null, null))); + + // Also, must NOT try to create using simple type + try { + SimpleType.construct(String[].class); + } catch (IllegalArgumentException e) { + verifyException(e, "for an array"); + } + } + + public void testCollectionType() + { + TypeFactory tf = TypeFactory.defaultInstance(); + // List<String> + JavaType collectionT = CollectionType.construct(List.class, tf.constructType(String.class)); + assertNotNull(collectionT); + assertTrue(collectionT.isContainerType()); + + // NOPs: + assertSame(collectionT, collectionT.narrowContentsBy(String.class)); + + assertNotNull(collectionT.toString()); + + assertTrue(collectionT.equals(collectionT)); + assertFalse(collectionT.equals(null)); + assertFalse(collectionT.equals("xyz")); + + assertTrue(collectionT.equals(CollectionType.construct(List.class, tf.constructType(String.class)))); + assertFalse(collectionT.equals(CollectionType.construct(Set.class, tf.constructType(String.class)))); + + // Also, must NOT try to create using simple type + try { + SimpleType.construct(ArrayList.class); + } catch (IllegalArgumentException e) { + verifyException(e, "for a Collection"); + } + } + + public void testClassKey() + { + ClassKey key = new ClassKey(String.class); + assertEquals(0, key.compareTo(key)); + assertTrue(key.equals(key)); + assertFalse(key.equals(null)); + assertFalse(key.equals("foo")); + assertFalse(key.equals(new ClassKey(Integer.class))); + assertEquals(String.class.getName(), key.toString()); + } +} +
diff --git a/1.9.10/src/test/org/codehaus/jackson/type/TestTypeBindings.java b/1.9.10/src/test/org/codehaus/jackson/type/TestTypeBindings.java new file mode 100644 index 0000000..9d9186b --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/type/TestTypeBindings.java
@@ -0,0 +1,78 @@ +package org.codehaus.jackson.type; + +import java.util.*; + +import org.codehaus.jackson.map.type.*; + +/** + * Simple tests to verify for generic type binding functionality + * implemented by {@link TypeBindings} class. + * + * @since 1.5 + */ +public class TestTypeBindings + extends main.BaseTest +{ + static class AbstractType<A,B> { } + + static class LongStringType extends AbstractType<Long,String> { } + + static class InnerGenericTyping<K, V> extends AbstractMap<K, Collection<V>> + { + @Override + public Set<java.util.Map.Entry<K, Collection<V>>> entrySet() { + return null; + } + public class InnerClass extends AbstractMap<K, Collection<V>> { + @Override + public Set<java.util.Map.Entry<K, Collection<V>>> entrySet() { + return null; + } + } + } + + /* + /********************************************************** + /* Test methods + /********************************************************** + */ + + public void testAbstract() throws Exception + { + /* Abstract type does declare type parameters, but they are only + * known as 'Object.class' (via lower bound) + */ + TypeFactory tf = TypeFactory.defaultInstance(); + TypeBindings b = new TypeBindings(tf, AbstractType.class); + assertEquals(2, b.getBindingCount()); + JavaType obType = tf.constructType(Object.class); + assertEquals(obType, b.findType("A")); + assertEquals(obType, b.findType("B")); + } + + public void testSimple() throws Exception + { + TypeFactory tf = TypeFactory.defaultInstance(); + // concrete class does have bindings however + TypeBindings b = new TypeBindings(tf, LongStringType.class); + assertEquals(2, b.getBindingCount()); + assertEquals(tf.constructType(Long.class), b.findType("A")); + assertEquals(tf.constructType(String.class), b.findType("B")); + } + + + // [JACKSON-677] + public void testInnerType() + { + TypeFactory tf = TypeFactory.defaultInstance(); + JavaType type = tf.constructType(InnerGenericTyping.InnerClass.class); + assertEquals(MapType.class, type.getClass()); + JavaType keyType = type.getKeyType(); + assertEquals(Object.class, keyType.getRawClass()); + JavaType valueType = type.getContentType(); + assertEquals(Collection.class, valueType.getRawClass()); + JavaType vt2 = valueType.getContentType(); + assertEquals(Object.class, vt2.getRawClass()); + } + +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/util/TestCharTypes.java b/1.9.10/src/test/org/codehaus/jackson/util/TestCharTypes.java new file mode 100644 index 0000000..24f4c31 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/util/TestCharTypes.java
@@ -0,0 +1,15 @@ +package org.codehaus.jackson.util; + +public class TestCharTypes + extends main.BaseTest +{ + public void testQuoting() + { + StringBuilder sb = new StringBuilder(); + CharTypes.appendQuoted(sb, "\n"); + assertEquals("\\n", sb.toString()); + sb = new StringBuilder(); + CharTypes.appendQuoted(sb, "\u0000"); + assertEquals("\\u0000", sb.toString()); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/util/TestDelegates.java b/1.9.10/src/test/org/codehaus/jackson/util/TestDelegates.java new file mode 100644 index 0000000..3c6b91d --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/util/TestDelegates.java
@@ -0,0 +1,43 @@ +package org.codehaus.jackson.util; + +import java.io.*; + +import org.codehaus.jackson.*; + +public class TestDelegates extends main.BaseTest +{ + /** + * Test default, non-overridden parser delegate. + */ + public void testParserDelegate() throws IOException + { + JsonParser jp = new JsonFactory().createJsonParser("[ 1, true ]"); + assertNull(jp.getCurrentToken()); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + assertEquals("[", jp.getText()); + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(1, jp.getIntValue()); + assertToken(JsonToken.VALUE_TRUE, jp.nextToken()); + assertTrue(jp.getBooleanValue()); + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + jp.close(); + assertTrue(jp.isClosed()); + } + + /** + * Test default, non-overridden generator delegate. + */ + public void testGeneratorDelegate() throws IOException + { + StringWriter sw = new StringWriter(); + JsonGenerator jg = new JsonFactory().createJsonGenerator(sw); + jg.writeStartArray(); + jg.writeNumber(13); + jg.writeNull(); + jg.writeBoolean(false); + jg.writeEndArray(); + jg.close(); + assertTrue(jg.isClosed()); + assertEquals("[13,null,false]", sw.toString()); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/util/TestJsonParserSequence.java b/1.9.10/src/test/org/codehaus/jackson/util/TestJsonParserSequence.java new file mode 100644 index 0000000..7de64db --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/util/TestJsonParserSequence.java
@@ -0,0 +1,89 @@ +package org.codehaus.jackson.util; + +import java.io.*; + +import org.codehaus.jackson.*; + +/** + * Unit tests to verify that {@link JsonParserSequence} works + * as expected. + * + * @since 1.5 + */ +public class TestJsonParserSequence + extends main.BaseTest +{ + public void testSimple() throws IOException + { + // Let's join a TokenBuffer with JsonParser first + TokenBuffer buf = new TokenBuffer(null); + buf.writeStartArray(); + buf.writeString("test"); + JsonParser jp = createParserUsingReader("[ true, null ]"); + + JsonParserSequence seq = JsonParserSequence.createFlattened(buf.asParser(), jp); + assertEquals(2, seq.containedParsersCount()); + + assertFalse(jp.isClosed()); + + assertFalse(seq.hasCurrentToken()); + assertNull(seq.getCurrentToken()); + assertNull(seq.getCurrentName()); + + assertToken(JsonToken.START_ARRAY, seq.nextToken()); + assertToken(JsonToken.VALUE_STRING, seq.nextToken()); + assertEquals("test", seq.getText()); + // end of first parser input, should switch over: + + assertToken(JsonToken.START_ARRAY, seq.nextToken()); + assertToken(JsonToken.VALUE_TRUE, seq.nextToken()); + assertToken(JsonToken.VALUE_NULL, seq.nextToken()); + assertToken(JsonToken.END_ARRAY, seq.nextToken()); + + /* 17-Jan-2009, tatus: At this point, we may or may not get an + * exception, depending on how underlying parsers work. + * Ideally this should be fixed, probably by asking underlying + * parsers to disable checking for balanced start/end markers. + */ + + // for this particular case, we won't get an exception tho... + assertNull(seq.nextToken()); + // not an error to call again... + assertNull(seq.nextToken()); + + // also: original parsers should be closed + assertTrue(jp.isClosed()); + } + + /** + * Test to verify that sequences get flattened, to minimize depth + * of nesting (to reduce call chaining) + */ + public void testFlattening() throws IOException + { + TokenBuffer buf1 = new TokenBuffer(null); + buf1.writeStartArray(); + TokenBuffer buf2 = new TokenBuffer(null); + buf2.writeString("a"); + TokenBuffer buf3 = new TokenBuffer(null); + buf3.writeNumber(13); + TokenBuffer buf4 = new TokenBuffer(null); + buf4.writeEndArray(); + + JsonParserSequence seq1 = JsonParserSequence.createFlattened(buf1.asParser(), buf2.asParser()); + assertEquals(2, seq1.containedParsersCount()); + JsonParserSequence seq2 = JsonParserSequence.createFlattened(buf3.asParser(), buf4.asParser()); + assertEquals(2, seq2.containedParsersCount()); + JsonParserSequence combo = JsonParserSequence.createFlattened(seq1, seq2); + // should flatten it to have 4 underlying parsers + assertEquals(4, combo.containedParsersCount()); + + assertToken(JsonToken.START_ARRAY, combo.nextToken()); + assertToken(JsonToken.VALUE_STRING, combo.nextToken()); + assertEquals("a", combo.getText()); + assertToken(JsonToken.VALUE_NUMBER_INT, combo.nextToken()); + assertEquals(13, combo.getIntValue()); + assertToken(JsonToken.END_ARRAY, combo.nextToken()); + assertNull(combo.nextToken()); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/util/TestNumberPrinting.java b/1.9.10/src/test/org/codehaus/jackson/util/TestNumberPrinting.java new file mode 100644 index 0000000..4fdda4b --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/util/TestNumberPrinting.java
@@ -0,0 +1,102 @@ +package org.codehaus.jackson.util; + +import java.util.Random; + +import org.codehaus.jackson.io.NumberOutput; + +/** + * Set of basic unit tests for verifying that the low-level number + * printingg methods work as expected. + */ +public class TestNumberPrinting + extends main.BaseTest +{ + public void testIntPrinting() + throws Exception + { + assertIntPrint(0); + assertIntPrint(-3); + assertIntPrint(1234); + assertIntPrint(-1234); + assertIntPrint(56789); + assertIntPrint(-56789); + assertIntPrint(999999); + assertIntPrint(-999999); + assertIntPrint(1000000); + assertIntPrint(-1000000); + assertIntPrint(10000001); + assertIntPrint(-10000001); + assertIntPrint(-100000012); + assertIntPrint(100000012); + assertIntPrint(1999888777); + assertIntPrint(-1999888777); + assertIntPrint(Integer.MAX_VALUE); + assertIntPrint(Integer.MIN_VALUE); + + Random rnd = new Random(12345L); + for (int i = 0; i < 251000; ++i) { + assertIntPrint(rnd.nextInt()); + } + } + + public void testLongPrinting() + throws Exception + { + // First, let's just cover couple of edge cases + assertLongPrint(0L, 0); + assertLongPrint(1L, 0); + assertLongPrint(-1L, 0); + assertLongPrint(Long.MAX_VALUE, 0); + assertLongPrint(Long.MIN_VALUE, 0); + assertLongPrint(Long.MAX_VALUE-1L, 0); + assertLongPrint(Long.MIN_VALUE+1L, 0); + + Random rnd = new Random(12345L); + // Bigger value space, need more iterations for long + for (int i = 0; i < 678000; ++i) { + long l = ((long) rnd.nextInt() << 32) | (long) rnd.nextInt(); + assertLongPrint(l, i); + } + } + + /* + //////////////////////////////////////////////////////// + // Internal methods + //////////////////////////////////////////////////////// + */ + + private void assertIntPrint(int value) + { + String exp = ""+value; + String act = printToString(value); + + if (!exp.equals(act)) { + assertEquals("Expected conversion (exp '"+exp+"', len "+exp.length()+"; act len "+act.length()+")", exp, act); + } + } + + private void assertLongPrint(long value, int index) + { + String exp = ""+value; + String act = printToString(value); + + if (!exp.equals(act)) { + assertEquals("Expected conversion (exp '"+exp+"', len "+exp.length()+"; act len "+act.length()+"; number index "+index+")", exp, act); + } + } + + private String printToString(int value) + { + char[] buffer = new char[12]; + int offset = NumberOutput.outputInt(value, buffer, 0); + return new String(buffer, 0, offset); + } + + private String printToString(long value) + { + char[] buffer = new char[22]; + int offset = NumberOutput.outputLong(value, buffer, 0); + return new String(buffer, 0, offset); + } +} +
diff --git a/1.9.10/src/test/org/codehaus/jackson/util/TestObjectBuffer.java b/1.9.10/src/test/org/codehaus/jackson/util/TestObjectBuffer.java new file mode 100644 index 0000000..da4083f --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/util/TestObjectBuffer.java
@@ -0,0 +1,73 @@ +package org.codehaus.jackson.util; + +import main.BaseTest; + +import java.util.*; + +import org.codehaus.jackson.map.util.*; + +public class TestObjectBuffer + extends BaseTest +{ + /** + * First a test that treats results as plain old Object[] + */ + public void testUntyped() + { + _testObjectBuffer(null); + } + + public void testTyped() + { + _testObjectBuffer(Integer.class); + } + + /* + ////////////////////////////////////////////////// + // Helper methods + ////////////////////////////////////////////////// + */ + + private void _testObjectBuffer(Class<?> clz) + { + int[] SIZES = new int[] { + 3, 19, 99, 1007, 79000, 256001 + }; + + // Let's loop separately for reused instance, new instance + for (int reuse = 0; reuse < 2; ++reuse) { + ObjectBuffer buf = (reuse == 0) ? null : new ObjectBuffer(); + + // then distinct sizes + for (int sizeIndex = 0; sizeIndex < SIZES.length; ++sizeIndex) { + int size = SIZES[sizeIndex]; + Random r = new Random(size); + ObjectBuffer thisBuf = (buf == null) ? new ObjectBuffer() : buf; + Object[] chunk = thisBuf.resetAndStart(); + int ix = 0; + + for (int i = 0; i < size; ++i) { + if (ix >= chunk.length) { + chunk = thisBuf.appendCompletedChunk(chunk); + ix = 0; + } + chunk[ix++] = Integer.valueOf(r.nextInt()); + } + + Object[] result; + + if (clz == null) { + result = thisBuf.completeAndClearBuffer(chunk, ix); + } else { + result = thisBuf.completeAndClearBuffer(chunk, ix, clz); + } + assertEquals(size, result.length); + + r = new Random(size); + for (int i = 0; i < size; ++i) { + assertEquals(r.nextInt(), ((Integer) result[i]).intValue()); + } + } + } + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/util/TestTextBuffer.java b/1.9.10/src/test/org/codehaus/jackson/util/TestTextBuffer.java new file mode 100644 index 0000000..2a0b783 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/util/TestTextBuffer.java
@@ -0,0 +1,63 @@ +package org.codehaus.jackson.util; + +public class TestTextBuffer + extends main.BaseTest +{ + /** + * Trivially simple basic test to ensure all basic append + * methods work + */ + public void testSimple() + { + TextBuffer tb = new TextBuffer(new BufferRecycler()); + tb.append('a'); + tb.append(new char[] { 'X', 'b' }, 1, 1); + tb.append("c", 0, 1); + assertEquals(3, tb.contentsAsArray().length); + assertEquals("abc", tb.toString()); + + assertNotNull(tb.expandCurrentSegment()); + } + + public void testLonger() + { + TextBuffer tb = new TextBuffer(new BufferRecycler()); + for (int i = 0; i < 2000; ++i) { + tb.append("abc", 0, 3); + } + String str = tb.contentsAsString(); + assertEquals(6000, str.length()); + assertEquals(6000, tb.contentsAsArray().length); + + tb.resetWithShared(new char[] { 'a' }, 0, 1); + assertEquals(1, tb.toString().length()); + } + + // [Issue-24] + public void testLongAppend() + { + final int len = TextBuffer.MAX_SEGMENT_LEN * 3 / 2; + StringBuilder sb = new StringBuilder(len); + for (int i = 0; i < len; ++i) { + sb.append('x'); + } + final String STR = sb.toString(); + final String EXP = "a" + STR + "c"; + + // ok: first test with String: + TextBuffer tb = new TextBuffer(new BufferRecycler()); + tb.append('a'); + tb.append(STR, 0, len); + tb.append('c'); + assertEquals(len+2, tb.size()); + assertEquals(EXP, tb.contentsAsString()); + + // then char[] + tb = new TextBuffer(new BufferRecycler()); + tb.append('a'); + tb.append(STR.toCharArray(), 0, len); + tb.append('c'); + assertEquals(len+2, tb.size()); + assertEquals(EXP, tb.contentsAsString()); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/util/TestTokenBuffer.java b/1.9.10/src/test/org/codehaus/jackson/util/TestTokenBuffer.java new file mode 100644 index 0000000..fd76162 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/util/TestTokenBuffer.java
@@ -0,0 +1,165 @@ +package org.codehaus.jackson.util; + +import java.io.*; + +import org.codehaus.jackson.*; + +public class TestTokenBuffer extends main.BaseTest +{ + /** + * Test writing of individual simple values + */ + public void testSimpleWrites() throws IOException + { + TokenBuffer buf = new TokenBuffer(null); // no ObjectCodec + + // First, with empty buffer + JsonParser jp = buf.asParser(); + assertNull(jp.getCurrentToken()); + assertNull(jp.nextToken()); + jp.close(); + + // Then with simple text + buf.writeString("abc"); + + // First, simple text + jp = buf.asParser(); + assertNull(jp.getCurrentToken()); + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + assertEquals("abc", jp.getText()); + assertNull(jp.nextToken()); + jp.close(); + + // Then, let's append at root level + buf.writeNumber(13); + jp = buf.asParser(); + assertNull(jp.getCurrentToken()); + assertToken(JsonToken.VALUE_STRING, jp.nextToken()); + assertToken(JsonToken.VALUE_NUMBER_INT, jp.nextToken()); + assertEquals(13, jp.getIntValue()); + assertNull(jp.nextToken()); + jp.close(); + } + + public void testSimpleArray() throws IOException + { + TokenBuffer buf = new TokenBuffer(null); // no ObjectCodec + + // First, empty array + assertTrue(buf.getOutputContext().inRoot()); + buf.writeStartArray(); + assertTrue(buf.getOutputContext().inArray()); + buf.writeEndArray(); + assertTrue(buf.getOutputContext().inRoot()); + + JsonParser jp = buf.asParser(); + assertNull(jp.getCurrentToken()); + assertTrue(jp.getParsingContext().inRoot()); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + assertTrue(jp.getParsingContext().inArray()); + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + assertTrue(jp.getParsingContext().inRoot()); + assertNull(jp.nextToken()); + jp.close(); + + // Then one with simple contents + buf = new TokenBuffer(null); + buf.writeStartArray(); + buf.writeBoolean(true); + buf.writeNull(); + buf.writeEndArray(); + jp = buf.asParser(); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + assertToken(JsonToken.VALUE_TRUE, jp.nextToken()); + assertTrue(jp.getBooleanValue()); + assertToken(JsonToken.VALUE_NULL, jp.nextToken()); + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + assertNull(jp.nextToken()); + jp.close(); + + // And finally, with array-in-array + buf = new TokenBuffer(null); + buf.writeStartArray(); + buf.writeStartArray(); + buf.writeBinary(new byte[3]); + buf.writeEndArray(); + buf.writeEndArray(); + jp = buf.asParser(); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + assertToken(JsonToken.START_ARRAY, jp.nextToken()); + // TokenBuffer exposes it as embedded object... + assertToken(JsonToken.VALUE_EMBEDDED_OBJECT, jp.nextToken()); + Object ob = jp.getEmbeddedObject(); + assertNotNull(ob); + assertTrue(ob instanceof byte[]); + assertEquals(3, ((byte[]) ob).length); + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + assertToken(JsonToken.END_ARRAY, jp.nextToken()); + assertNull(jp.nextToken()); + jp.close(); + } + + public void testSimpleObject() throws IOException + { + TokenBuffer buf = new TokenBuffer(null); + + // First, empty JSON Object + assertTrue(buf.getOutputContext().inRoot()); + buf.writeStartObject(); + assertTrue(buf.getOutputContext().inObject()); + buf.writeEndObject(); + assertTrue(buf.getOutputContext().inRoot()); + + JsonParser jp = buf.asParser(); + assertNull(jp.getCurrentToken()); + assertTrue(jp.getParsingContext().inRoot()); + assertToken(JsonToken.START_OBJECT, jp.nextToken()); + assertTrue(jp.getParsingContext().inObject()); + assertToken(JsonToken.END_OBJECT, jp.nextToken()); + assertTrue(jp.getParsingContext().inRoot()); + assertNull(jp.nextToken()); + jp.close(); + + // Then one with simple contents + buf = new TokenBuffer(null); + buf.writeStartObject(); + buf.writeNumberField("num", 1.25); + buf.writeEndObject(); + + jp = buf.asParser(); + assertNull(jp.getCurrentToken()); + assertToken(JsonToken.START_OBJECT, jp.nextToken()); + assertNull(jp.getCurrentName()); + assertToken(JsonToken.FIELD_NAME, jp.nextToken()); + assertEquals("num", jp.getCurrentName()); + assertToken(JsonToken.VALUE_NUMBER_FLOAT, jp.nextToken()); + assertEquals(1.25, jp.getDoubleValue()); + // should still have access to name + assertEquals("num", jp.getCurrentName()); + assertToken(JsonToken.END_OBJECT, jp.nextToken()); + // but not any more + assertNull(jp.getCurrentName()); + assertNull(jp.nextToken()); + jp.close(); + } + + /** + * Verify handling of that "standard" test document (from JSON + * specification) + */ + public void testWithJSONSampleDoc() throws Exception + { + // First, copy events from known good source (StringReader) + JsonParser jp = createParserUsingReader(SAMPLE_DOC_JSON_SPEC); + TokenBuffer tb = new TokenBuffer(null); + while (jp.nextToken() != null) { + tb.copyCurrentEvent(jp); + } + + // And then request verification; first structure only: + verifyJsonSpecSampleDoc(tb.asParser(), false); + + // then content check too: + verifyJsonSpecSampleDoc(tb.asParser(), true); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/util/TestVersionUtil.java b/1.9.10/src/test/org/codehaus/jackson/util/TestVersionUtil.java new file mode 100644 index 0000000..9102f84 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/util/TestVersionUtil.java
@@ -0,0 +1,18 @@ +package org.codehaus.jackson.util; + +import org.codehaus.jackson.Version; + +public class TestVersionUtil extends main.BaseTest +{ + public void testVersionPartParsing() + { + assertEquals(13, VersionUtil.parseVersionPart("13")); + assertEquals(27, VersionUtil.parseVersionPart("27.8")); + assertEquals(0, VersionUtil.parseVersionPart("-3")); + } + + public void testVersionParsing() + { + assertEquals(new Version(1, 2, 15, "foo"), VersionUtil.parseVersion("1.2.15-foo")); + } +}
diff --git a/1.9.10/src/test/org/codehaus/jackson/version/TestVersions.java b/1.9.10/src/test/org/codehaus/jackson/version/TestVersions.java new file mode 100644 index 0000000..57bf0d8 --- /dev/null +++ b/1.9.10/src/test/org/codehaus/jackson/version/TestVersions.java
@@ -0,0 +1,109 @@ +package org.codehaus.jackson.version; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.impl.ReaderBasedParser; +import org.codehaus.jackson.impl.WriterBasedGenerator; +import org.codehaus.jackson.io.IOContext; +import org.codehaus.jackson.util.BufferRecycler; +import org.codehaus.jackson.jaxrs.JacksonJsonProvider; +import org.codehaus.jackson.map.ObjectMapper; +import org.codehaus.jackson.mrbean.AbstractTypeMaterializer; +import org.codehaus.jackson.smile.SmileFactory; +import org.codehaus.jackson.smile.SmileGenerator; +import org.codehaus.jackson.smile.SmileParser; +import org.codehaus.jackson.xc.JaxbAnnotationIntrospector; + +/** + * Tests to verify [JACKSON-278] + * + * @since 1.6 + */ +public class TestVersions extends main.BaseTest +{ + /** + * 18-Nov-2010, tatu: Not a good to do this, but has to do, for now... + */ + private final static int MAJOR_VERSION = 1; + private final static int MINOR_VERSION = 9; + + public void testCoreVersions() + { + /* 01-Sep-2010, tatu: Somewhat of a dirty hack; let's only run when specific system + * property is set; and set that flag from Ant unit test. Why? To prevent running + * from Eclipse, where this would just fail + */ + if (runsFromAnt()) { + System.out.println("Note: running version tests (FROM_ANT=true)"); + assertVersion(new JsonFactory().version(), MAJOR_VERSION, MINOR_VERSION); + assertVersion(new ReaderBasedParser(getIOContext(), 0, null, null, null).version(), + MAJOR_VERSION, MINOR_VERSION); + assertVersion(new WriterBasedGenerator(getIOContext(), 0, null, null).version(), + MAJOR_VERSION, MINOR_VERSION); + } else { + System.out.println("Skipping version test (FROM_ANT=false)"); + } + } + + public void testMapperVersions() + { + if (runsFromAnt()) { + ObjectMapper mapper = new ObjectMapper(); + assertVersion(mapper.version(), MAJOR_VERSION, MINOR_VERSION); + assertVersion(mapper.writer().version(), MAJOR_VERSION, MINOR_VERSION); + assertVersion(mapper.reader().version(), MAJOR_VERSION, MINOR_VERSION); + } + } + + public void testXcVersions() + { + if (runsFromAnt()) { + assertVersion(new JaxbAnnotationIntrospector().version(), MAJOR_VERSION, MINOR_VERSION); + } + } + + public void testJaxRsVersions() + { + if (runsFromAnt()) { + assertVersion(new JacksonJsonProvider().version(), MAJOR_VERSION, MINOR_VERSION); + } + } + + public void testSmileVersions() + { + if (runsFromAnt()) { + assertVersion(new SmileFactory().version(), MAJOR_VERSION, MINOR_VERSION); + assertVersion(new SmileGenerator(getIOContext(), 0, 0, null, null).version(), + MAJOR_VERSION, MINOR_VERSION); + assertVersion(new SmileParser(getIOContext(), 0, 0, null, null, null, null, 0, 0, false).version(), + MAJOR_VERSION, MINOR_VERSION); + } + } + + public void testMrBeanVersions() + { + if (runsFromAnt()) { + assertVersion(new AbstractTypeMaterializer().version(), MAJOR_VERSION, MINOR_VERSION); + } + } + + /* + /********************************************************** + /* Helper methods + /********************************************************** + */ + + private void assertVersion(Version v, int major, int minor) + { + assertFalse("Should find version information (got "+v+")", v.isUknownVersion()); + assertEquals(major, v.getMajorVersion()); + assertEquals(minor, v.getMinorVersion()); + // 07-Jan-2011, tatus: Check patch level initially, comment out for maint versions + + //assertEquals(0, v.getPatchLevel()); + } + + private IOContext getIOContext() { + return new IOContext(new BufferRecycler(), null, false); + } +} +
diff --git a/1.9.10/src/tools/CheckNumberSpeed.java b/1.9.10/src/tools/CheckNumberSpeed.java new file mode 100644 index 0000000..5a8f88d --- /dev/null +++ b/1.9.10/src/tools/CheckNumberSpeed.java
@@ -0,0 +1,110 @@ +import java.math.BigInteger; + +/** + * Simple test to see what is the performance difference between converting + * simple int values into different wrapper types. + */ +public final class CheckNumberSpeed +{ + final int[] data; + + final static int REPS = 2000; + + private CheckNumberSpeed() { + data = new int[1200]; + for (int i = 0; i < data.length; ++i) { + // mostly small positive numbers, some negative + data[i] = i - 100; + } + } + + public void test() throws Exception + { + int nr = 0; + + while (true) { + int type = (nr++) % 4; + long start = System.nanoTime(); + String str; + Object o; + + switch (type) { + case 0: + o = testIntsValueOf(data); + str = "int/share"; + break; + case 1: + o = testIntsCreate(data); + str = "int/create"; + break; + case 2: + o = testLongs(data); + str = "longs"; + break; + default: + o = testBigInts(data); + str = "BigInts"; + break; + } + + long time = System.nanoTime() - start; + time = time >> 10; // from nano to micro + + System.out.println("Time for '"+str+"' -> "+time+" us (hash: "+o.hashCode()+")"); + Thread.sleep(200L); + } + } + + Integer testIntsValueOf(int[] ints) + { + Integer v = null; + int reps = REPS; + while (--reps > 0) { + for (int value : ints) { + v = Integer.valueOf(value); + } + } + return v; + } + + Integer testIntsCreate(int[] ints) + { + Integer v = null; + int reps = REPS; + while (--reps > 0) { + for (int value : ints) { + v = new Integer(value); + } + } + return v; + } + + Long testLongs(int[] ints) + { + Long v = null; + int reps = REPS; + while (--reps > 0) { + for (int value : ints) { + v = Long.valueOf(value); + } + } + return v; + } + + BigInteger testBigInts(int[] ints) + { + BigInteger v = null; + int reps = REPS; + while (--reps > 0) { + for (int value : ints) { + v = BigInteger.valueOf(value); + } + } + return v; + } + + public static void main(String[] args) throws Exception + { + new CheckNumberSpeed().test(); + } +}
diff --git a/1.9.10/src/tools/GenerateDoubleDoc.java b/1.9.10/src/tools/GenerateDoubleDoc.java new file mode 100644 index 0000000..2ae12ac --- /dev/null +++ b/1.9.10/src/tools/GenerateDoubleDoc.java
@@ -0,0 +1,64 @@ + + +import java.io.*; +import java.util.Random; + +import org.codehaus.jackson.*; + +public class GenerateDoubleDoc +{ + final static int AVG_ARRAY_LEN = 32; + + private GenerateDoubleDoc() { } + + private void generate(OutputStream out, int kbSize) + throws IOException + { + int bsize = kbSize * 1000; + + // Let's first buffer in memory, to know exact length + ByteArrayOutputStream bos = new ByteArrayOutputStream(bsize + 500); + Random r = new Random(kbSize); + JsonGenerator gen = new JsonFactory().createJsonGenerator(bos, JsonEncoding.UTF8); + gen.writeStartArray(); // outermost array + gen.writeStartArray(); // inner array + + do { + // First, do we close current, start new array? + if (r.nextInt(AVG_ARRAY_LEN) == 3) { // to get average array length of 16 + gen.writeEndArray(); + if (r.nextBoolean()) { + gen.writeRaw("\n"); + } + gen.writeStartArray(); + gen.flush(); + } + // Then need to calculate number to output + float f; + + do { + f = Float.intBitsToFloat(r.nextInt()); + } while (Double.isNaN(f) || Double.isInfinite(f)); + gen.writeNumber(f); + } while (bos.size() < bsize); + + gen.writeEndArray(); + gen.writeEndArray(); + gen.writeRaw("\n"); + gen.close(); + + bos.writeTo(out); + } + + public static void main(String[] args) + throws Exception + { + if (args.length != 1) { + System.err.println("Usage: java test.GenerateDoubleDoc <size-in-kbytes>"); + System.exit(1); + } + new GenerateDoubleDoc().generate(System.out, Integer.parseInt(args[0])); + System.out.flush(); + } +} +
diff --git a/1.9.10/src/tools/GenerateIntDoc.java b/1.9.10/src/tools/GenerateIntDoc.java new file mode 100644 index 0000000..bb316b9 --- /dev/null +++ b/1.9.10/src/tools/GenerateIntDoc.java
@@ -0,0 +1,69 @@ + + +import java.io.*; +import java.util.Random; + +import org.codehaus.jackson.*; + +public class GenerateIntDoc +{ + final static int AVG_ARRAY_LEN = 32; + + private GenerateIntDoc() { } + + private void generate(OutputStream out, int kbSize) + throws IOException + { + int bsize = kbSize * 1000; + + // Let's first buffer in memory, to know exact length + ByteArrayOutputStream bos = new ByteArrayOutputStream(bsize + 500); + Random r = new Random(kbSize); + JsonGenerator gen = new JsonFactory().createJsonGenerator(bos, JsonEncoding.UTF8); + gen.writeStartArray(); // outermost array + gen.writeStartArray(); // inner array + + do { + // First, do we close current, start new array? + if (r.nextInt(AVG_ARRAY_LEN) == 3) { // to get average array length of 16 + gen.writeEndArray(); + if (r.nextBoolean()) { + gen.writeRaw("\n"); + } + gen.writeStartArray(); + gen.flush(); + } + // Then need to calculate number to output + int nr = r.nextInt(32); + if (r.nextBoolean()) { + nr *= r.nextInt(256); // up to 8k + if (r.nextBoolean()) { + nr *= r.nextInt(0x20000); // up to 1G + } + } + if (r.nextBoolean()) { + nr = -nr; + } + gen.writeNumber(nr); + } while (bos.size() < bsize); + + gen.writeEndArray(); + gen.writeEndArray(); + gen.writeRaw("\n"); + gen.close(); + + bos.writeTo(out); + } + + public static void main(String[] args) + throws Exception + { + if (args.length != 1) { + System.err.println("Usage: java test.GenerateIntDoc <size-in-kbytes>"); + System.exit(1); + } + new GenerateIntDoc().generate(System.out, Integer.parseInt(args[0])); + System.out.flush(); + } +} +
diff --git a/1.9.10/src/tools/TestBeanMapper.java b/1.9.10/src/tools/TestBeanMapper.java new file mode 100644 index 0000000..5011bff --- /dev/null +++ b/1.9.10/src/tools/TestBeanMapper.java
@@ -0,0 +1,70 @@ + + +import java.io.*; +import java.util.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.*; + +public class TestBeanMapper +{ + private TestBeanMapper() { } + + private void test() throws Exception + { + JsonFactory f = new JsonFactory(); + ObjectMapper jmap = new ObjectMapper(); + Object foo = new MyObject(5, -90, "Desc"); + StringWriter sw = new StringWriter(); + JsonGenerator jg = f.createJsonGenerator(sw); + try { + jmap.writeValue(jg, foo); + } catch (Exception e) { + try { jg.flush(); } catch (IOException ioe) { } + System.err.println("Error, intermediate result = |"+sw+"|"); + throw e; + } + jg.close(); + + System.out.println("Write result: <"+sw.toString()+">"); + } + + public static void main(String[] args) throws Exception + { + new TestBeanMapper().test(); + } + + @SuppressWarnings("unused") + private final class MyObject + { + final int _x, _y; + + final String _desc; + + public MyObject(int x, int y, String desc) + { + _x = x; + _y = y; + _desc = desc; + } + + public String getDesc() { return _desc; } + public int getX() { return _x; } + public int getY() { return _y; } + + public int[] getFoobar() { return new int[] { 1, 2, 3 }; } + + public MyObject2 getNext() { + return new MyObject2(); + } + + public Collection<?> getMisc() { + return new ArrayList<Object>(); + } + } + + final static class MyObject2 { + public String getName() { return "dummy"; } + } +} +
diff --git a/1.9.10/src/tools/TestGenerator.java b/1.9.10/src/tools/TestGenerator.java new file mode 100644 index 0000000..866eca6 --- /dev/null +++ b/1.9.10/src/tools/TestGenerator.java
@@ -0,0 +1,34 @@ + + +import java.io.*; +import java.math.BigDecimal; + +import org.codehaus.jackson.*; + +public class TestGenerator +{ + private TestGenerator() { } + + public static void main(String[] args) + throws Exception + { + StringWriter strw = new StringWriter(); + JsonGenerator jg = new JsonFactory().createJsonGenerator(strw); + + jg.writeStartObject(); + jg.writeFieldName("pi"); + //jg.writeNumber(new BigDecimal("1.23")); + jg.writeNumber(new BigDecimal("1.23")); + jg.writeFieldName("binary"); + byte[] data = "Test string!".getBytes("UTF-8"); + jg.writeBinary(data); + + // what happens if we leave this out? + //jg.writeEndObject(); + + jg.close(); + + System.out.println("Result: <"+strw.toString()+">"); + } +} +
diff --git a/1.9.10/src/tools/TestMapSpeed.java b/1.9.10/src/tools/TestMapSpeed.java new file mode 100644 index 0000000..52d19d3 --- /dev/null +++ b/1.9.10/src/tools/TestMapSpeed.java
@@ -0,0 +1,180 @@ +import java.io.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.*; + +public final class TestMapSpeed +{ + /** + * Number of repetitions to run per test. Dynamically variable, + * based on observed runtime, to try to keep it high enough. + */ + private int REPS; + + /** + * Let's keep per-run times above 50 milliseconds + */ + //final static int MIN_RUN_TIME = 50; + final static int MIN_RUN_TIME = 5; + + /** + * Let's keep per-run times below 300 milliseconds + */ + //final static int MAX_RUN_TIME = 300; + final static int MAX_RUN_TIME = 1000; + + private final static int TEST_PER_GC = 17; + + final JsonFactory _factory; + final ObjectMapper _mapper; + + final Object _objectToMap; + + private TestMapSpeed(byte[] data) + throws Exception + { + _factory = new JsonFactory(); + _mapper = new ObjectMapper(); + JsonParser jp = _factory.createJsonParser(data, 0, data.length); + _objectToMap = _mapper.readValue(jp, Object.class); + jp.close(); + + // Ok how should we guestimate speed... perhaps from data size? + REPS = 100 + ((8 * 1000 * 1000) / data.length); + System.out.println("Based on size, will use "+REPS+" repetitions"); + } + + protected int test() + throws Exception + { + int i = 0; + int total = 0; + + final int TEST_CASES = 2; + final ByteArrayOutputStream bos = new ByteArrayOutputStream(1000); + + while (true) { + try { Thread.sleep(150L); } catch (InterruptedException ie) { } + int round = (i++ % TEST_CASES); + + long now = System.currentTimeMillis(); + String msg; + int sum = 0; +//round = 1; // testing just old or new? + + switch (round) { + case 0: + msg = "Map using OLD"; + sum = testOld(REPS, bos); + break; + case 1: + msg = "Map using NEW"; + sum = testNew(REPS, bos); + break; + + default: + throw new Error("Internal error"); + } + + now = System.currentTimeMillis() - now; + if (round == 0) { + System.out.println(); + } + System.out.println("Test '"+msg+"' -> "+now+" msecs (" + +sum+" -> "+(total & 0xFF)+")."); + + total += sum; + + if ((i % TEST_PER_GC) == 0) { + System.out.println("[GC]"); + try { Thread.sleep(100L); } catch (InterruptedException ie) { } + System.gc(); + try { Thread.sleep(200L); } catch (InterruptedException ie) { } + + /* One more tweak: let's add load if things start + * running too fast or slow, to try to get sweet range + * of 50 to 250 millisseconds + */ + if (now < MIN_RUN_TIME) { + REPS += (REPS / 5); // 20% up + System.out.println("[NOTE: increasing reps, now: "+REPS+"]"); + try { Thread.sleep(200L); } catch (InterruptedException ie) { } + } else if (now > MAX_RUN_TIME && i > 20) { + /* Let's reduce load slower than increase; also, + * due to initial warmup, let's not adjust until + * we've gone through a few cycles + */ + REPS -= (REPS / 10); // 10% down + System.out.println("[NOTE: decreasing reps, now: "+REPS+"]"); + try { Thread.sleep(200L); } catch (InterruptedException ie) { } + } + } + } + } + + /* + ///////////////////////////////////////////////////////// + // Actual value type access, ones via Stax 1.0 + ///////////////////////////////////////////////////////// + */ + + protected int testOld(int reps, ByteArrayOutputStream out) + throws Exception + { + int total = 0; + for (int i = 0; i < reps; ++i) { + out.reset(); + JsonGenerator jg = _factory.createJsonGenerator(out, JsonEncoding.UTF8); + _mapper.writeValue(jg, _objectToMap); + jg.close(); + total = out.size(); + } + return total; + } + + protected int testNew(int reps, ByteArrayOutputStream out) + throws Exception + { + int total = 0; + for (int i = 0; i < reps; ++i) { + out.reset(); + JsonGenerator jg = _factory.createJsonGenerator(out, JsonEncoding.UTF8); + _mapper.writeValue(jg, _objectToMap); + jg.close(); + total = out.size(); + } + return total; + } + + /* + ///////////////////////////////////////////////////////// + // Helper methods + ///////////////////////////////////////////////////////// + */ + + static byte[] readData(File file) throws IOException + { + InputStream fin = new FileInputStream(file); + byte[] buf = new byte[4000]; + ByteArrayOutputStream bos = new ByteArrayOutputStream(4000); + int count; + + while ((count = fin.read(buf)) > 0) { + bos.write(buf, 0, count); + } + fin.close(); + return bos.toByteArray(); + } + + public static void main(String[] args) + throws Exception + { + if (args.length != 1) { + System.err.println("Usage: java ... <file>"); + System.exit(1); + } + byte[] data = readData(new File(args[0])); + System.out.println(" -> "+data.length+" bytes read."); + new TestMapSpeed(data).test(); + } +}
diff --git a/1.9.10/src/tools/TestObjectMapper.java b/1.9.10/src/tools/TestObjectMapper.java new file mode 100644 index 0000000..3aa3155 --- /dev/null +++ b/1.9.10/src/tools/TestObjectMapper.java
@@ -0,0 +1,40 @@ +import java.io.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.map.*; + +public class TestObjectMapper +{ + private TestObjectMapper() { } + + public static void main(String[] args) + throws Exception + { + if (args.length != 1) { + System.err.println("Usage: java test.TestObjectMapper <file>"); + System.exit(1); + } + FileInputStream in = new FileInputStream(new File(args[0])); + JsonFactory f = new JsonFactory(); + JsonParser jp = f.createJsonParser(in); + ObjectMapper map = new ObjectMapper(); + // 06-Jan-2009, tatu: This will mean "untyped" mapping + Object result = map.readValue(jp, Object.class); + jp.close(); + System.out.println("Read result ("+(result.getClass())+"): <"+result+">"); + + StringWriter sw = new StringWriter(); + JsonGenerator jg = f.createJsonGenerator(sw); + try { + map.writeValue(jg, result); + } catch (Exception e) { + try { jg.flush(); } catch (IOException ioe) { } + System.err.println("Error, intermediate result = |"+sw+"|"); + throw e; + } + jg.close(); + + System.out.println("Write result: <"+sw.toString()+">"); + } +} +
diff --git a/1.9.10/src/tools/TestParser.java b/1.9.10/src/tools/TestParser.java new file mode 100644 index 0000000..174e851 --- /dev/null +++ b/1.9.10/src/tools/TestParser.java
@@ -0,0 +1,50 @@ + + +import java.io.*; + +import org.codehaus.jackson.*; + +public class TestParser +{ + public static void main(String[] args) + throws IOException + { + if (args.length != 1) { + System.err.println("Usage: java ... TestParser [file]"); + System.exit(1); + } + JsonFactory f = new JsonFactory(); + // [JACKSON-259]: ability to suppress canonicalization + f.disable(JsonParser.Feature.CANONICALIZE_FIELD_NAMES); + + JsonParser jp = f.createJsonParser(new File(args[0])); + //JsonParser jp = f.createJsonParser(new InputStreamReader(new FileInputStream(args[0]), "UTF-8")); + jp.enable(JsonParser.Feature.ALLOW_COMMENTS); + + System.out.println("Parser: "+jp); + + JsonToken t; + + while ((t = jp.nextToken()) != null) { + System.out.print("Token: "+t); + if (t == JsonToken.FIELD_NAME) { + //String name = new String(jp.getTextCharacters(), jp.getTextOffset(), jp.getTextLength()); + String name = jp.getCurrentName(); + System.out.print(", name = '"+name+"' (len: "+name.length()+")"); + // Troubleshoot: + int ix = name.indexOf('\0'); + if (ix >= 0) { + throw new RuntimeException("Null byte for name, at index #"+ix); + } + } else if (t.toString().startsWith("VALUE")) { + if (t == JsonToken.VALUE_STRING) { + System.out.print(" [len: "+jp.getTextLength()+"]"); + } + System.out.print(", value = \""+jp.getText()+"\""); + } + System.out.println(); + } + + jp.close(); + } +}
diff --git a/1.9.10/src/tools/TestReflection.java b/1.9.10/src/tools/TestReflection.java new file mode 100644 index 0000000..96e10ff --- /dev/null +++ b/1.9.10/src/tools/TestReflection.java
@@ -0,0 +1,125 @@ + + +import java.lang.reflect.*; +import java.util.*; + +/** + * Manually run class used for figuring out exactly how JDK/generics + * expose type information. + */ +@SuppressWarnings("serial") +public class TestReflection + extends ArrayList<Integer> +{ + public static void main(String[] args) + throws Exception + { + TestReflection test = new TestReflection(); + test.test0(); + } + + @SuppressWarnings("unused") + private void test() throws Exception + { + //Class<?> cls1 = ArrayList.class; + //Class<?> cls2 = new ArrayList<Object>().getClass(); + + Class<?> cls1 = ArrayList[].class; + Class<?> cls2 = List[].class; + + System.out.println("Cls 1 = "+cls1); + System.out.println("Cls 2 = "+cls2); + System.out.println("1 === 2? "+(cls1 == cls2)); + System.out.println("1 == 2? "+(cls1.equals(cls2))); + } + + private void test0() throws Exception + { + testMethod(getClass().getMethod("methodPlain")); + testMethod(getClass().getMethod("methodParam")); + testMethod(getClass().getMethod("methodArrayPlain")); + testMethod(getClass().getMethod("methodArrayParam")); + testMethod(getClass().getMethod("methodWildcard")); + } + + public LinkedHashMap<Class<Integer>, Boolean[]> methodParam() { return null; } + + public Integer methodPlain() { return null; } + + public int[][][] methodArrayPlain() { return null; } + public LinkedList<List<List<Integer>>>[][][] methodArrayParam() { return null; } + + public Set<? extends List<?>> methodWildcard() { return null; } + + private void testMethod(Method m) throws Exception + { + System.out.println("Return type for ["+m+"]:"); + //int ix = 0; + Type type = m.getGenericReturnType(); + + printType(1, type); + } + + private void indent(int amount) + { + for (int i = 0; i < amount; ++i) { + System.out.print(" "); + } + } + + private void printType(int indent, Type type) + { + indent(indent); + if (type == null) { + System.out.println("[null]"); + } + else if (type instanceof Class<?>) { + System.out.println("simple class: "+((Class<?>) type).getName()); + } + else if (type instanceof GenericArrayType) { + System.out.println("array type, component:"); + GenericArrayType at = (GenericArrayType) type; + printType(indent+1, at.getGenericComponentType()); + } + else if (type instanceof ParameterizedType) { + ParameterizedType pt = (ParameterizedType) type; + System.out.println("parameterized type:"); + ++indent; + indent(indent); + System.out.println("owner -> "); + printType(indent+1, pt.getOwnerType()); + indent(indent); + System.out.println("raw -> "); + printType(indent+1, pt.getRawType()); + + int ix = 0; + for (Type t2 : pt.getActualTypeArguments()) { + ++ix; + indent(indent); + System.out.println("actual #"+ix+" -> "); + printType(indent+1, t2); + } + } + else if (type instanceof TypeVariable<?>) { + TypeVariable<?> v = (TypeVariable<?>) type; + System.out.println("type variable '"+v.getName()+"'"); + } + else if (type instanceof WildcardType) { + WildcardType w = (WildcardType) type; + System.out.println("wildcard type:"); + ++indent; + indent(indent); + System.out.println("lower bounds[] -> "); + for (Type t2 : w.getLowerBounds()) { + printType(indent+1, t2); + } + indent(indent); + System.out.println("upper bounds[] -> "); + for (Type t2 : w.getUpperBounds()) { + printType(indent+1, t2); + } + } else { + throw new IllegalArgumentException("Weird type! "+type.getClass()); + } + } +}
diff --git a/1.9.10/src/tools/TestSerializationError.java b/1.9.10/src/tools/TestSerializationError.java new file mode 100644 index 0000000..30697de --- /dev/null +++ b/1.9.10/src/tools/TestSerializationError.java
@@ -0,0 +1,37 @@ +import java.io.*; +import java.util.*; + +import org.codehaus.jackson.map.*; + +public class TestSerializationError +{ + final static class OkBean { + ArrayList<NonBean[]> _beans; + + public OkBean() { + _beans = new ArrayList<NonBean[]>(); + _beans.add(new NonBean[] { new NonBean() });; + } + + public List<NonBean[]> getNonBeans() { return _beans; } + } + + final static class NonBean { + public NonBean() { } + } + + public static void main(String[] args) + throws Exception + { + ObjectMapper mapper = new ObjectMapper(); + ArrayList<OkBean> list = new ArrayList<OkBean>(); + list.add(new OkBean()); + HashMap<String,Object> map = new HashMap<String,Object>(); + map.put("foo", list); + // should error out, but what do we see there? + StringWriter sw = new StringWriter(); + mapper.writeValue(sw, map); + + System.out.println("Odd, didn't fail, got: "+sw.toString()); + } +}
diff --git a/1.9.10/src/tools/VerifySmileDocs.java b/1.9.10/src/tools/VerifySmileDocs.java new file mode 100644 index 0000000..20bbd5f --- /dev/null +++ b/1.9.10/src/tools/VerifySmileDocs.java
@@ -0,0 +1,144 @@ +import java.io.*; + +import org.codehaus.jackson.*; +import org.codehaus.jackson.smile.SmileFactory; +import org.codehaus.jackson.smile.SmileGenerator; + +/** + * Helper test class that will check to see that we can round-trip + * JSON-to-Smile-to-JSON, without loss of data. + */ +public class VerifySmileDocs +{ + private final static JsonFactory jsonFactory = new JsonFactory(); + private final static SmileFactory smileFactoryWithNoBackrefs = new SmileFactory(); + { + smileFactoryWithNoBackrefs.configure(SmileGenerator.Feature.CHECK_SHARED_NAMES, false); + smileFactoryWithNoBackrefs.configure(SmileGenerator.Feature.CHECK_SHARED_STRING_VALUES, false); + } + private final static SmileFactory jsonFactoryWithBackrefs = new SmileFactory(); + { + jsonFactoryWithBackrefs.configure(SmileGenerator.Feature.CHECK_SHARED_NAMES, true); + jsonFactoryWithBackrefs.configure(SmileGenerator.Feature.CHECK_SHARED_STRING_VALUES, true); + } + + private VerifySmileDocs() {} + + private void verifyAll(File inputDir) throws IOException + { + File[] files = inputDir.listFiles(new FilenameFilter() { + @Override + public boolean accept(File dir, String name) { + int i = name.lastIndexOf('.'); + if (i > 0) { + String suffix = name.substring(i+1); + if ("json".equals(suffix) || "jsn".equals(suffix)) { + return true; + } + } + return false; + } + }); + if (files.length == 0) { + throw new IOException("No files with suffix '.json' or '.jsn' found from under '" + + inputDir.getAbsolutePath()+"'"); + } + System.out.printf("Found %d JSON files to test with...\n", files.length); + int failures = 0; + + for (File file : files) { + System.out.printf(" verifying file '%s'...", file.getName()); + if (!verify(file, false) || !verify(file, true)) { + ++failures; + } else { + System.out.println(" OK"); + } + } + + System.out.printf("Done: %d files had issues\n", failures); + } + + private boolean verify(File inputFile, boolean backrefs) throws IOException + { + JsonFactory smileFactory = backrefs ? jsonFactoryWithBackrefs : smileFactoryWithNoBackrefs; + byte[] smileDoc = convertToSmile(inputFile, smileFactory); + JsonParser jpWithDiff = compareJsonToSmile(inputFile, smileDoc, smileFactory); + if (jpWithDiff != null) { + System.err.printf(" events differ (expected %s), location (backrefs: %s): %s\n", + String.valueOf(jpWithDiff.getCurrentToken()), + backrefs, + inputFile.getName()); + jpWithDiff.close(); + return false; + } + return true; + } + + private byte[] convertToSmile(File inputFile, JsonFactory outputFactory) throws IOException + { + ByteArrayOutputStream bytes = new ByteArrayOutputStream(1000); + JsonParser jp = jsonFactory.createJsonParser(inputFile); + JsonGenerator jgen = outputFactory.createJsonGenerator(bytes); + while (jp.nextToken() != null) { + jgen.copyCurrentEvent(jp); + } + jp.close(); + jgen.close(); + return bytes.toByteArray(); + } + + private JsonParser compareJsonToSmile(File inputFile, byte[] smileBytes, + JsonFactory smileFactory) throws IOException + { + JsonParser jsonParser = jsonFactory.createJsonParser(inputFile); + JsonParser smileParser = smileFactory.createJsonParser(smileBytes); + JsonToken t1; + + while ((t1 = jsonParser.nextToken()) != null) { + JsonToken t2 = smileParser.nextToken(); + // first: token types must match + if (t1 != t2) { + return jsonParser; + } + // and second, values as well + switch (t1) { + case VALUE_STRING: + case FIELD_NAME: + if (!jsonParser.getText().equals(smileParser.getText())) { + return jsonParser; + } + break; + case VALUE_NUMBER_INT: + if (jsonParser.getLongValue() != smileParser.getLongValue()) { + return jsonParser; + } + break; + case VALUE_NUMBER_FLOAT: + if (jsonParser.getDoubleValue() != smileParser.getDoubleValue()) { + return jsonParser; + } + break; + // others are fine: + // Boolean values are distinct tokens; + // Object/Array start/end likewise + } + } + if (t1 == null) { + if (smileParser.nextToken() != null) { + return jsonParser; + } + } + jsonParser.close(); + smileParser.close(); + return null; + } + + public static void main(String[] args) throws Exception + { + if (args.length != 1) { + System.err.println("Usage: java ... [input-dir]"); + System.exit(1); + } + new VerifySmileDocs().verifyAll(new File(args[0])); + } +}
diff --git a/1.9.10/src/xc/java/org/codehaus/jackson/xc/DataHandlerJsonDeserializer.java b/1.9.10/src/xc/java/org/codehaus/jackson/xc/DataHandlerJsonDeserializer.java new file mode 100644 index 0000000..cbb9855 --- /dev/null +++ b/1.9.10/src/xc/java/org/codehaus/jackson/xc/DataHandlerJsonDeserializer.java
@@ -0,0 +1,56 @@ +package org.codehaus.jackson.xc; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.ByteArrayInputStream; + +import javax.activation.DataHandler; +import javax.activation.DataSource; + +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.map.DeserializationContext; +import org.codehaus.jackson.map.deser.std.StdScalarDeserializer; + +/** + * @author Ryan Heaton + */ +public class DataHandlerJsonDeserializer + extends StdScalarDeserializer<DataHandler> +{ + public DataHandlerJsonDeserializer() { super(DataHandler.class); } + + @Override + public DataHandler deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + final byte[] value = jp.getBinaryValue(); + return new DataHandler(new DataSource() + { + @Override + public InputStream getInputStream() throws IOException + { + return new ByteArrayInputStream(value); + } + + @Override + public OutputStream getOutputStream() throws IOException + { + throw new IOException(); + } + + @Override + public String getContentType() + { + return "application/octet-stream"; + } + + @Override + public String getName() + { + return "json-binary-data"; + } + }); + } +}
diff --git a/1.9.10/src/xc/java/org/codehaus/jackson/xc/DataHandlerJsonSerializer.java b/1.9.10/src/xc/java/org/codehaus/jackson/xc/DataHandlerJsonSerializer.java new file mode 100644 index 0000000..4b49a4c --- /dev/null +++ b/1.9.10/src/xc/java/org/codehaus/jackson/xc/DataHandlerJsonSerializer.java
@@ -0,0 +1,55 @@ +package org.codehaus.jackson.xc; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Type; + +import javax.activation.DataHandler; + +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.map.SerializerProvider; +import org.codehaus.jackson.map.ser.std.SerializerBase; +import org.codehaus.jackson.node.ObjectNode; + +/** + * @author Ryan Heaton + */ +public class DataHandlerJsonSerializer extends SerializerBase<DataHandler> +{ + public DataHandlerJsonSerializer() { super(DataHandler.class); } + + @Override + public void serialize(DataHandler value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonProcessingException + { + final ByteArrayOutputStream out = new ByteArrayOutputStream(); + /* for copy-through, a small buffer should suffice: ideally + * we might want to reuse a generic byte buffer, but for now + * there's no serializer context to hold them. + * + * Also: it'd be nice not to have buffer all data, but use a + * streaming output. But currently JsonGenerator won't allow + * that. + */ + byte[] buffer = new byte[1024 * 4]; //10k? + InputStream in = value.getInputStream(); + int len = in.read(buffer); + while (len > 0) { + out.write(buffer, 0, len); + len = in.read(buffer); + } + jgen.writeBinary(out.toByteArray()); + } + + @Override + public JsonNode getSchema(SerializerProvider provider, Type typeHint) + { + ObjectNode o = createSchemaNode("array", true); + ObjectNode itemSchema = createSchemaNode("string"); //binary values written as strings? + o.put("items", itemSchema); + return o; + } +}
diff --git a/1.9.10/src/xc/java/org/codehaus/jackson/xc/DomElementJsonDeserializer.java b/1.9.10/src/xc/java/org/codehaus/jackson/xc/DomElementJsonDeserializer.java new file mode 100644 index 0000000..cf9c073 --- /dev/null +++ b/1.9.10/src/xc/java/org/codehaus/jackson/xc/DomElementJsonDeserializer.java
@@ -0,0 +1,97 @@ +package org.codehaus.jackson.xc; + +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.map.DeserializationContext; +import org.codehaus.jackson.map.JsonMappingException; +import org.codehaus.jackson.map.deser.std.StdDeserializer; +import org.codehaus.jackson.node.ArrayNode; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import java.io.IOException; +import java.util.Iterator; + +/** + * @author Ryan Heaton + */ +public class DomElementJsonDeserializer + extends StdDeserializer<Element> +{ + private final DocumentBuilder builder; + + public DomElementJsonDeserializer() + { + super(Element.class); + try { + DocumentBuilderFactory bf = DocumentBuilderFactory.newInstance(); + bf.setNamespaceAware(true); + builder = bf.newDocumentBuilder(); + } catch (ParserConfigurationException e) { + throw new RuntimeException(); + } + } + + public DomElementJsonDeserializer(DocumentBuilder builder) + { + super(Element.class); + this.builder = builder; + } + + @Override + public Element deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + Document document = builder.newDocument(); + return fromNode(document, jp.readValueAsTree()); + } + + protected Element fromNode(Document document, JsonNode jsonNode) + throws IOException + { + String ns = jsonNode.get("namespace") != null ? jsonNode.get("namespace").asText() : null; + String name = jsonNode.get("name") != null ? jsonNode.get("name").asText() : null; + if (name == null) { + throw new JsonMappingException("No name for DOM element was provided in the JSON object."); + } + Element element = document.createElementNS(ns, name); + + JsonNode attributesNode = jsonNode.get("attributes"); + if (attributesNode != null && attributesNode instanceof ArrayNode) { + Iterator<JsonNode> atts = attributesNode.getElements(); + while (atts.hasNext()) { + JsonNode node = atts.next(); + ns = node.get("namespace") != null ? node.get("namespace").asText() : null; + name = node.get("name") != null ? node.get("name").asText() : null; + String value = node.get("$") != null ? node.get("$").asText() : null; + + if (name != null) { + element.setAttributeNS(ns, name, value); + } + } + } + + JsonNode childsNode = jsonNode.get("children"); + if (childsNode != null && childsNode instanceof ArrayNode) { + Iterator<JsonNode> els = childsNode.getElements(); + while (els.hasNext()) { + JsonNode node = els.next(); + name = node.get("name") != null ? node.get("name").asText() : null; + String value = node.get("$") != null ? node.get("$").asText() : null; + + if (value != null) { + element.appendChild(document.createTextNode(value)); + } + else if (name != null) { + element.appendChild(fromNode(document, node)); + } + } + } + + return element; + } +}
diff --git a/1.9.10/src/xc/java/org/codehaus/jackson/xc/DomElementJsonSerializer.java b/1.9.10/src/xc/java/org/codehaus/jackson/xc/DomElementJsonSerializer.java new file mode 100644 index 0000000..3dd7ed3 --- /dev/null +++ b/1.9.10/src/xc/java/org/codehaus/jackson/xc/DomElementJsonSerializer.java
@@ -0,0 +1,82 @@ +package org.codehaus.jackson.xc; + +import org.codehaus.jackson.JsonGenerationException; +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.map.JsonMappingException; +import org.codehaus.jackson.map.SerializerProvider; +import org.codehaus.jackson.map.ser.std.SerializerBase; +import org.codehaus.jackson.node.ObjectNode; +import org.w3c.dom.*; + +import java.io.IOException; +import java.lang.reflect.Type; + +/** + * @author Ryan Heaton + */ +public class DomElementJsonSerializer + extends SerializerBase<Element> +{ + public DomElementJsonSerializer() { super(Element.class); } + + @Override + public void serialize(Element value, JsonGenerator jgen, SerializerProvider provider) + throws IOException, JsonGenerationException + { + jgen.writeStartObject(); + jgen.writeStringField("name", value.getTagName()); + if (value.getNamespaceURI() != null) { + jgen.writeStringField("namespace", value.getNamespaceURI()); + } + NamedNodeMap attributes = value.getAttributes(); + if (attributes != null && attributes.getLength() > 0) { + jgen.writeArrayFieldStart("attributes"); + for (int i = 0; i < attributes.getLength(); i++) { + Attr attribute = (Attr) attributes.item(i); + jgen.writeStartObject(); + jgen.writeStringField("$", attribute.getValue()); + jgen.writeStringField("name", attribute.getName()); + String ns = attribute.getNamespaceURI(); + if (ns != null) { + jgen.writeStringField("namespace", ns); + } + jgen.writeEndObject(); + } + jgen.writeEndArray(); + } + + NodeList children = value.getChildNodes(); + if (children != null && children.getLength() > 0) { + jgen.writeArrayFieldStart("children"); + for (int i = 0; i < children.getLength(); i++) { + Node child = children.item(i); + switch (child.getNodeType()) { + case Node.CDATA_SECTION_NODE: + case Node.TEXT_NODE: + jgen.writeStartObject(); + jgen.writeStringField("$", child.getNodeValue()); + jgen.writeEndObject(); + break; + case Node.ELEMENT_NODE: + serialize((Element) child, jgen, provider); + break; + } + } + jgen.writeEndArray(); + } + jgen.writeEndObject(); + } + + @Override + public JsonNode getSchema(SerializerProvider provider, Type typeHint) + throws JsonMappingException + { + ObjectNode o = createSchemaNode("object", true); + o.put("name", createSchemaNode("string")); + o.put("namespace", createSchemaNode("string", true)); + o.put("attributes", createSchemaNode("array", true)); + o.put("children", createSchemaNode("array", true)); + return o; + } +}
diff --git a/1.9.10/src/xc/java/org/codehaus/jackson/xc/JaxbAnnotationIntrospector.java b/1.9.10/src/xc/java/org/codehaus/jackson/xc/JaxbAnnotationIntrospector.java new file mode 100644 index 0000000..897d781 --- /dev/null +++ b/1.9.10/src/xc/java/org/codehaus/jackson/xc/JaxbAnnotationIntrospector.java
@@ -0,0 +1,1076 @@ +package org.codehaus.jackson.xc; + +import java.beans.Introspector; +import java.lang.annotation.Annotation; +import java.lang.reflect.*; +import java.util.*; + +import javax.xml.bind.JAXBElement; +import javax.xml.bind.annotation.*; +import javax.xml.bind.annotation.adapters.XmlAdapter; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; +import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapters; + +import org.codehaus.jackson.Version; +import org.codehaus.jackson.Versioned; +import org.codehaus.jackson.annotate.JsonAutoDetect.Visibility; +import org.codehaus.jackson.annotate.JsonTypeInfo; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.annotate.JsonCachable; +import org.codehaus.jackson.map.annotate.JsonSerialize; +import org.codehaus.jackson.map.introspect.*; +import org.codehaus.jackson.map.jsontype.NamedType; +import org.codehaus.jackson.map.jsontype.TypeResolverBuilder; +import org.codehaus.jackson.map.jsontype.impl.StdTypeResolverBuilder; +import org.codehaus.jackson.map.util.BeanUtil; +import org.codehaus.jackson.map.util.ClassUtil; +import org.codehaus.jackson.type.JavaType; +import org.codehaus.jackson.util.VersionUtil; + +/** + * Annotation introspector that leverages JAXB annotations where applicable to JSON mapping. + * <p/> + * The following JAXB annotations are not supported yet (but some may be supported in future) + * <ul> + * <li>{@link XmlAnyAttribute} not yet used (as of 1.5) but may be in future (as an alias for @JsonAnySetter?) + * <li>{@link XmlAnyElement} not yet used, may be as per [JACKSON-253] + * <li>{@link javax.xml.bind.annotation.XmlAttachmentRef}: JSON does not support external attachments + * <li>{@link XmlElementDecl} + * <li>{@link XmlElementRefs} because Jackson doesn't have any support for 'named' collection items -- however, + * this may become partially supported as per [JACKSON-253]. + * <li>{@link XmlID} because Jackson doesn't support referential integrity. NOTE: this too may be supported + * in future if/when id references are handled + * <li>{@link XmlIDREF} same as <code>XmlID</code> + * <li>{@link javax.xml.bind.annotation.XmlInlineBinaryData} since the underlying concepts + * (like XOP) do not exist in JSON -- Jackson will always use inline base64 encoding as the method + * <li>{@link javax.xml.bind.annotation.XmlList} because JSON does have (or necessarily need) + * method of serializing list of values as space-separated Strings + * <li>{@link javax.xml.bind.annotation.XmlMimeType} + * <li>{@link javax.xml.bind.annotation.XmlMixed} since JSON has no concept of mixed content + * <li>{@link XmlRegistry} + * <li>{@link XmlRootElement} is recognized and used (as of 1.7) for defining root wrapper name (if used) + * <li>{@link XmlSchema} not used, unlikely to be used + * <li>{@link XmlSchemaType} not used, unlikely to be used + * <li>{@link XmlSchemaTypes} not used, unlikely to be used + * <li>{@link XmlSeeAlso} not needed for anything currently (could theoretically be useful + * for locating subtypes for Polymorphic Type Handling) + * </ul> + * + * Note also the following limitations: + * + * <ul> + * <li>Any property annotated with {@link XmlValue} will have a property named 'value' on its JSON object. + * </ul> + * + * @author Ryan Heaton + * @author Tatu Saloranta + */ +public class JaxbAnnotationIntrospector + extends AnnotationIntrospector + implements Versioned +{ + protected final static String MARKER_FOR_DEFAULT = "##default"; + + protected final String _jaxbPackageName; + protected final JsonSerializer<?> _dataHandlerSerializer; + protected final JsonDeserializer<?> _dataHandlerDeserializer; + + public JaxbAnnotationIntrospector() + { + _jaxbPackageName = XmlElement.class.getPackage().getName(); + + JsonSerializer<?> dataHandlerSerializer = null; + JsonDeserializer<?> dataHandlerDeserializer = null; + /* Data handlers included dynamically, to try to prevent issues on platforms + * with less than complete support for JAXB API + */ + try { + dataHandlerSerializer = (JsonSerializer<?>) Class.forName("org.codehaus.jackson.xc.DataHandlerJsonSerializer").newInstance(); + dataHandlerDeserializer = (JsonDeserializer<?>) Class.forName("org.codehaus.jackson.xc.DataHandlerJsonDeserializer").newInstance(); + } catch (Throwable e) { + //dataHandlers not supported... + } + _dataHandlerSerializer = dataHandlerSerializer; + _dataHandlerDeserializer = dataHandlerDeserializer; + } + + /** + * Method that will return version information stored in and read from jar + * that contains this class. + * + * @since 1.6 + */ + @Override + public Version version() { + return VersionUtil.versionFor(getClass()); + } + + /* + /********************************************************** + /* General annotation properties + /********************************************************** + */ + + /** + * An annotation is handled if it's in the same package as @XmlElement, including subpackages. + * + * @param ann The annotation. + * @return Whether the annotation is in the JAXB package. + */ + @Override + public boolean isHandled(Annotation ann) + { + /* note: class we want is the annotation class, not instance + * (since annotation instances, like enums, may be of different + * physical type!) + */ + Class<?> cls = ann.annotationType(); + Package pkg = cls.getPackage(); + String pkgName = (pkg != null) ? pkg.getName() : cls.getName(); + if (pkgName.startsWith(_jaxbPackageName)) { + return true; + } + // as per [JACKSON-472], also need to recognize @JsonCachable + if (cls == JsonCachable.class) { + return true; + } + return false; + } + + /* + /********************************************************** + /* General class annotations + /********************************************************** + */ + + @Override + public Boolean findCachability(AnnotatedClass ac) + { + /* 30-Jan-2011, tatu: As per [JACKSON-472], we may want to also + * check Jackson annotation here, because sometimes JAXB + * introspector is used alone... + */ + JsonCachable ann = ac.getAnnotation(JsonCachable.class); + if (ann != null) { + return ann.value() ? Boolean.TRUE : Boolean.FALSE; + } + return null; + } + + @Override + public String findRootName(AnnotatedClass ac) + { + XmlRootElement elem = findRootElementAnnotation(ac); + if (elem != null) { + String name = elem.name(); + // default means "derive from class name"; so we'll return "" + return MARKER_FOR_DEFAULT.equals(name) ? "" : name; + } + return null; + } + + @Override + public String[] findPropertiesToIgnore(AnnotatedClass ac) { + // nothing in JAXB for this? + return null; + } + + @Override + public Boolean findIgnoreUnknownProperties(AnnotatedClass ac) { + /* 08-Nov-2009, tatus: This is bit trickier: by default JAXB + * does actually ignore all unknown properties. + * But since there is no annotation to + * specify or change this, it seems wrong to claim such setting + * is in effect. May need to revisit this issue in future + */ + return null; + } + + @Override + public Boolean isIgnorableType(AnnotatedClass ac) { + // Does JAXB have any such indicators? No? + return null; + } + + /* + /********************************************************** + /* General member (field, method/constructor) annotations + /********************************************************** + */ + + @Override + public boolean hasIgnoreMarker(AnnotatedMember m) { + return m.getAnnotation(XmlTransient.class) != null; + } + + /* + /********************************************************** + /* Property auto-detection + /********************************************************** + */ + + @Override + public VisibilityChecker<?> findAutoDetectVisibility(AnnotatedClass ac, + VisibilityChecker<?> checker) + { + XmlAccessType at = findAccessType(ac); + if (at == null) { + /* JAXB default is "PUBLIC_MEMBER"; however, here we should not + * override settings if there is no annotation -- that would mess + * up global baseline. Fortunately Jackson defaults are very close + * to JAXB 'PUBLIC_MEMBER' settings (considering that setters and + * getters must come in pairs) + */ + return checker; + } + + // Note: JAXB does not do creator auto-detection, can (and should) ignore + switch (at) { + case FIELD: // all fields, independent of visibility; no methods + return checker.withFieldVisibility(Visibility.ANY) + .withSetterVisibility(Visibility.NONE) + .withGetterVisibility(Visibility.NONE) + .withIsGetterVisibility(Visibility.NONE) + ; + case NONE: // no auto-detection + return checker.withFieldVisibility(Visibility.NONE) + .withSetterVisibility(Visibility.NONE) + .withGetterVisibility(Visibility.NONE) + .withIsGetterVisibility(Visibility.NONE) + ; + case PROPERTY: + return checker.withFieldVisibility(Visibility.NONE) + .withSetterVisibility(Visibility.PUBLIC_ONLY) + .withGetterVisibility(Visibility.PUBLIC_ONLY) + .withIsGetterVisibility(Visibility.PUBLIC_ONLY) + ; + case PUBLIC_MEMBER: + return checker.withFieldVisibility(Visibility.PUBLIC_ONLY) + .withSetterVisibility(Visibility.PUBLIC_ONLY) + .withGetterVisibility(Visibility.PUBLIC_ONLY) + .withIsGetterVisibility(Visibility.PUBLIC_ONLY) + ; + } + return checker; + } + + /** + * Method for locating JAXB {@link XmlAccessType} annotation value + * for given annotated entity, if it has one, or inherits one from + * its ancestors (in JAXB sense, package etc). Returns null if + * nothing has been explicitly defined. + */ + protected XmlAccessType findAccessType(Annotated ac) + { + XmlAccessorType at = findAnnotation(XmlAccessorType.class, ac, true, true, true); + return (at == null) ? null : at.value(); + } + + /* + /********************************************************** + /* Class annotations for PM type handling (1.5+) + /********************************************************** + */ + + @Override + public TypeResolverBuilder<?> findTypeResolver(MapperConfig<?> config, + AnnotatedClass ac, JavaType baseType) + { + // no per-class type resolvers, right? + return null; + } + + @Override + public TypeResolverBuilder<?> findPropertyTypeResolver(MapperConfig<?> config, + AnnotatedMember am, JavaType baseType) + { + /* First: @XmlElements and @XmlElementRefs only applies type for immediate property, if it + * is NOT a structured type. + */ + if (baseType.isContainerType()) return null; + return _typeResolverFromXmlElements(am); + } + + @Override + public TypeResolverBuilder<?> findPropertyContentTypeResolver(MapperConfig<?> config, + AnnotatedMember am, JavaType containerType) + { + /* First: let's ensure property is a container type: caller should have + * verified but just to be sure + */ + if (!containerType.isContainerType()) { + throw new IllegalArgumentException("Must call method with a container type (got "+containerType+")"); + } + return _typeResolverFromXmlElements(am); + } + + protected TypeResolverBuilder<?> _typeResolverFromXmlElements(AnnotatedMember am) + { + /* If simple type, @XmlElements and @XmlElementRefs are applicable. + * Note: @XmlElement and @XmlElementRef are NOT handled here, since they + * are handled specifically as non-polymorphic indication + * of the actual type + */ + XmlElements elems = findAnnotation(XmlElements.class, am, false, false, false); + XmlElementRefs elemRefs = findAnnotation(XmlElementRefs.class, am, false, false, false); + if (elems == null && elemRefs == null) { + return null; + } + + TypeResolverBuilder<?> b = new StdTypeResolverBuilder(); + // JAXB always uses type name as id + b = b.init(JsonTypeInfo.Id.NAME, null); + // and let's consider WRAPPER_OBJECT to be canonical inclusion method + b = b.inclusion(JsonTypeInfo.As.WRAPPER_OBJECT); + return b; + } + + @Override + public List<NamedType> findSubtypes(Annotated a) + { + // No package/superclass defaulting (only used with fields, methods) + XmlElements elems = findAnnotation(XmlElements.class, a, false, false, false); + if (elems != null) { + ArrayList<NamedType> result = new ArrayList<NamedType>(); + for (XmlElement elem : elems.value()) { + String name = elem.name(); + if (MARKER_FOR_DEFAULT.equals(name)) name = null; + result.add(new NamedType(elem.type(), name)); + } + return result; + } + else { + XmlElementRefs elemRefs = findAnnotation(XmlElementRefs.class, a, false, false, false); + if (elemRefs != null) { + ArrayList<NamedType> result = new ArrayList<NamedType>(); + for (XmlElementRef elemRef : elemRefs.value()) { + Class<?> refType = elemRef.type(); + // only good for types other than JAXBElement (which is XML based) + if (!JAXBElement.class.isAssignableFrom(refType)) { + // [JACKSON-253] first consider explicit name declaration + String name = elemRef.name(); + if (name == null || MARKER_FOR_DEFAULT.equals(name)) { + XmlRootElement rootElement = (XmlRootElement) refType.getAnnotation(XmlRootElement.class); + if (rootElement != null) { + name = rootElement.name(); + } + } + if (name == null || MARKER_FOR_DEFAULT.equals(name)) { + name = Introspector.decapitalize(refType.getSimpleName()); + } + result.add(new NamedType(refType, name)); + } + } + return result; + } + } + return null; + } + + @Override + public String findTypeName(AnnotatedClass ac) { + XmlType type = findAnnotation(XmlType.class, ac, false, false, false); + if (type != null) { + String name = type.name(); + if (!MARKER_FOR_DEFAULT.equals(name)) return name; + } + return null; + } + + /* + /********************************************************** + /* General method annotations + /********************************************************** + */ + + @Override + public boolean isIgnorableMethod(AnnotatedMethod m) + { + return m.getAnnotation(XmlTransient.class) != null; + } + + @Override + public boolean isIgnorableConstructor(AnnotatedConstructor c) + { + /* @XmlTransient can not be attached to constructors... + * so there seems to be no way to do this. But then again, + * JAXB does not use non-default constructors anyway. + */ + return false; + } + + /* + /********************************************************** + /* General field annotations + /********************************************************** + */ + + @Override + public boolean isIgnorableField(AnnotatedField f) + { + return f.getAnnotation(XmlTransient.class) != null; + } + + /* + /********************************************************** + /* Serialization: general annotations + /********************************************************** + */ + + @Override + public JsonSerializer<?> findSerializer(Annotated am) + { + XmlAdapter<Object,Object> adapter = findAdapter(am, true); + if (adapter != null) { + return new XmlAdapterJsonSerializer(adapter); + } + // [JACKSON-150]: add support for additional core XML types needed by JAXB + Class<?> type = am.getRawType(); + if (type != null) { + if (_dataHandlerSerializer != null && isDataHandler(type)) { + return _dataHandlerSerializer; + } + } + return null; + } + + /** + * Determines whether the type is assignable to class javax.activation.DataHandler without requiring that class + * to be on the classpath. + * + * @param type The type. + * @return Whether the type is assignable to class javax.activation.DataHandler + */ + private boolean isDataHandler(Class<?> type) + { + return type != null && (Object.class != type) + && (("javax.activation.DataHandler".equals(type.getName()) || isDataHandler(type.getSuperclass()))); + } + + @Override + public Class<?> findSerializationType(Annotated a) + { + // As per [JACKSON-416], need to allow coercing serialization type... + /* false for class, package, super-class, since annotation can + * only be attached to fields and methods + */ + // Note: caller does necessary sub/supertype checks + XmlElement annotation = findAnnotation(XmlElement.class, a, false, false, false); + if (annotation == null || annotation.type() == XmlElement.DEFAULT.class) { + return null; + } + /* [JACKSON-436]: Apparently collection types (array, Collection, maybe Map) + * require type definition to relate to contents, not collection type + * itself. So; we must return null here for those cases, and modify content + * type on another method. + */ + Class<?> rawPropType = a.getRawType(); + if (isIndexedType(rawPropType)) { + return null; + } + /* [JACKSON-288]: Further, JAXB has peculiar notion of declaring intermediate + * (and, for the most part, useless) type... So basically we better + * just ignore type if there is adapter annotation + * (we could check to see if intermediate type is compatible, but let's not yet + * bother) + * + */ + Class<?> allegedType = annotation.type(); + if (a.getAnnotation(XmlJavaTypeAdapter.class) != null) { + return null; + } + return allegedType; + } + + /** + * Implementation of this method is slightly tricky, given that JAXB defaults differ + * from Jackson defaults. As of version 1.5 and above, this is resolved by honoring + * Jackson defaults (which are configurable), and only using JAXB explicit annotations. + */ + @Override + public JsonSerialize.Inclusion findSerializationInclusion(Annotated a, JsonSerialize.Inclusion defValue) + { + XmlElementWrapper w = a.getAnnotation(XmlElementWrapper.class); + if (w != null) { + return w.nillable() ? JsonSerialize.Inclusion.ALWAYS : JsonSerialize.Inclusion.NON_NULL; + } + XmlElement e = a.getAnnotation(XmlElement.class); + if (e != null) { + return e.nillable() ? JsonSerialize.Inclusion.ALWAYS : JsonSerialize.Inclusion.NON_NULL; + } + /* [JACKSON-256]: better pass default value through, if no explicit direction indicating + * otherwise + */ + return defValue; + } + + @Override + public JsonSerialize.Typing findSerializationTyping(Annotated a) + { + return null; + } + + @Override + public Class<?>[] findSerializationViews(Annotated a) + { + // no JAXB annotations for views (can use different schemas) + return null; + } + + /* + /********************************************************** + /* Serialization: class annotations + /********************************************************** + */ + + @Override + public String[] findSerializationPropertyOrder(AnnotatedClass ac) + { + // @XmlType.propOrder fits the bill here: + XmlType type = findAnnotation(XmlType.class, ac, true, true, true); + if (type == null) { + return null; + } + String[] order = type.propOrder(); + if (order == null || order.length == 0) { + return null; + } + return order; + } + + @Override + public Boolean findSerializationSortAlphabetically(AnnotatedClass ac) { + // Yup, XmlAccessorOrder can provide this... + XmlAccessorOrder order = findAnnotation(XmlAccessorOrder.class, ac, true, true, true); + return (order == null) ? null : (order.value() == XmlAccessOrder.ALPHABETICAL); + } + + /* + /********************************************************** + /* Serialization: method annotations + /********************************************************** + */ + + @Override + public String findGettablePropertyName(AnnotatedMethod am) + { + if (!isVisible(am)) { + return null; + } + String name = findJaxbPropertyName(am, am.getRawType(), + BeanUtil.okNameForGetter(am)); + if (name == null) { + } + return name; + } + + @Override + public boolean hasAsValueAnnotation(AnnotatedMethod am) + { + //since jaxb says @XmlValue can exist with attributes, this won't map as a JSON value. + return false; + } + + /** + *<p> + * !!! 12-Oct-2009, tatu: This is hideously slow implementation, + * called potentially for every single enum value being + * serialized. Should improve... + */ + @Override + public String findEnumValue(Enum<?> e) + { + Class<?> enumClass = e.getDeclaringClass(); + String enumValue = e.name(); + try { + XmlEnumValue xmlEnumValue = enumClass.getDeclaredField(enumValue).getAnnotation(XmlEnumValue.class); + return (xmlEnumValue != null) ? xmlEnumValue.value() : enumValue; + } catch (NoSuchFieldException e1) { + throw new IllegalStateException("Could not locate Enum entry '"+enumValue+"' (Enum class "+enumClass.getName()+")", e1); + } + } + + /* + /********************************************************** + /* Serialization: field annotations + /********************************************************** + */ + + @Override + public String findSerializablePropertyName(AnnotatedField af) + { + if (!isVisible(af)) { + return null; + } + String name = findJaxbPropertyName(af, af.getRawType(), null); + /* This may seem wrong, but since JAXB field auto-detection + * needs to find even non-public fields (if enabled by + * JAXB access type), we need to return name like so: + */ + return (name == null) ? af.getName() : name; + } + + /* + /********************************************************** + /* Deserialization: general annotations + /********************************************************** + */ + + @Override + public JsonDeserializer<?> findDeserializer(Annotated am) + { + XmlAdapter<Object,Object> adapter = findAdapter(am, false); + if (adapter != null) { + return new XmlAdapterJsonDeserializer(adapter); + } + + /* [JACKSON-150]: add support for additional core XML + * types needed by JAXB + */ + Class<?> type = am.getRawType(); + if (type != null) { + if (_dataHandlerDeserializer != null && isDataHandler(type)) { + return _dataHandlerDeserializer; + } + } + + return null; + } + + @Override + public Class<KeyDeserializer> findKeyDeserializer(Annotated am) + { + // Is there something like this in JAXB? + return null; + } + + @Override + public Class<JsonDeserializer<?>> findContentDeserializer(Annotated am) + { + // Is there something like this in JAXB? + return null; + } + + /** + * JAXB does allow specifying (more) concrete class for + * deserialization by using \@XmlElement annotation. + */ + @Override + public Class<?> findDeserializationType(Annotated a, JavaType baseType, String propName) + { + /* First: only applicable for non-structured types (yes, JAXB annotations + * are tricky) + */ + if (!baseType.isContainerType()) { + return _doFindDeserializationType(a, baseType, propName); + } + return null; + } + + @Override + public Class<?> findDeserializationKeyType(Annotated am, JavaType baseKeyType, + String propName) + { + return null; + } + + @Override + public Class<?> findDeserializationContentType(Annotated a, JavaType baseContentType, String propName) + { + /* 15-Feb-2010, tatus: JAXB usage of XmlElement/XmlElements is really + * confusing: sometimes it's for type (non-container types), sometimes for + * contents (container) types. I guess it's frugal to reuse these... but + * I think it's rather short-sighted. Whatever, it is what it is, and here + * we are being given content type explicitly. + */ + return _doFindDeserializationType(a, baseContentType, propName); + } + + protected Class<?> _doFindDeserializationType(Annotated a, JavaType baseType, String propName) + { + /* As per [JACKSON-288], @XmlJavaTypeAdapter will complicate handling of type + * information; basically we better just ignore type we might find here altogether + * in that case + */ + if (a.hasAnnotation(XmlJavaTypeAdapter.class)) { + return null; + } + + /* false for class, package, super-class, since annotation can + * only be attached to fields and methods + */ + XmlElement annotation = findAnnotation(XmlElement.class, a, false, false, false); + if (annotation != null) { + Class<?> type = annotation.type(); + if (type != XmlElement.DEFAULT.class) { + return type; + } + } + /* 16-Feb-2010, tatu: May also have annotation associated with field, not method + * itself... and findAnnotation() won't find that (nor property descriptor) + */ + if ((a instanceof AnnotatedMethod) && propName != null) { + AnnotatedMethod am = (AnnotatedMethod) a; + annotation = this.findFieldAnnotation(XmlElement.class, am.getDeclaringClass(), propName); + if (annotation != null && annotation.type() != XmlElement.DEFAULT.class) { + return annotation.type(); + } + } + return null; + } + + @Override + public String findSettablePropertyName(AnnotatedMethod am) + { + if (!isVisible(am)) { + return null; + } + Class<?> rawType = am.getParameterClass(0); + String name = findJaxbPropertyName(am, rawType, BeanUtil.okNameForSetter(am)); + return name; + } + + @Override + public boolean hasAnySetterAnnotation(AnnotatedMethod am) + { + //(ryan) JAXB has @XmlAnyAttribute and @XmlAnyElement annotations, but they're not applicable in this case + // because JAXB says those annotations are only applicable to methods with specific signatures + // that Jackson doesn't support (Jackson's any setter needs 2 arguments, name and value, whereas + // JAXB expects use of Map + return false; + } + + @Override + public boolean hasCreatorAnnotation(Annotated am) + { + return false; + } + + @Override + public String findDeserializablePropertyName(AnnotatedField af) + { + if (!isVisible(af)) { + return null; + } + String name = findJaxbPropertyName(af, af.getRawType(), null); + /* This may seem wrong, but since JAXB field auto-detection + * needs to find even non-public fields (if enabled by + * JAXB access type), we need to return name like so: + */ + return (name == null) ? af.getName() : name; + } + + /* + /********************************************************** + /* Deserialization: parameters annotations + /********************************************************** + */ + + @Override + public String findPropertyNameForParam(AnnotatedParameter param) + { + // JAXB has nothing like this... + return null; + } + + /* + /********************************************************** + /* Helper methods (non-API) + /********************************************************** + */ + + /** + * Whether the specified field is invisible, per the JAXB visibility rules. + * + * @param f The field. + * @return Whether the field is invisible. + */ + private boolean isVisible(AnnotatedField f) + { + // TODO: use AnnotatedField's annotations directly + for (Annotation annotation : f.getAnnotated().getDeclaredAnnotations()) { + if (isHandled(annotation)) { + return true; + } + } + XmlAccessType accessType = XmlAccessType.PUBLIC_MEMBER; + XmlAccessorType at = findAnnotation(XmlAccessorType.class, f, true, true, true); + if (at != null) { + accessType = at.value(); + } + if (accessType == XmlAccessType.FIELD) { + return true; + } + if (accessType == XmlAccessType.PUBLIC_MEMBER) { + return Modifier.isPublic(f.getAnnotated().getModifiers()); + } + return false; + } + + private boolean isVisible(AnnotatedMethod m) + { + // TODO: use AnnotatedField's annotations directly + for (Annotation annotation : m.getAnnotated().getDeclaredAnnotations()) { + if (isHandled(annotation)) { + return true; + } + } + XmlAccessType accessType = XmlAccessType.PUBLIC_MEMBER; + XmlAccessorType at = findAnnotation(XmlAccessorType.class, m, true, true, true); + if (at != null) { + accessType = at.value(); + } + if (accessType == XmlAccessType.PROPERTY || accessType == XmlAccessType.PUBLIC_MEMBER) { + return Modifier.isPublic(m.getModifiers()); + } + return false; + } + + /** + * Finds an annotation associated with given annotatable thing; or if + * not found, a default annotation it may have (from super class, package + * and so on) + * + * @param annotationClass the annotation class. + * @param annotated The annotated element. + * @param includePackage Whether the annotation can be found on the package of the annotated element. + * @param includeClass Whether the annotation can be found on the class of the annotated element. + * @param includeSuperclasses Whether the annotation can be found on any superclasses of the class of the annotated element. + * @return The annotation, or null if not found. + */ + protected <A extends Annotation> A findAnnotation(Class<A> annotationClass, Annotated annotated, + boolean includePackage, boolean includeClass, boolean includeSuperclasses) + { + A annotation = annotated.getAnnotation(annotationClass); + if (annotation != null) { + return annotation; + } + Class<?> memberClass = null; + /* 13-Feb-2011, tatu: [JACKSON-495] - need to handle AnnotatedParameter + * bit differently, since there is no JDK counterpart. We can still + * access annotations directly, just using different calls. + */ + if (annotated instanceof AnnotatedParameter) { + memberClass = ((AnnotatedParameter) annotated).getDeclaringClass(); + } else { + AnnotatedElement annType = annotated.getAnnotated(); + if (annType instanceof Member) { + memberClass = ((Member) annType).getDeclaringClass(); + if (includeClass) { + annotation = (A) memberClass.getAnnotation(annotationClass); + if (annotation != null) { + return annotation; + } + } + } else if (annType instanceof Class<?>) { + memberClass = (Class<?>) annType; + } else { + throw new IllegalStateException("Unsupported annotated member: " + annotated.getClass().getName()); + } + } + if (memberClass != null) { + if (includeSuperclasses) { + Class<?> superclass = memberClass.getSuperclass(); + while (superclass != null && superclass != Object.class) { + annotation = (A) superclass.getAnnotation(annotationClass); + if (annotation != null) { + return annotation; + } + superclass = superclass.getSuperclass(); + } + } + if (includePackage) { + Package pkg = memberClass.getPackage(); + if (pkg != null) { + return memberClass.getPackage().getAnnotation(annotationClass); + } + } + } + return null; + } + + /** + * Helper method for locating field on given class, checking if + * it has specified annotation, and returning it if found. + * + * @since 1.5 + */ + private <A extends Annotation> A findFieldAnnotation(Class<A> annotationType, + Class<?> cls, String fieldName) + { + do { + for (Field f : cls.getDeclaredFields()) { + if (fieldName.equals(f.getName())) { + return f.getAnnotation(annotationType); + } + } + if (cls.isInterface() || cls == Object.class) { + break; + } + cls = cls.getSuperclass(); + } while (cls != null); + return null; + } + + /* + /********************************************************** + /* Helper methods for bean property introspection + /********************************************************** + */ + + private static String findJaxbPropertyName(Annotated ae, Class<?> aeType, String defaultName) + { + XmlElementWrapper elementWrapper = ae.getAnnotation(XmlElementWrapper.class); + if (elementWrapper != null) { + String name = elementWrapper.name(); + if (!MARKER_FOR_DEFAULT.equals(name)) { + return name; + } + return defaultName; + } + + XmlAttribute attribute = ae.getAnnotation(XmlAttribute.class); + if (attribute != null) { + String name = attribute.name(); + if (!MARKER_FOR_DEFAULT.equals(name)) { + return name; + } + return defaultName; + } + XmlElement element = ae.getAnnotation(XmlElement.class); + if (element != null) { + String name = element.name(); + if (!MARKER_FOR_DEFAULT.equals(name)) { + return name; + } + return defaultName; + } + XmlElementRef elementRef = ae.getAnnotation(XmlElementRef.class); + if (elementRef != null) { + String name = elementRef.name(); + if (!MARKER_FOR_DEFAULT.equals(name)) { + return name; + } + if (aeType != null) { + XmlRootElement rootElement = (XmlRootElement) aeType.getAnnotation(XmlRootElement.class); + if (rootElement != null) { + name = rootElement.name(); + if (!MARKER_FOR_DEFAULT.equals(name)) { + return name; + } + return Introspector.decapitalize(aeType.getSimpleName()); + } + } + } + + XmlValue valueInfo = ae.getAnnotation(XmlValue.class); + if (valueInfo != null) { + return "value"; + } + + return null; + } + + private XmlRootElement findRootElementAnnotation(AnnotatedClass ac) + { + // Yes, check package, no class (already included), yes superclasses + return findAnnotation(XmlRootElement.class, ac, true, false, true); + } + + /** + * Finds the XmlAdapter for the specified annotation. + * + * @param am The annotated element. + * @param forSerialization If true, adapter for serialization; if false, for deserialization + * + * @return The adapter, or null if none. + */ + private XmlAdapter<Object,Object> findAdapter(Annotated am, boolean forSerialization) + { + // First of all, are we looking for annotations for class? + if (am instanceof AnnotatedClass) { + return findAdapterForClass((AnnotatedClass) am, forSerialization); + } + // Otherwise for a member. First, let's figure out type of property + Class<?> memberType = am.getRawType(); + // ok; except for setters... + if (memberType == Void.TYPE && (am instanceof AnnotatedMethod)) { + memberType = ((AnnotatedMethod) am).getParameterClass(0); + } + + // 09-Nov-2010, tatu: Not quite sure why we are to check declaring class... but that's how code was: + Member member = (Member) am.getAnnotated(); + // [JACKSON-495]: Will be null for AnnotatedParam -- note, probably should find declaring class for it; won't for now + if (member != null) { + Class<?> potentialAdaptee = member.getDeclaringClass(); + if (potentialAdaptee != null) { + XmlJavaTypeAdapter adapterInfo = (XmlJavaTypeAdapter) potentialAdaptee.getAnnotation(XmlJavaTypeAdapter.class); + if (adapterInfo != null) { // should we try caching this? + XmlAdapter<Object,Object> adapter = checkAdapter(adapterInfo, memberType); + if (adapter != null) { + return adapter; + } + } + } + } + + XmlJavaTypeAdapter adapterInfo = findAnnotation(XmlJavaTypeAdapter.class, am, true, false, false); + if (adapterInfo != null) { + XmlAdapter<Object,Object> adapter = checkAdapter(adapterInfo, memberType); + if (adapter != null) { + return adapter; + } + } + XmlJavaTypeAdapters adapters = findAnnotation(XmlJavaTypeAdapters.class, am, true, false, false); + if (adapters != null) { + for (XmlJavaTypeAdapter info : adapters.value()) { + XmlAdapter<Object,Object> adapter = checkAdapter(info, memberType); + if (adapter != null) { + return adapter; + } + } + } + return null; + } + + @SuppressWarnings("unchecked") + private final XmlAdapter<Object,Object> checkAdapter(XmlJavaTypeAdapter adapterInfo, Class<?> typeNeeded) + { + // if annotation has no type, it's applicable; if it has, must match + Class<?> adaptedType = adapterInfo.type(); + if (adaptedType == XmlJavaTypeAdapter.DEFAULT.class + || adaptedType.isAssignableFrom(typeNeeded)) { + @SuppressWarnings("rawtypes") + Class<? extends XmlAdapter> cls = adapterInfo.value(); + return ClassUtil.createInstance(cls, false); + } + return null; + } + + @SuppressWarnings("unchecked") + private XmlAdapter<Object,Object> findAdapterForClass(AnnotatedClass ac, boolean forSerialization) + { + /* As per [JACKSON-411], XmlJavaTypeAdapter should not be inherited from super-class. + * It would still be nice to be able to use mix-ins; but unfortunately we seem to lose + * knowledge of class that actually declared the annotation. Thus, we'll only accept + * declaration from specific class itself. + */ + XmlJavaTypeAdapter adapterInfo = ac.getAnnotated().getAnnotation(XmlJavaTypeAdapter.class); + if (adapterInfo != null) { // should we try caching this? + @SuppressWarnings("rawtypes") + Class<? extends XmlAdapter> cls = adapterInfo.value(); + return ClassUtil.createInstance(cls, false); + } + return null; + } + + /** + * Helper method used to distinguish structured type, which with JAXB use different + * rules for defining content types. + */ + private boolean isIndexedType(Class<?> raw) + { + return raw.isArray() || Collection.class.isAssignableFrom(raw) + || Map.class.isAssignableFrom(raw); + } +}
diff --git a/1.9.10/src/xc/java/org/codehaus/jackson/xc/XmlAdapterJsonDeserializer.java b/1.9.10/src/xc/java/org/codehaus/jackson/xc/XmlAdapterJsonDeserializer.java new file mode 100644 index 0000000..2a5bd97 --- /dev/null +++ b/1.9.10/src/xc/java/org/codehaus/jackson/xc/XmlAdapterJsonDeserializer.java
@@ -0,0 +1,75 @@ +package org.codehaus.jackson.xc; + +import java.io.IOException; +import javax.xml.bind.annotation.adapters.XmlAdapter; + +import org.codehaus.jackson.JsonParser; +import org.codehaus.jackson.JsonProcessingException; +import org.codehaus.jackson.map.*; +import org.codehaus.jackson.map.deser.std.StdDeserializer; +import org.codehaus.jackson.map.type.TypeFactory; +import org.codehaus.jackson.type.JavaType; + +/** + * @author Ryan Heaton + * @author Tatu Saloranta + */ +public class XmlAdapterJsonDeserializer + extends StdDeserializer<Object> +{ + protected final static JavaType ADAPTER_TYPE = TypeFactory.defaultInstance().uncheckedSimpleType(XmlAdapter.class); + + protected final XmlAdapter<Object,Object> _xmlAdapter; + protected final JavaType _valueType; + + protected JsonDeserializer<?> _deserializer; + + public XmlAdapterJsonDeserializer(XmlAdapter<Object,Object> xmlAdapter) + { + super(Object.class); // type not yet known (will be in a second), but that's ok... + _xmlAdapter = xmlAdapter; + // [JACKSON-404] Need to figure out generic type parameters used... + /* 14-Mar-2011, tatu: This is sub-optimal, as we really should use + * configured TypeFactory, not global one; but it should not cause + * issues here (issue would be that it will ignore module-provided additional + * type manging, most relevant for languages other than Java) + */ + TypeFactory typeFactory = TypeFactory.defaultInstance(); + + JavaType type = typeFactory.constructType(xmlAdapter.getClass()); + JavaType[] rawTypes = typeFactory.findTypeParameters(type, XmlAdapter.class); + _valueType = (rawTypes == null || rawTypes.length == 0) + ? TypeFactory.unknownType() : rawTypes[0]; + } + + @Override + public Object deserialize(JsonParser jp, DeserializationContext ctxt) + throws IOException, JsonProcessingException + { + /* Unfortunately we can not use the usual resolution mechanism (ResolvableDeserializer) + * because it won't get called due to way adapters are created. So, need to do it + * lazily when we get here: + */ + JsonDeserializer<?> deser = _deserializer; + if (deser == null) { + DeserializationConfig config = ctxt.getConfig(); + _deserializer = deser = ctxt.getDeserializerProvider().findValueDeserializer + (config, _valueType, null); + } + Object boundObject = deser.deserialize(jp, ctxt); + try { + return _xmlAdapter.unmarshal(boundObject); + } catch (Exception e) { + throw new JsonMappingException("Unable to unmarshal (to type "+_valueType+"): "+e.getMessage(), e); + } + } + + @Override + public Object deserializeWithType(JsonParser jp, DeserializationContext ctxt, + TypeDeserializer typeDeserializer) + throws IOException, JsonProcessingException + { + // Output can be as JSON Object, Array or scalar: no way to know a priori. So: + return typeDeserializer.deserializeTypedFromAny(jp, ctxt); + } +}
diff --git a/1.9.10/src/xc/java/org/codehaus/jackson/xc/XmlAdapterJsonSerializer.java b/1.9.10/src/xc/java/org/codehaus/jackson/xc/XmlAdapterJsonSerializer.java new file mode 100644 index 0000000..17ee82d --- /dev/null +++ b/1.9.10/src/xc/java/org/codehaus/jackson/xc/XmlAdapterJsonSerializer.java
@@ -0,0 +1,72 @@ +package org.codehaus.jackson.xc; + +import java.io.IOException; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; + +import javax.xml.bind.annotation.adapters.XmlAdapter; + +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.JsonNode; +import org.codehaus.jackson.schema.SchemaAware; +import org.codehaus.jackson.schema.JsonSchema; +import org.codehaus.jackson.map.JsonMappingException; +import org.codehaus.jackson.map.JsonSerializer; +import org.codehaus.jackson.map.SerializerProvider; +import org.codehaus.jackson.map.ser.std.SerializerBase; + +/** + * @author Ryan Heaton + */ +public class XmlAdapterJsonSerializer extends SerializerBase<Object> + implements SchemaAware +{ + private final XmlAdapter<Object,Object> xmlAdapter; + + public XmlAdapterJsonSerializer(XmlAdapter<Object,Object> xmlAdapter) + { + super(Object.class); + this.xmlAdapter = xmlAdapter; + } + + @Override + public void serialize(Object value, JsonGenerator jgen, SerializerProvider provider) + throws IOException + { + Object adapted; + try { + adapted = this.xmlAdapter.marshal(value); + } catch (Exception e) { + throw new JsonMappingException("Unable to marshal: "+e.getMessage(), e); + } + if (adapted == null) { + provider.getNullValueSerializer().serialize(null, jgen, provider); + } else { + Class<?> c = adapted.getClass(); + // true -> do cache for future lookups + provider.findTypedValueSerializer(c, true, null).serialize(adapted, jgen, provider); + } + } + + @Override + public JsonNode getSchema(SerializerProvider provider, Type typeHint) + throws JsonMappingException + { + // no type resolver needed for schema + JsonSerializer<Object> ser = provider.findValueSerializer(findValueClass(), null); + JsonNode schemaNode = (ser instanceof SchemaAware) ? + ((SchemaAware) ser).getSchema(provider, null) : + JsonSchema.getDefaultSchemaNode(); + return schemaNode; + } + + private Class<?> findValueClass() + { + Type superClass = this.xmlAdapter.getClass().getGenericSuperclass(); + while (superClass instanceof ParameterizedType && XmlAdapter.class != ((ParameterizedType)superClass).getRawType()) { + superClass = ((Class<?>) ((ParameterizedType) superClass).getRawType()).getGenericSuperclass(); + } + return (Class<?>) ((ParameterizedType) superClass).getActualTypeArguments()[0]; + } + +}
diff --git a/1.9.10/src/xc/java/org/codehaus/jackson/xc/package-info.java b/1.9.10/src/xc/java/org/codehaus/jackson/xc/package-info.java new file mode 100644 index 0000000..42666b8 --- /dev/null +++ b/1.9.10/src/xc/java/org/codehaus/jackson/xc/package-info.java
@@ -0,0 +1,5 @@ +/** + * Package that contains XML Compatibility functionality for Jackson, such + * as handlers for JAXB annotations + */ +package org.codehaus.jackson.xc;