From 31fc1185a9d96e763d4f9dac61f073da6e3ccdb3 Mon Sep 17 00:00:00 2001 From: Trudu Laurent Date: Fri, 9 Jul 2021 15:59:56 +0200 Subject: [PATCH] Fiest Commit --- .gitignore | 9 + .idea/.gitignore | 3 + .idea/compiler.xml | 6 + .idea/gradle.xml | 19 + .idea/jarRepositories.xml | 25 + .idea/misc.xml | 14 + .idea/modules.xml | 9 + .idea/runConfigurations.xml | 10 + .idea/vcs.xml | 6 + README.md | 45 + build.gradle | 33 + datawedgeprofileintentswrapper/build.gradle | 135 ++ .../proguard-rules.pro | 21 + .../ExampleInstrumentedTest.java | 26 + .../src/main/AndroidManifest.xml | 2 + .../gson285/DefaultDateTypeAdapter.java | 165 ++ .../com/google/gson285/ExclusionStrategy.java | 109 ++ .../com/google/gson285/FieldAttributes.java | 161 ++ .../com/google/gson285/FieldNamingPolicy.java | 189 ++ .../google/gson285/FieldNamingStrategy.java | 40 + .../main/java/com/google/gson285/Gson.java | 1031 +++++++++++ .../java/com/google/gson285/GsonBuilder.java | 627 +++++++ .../com/google/gson285/InstanceCreator.java | 92 + .../java/com/google/gson285/JsonArray.java | 384 ++++ .../gson285/JsonDeserializationContext.java | 44 + .../com/google/gson285/JsonDeserializer.java | 91 + .../java/com/google/gson285/JsonElement.java | 335 ++++ .../com/google/gson285/JsonIOException.java | 45 + .../java/com/google/gson285/JsonNull.java | 67 + .../java/com/google/gson285/JsonObject.java | 218 +++ .../google/gson285/JsonParseException.java | 64 + .../java/com/google/gson285/JsonParser.java | 93 + .../com/google/gson285/JsonPrimitive.java | 345 ++++ .../gson285/JsonSerializationContext.java | 49 + .../com/google/gson285/JsonSerializer.java | 89 + .../com/google/gson285/JsonStreamParser.java | 122 ++ .../google/gson285/JsonSyntaxException.java | 47 + .../src/main/java/com/google/gson285/LICENSE | 206 +++ .../gson285/LongSerializationPolicy.java | 58 + .../main/java/com/google/gson285/README.md | 72 + .../java/com/google/gson285/TypeAdapter.java | 290 +++ .../google/gson285/TypeAdapterFactory.java | 170 ++ .../google/gson285/annotations/Expose.java | 81 + .../gson285/annotations/JsonAdapter.java | 104 ++ .../gson285/annotations/SerializedName.java | 93 + .../com/google/gson285/annotations/Since.java | 63 + .../com/google/gson285/annotations/Until.java | 68 + .../gson285/annotations/package-info.java | 6 + .../gson285/internal/$Gson$Preconditions.java | 49 + .../google/gson285/internal/$Gson$Types.java | 610 +++++++ .../internal/ConstructorConstructor.java | 238 +++ .../com/google/gson285/internal/Excluder.java | 260 +++ .../gson285/internal/GsonBuildConfig.java | 32 + .../google/gson285/internal/JavaVersion.java | 92 + .../internal/JsonReaderInternalAccess.java | 32 + .../gson285/internal/LazilyParsedNumber.java | 96 + .../gson285/internal/LinkedHashTreeMap.java | 864 +++++++++ .../gson285/internal/LinkedTreeMap.java | 630 +++++++ .../gson285/internal/ObjectConstructor.java | 33 + .../internal/PreJava9DateFormatProvider.java | 86 + .../google/gson285/internal/Primitives.java | 119 ++ .../com/google/gson285/internal/Streams.java | 120 ++ .../gson285/internal/UnsafeAllocator.java | 123 ++ .../internal/bind/ArrayTypeAdapter.java | 99 + .../bind/CollectionTypeAdapterFactory.java | 102 ++ .../internal/bind/DateTypeAdapter.java | 101 + ...onAdapterAnnotationTypeAdapterFactory.java | 83 + .../gson285/internal/bind/JsonTreeReader.java | 320 ++++ .../gson285/internal/bind/JsonTreeWriter.java | 208 +++ .../internal/bind/MapTypeAdapterFactory.java | 264 +++ .../internal/bind/ObjectTypeAdapter.java | 109 ++ .../bind/ReflectiveTypeAdapterFactory.java | 254 +++ .../internal/bind/SqlDateTypeAdapter.java | 67 + .../internal/bind/TimeTypeAdapter.java | 66 + .../internal/bind/TreeTypeAdapter.java | 165 ++ .../bind/TypeAdapterRuntimeTypeWrapper.java | 82 + .../gson285/internal/bind/TypeAdapters.java | 908 +++++++++ .../internal/bind/util/ISO8601Utils.java | 352 ++++ .../google/gson285/internal/package-info.java | 7 + .../reflect/PreJava9ReflectionAccessor.java | 33 + .../internal/reflect/ReflectionAccessor.java | 54 + .../reflect/UnsafeReflectionAccessor.java | 86 + .../java/com/google/gson285/package-info.java | 11 + .../com/google/gson285/reflect/TypeToken.java | 320 ++++ .../google/gson285/reflect/package-info.java | 6 + .../com/google/gson285/stream/JsonReader.java | 1617 +++++++++++++++++ .../com/google/gson285/stream/JsonScope.java | 71 + .../com/google/gson285/stream/JsonToken.java | 85 + .../com/google/gson285/stream/JsonWriter.java | 659 +++++++ .../stream/MalformedJsonException.java | 44 + .../BDF_E_OUTPUT_PLUGIN.java | 19 + .../DWScannerConfigEnumsHelper.java | 31 + .../datawedgeprofileenums/INT_E_DELIVERY.java | 19 + .../KEY_E_ACTION_CHAR.java | 20 + .../MB_E_CONFIG_MODE.java | 19 + ...C_E_1D_MARGINLESS_DECODE_EFFORT_LEVEL.java | 20 + .../datawedgeprofileenums/SC_E_AIM_MODE.java | 18 + .../datawedgeprofileenums/SC_E_AIM_TYPE.java | 22 + .../SC_E_CHARSET_NAME.java | 19 + .../SC_E_CODE11_VERIFY_CHECK_DIGIT.java | 20 + .../SC_E_CODE_ID_TYPE.java | 19 + .../SC_E_CONCAT_MODE.java | 19 + .../SC_E_I2OF5_CHECK_DIGIT.java | 19 + .../SC_E_ILLUMINATION_MODE.java | 18 + .../datawedgeprofileenums/SC_E_INVERSE.java | 19 + .../SC_E_INVERSE1DMODE_MODE.java | 19 + .../datawedgeprofileenums/SC_E_LCD_MODE.java | 18 + .../SC_E_LINEAR_SECURITY_LEVEL.java | 20 + .../datawedgeprofileenums/SC_E_LINK_MODE.java | 19 + .../SC_E_MSI_CHECK_DIGIT.java | 18 + .../SC_E_MSI_CHECK_DIGIT_SCHEME.java | 19 + .../SC_E_PICKLIST_MODE.java | 20 + .../SC_E_POOR_QUALITY_DECODE_LEVEL.java | 20 + .../datawedgeprofileenums/SC_E_PREAMBLE.java | 19 + .../SC_E_SCANNER_IDENTIFIER.java | 62 + .../SC_E_SCANNINGMODE.java | 24 + .../SC_E_SECURITY_LEVEL.java | 20 + .../SC_E_UPCEAN_BOOKLAND_FORMAT.java | 17 + .../SC_E_UPCEAN_COUPON_REPORT.java | 18 + .../SC_E_UPCEAN_SECURITY_LEVEL.java | 19 + .../SC_E_UPCEAN_SUPPLEMENTAL_MODE.java | 24 + .../SC_E_VOLUME_SLIDER_TYPE.java | 21 + .../DWDataWedgeDisable.java | 28 + .../DWDataWedgeEnable.java | 28 + .../DWEnumerateScanners.java | 153 ++ .../DWEnumerateScannersSettings.java | 4 + .../DWProfileBase.java | 94 + .../DWProfileBaseSettings.java | 67 + .../DWProfileChecker.java | 132 ++ .../DWProfileCheckerSettings.java | 4 + .../DWProfileCommandBase.java | 209 +++ .../DWProfileCreate.java | 37 + .../DWProfileCreateSettings.java | 4 + .../DWProfileDelete.java | 37 + .../DWProfileDeleteSettings.java | 4 + .../DWProfileSetConfig.java | 110 ++ .../DWProfileSetConfigSettings.java | 67 + .../DWProfileSwitchBarcodeParams.java | 28 + .../DWProfileSwitchBarcodeParamsSettings.java | 47 + .../DWScanReceiver.java | 230 +++ .../DWScannerPluginDisable.java | 29 + .../DWScannerPluginEnable.java | 29 + .../DWScannerStartScan.java | 29 + .../DWScannerStopScan.java | 29 + .../DWScannerToggleScan.java | 29 + .../DWStatusScanner.java | 117 ++ .../DWStatusScannerCallback.java | 5 + .../DWStatusScannerSettings.java | 13 + .../DWSynchronousMethods.java | 652 +++++++ .../DWSynchronousMethodsNT.java | 235 +++ .../DataWedgeConstants.java | 134 ++ .../SettingsPlugins/BaseSettings.java | 14 + .../SettingsPlugins/MainBundle.java | 31 + .../PluginBasicDataFormatting.java | 85 + .../SettingsPlugins/PluginIntent.java | 83 + .../SettingsPlugins/PluginKeystroke.java | 59 + .../SettingsPlugins/PluginScanner.java | 655 +++++++ .../SignatureCheck.java | 55 + .../src/main/res/values/strings.xml | 3 + .../ExampleUnitTest.java | 17 + gradle.properties | 18 + gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 53636 bytes gradle/wrapper/gradle-wrapper.properties | 6 + gradlew | 160 ++ gradlew.bat | 90 + settings.gradle | 1 + 166 files changed, 20077 insertions(+) create mode 100644 .gitignore create mode 100644 .idea/.gitignore create mode 100644 .idea/compiler.xml create mode 100644 .idea/gradle.xml create mode 100644 .idea/jarRepositories.xml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/runConfigurations.xml create mode 100644 .idea/vcs.xml create mode 100644 README.md create mode 100644 build.gradle create mode 100644 datawedgeprofileintentswrapper/build.gradle create mode 100644 datawedgeprofileintentswrapper/proguard-rules.pro create mode 100644 datawedgeprofileintentswrapper/src/androidTest/java/com/zebra/datawedgeprofileintents/ExampleInstrumentedTest.java create mode 100644 datawedgeprofileintentswrapper/src/main/AndroidManifest.xml create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/DefaultDateTypeAdapter.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/ExclusionStrategy.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/FieldAttributes.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/FieldNamingPolicy.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/FieldNamingStrategy.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/Gson.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/GsonBuilder.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/InstanceCreator.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/JsonArray.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/JsonDeserializationContext.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/JsonDeserializer.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/JsonElement.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/JsonIOException.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/JsonNull.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/JsonObject.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/JsonParseException.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/JsonParser.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/JsonPrimitive.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/JsonSerializationContext.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/JsonSerializer.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/JsonStreamParser.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/JsonSyntaxException.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/LICENSE create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/LongSerializationPolicy.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/README.md create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/TypeAdapter.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/TypeAdapterFactory.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/annotations/Expose.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/annotations/JsonAdapter.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/annotations/SerializedName.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/annotations/Since.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/annotations/Until.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/annotations/package-info.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/$Gson$Preconditions.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/$Gson$Types.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/ConstructorConstructor.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/Excluder.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/GsonBuildConfig.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/JavaVersion.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/JsonReaderInternalAccess.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/LazilyParsedNumber.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/LinkedHashTreeMap.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/LinkedTreeMap.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/ObjectConstructor.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/PreJava9DateFormatProvider.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/Primitives.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/Streams.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/UnsafeAllocator.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/bind/ArrayTypeAdapter.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/bind/CollectionTypeAdapterFactory.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/bind/DateTypeAdapter.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/bind/JsonAdapterAnnotationTypeAdapterFactory.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/bind/JsonTreeReader.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/bind/JsonTreeWriter.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/bind/MapTypeAdapterFactory.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/bind/ObjectTypeAdapter.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/bind/ReflectiveTypeAdapterFactory.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/bind/SqlDateTypeAdapter.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/bind/TimeTypeAdapter.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/bind/TreeTypeAdapter.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/bind/TypeAdapterRuntimeTypeWrapper.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/bind/TypeAdapters.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/bind/util/ISO8601Utils.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/package-info.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/reflect/PreJava9ReflectionAccessor.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/reflect/ReflectionAccessor.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/reflect/UnsafeReflectionAccessor.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/package-info.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/reflect/TypeToken.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/reflect/package-info.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/stream/JsonReader.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/stream/JsonScope.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/stream/JsonToken.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/stream/JsonWriter.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/google/gson285/stream/MalformedJsonException.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileenums/BDF_E_OUTPUT_PLUGIN.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileenums/DWScannerConfigEnumsHelper.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileenums/INT_E_DELIVERY.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileenums/KEY_E_ACTION_CHAR.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileenums/MB_E_CONFIG_MODE.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileenums/SC_E_1D_MARGINLESS_DECODE_EFFORT_LEVEL.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileenums/SC_E_AIM_MODE.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileenums/SC_E_AIM_TYPE.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileenums/SC_E_CHARSET_NAME.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileenums/SC_E_CODE11_VERIFY_CHECK_DIGIT.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileenums/SC_E_CODE_ID_TYPE.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileenums/SC_E_CONCAT_MODE.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileenums/SC_E_I2OF5_CHECK_DIGIT.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileenums/SC_E_ILLUMINATION_MODE.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileenums/SC_E_INVERSE.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileenums/SC_E_INVERSE1DMODE_MODE.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileenums/SC_E_LCD_MODE.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileenums/SC_E_LINEAR_SECURITY_LEVEL.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileenums/SC_E_LINK_MODE.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileenums/SC_E_MSI_CHECK_DIGIT.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileenums/SC_E_MSI_CHECK_DIGIT_SCHEME.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileenums/SC_E_PICKLIST_MODE.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileenums/SC_E_POOR_QUALITY_DECODE_LEVEL.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileenums/SC_E_PREAMBLE.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileenums/SC_E_SCANNER_IDENTIFIER.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileenums/SC_E_SCANNINGMODE.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileenums/SC_E_SECURITY_LEVEL.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileenums/SC_E_UPCEAN_BOOKLAND_FORMAT.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileenums/SC_E_UPCEAN_COUPON_REPORT.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileenums/SC_E_UPCEAN_SECURITY_LEVEL.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileenums/SC_E_UPCEAN_SUPPLEMENTAL_MODE.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileenums/SC_E_VOLUME_SLIDER_TYPE.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileintents/DWDataWedgeDisable.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileintents/DWDataWedgeEnable.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileintents/DWEnumerateScanners.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileintents/DWEnumerateScannersSettings.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileintents/DWProfileBase.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileintents/DWProfileBaseSettings.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileintents/DWProfileChecker.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileintents/DWProfileCheckerSettings.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileintents/DWProfileCommandBase.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileintents/DWProfileCreate.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileintents/DWProfileCreateSettings.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileintents/DWProfileDelete.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileintents/DWProfileDeleteSettings.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileintents/DWProfileSetConfig.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileintents/DWProfileSetConfigSettings.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileintents/DWProfileSwitchBarcodeParams.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileintents/DWProfileSwitchBarcodeParamsSettings.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileintents/DWScanReceiver.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileintents/DWScannerPluginDisable.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileintents/DWScannerPluginEnable.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileintents/DWScannerStartScan.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileintents/DWScannerStopScan.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileintents/DWScannerToggleScan.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileintents/DWStatusScanner.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileintents/DWStatusScannerCallback.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileintents/DWStatusScannerSettings.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileintents/DWSynchronousMethods.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileintents/DWSynchronousMethodsNT.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileintents/DataWedgeConstants.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileintents/SettingsPlugins/BaseSettings.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileintents/SettingsPlugins/MainBundle.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileintents/SettingsPlugins/PluginBasicDataFormatting.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileintents/SettingsPlugins/PluginIntent.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileintents/SettingsPlugins/PluginKeystroke.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileintents/SettingsPlugins/PluginScanner.java create mode 100644 datawedgeprofileintentswrapper/src/main/java/com/zebra/datawedgeprofileintents/SignatureCheck.java create mode 100644 datawedgeprofileintentswrapper/src/main/res/values/strings.xml create mode 100644 datawedgeprofileintentswrapper/src/test/java/com/zebra/datawedgeprofileintents/ExampleUnitTest.java create mode 100644 gradle.properties create mode 100644 gradle/wrapper/gradle-wrapper.jar create mode 100644 gradle/wrapper/gradle-wrapper.properties create mode 100644 gradlew create mode 100644 gradlew.bat create mode 100644 settings.gradle diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6fcd948 --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +*.iml +.gradle +/local.properties +/.idea/workspace.xml +/.idea/libraries +.DS_Store +/build +/captures +datawedgeprofileintentswrapper/build/ diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..61a9130 --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 0000000..89b0cc3 --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,19 @@ + + + + + + \ No newline at end of file diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml new file mode 100644 index 0000000..a5f05cd --- /dev/null +++ b/.idea/jarRepositories.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..3378229 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..69533cf --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml new file mode 100644 index 0000000..797acea --- /dev/null +++ b/.idea/runConfigurations.xml @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..a202d8d --- /dev/null +++ b/README.md @@ -0,0 +1,45 @@ +This library is available in jcenter. + +Add the following line in your module build.gradle to include it : + +api 'com.zebra.datawedgeprofileintentswrapper:datawedgeprofileintentswrapper:6.7.2' + + +# END USER LICENSE AGREEMENT (UNRESTRICTED SOFTWARE) + + +IMPORTANT PLEASE READ CAREFULLY: This End User License Agreement ("EULA") is a legal agreement between you (either an individual or a single entity) and Zebra International Holdings Corporation ("Zebra") for software, owned by Zebra and its affiliated companies and its third party suppliers and licensors, that accompanies this EULA. ("Software"). BY USING THE SOFTWARE, YOU ACKNOWLEDGE ACCEPTANCE OF THE TERMS OF THIS EULA. IF YOU DO NOT ACCEPT THESE TERMS, DO NOT USE THE SOFTWARE. + +1. GRANT OF LICENSE. Zebra grants you, End-User Customer, the following rights provided that you comply with all terms and conditions of this EULA: For Software associated with Zebra hardware, Zebra hereby grants you ("Licensee" or "you") a personal, nonexclusive, nontransferable, nonassignable, nonsublicenseable license to use the Software subject to the terms and conditions of this Agreement. Only your employees or subcontractors may use the Software. You shall take all necessary steps to insure that your employees and subcontractors abide by the terms of this Agreement. You shall use the Software only for your internal business purposes, exclusively to support the Zebra hardware, including the right to (i) use, modify, and incorporate all or portions of the sample source code (the "Sample Code"), runtime library files, and/or documentation files that may be included in the unmodified Software into Licensees own programs (the "User Programs") to support the Zebra hardware exclusively, provided that no license is granted herein under any patents that may be infringed by Licensees modifications, derivative works or by other works in which any portion of the Software may be incorporated; (ii) distribute the Sample Code in object code format only as substantially modified or only as part of the User Programs to support the Zebra hardware exclusively; and (iii) distribute the runtime library files in their original form to support the Zebra hardware exclusively. For a standalone Software application, you may install, use, modify, and incorporate all or portions of any object code, available source code ("Source Code"), runtime library files, and/or documentation files that may be included with the unmodified Software into your own programs (the "User Programs") and distribute the User Programs to third parties. Any use of the Software outside of the conditions set forth herein is strictly prohibited and will be deemed a breach of this Agreement resulting in immediate termination of your License. Zebra will be entitled to all available remedies at law or in equity (including immediate injunctive relief and repossession of all Software unless Licensee is a Federal agency of the United States Government). + +Certain items of the Software may be subject to open source licenses. The open source license provisions may override some of the terms of this EULA. Zebra makes the applicable open source licenses available to you on a Legal Notices readme file available on your device and/or in System Reference guides or in Command Line Interface (CLI) Reference guides associated with certain Zebra products. + +2. RESERVATION OF RIGHTS AND OWNERSHIP. Zebra reserves all rights not expressly granted to you in this EULA. The Software is protected by copyright and other intellectual property laws and treaties. Zebra or its suppliers own the title, copyright and other intellectual property rights in the Software. The Software is licensed, not sold. + +3. LIMITATIONS ON END USER RIGHTS. You shall not distribute, sublicense, rent, loan, lease, export, re-export, resell, ship or divert or cause to be exported, re-exported, resold, shipped or diverted, directly or indirectly, the unmodified Software under this Agreement. You shall not, and shall not permit others to: (i) combine the Software including any Sample or Source Code, in whole or in part, with any Open Source Software having license terms and obligations that include copyleft obligations and/or intellectual property encumbrances; (ii) remove any proprietary notices, marks, labels, or logos from the Software; (iii) rent or transfer all or some of the Software to any other party without Zebras prior written consent; or (iv) utilize any computer software or hardware which is designed to defeat any copy protection device, should the Software be equipped with such a protection device. + +4. MACHINE DATA. Machine Data means anonymized usage data collected by devices sold (or licensed) under this Agreement such as battery management (time to empty, standby current, average current), device system time, CPU processing load, free RAM, number of running processes, network information (name, identifier), device identifier, firmware version, hardware version device type, audio volume, LED state, beeper volume, backlight level, key light, odometer count, reboot, reboot cause, total storage and physical memory availability, power cycle count, and device up time. Notwithstanding anything else in this Agreement, all title and ownership rights in and to Machine Data are held by Zebra. In the event, and to the extent you are deemed to have any ownership rights in Machine Data, you hereby grant Zebra a limited, revocable, non-exclusive right and license to use Machine Data. + +5. LOCATION INFORMATION. The Software may enable you to collect location-based data from one or more client devices which may allow you to track the actual location of those client devices. Zebra specifically disclaims any liability for your use or misuse of the location-based data. You agree to pay all reasonable costs and expenses of Zebra arising from or related to third party claims resulting from your use of the location-based data. + +6. SOFTWARE RELEASES. Zebra may periodically release new versions of the Software which will be made available to you. + +7. EXPORT RESTRICTIONS. You acknowledge that the Software is subject to export restrictions of various countries. You agree to comply with all applicable international and national laws that apply to the Software, including all the applicable export restriction laws and regulations. + +8. ASSIGNMENT.You may not assign this Agreement or any of your rights or obligations hereunder (by operation of law or otherwise) without the prior written consent of Zebra. Zebra may assign this Agreement and its rights and obligations without your consent. Subject to the foregoing, this Agreement shall be binding upon and inure to the benefit of the parties to it and their respective legal representatives, successors and permitted assigns. + +9. TERMINATION. This EULA is effective until terminated. Your rights under this License will terminate automatically without notice from Zebra if you fail to comply with any of the terms and conditions of this EULA. Zebra may terminate this Agreement by offering you a superseding Agreement for the Software or for any new release of the Software and conditioning your continued use of the Software or such new release on your acceptance of such superseding Agreement. Upon termination of this EULA, you must cease all use of the Software and destroy all copies, full or partial, of the Software. + +10. DISCLAIMER OF WARRANTY. UNLESS SEPARATELY STATED IN A WRITTEN EXPRESS LIMITED WARRANTY, ALL SOFTWARE PROVIDED BY ZEBRA IS PROVIDED "AS IS" AND ON AN "AS AVAILABLE" BASIS, WITHOUT WARRANTIES OF ANY KIND FROM ZEBRA, EITHER EXPRESS OR IMPLIED. TO THE FULLEST EXTENT POSSIBLE PURSUANT TO APPLICABLE LAW, ZEBRA DISCLAIMS ALL WARRANTIES EXPRESS, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY, SATISFACTORY QUALITY OR WORKMANLIKE EFFORT, FITNESS FOR A PARTICULAR PURPOSE, RELIABILITY OR AVAILABILITY, ACCURACY, LACK OF VIRUSES, NON INFRINGEMENT OF THIRD PARTY RIGHTS OR OTHER VIOLATION OF RIGHTS. ZEBRA DOES NOT WARRANT THAT THE OPERATION OF THE SOFTWARE WILL BE UNINTERRUPTED OR ERROR FREE. TO THE EXTENT THAT THE SOFTWARE COVERED BY THIS EULA INCLUDES EMULATION LIBRARIES, SUCH EMULATION LIBRARIES DO NOT WORK 100% CORRECTLY OR COVER 100% OF THE FUNCTIONALITY BEING EMULATED, ARE OFFERED "AS IS" AND WITH ALL FAULTS, AND ALL THE DISCLAIMERS AND LIMITATIONS CONTAINED IN THIS PARAGRAPH AND THIS AGREEMENT APPLY TO SUCH EMULATION LIBRARIES.SOME JURISDICTIONS DO NOT ALLOW EXCLUSIONS OR LIMITATIONS OF IMPLIED WARRANTIES, SO THE ABOVE EXCLUSIONS OR LIMITATIONS MAY NOT APPLY TO YOU. NO ADVICE OR INFORMATION, WHETHER ORAL OR WRITTEN, OBTAINED BY YOU FROM ZEBRA OR ITS AFFILIATES SHALL BE DEEMED TO ALTER THIS DISCLAIMER BY ZEBRA OF WARRANTY REGARDING THE SOFTWARE, OR TO CREATE ANY WARRANTY OF ANY SORT FROM ZEBRA. + +11. THIRD-PARTY APPLICATIONS. Certain third party applications may be included with, or downloaded with this Software. Zebra makes no representations whatsoever about any of these applications. Since Zebra has no control over such applications, you acknowledge and agree that Zebra is not responsible for such applications. You expressly acknowledge and agree that use of third party applications is at your sole risk and that the entire risk of unsatisfactory quality, performance, accuracy and effort is with you. You agree that Zebra shall not be responsible or liable, directly or indirectly, for any damage or loss, including but not limited to any damage to or loss of data, caused or alleged to be caused by, or in connection with, use of or reliance on any such third party content, products, or services available on or through any such application. You acknowledge and agree that the use of any third-party application is governed by such third party application provider's Terms of Use, License Agreement, Privacy Policy, or other such agreement and that any information or personal data you provide, whether knowingly or unknowingly, to such third-party application provider, will be subject to such third party application provider's privacy policy, if such a policy exists. ZEBRA DISCLAIMS ANY RESPONSIBILITY FOR ANY DISCLOSURE OF INFORMATION OR ANY OTHER PRACTICES OF ANY THIRD PARTY APPLICATION PROVIDER. ZEBRA EXPRESSLY DISCLAIMS ANY WARRANTY REGARDING WHETHER YOUR PERSONAL INFORMATION IS CAPTURED BY ANY THIRD PARTY APPLICATION PROVIDER OR THE USE TO WHICH SUCH PERSONAL INFORMATION MAY BE PUT BY SUCH THIRD PARTY APPLICATION PROVIDER. + +12. LIMITATION OF LIABILITY. ZEBRA WILL NOT BE LIABLE FOR ANY DAMAGES OF ANY KIND ARISING OUT OF OR RELATING TO THE USE OR THE INABILITY TO USE THE SOFTWARE OR ANY THIRD PARTY APPLICATION, ITS CONTENT OR FUNCTIONALITY, INCLUDING BUT NOT LIMITED TO DAMAGES CAUSED BY OR RELATED TO ERRORS, OMISSIONS, INTERRUPTIONS, DEFECTS, DELAY IN OPERATION OR TRANSMISSION, COMPUTER VIRUS, FAILURE TO CONNECT, NETWORK CHARGES, IN-APP PURCHASES, AND ALL OTHER DIRECT, INDIRECT, SPECIAL, INCIDENTAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES EVEN IF ZEBRA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THE ABOVE EXCLUSIONS OR LIMITATIONS MAY NOT APPLY TO YOU. NOTWITHSTANDING THE FOREGOING, ZEBRAS TOTAL LIABILITY TO YOU FOR ALL LOSSES, DAMAGES, CAUSES OF ACTION, INCLUDING BUT NOT LIMITED TO THOSE BASED ON CONTRACT, TORT, OR OTHERWISE, ARISING OUT OF YOUR USE OF THE SOFTWARE OR THIRD PARTY APPLICATIONS, OR ANY OTHER PROVISION OF THIS EULA, SHALL NOT EXCEED THE FAIR MARKET VALUE OF THE SOFTWARE OR AMOUNT PURCHASER PAID SPECIFICALLY FOR THE SOFTWARE. THE FOREGOING LIMITATIONS, EXCLUSIONS, AND DISCLAIMERS (INCLUDING SECTIONS 10, 11, 12, AND 15) SHALL APPLY TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, EVEN IF ANY REMEDY FAILS ITS ESSENTIAL PURPOSE. + +13. INJUNCTIVE RELIEF.You acknowledge that, in the event you breach any provision of this Agreement, Zebra will not have an adequate remedy in money or damages. Zebra shall therefore be entitled to obtain an injunction against such breach from any court of competent jurisdiction immediately upon request without posting bond. Zebra's right to obtain injunctive relief shall not limit its right to seek further remedies. + +14. MODIFICATION.No modification of this Agreement shall be binding unless it is in writing and is signed by an authorized representative of the party against whom enforcement of the modification is sought. + +15. U.S. GOVERNMENT END USERS RESTRICTED RIGHTS. This provision only applies to U.S. Government end users. The Software is a commercial item as that term is defined at 48 C.F.R. Part 2.101, consisting of commercial computer software and computer software documentation as such terms are defined in 48 C.F.R. Part 252.227-7014(a)(1) and 48 C.F.R. Part 252.227-7014(a)(5), and used in 48 C.F.R. Part 12.212 and 48 C.F.R. Part 227.7202, as applicable. Consistent with 48 C.F.R. Part 12.212, 48 C.F.R. Part 252.227-7015, 48 C.F.R. Part 227.7202-1 through 227.7202-4, 48 C.F.R. Part 52.227-19, and other relevant sections of the Code of Federal Regulations, as applicable, the Software is distributed and licensed to U.S. Government end users (a) only as a commercial item, and (b) with only those rights as are granted to all other end users pursuant to the terms and conditions contained herein. + +16. APPLICABLE LAW. This EULA is governed by the laws of the state of Illinois, without regard to its conflict of law provisions. This EULA shall not be governed by the UN Convention on Contracts for the International Sale of Goods, the application of which is expressly excluded. diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..d37f813 --- /dev/null +++ b/build.gradle @@ -0,0 +1,33 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. + +buildscript { + repositories { + jcenter() + google() + //maven { url 'https://jitpack.io' } + //maven { + // url "https://dl.bintray.com/ltrudu/Zebra_Open_Source_Tools_And_Libraries" + //} + } + dependencies { + classpath 'com.android.tools.build:gradle:4.2.2' + + // NOTE: Do not place your application dependencies here; they belong + // in the individual module build.gradle files + } +} + +allprojects { + repositories { + jcenter() + //maven { url 'https://jitpack.io' } + google() + //maven { + // url "https://dl.bintray.com/ltrudu/Zebra_Open_Source_Tools_And_Libraries" + //} + } +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/datawedgeprofileintentswrapper/build.gradle b/datawedgeprofileintentswrapper/build.gradle new file mode 100644 index 0000000..d76070a --- /dev/null +++ b/datawedgeprofileintentswrapper/build.gradle @@ -0,0 +1,135 @@ +apply plugin: 'com.android.library' + +ext { + PUBLISH_GROUP_ID = 'com.zebra.datawedgeprofileintentswrapper' + PUBLISH_ARTIFACT_ID = 'datawedgeprofileintentswrapper' + PUBLISH_VERSION = '6.7.5' +} + +android { + compileSdkVersion 30 + + defaultConfig { + minSdkVersion 19 + targetSdkVersion 30 + versionCode 4 + versionName "1.3" + + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } + +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + + //implementation 'androidx.appcompat:appcompat:1.2.0' + testImplementation 'junit:junit:4.12' + androidTestImplementation 'androidx.test.ext:junit:1.1.2' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0' + // https://mvnrepository.com/artifact/com.google.code.gson/gson + //implementation group: 'com.google.code.gson', name: 'gson', version: '2.7' +} + +def jarName = 'datawedgeprofileintents.jar' + +task clearJarRelease(type: Delete) { + delete "${project.buildDir}/outputs/jar/release/" + jarName +} + +task clearJarDebug(type: Delete) { + delete "${project.buildDir}/outputs/jar/debug/" + jarName +} + +task makeJarRelease(type: Copy) { + from("${project.buildDir}/intermediates/intermediate-jars/release/") + into("${project.buildDir}/outputs/jar/release") + include('classes.jar') + rename('classes.jar', jarName) +} + +task makeJarDebug(type: Copy) { + from("${project.buildDir}/intermediates/intermediate-jars/debug/") + into("${project.buildDir}/outputs/jar/debug") + include('classes.jar') + rename('classes.jar', jarName) +} + +task makeAllJar(type: Copy) {} + +makeJarRelease.dependsOn(clearJarRelease, build) +makeJarDebug.dependsOn(clearJarDebug, build) + +makeAllJar.dependsOn(makeJarDebug,makeJarRelease) + +/* +Publish tasks +https://medium.com/@daniellevass/how-to-publish-your-android-studio-library-to-jcenter-5384172c4739 +https://raw.githubusercontent.com/blundell/release-android-library/master/android-release-aar.gradle + */ + +// ./gradlew clean build generateRelease +apply plugin: 'maven' + +def groupId = project.PUBLISH_GROUP_ID +def artifactId = project.PUBLISH_ARTIFACT_ID +def version = project.PUBLISH_VERSION + +def localReleaseDest = "${buildDir}/release/${version}" + +task androidJavadocs(type: Javadoc) { + failOnError = false + source = android.sourceSets.main.java.srcDirs + ext.androidJar = "${android.sdkDirectory}/platforms/${android.compileSdkVersion}/android.jar" + classpath += files(ext.androidJar) +} + +task androidJavadocsJar(type: Jar, dependsOn: androidJavadocs) { + archiveClassifier = 'javadoc' + from androidJavadocs.destinationDir +} + +task androidSourcesJar(type: Jar) { + archiveClassifier = 'sources' + from android.sourceSets.main.java.srcDirs +} + +uploadArchives { + repositories.mavenDeployer { + pom.groupId = groupId + pom.artifactId = artifactId + pom.version = version + // Add other pom properties here if you want (developer details / licenses) + repository(url: "file://${localReleaseDest}") + } +} + +task zipRelease(type: Zip) { + from localReleaseDest + destinationDir buildDir + archiveBaseName = "release-${version}" //.zip" +} + +task generateRelease { + doLast { + println "Release ${version} can be found at ${localReleaseDest}/" + println "Release ${version} zipped can be found ${buildDir}/release-${version}.zip" + } +} + +generateRelease.dependsOn(uploadArchives) +generateRelease.dependsOn(zipRelease) + + +artifacts { + archives androidSourcesJar + archives androidJavadocsJar +} \ No newline at end of file diff --git a/datawedgeprofileintentswrapper/proguard-rules.pro b/datawedgeprofileintentswrapper/proguard-rules.pro new file mode 100644 index 0000000..f1b4245 --- /dev/null +++ b/datawedgeprofileintentswrapper/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile diff --git a/datawedgeprofileintentswrapper/src/androidTest/java/com/zebra/datawedgeprofileintents/ExampleInstrumentedTest.java b/datawedgeprofileintentswrapper/src/androidTest/java/com/zebra/datawedgeprofileintents/ExampleInstrumentedTest.java new file mode 100644 index 0000000..5998af9 --- /dev/null +++ b/datawedgeprofileintentswrapper/src/androidTest/java/com/zebra/datawedgeprofileintents/ExampleInstrumentedTest.java @@ -0,0 +1,26 @@ +package com.zebra.datawedgeprofileintents; + +import android.content.Context; +import android.support.test.InstrumentationRegistry; +import android.support.test.runner.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.*; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getTargetContext(); + + assertEquals("com.zebra.datawedgeprofileintents.test", appContext.getPackageName()); + } +} diff --git a/datawedgeprofileintentswrapper/src/main/AndroidManifest.xml b/datawedgeprofileintentswrapper/src/main/AndroidManifest.xml new file mode 100644 index 0000000..cc7d996 --- /dev/null +++ b/datawedgeprofileintentswrapper/src/main/AndroidManifest.xml @@ -0,0 +1,2 @@ + diff --git a/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/DefaultDateTypeAdapter.java b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/DefaultDateTypeAdapter.java new file mode 100644 index 0000000..9f3ef2d --- /dev/null +++ b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/DefaultDateTypeAdapter.java @@ -0,0 +1,165 @@ +/* + * Copyright (C) 2008 Google Inc. + * + * 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. + */ + +package com.google.gson285; + +import java.io.IOException; +import java.sql.Timestamp; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.ParsePosition; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Locale; + +import com.google.gson285.internal.JavaVersion; +import com.google.gson285.internal.PreJava9DateFormatProvider; +import com.google.gson285.internal.bind.util.ISO8601Utils; +import com.google.gson285.stream.JsonReader; +import com.google.gson285.stream.JsonToken; +import com.google.gson285.stream.JsonWriter; + +/** + * This type adapter supports three subclasses of date: Date, Timestamp, and + * java.sql.Date. + * + * @author Inderjeet Singh + * @author Joel Leitch + */ +final class DefaultDateTypeAdapter extends TypeAdapter { + + private static final String SIMPLE_NAME = "DefaultDateTypeAdapter"; + + private final Class dateType; + + /** + * List of 1 or more different date formats used for de-serialization attempts. + * The first of them is used for serialization as well. + */ + private final List dateFormats = new ArrayList(); + + DefaultDateTypeAdapter(Class dateType) { + this.dateType = verifyDateType(dateType); + dateFormats.add(DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.US)); + if (!Locale.getDefault().equals(Locale.US)) { + dateFormats.add(DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT)); + } + if (JavaVersion.isJava9OrLater()) { + dateFormats.add(PreJava9DateFormatProvider.getUSDateTimeFormat(DateFormat.DEFAULT, DateFormat.DEFAULT)); + } + } + + DefaultDateTypeAdapter(Class dateType, String datePattern) { + this.dateType = verifyDateType(dateType); + dateFormats.add(new SimpleDateFormat(datePattern, Locale.US)); + if (!Locale.getDefault().equals(Locale.US)) { + dateFormats.add(new SimpleDateFormat(datePattern)); + } + } + + DefaultDateTypeAdapter(Class dateType, int style) { + this.dateType = verifyDateType(dateType); + dateFormats.add(DateFormat.getDateInstance(style, Locale.US)); + if (!Locale.getDefault().equals(Locale.US)) { + dateFormats.add(DateFormat.getDateInstance(style)); + } + if (JavaVersion.isJava9OrLater()) { + dateFormats.add(PreJava9DateFormatProvider.getUSDateFormat(style)); + } + } + + public DefaultDateTypeAdapter(int dateStyle, int timeStyle) { + this(Date.class, dateStyle, timeStyle); + } + + public DefaultDateTypeAdapter(Class dateType, int dateStyle, int timeStyle) { + this.dateType = verifyDateType(dateType); + dateFormats.add(DateFormat.getDateTimeInstance(dateStyle, timeStyle, Locale.US)); + if (!Locale.getDefault().equals(Locale.US)) { + dateFormats.add(DateFormat.getDateTimeInstance(dateStyle, timeStyle)); + } + if (JavaVersion.isJava9OrLater()) { + dateFormats.add(PreJava9DateFormatProvider.getUSDateTimeFormat(dateStyle, timeStyle)); + } + } + + private static Class verifyDateType(Class dateType) { + if ( dateType != Date.class && dateType != java.sql.Date.class && dateType != Timestamp.class ) { + throw new IllegalArgumentException("Date type must be one of " + Date.class + ", " + Timestamp.class + ", or " + java.sql.Date.class + " but was " + dateType); + } + return dateType; + } + + // These methods need to be synchronized since JDK DateFormat classes are not thread-safe + // See issue 162 + @Override + public void write(JsonWriter out, Date value) throws IOException { + if (value == null) { + out.nullValue(); + return; + } + synchronized(dateFormats) { + String dateFormatAsString = dateFormats.get(0).format(value); + out.value(dateFormatAsString); + } + } + + @Override + public Date read(JsonReader in) throws IOException { + if (in.peek() == JsonToken.NULL) { + in.nextNull(); + return null; + } + Date date = deserializeToDate(in.nextString()); + if (dateType == Date.class) { + return date; + } else if (dateType == Timestamp.class) { + return new Timestamp(date.getTime()); + } else if (dateType == java.sql.Date.class) { + return new java.sql.Date(date.getTime()); + } else { + // This must never happen: dateType is guarded in the primary constructor + throw new AssertionError(); + } + } + + private Date deserializeToDate(String s) { + synchronized (dateFormats) { + for (DateFormat dateFormat : dateFormats) { + try { + return dateFormat.parse(s); + } catch (ParseException ignored) {} + } + try { + return ISO8601Utils.parse(s, new ParsePosition(0)); + } catch (ParseException e) { + throw new JsonSyntaxException(s, e); + } + } + } + + @Override + public String toString() { + DateFormat defaultFormat = dateFormats.get(0); + if (defaultFormat instanceof SimpleDateFormat) { + return SIMPLE_NAME + '(' + ((SimpleDateFormat) defaultFormat).toPattern() + ')'; + } else { + return SIMPLE_NAME + '(' + defaultFormat.getClass().getSimpleName() + ')'; + } + } +} diff --git a/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/ExclusionStrategy.java b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/ExclusionStrategy.java new file mode 100644 index 0000000..c74e2b7 --- /dev/null +++ b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/ExclusionStrategy.java @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2008 Google Inc. + * + * 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. + */ + +package com.google.gson285; + +/** + * A strategy (or policy) definition that is used to decide whether or not a field or top-level + * class should be serialized or deserialized as part of the JSON output/input. For serialization, + * if the {@link #shouldSkipClass(Class)} method returns true then that class or field type + * will not be part of the JSON output. For deserialization, if {@link #shouldSkipClass(Class)} + * returns true, then it will not be set as part of the Java object structure. + * + *

The following are a few examples that shows how you can use this exclusion mechanism. + * + *

Exclude fields and objects based on a particular class type: + *

+ * private static class SpecificClassExclusionStrategy implements ExclusionStrategy {
+ *   private final Class<?> excludedThisClass;
+ *
+ *   public SpecificClassExclusionStrategy(Class<?> excludedThisClass) {
+ *     this.excludedThisClass = excludedThisClass;
+ *   }
+ *
+ *   public boolean shouldSkipClass(Class<?> clazz) {
+ *     return excludedThisClass.equals(clazz);
+ *   }
+ *
+ *   public boolean shouldSkipField(FieldAttributes f) {
+ *     return excludedThisClass.equals(f.getDeclaredClass());
+ *   }
+ * }
+ * 
+ * + *

Excludes fields and objects based on a particular annotation: + *

+ * public @interface FooAnnotation {
+ *   // some implementation here
+ * }
+ *
+ * // Excludes any field (or class) that is tagged with an "@FooAnnotation"
+ * private static class FooAnnotationExclusionStrategy implements ExclusionStrategy {
+ *   public boolean shouldSkipClass(Class<?> clazz) {
+ *     return clazz.getAnnotation(FooAnnotation.class) != null;
+ *   }
+ *
+ *   public boolean shouldSkipField(FieldAttributes f) {
+ *     return f.getAnnotation(FooAnnotation.class) != null;
+ *   }
+ * }
+ * 
+ * + *

Now if you want to configure {@code Gson} to use a user defined exclusion strategy, then + * the {@code GsonBuilder} is required. The following is an example of how you can use the + * {@code GsonBuilder} to configure Gson to use one of the above sample: + *

+ * ExclusionStrategy excludeStrings = new UserDefinedExclusionStrategy(String.class);
+ * Gson gson = new GsonBuilder()
+ *     .setExclusionStrategies(excludeStrings)
+ *     .create();
+ * 
+ * + *

For certain model classes, you may only want to serialize a field, but exclude it for + * deserialization. To do that, you can write an {@code ExclusionStrategy} as per normal; + * however, you would register it with the + * {@link GsonBuilder#addDeserializationExclusionStrategy(ExclusionStrategy)} method. + * For example: + *

+ * ExclusionStrategy excludeStrings = new UserDefinedExclusionStrategy(String.class);
+ * Gson gson = new GsonBuilder()
+ *     .addDeserializationExclusionStrategy(excludeStrings)
+ *     .create();
+ * 
+ * + * @author Inderjeet Singh + * @author Joel Leitch + * + * @see GsonBuilder#setExclusionStrategies(ExclusionStrategy...) + * @see GsonBuilder#addDeserializationExclusionStrategy(ExclusionStrategy) + * @see GsonBuilder#addSerializationExclusionStrategy(ExclusionStrategy) + * + * @since 1.4 + */ +public interface ExclusionStrategy { + + /** + * @param f the field object that is under test + * @return true if the field should be ignored; otherwise false + */ + public boolean shouldSkipField(FieldAttributes f); + + /** + * @param clazz the class object that is under test + * @return true if the class should be ignored; otherwise false + */ + public boolean shouldSkipClass(Class clazz); +} diff --git a/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/FieldAttributes.java b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/FieldAttributes.java new file mode 100644 index 0000000..a08040d --- /dev/null +++ b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/FieldAttributes.java @@ -0,0 +1,161 @@ +/* + * Copyright (C) 2009 Google Inc. + * + * 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. + */ + +package com.google.gson285; + +import com.google.gson285.internal.$Gson$Preconditions; +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; +import java.lang.reflect.Type; +import java.util.Arrays; +import java.util.Collection; + +/** + * A data object that stores attributes of a field. + * + *

This class is immutable; therefore, it can be safely shared across threads. + * + * @author Inderjeet Singh + * @author Joel Leitch + * + * @since 1.4 + */ +public final class FieldAttributes { + private final Field field; + + /** + * Constructs a Field Attributes object from the {@code f}. + * + * @param f the field to pull attributes from + */ + public FieldAttributes(Field f) { + $Gson$Preconditions.checkNotNull(f); + this.field = f; + } + + /** + * @return the declaring class that contains this field + */ + public Class getDeclaringClass() { + return field.getDeclaringClass(); + } + + /** + * @return the name of the field + */ + public String getName() { + return field.getName(); + } + + /** + *

For example, assume the following class definition: + *

+   * public class Foo {
+   *   private String bar;
+   *   private List<String> red;
+   * }
+   *
+   * Type listParameterizedType = new TypeToken<List<String>>() {}.getType();
+   * 
+ * + *

This method would return {@code String.class} for the {@code bar} field and + * {@code listParameterizedType} for the {@code red} field. + * + * @return the specific type declared for this field + */ + public Type getDeclaredType() { + return field.getGenericType(); + } + + /** + * Returns the {@code Class} object that was declared for this field. + * + *

For example, assume the following class definition: + *

+   * public class Foo {
+   *   private String bar;
+   *   private List<String> red;
+   * }
+   * 
+ * + *

This method would return {@code String.class} for the {@code bar} field and + * {@code List.class} for the {@code red} field. + * + * @return the specific class object that was declared for the field + */ + public Class getDeclaredClass() { + return field.getType(); + } + + /** + * Return the {@code T} annotation object from this field if it exist; otherwise returns + * {@code null}. + * + * @param annotation the class of the annotation that will be retrieved + * @return the annotation instance if it is bound to the field; otherwise {@code null} + */ + public T getAnnotation(Class annotation) { + return field.getAnnotation(annotation); + } + + /** + * Return the annotations that are present on this field. + * + * @return an array of all the annotations set on the field + * @since 1.4 + */ + public Collection getAnnotations() { + return Arrays.asList(field.getAnnotations()); + } + + /** + * Returns {@code true} if the field is defined with the {@code modifier}. + * + *

This method is meant to be called as: + *

+   * boolean hasPublicModifier = fieldAttribute.hasModifier(java.lang.reflect.Modifier.PUBLIC);
+   * 
+ * + * @see java.lang.reflect.Modifier + */ + public boolean hasModifier(int modifier) { + return (field.getModifiers() & modifier) != 0; + } + + /** + * Returns the value of the field represented by this {@code Field}, on + * the specified object. The value is automatically wrapped in an + * object if it has a primitive type. + * + * @return the value of the represented field in object + * {@code obj}; primitive values are wrapped in an appropriate + * object before being returned + * @throws IllegalAccessException + * @throws IllegalArgumentException + */ + Object get(Object instance) throws IllegalAccessException { + return field.get(instance); + } + + /** + * This is exposed internally only for the removing synthetic fields from the JSON output. + * + * @return true if the field is synthetic; otherwise false + */ + boolean isSynthetic() { + return field.isSynthetic(); + } +} diff --git a/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/FieldNamingPolicy.java b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/FieldNamingPolicy.java new file mode 100644 index 0000000..bab4da1 --- /dev/null +++ b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/FieldNamingPolicy.java @@ -0,0 +1,189 @@ +/* + * Copyright (C) 2008 Google Inc. + * + * 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. + */ + +package com.google.gson285; + +import java.lang.reflect.Field; +import java.util.Locale; + +/** + * An enumeration that defines a few standard naming conventions for JSON field names. + * This enumeration should be used in conjunction with {@link com.google.gson285.GsonBuilder} + * to configure a {@link com.google.gson285.Gson} instance to properly translate Java field + * names into the desired JSON field names. + * + * @author Inderjeet Singh + * @author Joel Leitch + */ +public enum FieldNamingPolicy implements FieldNamingStrategy { + + /** + * Using this naming policy with Gson will ensure that the field name is + * unchanged. + */ + IDENTITY() { + @Override public String translateName(Field f) { + return f.getName(); + } + }, + + /** + * Using this naming policy with Gson will ensure that the first "letter" of the Java + * field name is capitalized when serialized to its JSON form. + * + *

Here's a few examples of the form "Java Field Name" ---> "JSON Field Name":

+ *
    + *
  • someFieldName ---> SomeFieldName
  • + *
  • _someFieldName ---> _SomeFieldName
  • + *
+ */ + UPPER_CAMEL_CASE() { + @Override public String translateName(Field f) { + return upperCaseFirstLetter(f.getName()); + } + }, + + /** + * Using this naming policy with Gson will ensure that the first "letter" of the Java + * field name is capitalized when serialized to its JSON form and the words will be + * separated by a space. + * + *

Here's a few examples of the form "Java Field Name" ---> "JSON Field Name":

+ *
    + *
  • someFieldName ---> Some Field Name
  • + *
  • _someFieldName ---> _Some Field Name
  • + *
+ * + * @since 1.4 + */ + UPPER_CAMEL_CASE_WITH_SPACES() { + @Override public String translateName(Field f) { + return upperCaseFirstLetter(separateCamelCase(f.getName(), " ")); + } + }, + + /** + * Using this naming policy with Gson will modify the Java Field name from its camel cased + * form to a lower case field name where each word is separated by an underscore (_). + * + *

Here's a few examples of the form "Java Field Name" ---> "JSON Field Name":

+ *
    + *
  • someFieldName ---> some_field_name
  • + *
  • _someFieldName ---> _some_field_name
  • + *
  • aStringField ---> a_string_field
  • + *
  • aURL ---> a_u_r_l
  • + *
+ */ + LOWER_CASE_WITH_UNDERSCORES() { + @Override public String translateName(Field f) { + return separateCamelCase(f.getName(), "_").toLowerCase(Locale.ENGLISH); + } + }, + + /** + * Using this naming policy with Gson will modify the Java Field name from its camel cased + * form to a lower case field name where each word is separated by a dash (-). + * + *

Here's a few examples of the form "Java Field Name" ---> "JSON Field Name":

+ *
    + *
  • someFieldName ---> some-field-name
  • + *
  • _someFieldName ---> _some-field-name
  • + *
  • aStringField ---> a-string-field
  • + *
  • aURL ---> a-u-r-l
  • + *
+ * Using dashes in JavaScript is not recommended since dash is also used for a minus sign in + * expressions. This requires that a field named with dashes is always accessed as a quoted + * property like {@code myobject['my-field']}. Accessing it as an object field + * {@code myobject.my-field} will result in an unintended javascript expression. + * @since 1.4 + */ + LOWER_CASE_WITH_DASHES() { + @Override public String translateName(Field f) { + return separateCamelCase(f.getName(), "-").toLowerCase(Locale.ENGLISH); + } + }, + + /** + * Using this naming policy with Gson will modify the Java Field name from its camel cased + * form to a lower case field name where each word is separated by a dot (.). + * + *

Here's a few examples of the form "Java Field Name" ---> "JSON Field Name":

+ *
    + *
  • someFieldName ---> some.field.name
  • + *
  • _someFieldName ---> _some.field.name
  • + *
  • aStringField ---> a.string.field
  • + *
  • aURL ---> a.u.r.l
  • + *
+ * Using dots in JavaScript is not recommended since dot is also used for a member sign in + * expressions. This requires that a field named with dots is always accessed as a quoted + * property like {@code myobject['my.field']}. Accessing it as an object field + * {@code myobject.my.field} will result in an unintended javascript expression. + * @since 2.8 + */ + LOWER_CASE_WITH_DOTS() { + @Override public String translateName(Field f) { + return separateCamelCase(f.getName(), ".").toLowerCase(Locale.ENGLISH); + } + }; + + /** + * Converts the field name that uses camel-case define word separation into + * separate words that are separated by the provided {@code separatorString}. + */ + static String separateCamelCase(String name, String separator) { + StringBuilder translation = new StringBuilder(); + for (int i = 0, length = name.length(); i < length; i++) { + char character = name.charAt(i); + if (Character.isUpperCase(character) && translation.length() != 0) { + translation.append(separator); + } + translation.append(character); + } + return translation.toString(); + } + + /** + * Ensures the JSON field names begins with an upper case letter. + */ + static String upperCaseFirstLetter(String name) { + StringBuilder fieldNameBuilder = new StringBuilder(); + int index = 0; + char firstCharacter = name.charAt(index); + int length = name.length(); + + while (index < length - 1) { + if (Character.isLetter(firstCharacter)) { + break; + } + + fieldNameBuilder.append(firstCharacter); + firstCharacter = name.charAt(++index); + } + + if (!Character.isUpperCase(firstCharacter)) { + String modifiedTarget = modifyString(Character.toUpperCase(firstCharacter), name, ++index); + return fieldNameBuilder.append(modifiedTarget).toString(); + } else { + return name; + } + } + + private static String modifyString(char firstCharacter, String srcString, int indexOfSubstring) { + return (indexOfSubstring < srcString.length()) + ? firstCharacter + srcString.substring(indexOfSubstring) + : String.valueOf(firstCharacter); + } +} diff --git a/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/FieldNamingStrategy.java b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/FieldNamingStrategy.java new file mode 100644 index 0000000..58e7c43 --- /dev/null +++ b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/FieldNamingStrategy.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2008 Google Inc. + * + * 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. + */ + +package com.google.gson285; + +import java.lang.reflect.Field; + +/** + * A mechanism for providing custom field naming in Gson. This allows the client code to translate + * field names into a particular convention that is not supported as a normal Java field + * declaration rules. For example, Java does not support "-" characters in a field name. + * + * @author Inderjeet Singh + * @author Joel Leitch + * @since 1.3 + */ +public interface FieldNamingStrategy { + + /** + * Translates the field name into its JSON field name representation. + * + * @param f the field object that we are translating + * @return the translated field name. + * @since 1.3 + */ + public String translateName(Field f); +} diff --git a/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/Gson.java b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/Gson.java new file mode 100644 index 0000000..a38a3b3 --- /dev/null +++ b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/Gson.java @@ -0,0 +1,1031 @@ +/* + * Copyright (C) 2008 Google Inc. + * + * 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. + */ + +package com.google.gson285; + +import java.io.EOFException; +import java.io.IOException; +import java.io.Reader; +import java.io.StringReader; +import java.io.StringWriter; +import java.io.Writer; +import java.lang.reflect.Type; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.text.DateFormat; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicLong; +import java.util.concurrent.atomic.AtomicLongArray; + +import com.google.gson285.internal.ConstructorConstructor; +import com.google.gson285.internal.Excluder; +import com.google.gson285.internal.GsonBuildConfig; +import com.google.gson285.internal.Primitives; +import com.google.gson285.internal.Streams; +import com.google.gson285.internal.bind.ArrayTypeAdapter; +import com.google.gson285.internal.bind.CollectionTypeAdapterFactory; +import com.google.gson285.internal.bind.DateTypeAdapter; +import com.google.gson285.internal.bind.JsonAdapterAnnotationTypeAdapterFactory; +import com.google.gson285.internal.bind.JsonTreeReader; +import com.google.gson285.internal.bind.JsonTreeWriter; +import com.google.gson285.internal.bind.MapTypeAdapterFactory; +import com.google.gson285.internal.bind.ObjectTypeAdapter; +import com.google.gson285.internal.bind.ReflectiveTypeAdapterFactory; +import com.google.gson285.internal.bind.SqlDateTypeAdapter; +import com.google.gson285.internal.bind.TimeTypeAdapter; +import com.google.gson285.internal.bind.TypeAdapters; +import com.google.gson285.reflect.TypeToken; +import com.google.gson285.stream.JsonReader; +import com.google.gson285.stream.JsonToken; +import com.google.gson285.stream.JsonWriter; +import com.google.gson285.stream.MalformedJsonException; + +/** + * This is the main class for using Gson. Gson is typically used by first constructing a + * Gson instance and then invoking {@link #toJson(Object)} or {@link #fromJson(String, Class)} + * methods on it. Gson instances are Thread-safe so you can reuse them freely across multiple + * threads. + * + *

You can create a Gson instance by invoking {@code new Gson()} if the default configuration + * is all you need. You can also use {@link GsonBuilder} to build a Gson instance with various + * configuration options such as versioning support, pretty printing, custom + * {@link JsonSerializer}s, {@link JsonDeserializer}s, and {@link InstanceCreator}s.

+ * + *

Here is an example of how Gson is used for a simple Class: + * + *

+ * Gson gson = new Gson(); // Or use new GsonBuilder().create();
+ * MyType target = new MyType();
+ * String json = gson.toJson(target); // serializes target to Json
+ * MyType target2 = gson.fromJson(json, MyType.class); // deserializes json into target2
+ * 

+ * + *

If the object that your are serializing/deserializing is a {@code ParameterizedType} + * (i.e. contains at least one type parameter and may be an array) then you must use the + * {@link #toJson(Object, Type)} or {@link #fromJson(String, Type)} method. Here is an + * example for serializing and deserializing a {@code ParameterizedType}: + * + *

+ * Type listType = new TypeToken<List<String>>() {}.getType();
+ * List<String> target = new LinkedList<String>();
+ * target.add("blah");
+ *
+ * Gson gson = new Gson();
+ * String json = gson.toJson(target, listType);
+ * List<String> target2 = gson.fromJson(json, listType);
+ * 

+ * + *

See the Gson User Guide + * for a more complete set of examples.

+ * + * @see com.google.gson285.reflect.TypeToken + * + * @author Inderjeet Singh + * @author Joel Leitch + * @author Jesse Wilson + */ +public final class Gson { + static final boolean DEFAULT_JSON_NON_EXECUTABLE = false; + static final boolean DEFAULT_LENIENT = false; + static final boolean DEFAULT_PRETTY_PRINT = false; + static final boolean DEFAULT_ESCAPE_HTML = true; + static final boolean DEFAULT_SERIALIZE_NULLS = false; + static final boolean DEFAULT_COMPLEX_MAP_KEYS = false; + static final boolean DEFAULT_SPECIALIZE_FLOAT_VALUES = false; + + private static final TypeToken NULL_KEY_SURROGATE = TypeToken.get(Object.class); + private static final String JSON_NON_EXECUTABLE_PREFIX = ")]}'\n"; + + /** + * This thread local guards against reentrant calls to getAdapter(). In + * certain object graphs, creating an adapter for a type may recursively + * require an adapter for the same type! Without intervention, the recursive + * lookup would stack overflow. We cheat by returning a proxy type adapter. + * The proxy is wired up once the initial adapter has been created. + */ + private final ThreadLocal, FutureTypeAdapter>> calls + = new ThreadLocal, FutureTypeAdapter>>(); + + private final Map, TypeAdapter> typeTokenCache = new ConcurrentHashMap, TypeAdapter>(); + + private final ConstructorConstructor constructorConstructor; + private final JsonAdapterAnnotationTypeAdapterFactory jsonAdapterFactory; + + final List factories; + + final Excluder excluder; + final FieldNamingStrategy fieldNamingStrategy; + final Map> instanceCreators; + final boolean serializeNulls; + final boolean complexMapKeySerialization; + final boolean generateNonExecutableJson; + final boolean htmlSafe; + final boolean prettyPrinting; + final boolean lenient; + final boolean serializeSpecialFloatingPointValues; + final String datePattern; + final int dateStyle; + final int timeStyle; + final LongSerializationPolicy longSerializationPolicy; + final List builderFactories; + final List builderHierarchyFactories; + + /** + * Constructs a Gson object with default configuration. The default configuration has the + * following settings: + *
    + *
  • The JSON generated by toJson methods is in compact representation. This + * means that all the unneeded white-space is removed. You can change this behavior with + * {@link GsonBuilder#setPrettyPrinting()}.
  • + *
  • The generated JSON omits all the fields that are null. Note that nulls in arrays are + * kept as is since an array is an ordered list. Moreover, if a field is not null, but its + * generated JSON is empty, the field is kept. You can configure Gson to serialize null values + * by setting {@link GsonBuilder#serializeNulls()}.
  • + *
  • Gson provides default serialization and deserialization for Enums, {@link Map}, + * {@link java.net.URL}, {@link java.net.URI}, {@link java.util.Locale}, {@link java.util.Date}, + * {@link java.math.BigDecimal}, and {@link java.math.BigInteger} classes. If you would prefer + * to change the default representation, you can do so by registering a type adapter through + * {@link GsonBuilder#registerTypeAdapter(Type, Object)}.
  • + *
  • The default Date format is same as {@link java.text.DateFormat#DEFAULT}. This format + * ignores the millisecond portion of the date during serialization. You can change + * this by invoking {@link GsonBuilder#setDateFormat(int)} or + * {@link GsonBuilder#setDateFormat(String)}.
  • + *
  • By default, Gson ignores the {@link com.google.gson285.annotations.Expose} annotation. + * You can enable Gson to serialize/deserialize only those fields marked with this annotation + * through {@link GsonBuilder#excludeFieldsWithoutExposeAnnotation()}.
  • + *
  • By default, Gson ignores the {@link com.google.gson285.annotations.Since} annotation. You + * can enable Gson to use this annotation through {@link GsonBuilder#setVersion(double)}.
  • + *
  • The default field naming policy for the output Json is same as in Java. So, a Java class + * field versionNumber will be output as "versionNumber" in + * Json. The same rules are applied for mapping incoming Json to the Java classes. You can + * change this policy through {@link GsonBuilder#setFieldNamingPolicy(FieldNamingPolicy)}.
  • + *
  • By default, Gson excludes transient or static fields from + * consideration for serialization and deserialization. You can change this behavior through + * {@link GsonBuilder#excludeFieldsWithModifiers(int...)}.
  • + *
+ */ + public Gson() { + this(Excluder.DEFAULT, FieldNamingPolicy.IDENTITY, + Collections.>emptyMap(), DEFAULT_SERIALIZE_NULLS, + DEFAULT_COMPLEX_MAP_KEYS, DEFAULT_JSON_NON_EXECUTABLE, DEFAULT_ESCAPE_HTML, + DEFAULT_PRETTY_PRINT, DEFAULT_LENIENT, DEFAULT_SPECIALIZE_FLOAT_VALUES, + LongSerializationPolicy.DEFAULT, null, DateFormat.DEFAULT, DateFormat.DEFAULT, + Collections.emptyList(), Collections.emptyList(), + Collections.emptyList()); + } + + Gson(final Excluder excluder, final FieldNamingStrategy fieldNamingStrategy, + final Map> instanceCreators, boolean serializeNulls, + boolean complexMapKeySerialization, boolean generateNonExecutableGson, boolean htmlSafe, + boolean prettyPrinting, boolean lenient, boolean serializeSpecialFloatingPointValues, + LongSerializationPolicy longSerializationPolicy, String datePattern, int dateStyle, + int timeStyle, List builderFactories, + List builderHierarchyFactories, + List factoriesToBeAdded) { + this.excluder = excluder; + this.fieldNamingStrategy = fieldNamingStrategy; + this.instanceCreators = instanceCreators; + this.constructorConstructor = new ConstructorConstructor(instanceCreators); + this.serializeNulls = serializeNulls; + this.complexMapKeySerialization = complexMapKeySerialization; + this.generateNonExecutableJson = generateNonExecutableGson; + this.htmlSafe = htmlSafe; + this.prettyPrinting = prettyPrinting; + this.lenient = lenient; + this.serializeSpecialFloatingPointValues = serializeSpecialFloatingPointValues; + this.longSerializationPolicy = longSerializationPolicy; + this.datePattern = datePattern; + this.dateStyle = dateStyle; + this.timeStyle = timeStyle; + this.builderFactories = builderFactories; + this.builderHierarchyFactories = builderHierarchyFactories; + + List factories = new ArrayList(); + + // built-in type adapters that cannot be overridden + factories.add(TypeAdapters.JSON_ELEMENT_FACTORY); + factories.add(ObjectTypeAdapter.FACTORY); + + // the excluder must precede all adapters that handle user-defined types + factories.add(excluder); + + // users' type adapters + factories.addAll(factoriesToBeAdded); + + // type adapters for basic platform types + factories.add(TypeAdapters.STRING_FACTORY); + factories.add(TypeAdapters.INTEGER_FACTORY); + factories.add(TypeAdapters.BOOLEAN_FACTORY); + factories.add(TypeAdapters.BYTE_FACTORY); + factories.add(TypeAdapters.SHORT_FACTORY); + TypeAdapter longAdapter = longAdapter(longSerializationPolicy); + factories.add(TypeAdapters.newFactory(long.class, Long.class, longAdapter)); + factories.add(TypeAdapters.newFactory(double.class, Double.class, + doubleAdapter(serializeSpecialFloatingPointValues))); + factories.add(TypeAdapters.newFactory(float.class, Float.class, + floatAdapter(serializeSpecialFloatingPointValues))); + factories.add(TypeAdapters.NUMBER_FACTORY); + factories.add(TypeAdapters.ATOMIC_INTEGER_FACTORY); + factories.add(TypeAdapters.ATOMIC_BOOLEAN_FACTORY); + factories.add(TypeAdapters.newFactory(AtomicLong.class, atomicLongAdapter(longAdapter))); + factories.add(TypeAdapters.newFactory(AtomicLongArray.class, atomicLongArrayAdapter(longAdapter))); + factories.add(TypeAdapters.ATOMIC_INTEGER_ARRAY_FACTORY); + factories.add(TypeAdapters.CHARACTER_FACTORY); + factories.add(TypeAdapters.STRING_BUILDER_FACTORY); + factories.add(TypeAdapters.STRING_BUFFER_FACTORY); + factories.add(TypeAdapters.newFactory(BigDecimal.class, TypeAdapters.BIG_DECIMAL)); + factories.add(TypeAdapters.newFactory(BigInteger.class, TypeAdapters.BIG_INTEGER)); + factories.add(TypeAdapters.URL_FACTORY); + factories.add(TypeAdapters.URI_FACTORY); + factories.add(TypeAdapters.UUID_FACTORY); + factories.add(TypeAdapters.CURRENCY_FACTORY); + factories.add(TypeAdapters.LOCALE_FACTORY); + factories.add(TypeAdapters.INET_ADDRESS_FACTORY); + factories.add(TypeAdapters.BIT_SET_FACTORY); + factories.add(DateTypeAdapter.FACTORY); + factories.add(TypeAdapters.CALENDAR_FACTORY); + factories.add(TimeTypeAdapter.FACTORY); + factories.add(SqlDateTypeAdapter.FACTORY); + factories.add(TypeAdapters.TIMESTAMP_FACTORY); + factories.add(ArrayTypeAdapter.FACTORY); + factories.add(TypeAdapters.CLASS_FACTORY); + + // type adapters for composite and user-defined types + factories.add(new CollectionTypeAdapterFactory(constructorConstructor)); + factories.add(new MapTypeAdapterFactory(constructorConstructor, complexMapKeySerialization)); + this.jsonAdapterFactory = new JsonAdapterAnnotationTypeAdapterFactory(constructorConstructor); + factories.add(jsonAdapterFactory); + factories.add(TypeAdapters.ENUM_FACTORY); + factories.add(new ReflectiveTypeAdapterFactory( + constructorConstructor, fieldNamingStrategy, excluder, jsonAdapterFactory)); + + this.factories = Collections.unmodifiableList(factories); + } + + /** + * Returns a new GsonBuilder containing all custom factories and configuration used by the current + * instance. + * + * @return a GsonBuilder instance. + */ + public GsonBuilder newBuilder() { + return new GsonBuilder(this); + } + + public Excluder excluder() { + return excluder; + } + + public FieldNamingStrategy fieldNamingStrategy() { + return fieldNamingStrategy; + } + + public boolean serializeNulls() { + return serializeNulls; + } + + public boolean htmlSafe() { + return htmlSafe; + } + + private TypeAdapter doubleAdapter(boolean serializeSpecialFloatingPointValues) { + if (serializeSpecialFloatingPointValues) { + return TypeAdapters.DOUBLE; + } + return new TypeAdapter() { + @Override public Double read(JsonReader in) throws IOException { + if (in.peek() == JsonToken.NULL) { + in.nextNull(); + return null; + } + return in.nextDouble(); + } + @Override public void write(JsonWriter out, Number value) throws IOException { + if (value == null) { + out.nullValue(); + return; + } + double doubleValue = value.doubleValue(); + checkValidFloatingPoint(doubleValue); + out.value(value); + } + }; + } + + private TypeAdapter floatAdapter(boolean serializeSpecialFloatingPointValues) { + if (serializeSpecialFloatingPointValues) { + return TypeAdapters.FLOAT; + } + return new TypeAdapter() { + @Override public Float read(JsonReader in) throws IOException { + if (in.peek() == JsonToken.NULL) { + in.nextNull(); + return null; + } + return (float) in.nextDouble(); + } + @Override public void write(JsonWriter out, Number value) throws IOException { + if (value == null) { + out.nullValue(); + return; + } + float floatValue = value.floatValue(); + checkValidFloatingPoint(floatValue); + out.value(value); + } + }; + } + + static void checkValidFloatingPoint(double value) { + if (Double.isNaN(value) || Double.isInfinite(value)) { + throw new IllegalArgumentException(value + + " is not a valid double value as per JSON specification. To override this" + + " behavior, use GsonBuilder.serializeSpecialFloatingPointValues() method."); + } + } + + private static TypeAdapter longAdapter(LongSerializationPolicy longSerializationPolicy) { + if (longSerializationPolicy == LongSerializationPolicy.DEFAULT) { + return TypeAdapters.LONG; + } + return new TypeAdapter() { + @Override public Number read(JsonReader in) throws IOException { + if (in.peek() == JsonToken.NULL) { + in.nextNull(); + return null; + } + return in.nextLong(); + } + @Override public void write(JsonWriter out, Number value) throws IOException { + if (value == null) { + out.nullValue(); + return; + } + out.value(value.toString()); + } + }; + } + + private static TypeAdapter atomicLongAdapter(final TypeAdapter longAdapter) { + return new TypeAdapter() { + @Override public void write(JsonWriter out, AtomicLong value) throws IOException { + longAdapter.write(out, value.get()); + } + @Override public AtomicLong read(JsonReader in) throws IOException { + Number value = longAdapter.read(in); + return new AtomicLong(value.longValue()); + } + }.nullSafe(); + } + + private static TypeAdapter atomicLongArrayAdapter(final TypeAdapter longAdapter) { + return new TypeAdapter() { + @Override public void write(JsonWriter out, AtomicLongArray value) throws IOException { + out.beginArray(); + for (int i = 0, length = value.length(); i < length; i++) { + longAdapter.write(out, value.get(i)); + } + out.endArray(); + } + @Override public AtomicLongArray read(JsonReader in) throws IOException { + List list = new ArrayList(); + in.beginArray(); + while (in.hasNext()) { + long value = longAdapter.read(in).longValue(); + list.add(value); + } + in.endArray(); + int length = list.size(); + AtomicLongArray array = new AtomicLongArray(length); + for (int i = 0; i < length; ++i) { + array.set(i, list.get(i)); + } + return array; + } + }.nullSafe(); + } + + /** + * Returns the type adapter for {@code} type. + * + * @throws IllegalArgumentException if this GSON cannot serialize and + * deserialize {@code type}. + */ + @SuppressWarnings("unchecked") + public TypeAdapter getAdapter(TypeToken type) { + TypeAdapter cached = typeTokenCache.get(type == null ? NULL_KEY_SURROGATE : type); + if (cached != null) { + return (TypeAdapter) cached; + } + + Map, FutureTypeAdapter> threadCalls = calls.get(); + boolean requiresThreadLocalCleanup = false; + if (threadCalls == null) { + threadCalls = new HashMap, FutureTypeAdapter>(); + calls.set(threadCalls); + requiresThreadLocalCleanup = true; + } + + // the key and value type parameters always agree + FutureTypeAdapter ongoingCall = (FutureTypeAdapter) threadCalls.get(type); + if (ongoingCall != null) { + return ongoingCall; + } + + try { + FutureTypeAdapter call = new FutureTypeAdapter(); + threadCalls.put(type, call); + + for (TypeAdapterFactory factory : factories) { + TypeAdapter candidate = factory.create(this, type); + if (candidate != null) { + call.setDelegate(candidate); + typeTokenCache.put(type, candidate); + return candidate; + } + } + throw new IllegalArgumentException("GSON (" + GsonBuildConfig.VERSION + ") cannot handle " + type); + } finally { + threadCalls.remove(type); + + if (requiresThreadLocalCleanup) { + calls.remove(); + } + } + } + + /** + * This method is used to get an alternate type adapter for the specified type. This is used + * to access a type adapter that is overridden by a {@link TypeAdapterFactory} that you + * may have registered. This features is typically used when you want to register a type + * adapter that does a little bit of work but then delegates further processing to the Gson + * default type adapter. Here is an example: + *

Let's say we want to write a type adapter that counts the number of objects being read + * from or written to JSON. We can achieve this by writing a type adapter factory that uses + * the getDelegateAdapter method: + *

 {@code
+   *  class StatsTypeAdapterFactory implements TypeAdapterFactory {
+   *    public int numReads = 0;
+   *    public int numWrites = 0;
+   *    public  TypeAdapter create(Gson gson, TypeToken type) {
+   *      final TypeAdapter delegate = gson.getDelegateAdapter(this, type);
+   *      return new TypeAdapter() {
+   *        public void write(JsonWriter out, T value) throws IOException {
+   *          ++numWrites;
+   *          delegate.write(out, value);
+   *        }
+   *        public T read(JsonReader in) throws IOException {
+   *          ++numReads;
+   *          return delegate.read(in);
+   *        }
+   *      };
+   *    }
+   *  }
+   *  } 
+ * This factory can now be used like this: + *
 {@code
+   *  StatsTypeAdapterFactory stats = new StatsTypeAdapterFactory();
+   *  Gson gson = new GsonBuilder().registerTypeAdapterFactory(stats).create();
+   *  // Call gson.toJson() and fromJson methods on objects
+   *  System.out.println("Num JSON reads" + stats.numReads);
+   *  System.out.println("Num JSON writes" + stats.numWrites);
+   *  }
+ * Note that this call will skip all factories registered before {@code skipPast}. In case of + * multiple TypeAdapterFactories registered it is up to the caller of this function to insure + * that the order of registration does not prevent this method from reaching a factory they + * would expect to reply from this call. + * Note that since you can not override type adapter factories for String and Java primitive + * types, our stats factory will not count the number of String or primitives that will be + * read or written. + * @param skipPast The type adapter factory that needs to be skipped while searching for + * a matching type adapter. In most cases, you should just pass this (the type adapter + * factory from where {@link #getDelegateAdapter} method is being invoked). + * @param type Type for which the delegate adapter is being searched for. + * + * @since 2.2 + */ + public TypeAdapter getDelegateAdapter(TypeAdapterFactory skipPast, TypeToken type) { + // Hack. If the skipPast factory isn't registered, assume the factory is being requested via + // our @JsonAdapter annotation. + if (!factories.contains(skipPast)) { + skipPast = jsonAdapterFactory; + } + + boolean skipPastFound = false; + for (TypeAdapterFactory factory : factories) { + if (!skipPastFound) { + if (factory == skipPast) { + skipPastFound = true; + } + continue; + } + + TypeAdapter candidate = factory.create(this, type); + if (candidate != null) { + return candidate; + } + } + throw new IllegalArgumentException("GSON cannot serialize " + type); + } + + /** + * Returns the type adapter for {@code} type. + * + * @throws IllegalArgumentException if this GSON cannot serialize and + * deserialize {@code type}. + */ + public TypeAdapter getAdapter(Class type) { + return getAdapter(TypeToken.get(type)); + } + + /** + * This method serializes the specified object into its equivalent representation as a tree of + * {@link JsonElement}s. This method should be used when the specified object is not a generic + * type. This method uses {@link Class#getClass()} to get the type for the specified object, but + * the {@code getClass()} loses the generic type information because of the Type Erasure feature + * of Java. Note that this method works fine if the any of the object fields are of generic type, + * just the object itself should not be of a generic type. If the object is of generic type, use + * {@link #toJsonTree(Object, Type)} instead. + * + * @param src the object for which Json representation is to be created setting for Gson + * @return Json representation of {@code src}. + * @since 1.4 + */ + public JsonElement toJsonTree(Object src) { + if (src == null) { + return JsonNull.INSTANCE; + } + return toJsonTree(src, src.getClass()); + } + + /** + * This method serializes the specified object, including those of generic types, into its + * equivalent representation as a tree of {@link JsonElement}s. This method must be used if the + * specified object is a generic type. For non-generic objects, use {@link #toJsonTree(Object)} + * instead. + * + * @param src the object for which JSON representation is to be created + * @param typeOfSrc The specific genericized type of src. You can obtain + * this type by using the {@link com.google.gson285.reflect.TypeToken} class. For example, + * to get the type for {@code Collection}, you should use: + *
+   * Type typeOfSrc = new TypeToken<Collection<Foo>>(){}.getType();
+   * 
+ * @return Json representation of {@code src} + * @since 1.4 + */ + public JsonElement toJsonTree(Object src, Type typeOfSrc) { + JsonTreeWriter writer = new JsonTreeWriter(); + toJson(src, typeOfSrc, writer); + return writer.get(); + } + + /** + * This method serializes the specified object into its equivalent Json representation. + * This method should be used when the specified object is not a generic type. This method uses + * {@link Class#getClass()} to get the type for the specified object, but the + * {@code getClass()} loses the generic type information because of the Type Erasure feature + * of Java. Note that this method works fine if the any of the object fields are of generic type, + * just the object itself should not be of a generic type. If the object is of generic type, use + * {@link #toJson(Object, Type)} instead. If you want to write out the object to a + * {@link Writer}, use {@link #toJson(Object, Appendable)} instead. + * + * @param src the object for which Json representation is to be created setting for Gson + * @return Json representation of {@code src}. + */ + public String toJson(Object src) { + if (src == null) { + return toJson(JsonNull.INSTANCE); + } + return toJson(src, src.getClass()); + } + + /** + * This method serializes the specified object, including those of generic types, into its + * equivalent Json representation. This method must be used if the specified object is a generic + * type. For non-generic objects, use {@link #toJson(Object)} instead. If you want to write out + * the object to a {@link Appendable}, use {@link #toJson(Object, Type, Appendable)} instead. + * + * @param src the object for which JSON representation is to be created + * @param typeOfSrc The specific genericized type of src. You can obtain + * this type by using the {@link com.google.gson285.reflect.TypeToken} class. For example, + * to get the type for {@code Collection}, you should use: + *
+   * Type typeOfSrc = new TypeToken<Collection<Foo>>(){}.getType();
+   * 
+ * @return Json representation of {@code src} + */ + public String toJson(Object src, Type typeOfSrc) { + StringWriter writer = new StringWriter(); + toJson(src, typeOfSrc, writer); + return writer.toString(); + } + + /** + * This method serializes the specified object into its equivalent Json representation. + * This method should be used when the specified object is not a generic type. This method uses + * {@link Class#getClass()} to get the type for the specified object, but the + * {@code getClass()} loses the generic type information because of the Type Erasure feature + * of Java. Note that this method works fine if the any of the object fields are of generic type, + * just the object itself should not be of a generic type. If the object is of generic type, use + * {@link #toJson(Object, Type, Appendable)} instead. + * + * @param src the object for which Json representation is to be created setting for Gson + * @param writer Writer to which the Json representation needs to be written + * @throws JsonIOException if there was a problem writing to the writer + * @since 1.2 + */ + public void toJson(Object src, Appendable writer) throws JsonIOException { + if (src != null) { + toJson(src, src.getClass(), writer); + } else { + toJson(JsonNull.INSTANCE, writer); + } + } + + /** + * This method serializes the specified object, including those of generic types, into its + * equivalent Json representation. This method must be used if the specified object is a generic + * type. For non-generic objects, use {@link #toJson(Object, Appendable)} instead. + * + * @param src the object for which JSON representation is to be created + * @param typeOfSrc The specific genericized type of src. You can obtain + * this type by using the {@link com.google.gson285.reflect.TypeToken} class. For example, + * to get the type for {@code Collection}, you should use: + *
+   * Type typeOfSrc = new TypeToken<Collection<Foo>>(){}.getType();
+   * 
+ * @param writer Writer to which the Json representation of src needs to be written. + * @throws JsonIOException if there was a problem writing to the writer + * @since 1.2 + */ + public void toJson(Object src, Type typeOfSrc, Appendable writer) throws JsonIOException { + try { + JsonWriter jsonWriter = newJsonWriter(Streams.writerForAppendable(writer)); + toJson(src, typeOfSrc, jsonWriter); + } catch (IOException e) { + throw new JsonIOException(e); + } + } + + /** + * Writes the JSON representation of {@code src} of type {@code typeOfSrc} to + * {@code writer}. + * @throws JsonIOException if there was a problem writing to the writer + */ + @SuppressWarnings("unchecked") + public void toJson(Object src, Type typeOfSrc, JsonWriter writer) throws JsonIOException { + TypeAdapter adapter = getAdapter(TypeToken.get(typeOfSrc)); + boolean oldLenient = writer.isLenient(); + writer.setLenient(true); + boolean oldHtmlSafe = writer.isHtmlSafe(); + writer.setHtmlSafe(htmlSafe); + boolean oldSerializeNulls = writer.getSerializeNulls(); + writer.setSerializeNulls(serializeNulls); + try { + ((TypeAdapter) adapter).write(writer, src); + } catch (IOException e) { + throw new JsonIOException(e); + } catch (AssertionError e) { + throw new AssertionError("AssertionError (GSON " + GsonBuildConfig.VERSION + "): " + e.getMessage(), e); + } finally { + writer.setLenient(oldLenient); + writer.setHtmlSafe(oldHtmlSafe); + writer.setSerializeNulls(oldSerializeNulls); + } + } + + /** + * Converts a tree of {@link JsonElement}s into its equivalent JSON representation. + * + * @param jsonElement root of a tree of {@link JsonElement}s + * @return JSON String representation of the tree + * @since 1.4 + */ + public String toJson(JsonElement jsonElement) { + StringWriter writer = new StringWriter(); + toJson(jsonElement, writer); + return writer.toString(); + } + + /** + * Writes out the equivalent JSON for a tree of {@link JsonElement}s. + * + * @param jsonElement root of a tree of {@link JsonElement}s + * @param writer Writer to which the Json representation needs to be written + * @throws JsonIOException if there was a problem writing to the writer + * @since 1.4 + */ + public void toJson(JsonElement jsonElement, Appendable writer) throws JsonIOException { + try { + JsonWriter jsonWriter = newJsonWriter(Streams.writerForAppendable(writer)); + toJson(jsonElement, jsonWriter); + } catch (IOException e) { + throw new JsonIOException(e); + } + } + + /** + * Returns a new JSON writer configured for the settings on this Gson instance. + */ + public JsonWriter newJsonWriter(Writer writer) throws IOException { + if (generateNonExecutableJson) { + writer.write(JSON_NON_EXECUTABLE_PREFIX); + } + JsonWriter jsonWriter = new JsonWriter(writer); + if (prettyPrinting) { + jsonWriter.setIndent(" "); + } + jsonWriter.setSerializeNulls(serializeNulls); + return jsonWriter; + } + + /** + * Returns a new JSON reader configured for the settings on this Gson instance. + */ + public JsonReader newJsonReader(Reader reader) { + JsonReader jsonReader = new JsonReader(reader); + jsonReader.setLenient(lenient); + return jsonReader; + } + + /** + * Writes the JSON for {@code jsonElement} to {@code writer}. + * @throws JsonIOException if there was a problem writing to the writer + */ + public void toJson(JsonElement jsonElement, JsonWriter writer) throws JsonIOException { + boolean oldLenient = writer.isLenient(); + writer.setLenient(true); + boolean oldHtmlSafe = writer.isHtmlSafe(); + writer.setHtmlSafe(htmlSafe); + boolean oldSerializeNulls = writer.getSerializeNulls(); + writer.setSerializeNulls(serializeNulls); + try { + Streams.write(jsonElement, writer); + } catch (IOException e) { + throw new JsonIOException(e); + } catch (AssertionError e) { + throw new AssertionError("AssertionError (GSON " + GsonBuildConfig.VERSION + "): " + e.getMessage(), e); + } finally { + writer.setLenient(oldLenient); + writer.setHtmlSafe(oldHtmlSafe); + writer.setSerializeNulls(oldSerializeNulls); + } + } + + /** + * This method deserializes the specified Json into an object of the specified class. It is not + * suitable to use if the specified class is a generic type since it will not have the generic + * type information because of the Type Erasure feature of Java. Therefore, this method should not + * be used if the desired type is a generic type. Note that this method works fine if the any of + * the fields of the specified object are generics, just the object itself should not be a + * generic type. For the cases when the object is of generic type, invoke + * {@link #fromJson(String, Type)}. If you have the Json in a {@link Reader} instead of + * a String, use {@link #fromJson(Reader, Class)} instead. + * + * @param the type of the desired object + * @param json the string from which the object is to be deserialized + * @param classOfT the class of T + * @return an object of type T from the string. Returns {@code null} if {@code json} is {@code null} + * or if {@code json} is empty. + * @throws JsonSyntaxException if json is not a valid representation for an object of type + * classOfT + */ + public T fromJson(String json, Class classOfT) throws JsonSyntaxException { + Object object = fromJson(json, (Type) classOfT); + return Primitives.wrap(classOfT).cast(object); + } + + /** + * This method deserializes the specified Json into an object of the specified type. This method + * is useful if the specified object is a generic type. For non-generic objects, use + * {@link #fromJson(String, Class)} instead. If you have the Json in a {@link Reader} instead of + * a String, use {@link #fromJson(Reader, Type)} instead. + * + * @param the type of the desired object + * @param json the string from which the object is to be deserialized + * @param typeOfT The specific genericized type of src. You can obtain this type by using the + * {@link com.google.gson285.reflect.TypeToken} class. For example, to get the type for + * {@code Collection}, you should use: + *
+   * Type typeOfT = new TypeToken<Collection<Foo>>(){}.getType();
+   * 
+ * @return an object of type T from the string. Returns {@code null} if {@code json} is {@code null}. + * @throws JsonParseException if json is not a valid representation for an object of type typeOfT + * @throws JsonSyntaxException if json is not a valid representation for an object of type + */ + @SuppressWarnings("unchecked") + public T fromJson(String json, Type typeOfT) throws JsonSyntaxException { + if (json == null) { + return null; + } + StringReader reader = new StringReader(json); + T target = (T) fromJson(reader, typeOfT); + return target; + } + + /** + * This method deserializes the Json read from the specified reader into an object of the + * specified class. It is not suitable to use if the specified class is a generic type since it + * will not have the generic type information because of the Type Erasure feature of Java. + * Therefore, this method should not be used if the desired type is a generic type. Note that + * this method works fine if the any of the fields of the specified object are generics, just the + * object itself should not be a generic type. For the cases when the object is of generic type, + * invoke {@link #fromJson(Reader, Type)}. If you have the Json in a String form instead of a + * {@link Reader}, use {@link #fromJson(String, Class)} instead. + * + * @param the type of the desired object + * @param json the reader producing the Json from which the object is to be deserialized. + * @param classOfT the class of T + * @return an object of type T from the string. Returns {@code null} if {@code json} is at EOF. + * @throws JsonIOException if there was a problem reading from the Reader + * @throws JsonSyntaxException if json is not a valid representation for an object of type + * @since 1.2 + */ + public T fromJson(Reader json, Class classOfT) throws JsonSyntaxException, JsonIOException { + JsonReader jsonReader = newJsonReader(json); + Object object = fromJson(jsonReader, classOfT); + assertFullConsumption(object, jsonReader); + return Primitives.wrap(classOfT).cast(object); + } + + /** + * This method deserializes the Json read from the specified reader into an object of the + * specified type. This method is useful if the specified object is a generic type. For + * non-generic objects, use {@link #fromJson(Reader, Class)} instead. If you have the Json in a + * String form instead of a {@link Reader}, use {@link #fromJson(String, Type)} instead. + * + * @param the type of the desired object + * @param json the reader producing Json from which the object is to be deserialized + * @param typeOfT The specific genericized type of src. You can obtain this type by using the + * {@link com.google.gson285.reflect.TypeToken} class. For example, to get the type for + * {@code Collection}, you should use: + *
+   * Type typeOfT = new TypeToken<Collection<Foo>>(){}.getType();
+   * 
+ * @return an object of type T from the json. Returns {@code null} if {@code json} is at EOF. + * @throws JsonIOException if there was a problem reading from the Reader + * @throws JsonSyntaxException if json is not a valid representation for an object of type + * @since 1.2 + */ + @SuppressWarnings("unchecked") + public T fromJson(Reader json, Type typeOfT) throws JsonIOException, JsonSyntaxException { + JsonReader jsonReader = newJsonReader(json); + T object = (T) fromJson(jsonReader, typeOfT); + assertFullConsumption(object, jsonReader); + return object; + } + + private static void assertFullConsumption(Object obj, JsonReader reader) { + try { + if (obj != null && reader.peek() != JsonToken.END_DOCUMENT) { + throw new JsonIOException("JSON document was not fully consumed."); + } + } catch (MalformedJsonException e) { + throw new JsonSyntaxException(e); + } catch (IOException e) { + throw new JsonIOException(e); + } + } + + /** + * Reads the next JSON value from {@code reader} and convert it to an object + * of type {@code typeOfT}. Returns {@code null}, if the {@code reader} is at EOF. + * Since Type is not parameterized by T, this method is type unsafe and should be used carefully + * + * @throws JsonIOException if there was a problem writing to the Reader + * @throws JsonSyntaxException if json is not a valid representation for an object of type + */ + @SuppressWarnings("unchecked") + public T fromJson(JsonReader reader, Type typeOfT) throws JsonIOException, JsonSyntaxException { + boolean isEmpty = true; + boolean oldLenient = reader.isLenient(); + reader.setLenient(true); + try { + reader.peek(); + isEmpty = false; + TypeToken typeToken = (TypeToken) TypeToken.get(typeOfT); + TypeAdapter typeAdapter = getAdapter(typeToken); + T object = typeAdapter.read(reader); + return object; + } catch (EOFException e) { + /* + * For compatibility with JSON 1.5 and earlier, we return null for empty + * documents instead of throwing. + */ + if (isEmpty) { + return null; + } + throw new JsonSyntaxException(e); + } catch (IllegalStateException e) { + throw new JsonSyntaxException(e); + } catch (IOException e) { + // TODO(inder): Figure out whether it is indeed right to rethrow this as JsonSyntaxException + throw new JsonSyntaxException(e); + } catch (AssertionError e) { + throw new AssertionError("AssertionError (GSON " + GsonBuildConfig.VERSION + "): " + e.getMessage(), e); + } finally { + reader.setLenient(oldLenient); + } + } + + /** + * This method deserializes the Json read from the specified parse tree into an object of the + * specified type. It is not suitable to use if the specified class is a generic type since it + * will not have the generic type information because of the Type Erasure feature of Java. + * Therefore, this method should not be used if the desired type is a generic type. Note that + * this method works fine if the any of the fields of the specified object are generics, just the + * object itself should not be a generic type. For the cases when the object is of generic type, + * invoke {@link #fromJson(JsonElement, Type)}. + * @param the type of the desired object + * @param json the root of the parse tree of {@link JsonElement}s from which the object is to + * be deserialized + * @param classOfT The class of T + * @return an object of type T from the json. Returns {@code null} if {@code json} is {@code null}. + * @throws JsonSyntaxException if json is not a valid representation for an object of type typeOfT + * @since 1.3 + */ + public T fromJson(JsonElement json, Class classOfT) throws JsonSyntaxException { + Object object = fromJson(json, (Type) classOfT); + return Primitives.wrap(classOfT).cast(object); + } + + /** + * This method deserializes the Json read from the specified parse tree into an object of the + * specified type. This method is useful if the specified object is a generic type. For + * non-generic objects, use {@link #fromJson(JsonElement, Class)} instead. + * + * @param the type of the desired object + * @param json the root of the parse tree of {@link JsonElement}s from which the object is to + * be deserialized + * @param typeOfT The specific genericized type of src. You can obtain this type by using the + * {@link com.google.gson285.reflect.TypeToken} class. For example, to get the type for + * {@code Collection}, you should use: + *
+   * Type typeOfT = new TypeToken<Collection<Foo>>(){}.getType();
+   * 
+ * @return an object of type T from the json. Returns {@code null} if {@code json} is {@code null}. + * @throws JsonSyntaxException if json is not a valid representation for an object of type typeOfT + * @since 1.3 + */ + @SuppressWarnings("unchecked") + public T fromJson(JsonElement json, Type typeOfT) throws JsonSyntaxException { + if (json == null) { + return null; + } + return (T) fromJson(new JsonTreeReader(json), typeOfT); + } + + static class FutureTypeAdapter extends TypeAdapter { + private TypeAdapter delegate; + + public void setDelegate(TypeAdapter typeAdapter) { + if (delegate != null) { + throw new AssertionError(); + } + delegate = typeAdapter; + } + + @Override public T read(JsonReader in) throws IOException { + if (delegate == null) { + throw new IllegalStateException(); + } + return delegate.read(in); + } + + @Override public void write(JsonWriter out, T value) throws IOException { + if (delegate == null) { + throw new IllegalStateException(); + } + delegate.write(out, value); + } + } + + @Override + public String toString() { + return new StringBuilder("{serializeNulls:") + .append(serializeNulls) + .append(",factories:").append(factories) + .append(",instanceCreators:").append(constructorConstructor) + .append("}") + .toString(); + } +} diff --git a/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/GsonBuilder.java b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/GsonBuilder.java new file mode 100644 index 0000000..770bb12 --- /dev/null +++ b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/GsonBuilder.java @@ -0,0 +1,627 @@ +/* + * Copyright (C) 2008 Google Inc. + * + * 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. + */ + +package com.google.gson285; + +import java.lang.reflect.Type; +import java.sql.Timestamp; +import java.text.DateFormat; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.google.gson285.internal.$Gson$Preconditions; +import com.google.gson285.internal.Excluder; +import com.google.gson285.internal.bind.TreeTypeAdapter; +import com.google.gson285.internal.bind.TypeAdapters; +import com.google.gson285.reflect.TypeToken; +import com.google.gson285.stream.JsonReader; + +import static com.google.gson285.Gson.DEFAULT_COMPLEX_MAP_KEYS; +import static com.google.gson285.Gson.DEFAULT_ESCAPE_HTML; +import static com.google.gson285.Gson.DEFAULT_JSON_NON_EXECUTABLE; +import static com.google.gson285.Gson.DEFAULT_LENIENT; +import static com.google.gson285.Gson.DEFAULT_PRETTY_PRINT; +import static com.google.gson285.Gson.DEFAULT_SERIALIZE_NULLS; +import static com.google.gson285.Gson.DEFAULT_SPECIALIZE_FLOAT_VALUES; + +/** + *

Use this builder to construct a {@link Gson} instance when you need to set configuration + * options other than the default. For {@link Gson} with default configuration, it is simpler to + * use {@code new Gson()}. {@code GsonBuilder} is best used by creating it, and then invoking its + * various configuration methods, and finally calling create.

+ * + *

The following is an example shows how to use the {@code GsonBuilder} to construct a Gson + * instance: + * + *

+ * Gson gson = new GsonBuilder()
+ *     .registerTypeAdapter(Id.class, new IdTypeAdapter())
+ *     .enableComplexMapKeySerialization()
+ *     .serializeNulls()
+ *     .setDateFormat(DateFormat.LONG)
+ *     .setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE)
+ *     .setPrettyPrinting()
+ *     .setVersion(1.0)
+ *     .create();
+ * 

+ * + *

NOTES: + *

    + *
  • the order of invocation of configuration methods does not matter.
  • + *
  • The default serialization of {@link Date} and its subclasses in Gson does + * not contain time-zone information. So, if you are using date/time instances, + * use {@code GsonBuilder} and its {@code setDateFormat} methods.
  • + *
+ *

+ * + * @author Inderjeet Singh + * @author Joel Leitch + * @author Jesse Wilson + */ +public final class GsonBuilder { + private Excluder excluder = Excluder.DEFAULT; + private LongSerializationPolicy longSerializationPolicy = LongSerializationPolicy.DEFAULT; + private FieldNamingStrategy fieldNamingPolicy = FieldNamingPolicy.IDENTITY; + private final Map> instanceCreators + = new HashMap>(); + private final List factories = new ArrayList(); + /** tree-style hierarchy factories. These come after factories for backwards compatibility. */ + private final List hierarchyFactories = new ArrayList(); + private boolean serializeNulls = DEFAULT_SERIALIZE_NULLS; + private String datePattern; + private int dateStyle = DateFormat.DEFAULT; + private int timeStyle = DateFormat.DEFAULT; + private boolean complexMapKeySerialization = DEFAULT_COMPLEX_MAP_KEYS; + private boolean serializeSpecialFloatingPointValues = DEFAULT_SPECIALIZE_FLOAT_VALUES; + private boolean escapeHtmlChars = DEFAULT_ESCAPE_HTML; + private boolean prettyPrinting = DEFAULT_PRETTY_PRINT; + private boolean generateNonExecutableJson = DEFAULT_JSON_NON_EXECUTABLE; + private boolean lenient = DEFAULT_LENIENT; + + /** + * Creates a GsonBuilder instance that can be used to build Gson with various configuration + * settings. GsonBuilder follows the builder pattern, and it is typically used by first + * invoking various configuration methods to set desired options, and finally calling + * {@link #create()}. + */ + public GsonBuilder() { + } + + /** + * Constructs a GsonBuilder instance from a Gson instance. The newly constructed GsonBuilder + * has the same configuration as the previously built Gson instance. + * + * @param gson the gson instance whose configuration should by applied to a new GsonBuilder. + */ + GsonBuilder(Gson gson) { + this.excluder = gson.excluder; + this.fieldNamingPolicy = gson.fieldNamingStrategy; + this.instanceCreators.putAll(gson.instanceCreators); + this.serializeNulls = gson.serializeNulls; + this.complexMapKeySerialization = gson.complexMapKeySerialization; + this.generateNonExecutableJson = gson.generateNonExecutableJson; + this.escapeHtmlChars = gson.htmlSafe; + this.prettyPrinting = gson.prettyPrinting; + this.lenient = gson.lenient; + this.serializeSpecialFloatingPointValues = gson.serializeSpecialFloatingPointValues; + this.longSerializationPolicy = gson.longSerializationPolicy; + this.datePattern = gson.datePattern; + this.dateStyle = gson.dateStyle; + this.timeStyle = gson.timeStyle; + this.factories.addAll(gson.builderFactories); + this.hierarchyFactories.addAll(gson.builderHierarchyFactories); + } + + /** + * Configures Gson to enable versioning support. + * + * @param ignoreVersionsAfter any field or type marked with a version higher than this value + * are ignored during serialization or deserialization. + * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern + */ + public GsonBuilder setVersion(double ignoreVersionsAfter) { + excluder = excluder.withVersion(ignoreVersionsAfter); + return this; + } + + /** + * Configures Gson to excludes all class fields that have the specified modifiers. By default, + * Gson will exclude all fields marked transient or static. This method will override that + * behavior. + * + * @param modifiers the field modifiers. You must use the modifiers specified in the + * {@link java.lang.reflect.Modifier} class. For example, + * {@link java.lang.reflect.Modifier#TRANSIENT}, + * {@link java.lang.reflect.Modifier#STATIC}. + * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern + */ + public GsonBuilder excludeFieldsWithModifiers(int... modifiers) { + excluder = excluder.withModifiers(modifiers); + return this; + } + + /** + * Makes the output JSON non-executable in Javascript by prefixing the generated JSON with some + * special text. This prevents attacks from third-party sites through script sourcing. See + * Gson Issue 42 + * for details. + * + * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern + * @since 1.3 + */ + public GsonBuilder generateNonExecutableJson() { + this.generateNonExecutableJson = true; + return this; + } + + /** + * Configures Gson to exclude all fields from consideration for serialization or deserialization + * that do not have the {@link com.google.gson285.annotations.Expose} annotation. + * + * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern + */ + public GsonBuilder excludeFieldsWithoutExposeAnnotation() { + excluder = excluder.excludeFieldsWithoutExposeAnnotation(); + return this; + } + + /** + * Configure Gson to serialize null fields. By default, Gson omits all fields that are null + * during serialization. + * + * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern + * @since 1.2 + */ + public GsonBuilder serializeNulls() { + this.serializeNulls = true; + return this; + } + + /** + * Enabling this feature will only change the serialized form if the map key is + * a complex type (i.e. non-primitive) in its serialized JSON + * form. The default implementation of map serialization uses {@code toString()} + * on the key; however, when this is called then one of the following cases + * apply: + * + *

Maps as JSON objects

+ * For this case, assume that a type adapter is registered to serialize and + * deserialize some {@code Point} class, which contains an x and y coordinate, + * to/from the JSON Primitive string value {@code "(x,y)"}. The Java map would + * then be serialized as a {@link JsonObject}. + * + *

Below is an example: + *

  {@code
+   *   Gson gson = new GsonBuilder()
+   *       .register(Point.class, new MyPointTypeAdapter())
+   *       .enableComplexMapKeySerialization()
+   *       .create();
+   *
+   *   Map original = new LinkedHashMap();
+   *   original.put(new Point(5, 6), "a");
+   *   original.put(new Point(8, 8), "b");
+   *   System.out.println(gson.toJson(original, type));
+   * }
+ * The above code prints this JSON object:
  {@code
+   *   {
+   *     "(5,6)": "a",
+   *     "(8,8)": "b"
+   *   }
+   * }
+ * + *

Maps as JSON arrays

+ * For this case, assume that a type adapter was NOT registered for some + * {@code Point} class, but rather the default Gson serialization is applied. + * In this case, some {@code new Point(2,3)} would serialize as {@code + * {"x":2,"y":5}}. + * + *

Given the assumption above, a {@code Map} will be + * serialize as an array of arrays (can be viewed as an entry set of pairs). + * + *

Below is an example of serializing complex types as JSON arrays: + *

 {@code
+   *   Gson gson = new GsonBuilder()
+   *       .enableComplexMapKeySerialization()
+   *       .create();
+   *
+   *   Map original = new LinkedHashMap();
+   *   original.put(new Point(5, 6), "a");
+   *   original.put(new Point(8, 8), "b");
+   *   System.out.println(gson.toJson(original, type));
+   * }
+   *
+   * The JSON output would look as follows:
+   * 
   {@code
+   *   [
+   *     [
+   *       {
+   *         "x": 5,
+   *         "y": 6
+   *       },
+   *       "a"
+   *     ],
+   *     [
+   *       {
+   *         "x": 8,
+   *         "y": 8
+   *       },
+   *       "b"
+   *     ]
+   *   ]
+   * }
+ * + * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern + * @since 1.7 + */ + public GsonBuilder enableComplexMapKeySerialization() { + complexMapKeySerialization = true; + return this; + } + + /** + * Configures Gson to exclude inner classes during serialization. + * + * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern + * @since 1.3 + */ + public GsonBuilder disableInnerClassSerialization() { + excluder = excluder.disableInnerClassSerialization(); + return this; + } + + /** + * Configures Gson to apply a specific serialization policy for {@code Long} and {@code long} + * objects. + * + * @param serializationPolicy the particular policy to use for serializing longs. + * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern + * @since 1.3 + */ + public GsonBuilder setLongSerializationPolicy(LongSerializationPolicy serializationPolicy) { + this.longSerializationPolicy = serializationPolicy; + return this; + } + + /** + * Configures Gson to apply a specific naming policy to an object's field during serialization + * and deserialization. + * + * @param namingConvention the JSON field naming convention to use for serialization and + * deserialization. + * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern + */ + public GsonBuilder setFieldNamingPolicy(FieldNamingPolicy namingConvention) { + this.fieldNamingPolicy = namingConvention; + return this; + } + + /** + * Configures Gson to apply a specific naming policy strategy to an object's field during + * serialization and deserialization. + * + * @param fieldNamingStrategy the actual naming strategy to apply to the fields + * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern + * @since 1.3 + */ + public GsonBuilder setFieldNamingStrategy(FieldNamingStrategy fieldNamingStrategy) { + this.fieldNamingPolicy = fieldNamingStrategy; + return this; + } + + /** + * Configures Gson to apply a set of exclusion strategies during both serialization and + * deserialization. Each of the {@code strategies} will be applied as a disjunction rule. + * This means that if one of the {@code strategies} suggests that a field (or class) should be + * skipped then that field (or object) is skipped during serialization/deserialization. + * + * @param strategies the set of strategy object to apply during object (de)serialization. + * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern + * @since 1.4 + */ + public GsonBuilder setExclusionStrategies(ExclusionStrategy... strategies) { + for (ExclusionStrategy strategy : strategies) { + excluder = excluder.withExclusionStrategy(strategy, true, true); + } + return this; + } + + /** + * Configures Gson to apply the passed in exclusion strategy during serialization. + * If this method is invoked numerous times with different exclusion strategy objects + * then the exclusion strategies that were added will be applied as a disjunction rule. + * This means that if one of the added exclusion strategies suggests that a field (or + * class) should be skipped then that field (or object) is skipped during its + * serialization. + * + * @param strategy an exclusion strategy to apply during serialization. + * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern + * @since 1.7 + */ + public GsonBuilder addSerializationExclusionStrategy(ExclusionStrategy strategy) { + excluder = excluder.withExclusionStrategy(strategy, true, false); + return this; + } + + /** + * Configures Gson to apply the passed in exclusion strategy during deserialization. + * If this method is invoked numerous times with different exclusion strategy objects + * then the exclusion strategies that were added will be applied as a disjunction rule. + * This means that if one of the added exclusion strategies suggests that a field (or + * class) should be skipped then that field (or object) is skipped during its + * deserialization. + * + * @param strategy an exclusion strategy to apply during deserialization. + * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern + * @since 1.7 + */ + public GsonBuilder addDeserializationExclusionStrategy(ExclusionStrategy strategy) { + excluder = excluder.withExclusionStrategy(strategy, false, true); + return this; + } + + /** + * Configures Gson to output Json that fits in a page for pretty printing. This option only + * affects Json serialization. + * + * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern + */ + public GsonBuilder setPrettyPrinting() { + prettyPrinting = true; + return this; + } + + /** + * By default, Gson is strict and only accepts JSON as specified by + * RFC 4627. This option makes the parser + * liberal in what it accepts. + * + * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern + * @see JsonReader#setLenient(boolean) + */ + public GsonBuilder setLenient() { + lenient = true; + return this; + } + + /** + * By default, Gson escapes HTML characters such as < > etc. Use this option to configure + * Gson to pass-through HTML characters as is. + * + * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern + * @since 1.3 + */ + public GsonBuilder disableHtmlEscaping() { + this.escapeHtmlChars = false; + return this; + } + + /** + * Configures Gson to serialize {@code Date} objects according to the pattern provided. You can + * call this method or {@link #setDateFormat(int)} multiple times, but only the last invocation + * will be used to decide the serialization format. + * + *

The date format will be used to serialize and deserialize {@link java.util.Date}, {@link + * java.sql.Timestamp} and {@link java.sql.Date}. + * + *

Note that this pattern must abide by the convention provided by {@code SimpleDateFormat} + * class. See the documentation in {@link java.text.SimpleDateFormat} for more information on + * valid date and time patterns.

+ * + * @param pattern the pattern that dates will be serialized/deserialized to/from + * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern + * @since 1.2 + */ + public GsonBuilder setDateFormat(String pattern) { + // TODO(Joel): Make this fail fast if it is an invalid date format + this.datePattern = pattern; + return this; + } + + /** + * Configures Gson to to serialize {@code Date} objects according to the style value provided. + * You can call this method or {@link #setDateFormat(String)} multiple times, but only the last + * invocation will be used to decide the serialization format. + * + *

Note that this style value should be one of the predefined constants in the + * {@code DateFormat} class. See the documentation in {@link java.text.DateFormat} for more + * information on the valid style constants.

+ * + * @param style the predefined date style that date objects will be serialized/deserialized + * to/from + * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern + * @since 1.2 + */ + public GsonBuilder setDateFormat(int style) { + this.dateStyle = style; + this.datePattern = null; + return this; + } + + /** + * Configures Gson to to serialize {@code Date} objects according to the style value provided. + * You can call this method or {@link #setDateFormat(String)} multiple times, but only the last + * invocation will be used to decide the serialization format. + * + *

Note that this style value should be one of the predefined constants in the + * {@code DateFormat} class. See the documentation in {@link java.text.DateFormat} for more + * information on the valid style constants.

+ * + * @param dateStyle the predefined date style that date objects will be serialized/deserialized + * to/from + * @param timeStyle the predefined style for the time portion of the date objects + * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern + * @since 1.2 + */ + public GsonBuilder setDateFormat(int dateStyle, int timeStyle) { + this.dateStyle = dateStyle; + this.timeStyle = timeStyle; + this.datePattern = null; + return this; + } + + /** + * Configures Gson for custom serialization or deserialization. This method combines the + * registration of an {@link TypeAdapter}, {@link InstanceCreator}, {@link JsonSerializer}, and a + * {@link JsonDeserializer}. It is best used when a single object {@code typeAdapter} implements + * all the required interfaces for custom serialization with Gson. If a type adapter was + * previously registered for the specified {@code type}, it is overwritten. + * + *

This registers the type specified and no other types: you must manually register related + * types! For example, applications registering {@code boolean.class} should also register {@code + * Boolean.class}. + * + * @param type the type definition for the type adapter being registered + * @param typeAdapter This object must implement at least one of the {@link TypeAdapter}, + * {@link InstanceCreator}, {@link JsonSerializer}, and a {@link JsonDeserializer} interfaces. + * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern + */ + @SuppressWarnings({"unchecked", "rawtypes"}) + public GsonBuilder registerTypeAdapter(Type type, Object typeAdapter) { + $Gson$Preconditions.checkArgument(typeAdapter instanceof JsonSerializer + || typeAdapter instanceof JsonDeserializer + || typeAdapter instanceof InstanceCreator + || typeAdapter instanceof TypeAdapter); + if (typeAdapter instanceof InstanceCreator) { + instanceCreators.put(type, (InstanceCreator) typeAdapter); + } + if (typeAdapter instanceof JsonSerializer || typeAdapter instanceof JsonDeserializer) { + TypeToken typeToken = TypeToken.get(type); + factories.add(TreeTypeAdapter.newFactoryWithMatchRawType(typeToken, typeAdapter)); + } + if (typeAdapter instanceof TypeAdapter) { + factories.add(TypeAdapters.newFactory(TypeToken.get(type), (TypeAdapter)typeAdapter)); + } + return this; + } + + /** + * Register a factory for type adapters. Registering a factory is useful when the type + * adapter needs to be configured based on the type of the field being processed. Gson + * is designed to handle a large number of factories, so you should consider registering + * them to be at par with registering an individual type adapter. + * + * @since 2.1 + */ + public GsonBuilder registerTypeAdapterFactory(TypeAdapterFactory factory) { + factories.add(factory); + return this; + } + + /** + * Configures Gson for custom serialization or deserialization for an inheritance type hierarchy. + * This method combines the registration of a {@link TypeAdapter}, {@link JsonSerializer} and + * a {@link JsonDeserializer}. If a type adapter was previously registered for the specified + * type hierarchy, it is overridden. If a type adapter is registered for a specific type in + * the type hierarchy, it will be invoked instead of the one registered for the type hierarchy. + * + * @param baseType the class definition for the type adapter being registered for the base class + * or interface + * @param typeAdapter This object must implement at least one of {@link TypeAdapter}, + * {@link JsonSerializer} or {@link JsonDeserializer} interfaces. + * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern + * @since 1.7 + */ + @SuppressWarnings({"unchecked", "rawtypes"}) + public GsonBuilder registerTypeHierarchyAdapter(Class baseType, Object typeAdapter) { + $Gson$Preconditions.checkArgument(typeAdapter instanceof JsonSerializer + || typeAdapter instanceof JsonDeserializer + || typeAdapter instanceof TypeAdapter); + if (typeAdapter instanceof JsonDeserializer || typeAdapter instanceof JsonSerializer) { + hierarchyFactories.add(TreeTypeAdapter.newTypeHierarchyFactory(baseType, typeAdapter)); + } + if (typeAdapter instanceof TypeAdapter) { + factories.add(TypeAdapters.newTypeHierarchyFactory(baseType, (TypeAdapter)typeAdapter)); + } + return this; + } + + /** + * Section 2.4 of JSON specification disallows + * special double values (NaN, Infinity, -Infinity). However, + * Javascript + * specification (see section 4.3.20, 4.3.22, 4.3.23) allows these values as valid Javascript + * values. Moreover, most JavaScript engines will accept these special values in JSON without + * problem. So, at a practical level, it makes sense to accept these values as valid JSON even + * though JSON specification disallows them. + * + *

Gson always accepts these special values during deserialization. However, it outputs + * strictly compliant JSON. Hence, if it encounters a float value {@link Float#NaN}, + * {@link Float#POSITIVE_INFINITY}, {@link Float#NEGATIVE_INFINITY}, or a double value + * {@link Double#NaN}, {@link Double#POSITIVE_INFINITY}, {@link Double#NEGATIVE_INFINITY}, it + * will throw an {@link IllegalArgumentException}. This method provides a way to override the + * default behavior when you know that the JSON receiver will be able to handle these special + * values. + * + * @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern + * @since 1.3 + */ + public GsonBuilder serializeSpecialFloatingPointValues() { + this.serializeSpecialFloatingPointValues = true; + return this; + } + + /** + * Creates a {@link Gson} instance based on the current configuration. This method is free of + * side-effects to this {@code GsonBuilder} instance and hence can be called multiple times. + * + * @return an instance of Gson configured with the options currently set in this builder + */ + public Gson create() { + List factories = new ArrayList(this.factories.size() + this.hierarchyFactories.size() + 3); + factories.addAll(this.factories); + Collections.reverse(factories); + + List hierarchyFactories = new ArrayList(this.hierarchyFactories); + Collections.reverse(hierarchyFactories); + factories.addAll(hierarchyFactories); + + addTypeAdaptersForDate(datePattern, dateStyle, timeStyle, factories); + + return new Gson(excluder, fieldNamingPolicy, instanceCreators, + serializeNulls, complexMapKeySerialization, + generateNonExecutableJson, escapeHtmlChars, prettyPrinting, lenient, + serializeSpecialFloatingPointValues, longSerializationPolicy, + datePattern, dateStyle, timeStyle, + this.factories, this.hierarchyFactories, factories); + } + + @SuppressWarnings("unchecked") + private void addTypeAdaptersForDate(String datePattern, int dateStyle, int timeStyle, + List factories) { + DefaultDateTypeAdapter dateTypeAdapter; + TypeAdapter timestampTypeAdapter; + TypeAdapter javaSqlDateTypeAdapter; + if (datePattern != null && !"".equals(datePattern.trim())) { + dateTypeAdapter = new DefaultDateTypeAdapter(Date.class, datePattern); + timestampTypeAdapter = (TypeAdapter) new DefaultDateTypeAdapter(Timestamp.class, datePattern); + javaSqlDateTypeAdapter = (TypeAdapter) new DefaultDateTypeAdapter(java.sql.Date.class, datePattern); + } else if (dateStyle != DateFormat.DEFAULT && timeStyle != DateFormat.DEFAULT) { + dateTypeAdapter = new DefaultDateTypeAdapter(Date.class, dateStyle, timeStyle); + timestampTypeAdapter = (TypeAdapter) new DefaultDateTypeAdapter(Timestamp.class, dateStyle, timeStyle); + javaSqlDateTypeAdapter = (TypeAdapter) new DefaultDateTypeAdapter(java.sql.Date.class, dateStyle, timeStyle); + } else { + return; + } + + factories.add(TypeAdapters.newFactory(Date.class, dateTypeAdapter)); + factories.add(TypeAdapters.newFactory(Timestamp.class, timestampTypeAdapter)); + factories.add(TypeAdapters.newFactory(java.sql.Date.class, javaSqlDateTypeAdapter)); + } +} diff --git a/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/InstanceCreator.java b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/InstanceCreator.java new file mode 100644 index 0000000..162139d --- /dev/null +++ b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/InstanceCreator.java @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2008 Google Inc. + * + * 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. + */ + +package com.google.gson285; + +import java.lang.reflect.Type; + +/** + * This interface is implemented to create instances of a class that does not define a no-args + * constructor. If you can modify the class, you should instead add a private, or public + * no-args constructor. However, that is not possible for library classes, such as JDK classes, or + * a third-party library that you do not have source-code of. In such cases, you should define an + * instance creator for the class. Implementations of this interface should be registered with + * {@link GsonBuilder#registerTypeAdapter(Type, Object)} method before Gson will be able to use + * them. + *

Let us look at an example where defining an InstanceCreator might be useful. The + * {@code Id} class defined below does not have a default no-args constructor.

+ * + *
+ * public class Id<T> {
+ *   private final Class<T> clazz;
+ *   private final long value;
+ *   public Id(Class<T> clazz, long value) {
+ *     this.clazz = clazz;
+ *     this.value = value;
+ *   }
+ * }
+ * 
+ * + *

If Gson encounters an object of type {@code Id} during deserialization, it will throw an + * exception. The easiest way to solve this problem will be to add a (public or private) no-args + * constructor as follows:

+ * + *
+ * private Id() {
+ *   this(Object.class, 0L);
+ * }
+ * 
+ * + *

However, let us assume that the developer does not have access to the source-code of the + * {@code Id} class, or does not want to define a no-args constructor for it. The developer + * can solve this problem by defining an {@code InstanceCreator} for {@code Id}:

+ * + *
+ * class IdInstanceCreator implements InstanceCreator<Id> {
+ *   public Id createInstance(Type type) {
+ *     return new Id(Object.class, 0L);
+ *   }
+ * }
+ * 
+ * + *

Note that it does not matter what the fields of the created instance contain since Gson will + * overwrite them with the deserialized values specified in Json. You should also ensure that a + * new object is returned, not a common object since its fields will be overwritten. + * The developer will need to register {@code IdInstanceCreator} with Gson as follows:

+ * + *
+ * Gson gson = new GsonBuilder().registerTypeAdapter(Id.class, new IdInstanceCreator()).create();
+ * 
+ * + * @param the type of object that will be created by this implementation. + * + * @author Inderjeet Singh + * @author Joel Leitch + */ +public interface InstanceCreator { + + /** + * Gson invokes this call-back method during deserialization to create an instance of the + * specified type. The fields of the returned instance are overwritten with the data present + * in the Json. Since the prior contents of the object are destroyed and overwritten, do not + * return an instance that is useful elsewhere. In particular, do not return a common instance, + * always use {@code new} to create a new instance. + * + * @param type the parameterized T represented as a {@link Type}. + * @return a default object instance of type T. + */ + public T createInstance(Type type); +} diff --git a/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/JsonArray.java b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/JsonArray.java new file mode 100644 index 0000000..3b51a0f --- /dev/null +++ b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/JsonArray.java @@ -0,0 +1,384 @@ +/* + * Copyright (C) 2008 Google Inc. + * + * 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. + */ + +package com.google.gson285; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +/** + * A class representing an array type in Json. An array is a list of {@link JsonElement}s each of + * which can be of a different type. This is an ordered list, meaning that the order in which + * elements are added is preserved. + * + * @author Inderjeet Singh + * @author Joel Leitch + */ +public final class JsonArray extends JsonElement implements Iterable { + private final List elements; + + /** + * Creates an empty JsonArray. + */ + public JsonArray() { + elements = new ArrayList(); + } + + public JsonArray(int capacity) { + elements = new ArrayList(capacity); + } + + /** + * Creates a deep copy of this element and all its children + * @since 2.8.2 + */ + @Override + public JsonArray deepCopy() { + if (!elements.isEmpty()) { + JsonArray result = new JsonArray(elements.size()); + for (JsonElement element : elements) { + result.add(element.deepCopy()); + } + return result; + } + return new JsonArray(); + } + + /** + * Adds the specified boolean to self. + * + * @param bool the boolean that needs to be added to the array. + */ + public void add(Boolean bool) { + elements.add(bool == null ? JsonNull.INSTANCE : new JsonPrimitive(bool)); + } + + /** + * Adds the specified character to self. + * + * @param character the character that needs to be added to the array. + */ + public void add(Character character) { + elements.add(character == null ? JsonNull.INSTANCE : new JsonPrimitive(character)); + } + + /** + * Adds the specified number to self. + * + * @param number the number that needs to be added to the array. + */ + public void add(Number number) { + elements.add(number == null ? JsonNull.INSTANCE : new JsonPrimitive(number)); + } + + /** + * Adds the specified string to self. + * + * @param string the string that needs to be added to the array. + */ + public void add(String string) { + elements.add(string == null ? JsonNull.INSTANCE : new JsonPrimitive(string)); + } + + /** + * Adds the specified element to self. + * + * @param element the element that needs to be added to the array. + */ + public void add(JsonElement element) { + if (element == null) { + element = JsonNull.INSTANCE; + } + elements.add(element); + } + + /** + * Adds all the elements of the specified array to self. + * + * @param array the array whose elements need to be added to the array. + */ + public void addAll(JsonArray array) { + elements.addAll(array.elements); + } + + /** + * Replaces the element at the specified position in this array with the specified element. + * Element can be null. + * @param index index of the element to replace + * @param element element to be stored at the specified position + * @return the element previously at the specified position + * @throws IndexOutOfBoundsException if the specified index is outside the array bounds + */ + public JsonElement set(int index, JsonElement element) { + return elements.set(index, element); + } + + /** + * Removes the first occurrence of the specified element from this array, if it is present. + * If the array does not contain the element, it is unchanged. + * @param element element to be removed from this array, if present + * @return true if this array contained the specified element, false otherwise + * @since 2.3 + */ + public boolean remove(JsonElement element) { + return elements.remove(element); + } + + /** + * Removes the element at the specified position in this array. Shifts any subsequent elements + * to the left (subtracts one from their indices). Returns the element that was removed from + * the array. + * @param index index the index of the element to be removed + * @return the element previously at the specified position + * @throws IndexOutOfBoundsException if the specified index is outside the array bounds + * @since 2.3 + */ + public JsonElement remove(int index) { + return elements.remove(index); + } + + /** + * Returns true if this array contains the specified element. + * @return true if this array contains the specified element. + * @param element whose presence in this array is to be tested + * @since 2.3 + */ + public boolean contains(JsonElement element) { + return elements.contains(element); + } + + /** + * Returns the number of elements in the array. + * + * @return the number of elements in the array. + */ + public int size() { + return elements.size(); + } + + /** + * Returns an iterator to navigate the elements of the array. Since the array is an ordered list, + * the iterator navigates the elements in the order they were inserted. + * + * @return an iterator to navigate the elements of the array. + */ + public Iterator iterator() { + return elements.iterator(); + } + + /** + * Returns the ith element of the array. + * + * @param i the index of the element that is being sought. + * @return the element present at the ith index. + * @throws IndexOutOfBoundsException if i is negative or greater than or equal to the + * {@link #size()} of the array. + */ + public JsonElement get(int i) { + return elements.get(i); + } + + /** + * convenience method to get this array as a {@link Number} if it contains a single element. + * + * @return get this element as a number if it is single element array. + * @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive} and + * is not a valid Number. + * @throws IllegalStateException if the array has more than one element. + */ + @Override + public Number getAsNumber() { + if (elements.size() == 1) { + return elements.get(0).getAsNumber(); + } + throw new IllegalStateException(); + } + + /** + * convenience method to get this array as a {@link String} if it contains a single element. + * + * @return get this element as a String if it is single element array. + * @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive} and + * is not a valid String. + * @throws IllegalStateException if the array has more than one element. + */ + @Override + public String getAsString() { + if (elements.size() == 1) { + return elements.get(0).getAsString(); + } + throw new IllegalStateException(); + } + + /** + * convenience method to get this array as a double if it contains a single element. + * + * @return get this element as a double if it is single element array. + * @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive} and + * is not a valid double. + * @throws IllegalStateException if the array has more than one element. + */ + @Override + public double getAsDouble() { + if (elements.size() == 1) { + return elements.get(0).getAsDouble(); + } + throw new IllegalStateException(); + } + + /** + * convenience method to get this array as a {@link BigDecimal} if it contains a single element. + * + * @return get this element as a {@link BigDecimal} if it is single element array. + * @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive}. + * @throws NumberFormatException if the element at index 0 is not a valid {@link BigDecimal}. + * @throws IllegalStateException if the array has more than one element. + * @since 1.2 + */ + @Override + public BigDecimal getAsBigDecimal() { + if (elements.size() == 1) { + return elements.get(0).getAsBigDecimal(); + } + throw new IllegalStateException(); + } + + /** + * convenience method to get this array as a {@link BigInteger} if it contains a single element. + * + * @return get this element as a {@link BigInteger} if it is single element array. + * @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive}. + * @throws NumberFormatException if the element at index 0 is not a valid {@link BigInteger}. + * @throws IllegalStateException if the array has more than one element. + * @since 1.2 + */ + @Override + public BigInteger getAsBigInteger() { + if (elements.size() == 1) { + return elements.get(0).getAsBigInteger(); + } + throw new IllegalStateException(); + } + + /** + * convenience method to get this array as a float if it contains a single element. + * + * @return get this element as a float if it is single element array. + * @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive} and + * is not a valid float. + * @throws IllegalStateException if the array has more than one element. + */ + @Override + public float getAsFloat() { + if (elements.size() == 1) { + return elements.get(0).getAsFloat(); + } + throw new IllegalStateException(); + } + + /** + * convenience method to get this array as a long if it contains a single element. + * + * @return get this element as a long if it is single element array. + * @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive} and + * is not a valid long. + * @throws IllegalStateException if the array has more than one element. + */ + @Override + public long getAsLong() { + if (elements.size() == 1) { + return elements.get(0).getAsLong(); + } + throw new IllegalStateException(); + } + + /** + * convenience method to get this array as an integer if it contains a single element. + * + * @return get this element as an integer if it is single element array. + * @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive} and + * is not a valid integer. + * @throws IllegalStateException if the array has more than one element. + */ + @Override + public int getAsInt() { + if (elements.size() == 1) { + return elements.get(0).getAsInt(); + } + throw new IllegalStateException(); + } + + @Override + public byte getAsByte() { + if (elements.size() == 1) { + return elements.get(0).getAsByte(); + } + throw new IllegalStateException(); + } + + @Override + public char getAsCharacter() { + if (elements.size() == 1) { + return elements.get(0).getAsCharacter(); + } + throw new IllegalStateException(); + } + + /** + * convenience method to get this array as a primitive short if it contains a single element. + * + * @return get this element as a primitive short if it is single element array. + * @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive} and + * is not a valid short. + * @throws IllegalStateException if the array has more than one element. + */ + @Override + public short getAsShort() { + if (elements.size() == 1) { + return elements.get(0).getAsShort(); + } + throw new IllegalStateException(); + } + + /** + * convenience method to get this array as a boolean if it contains a single element. + * + * @return get this element as a boolean if it is single element array. + * @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive} and + * is not a valid boolean. + * @throws IllegalStateException if the array has more than one element. + */ + @Override + public boolean getAsBoolean() { + if (elements.size() == 1) { + return elements.get(0).getAsBoolean(); + } + throw new IllegalStateException(); + } + + @Override + public boolean equals(Object o) { + return (o == this) || (o instanceof JsonArray && ((JsonArray) o).elements.equals(elements)); + } + + @Override + public int hashCode() { + return elements.hashCode(); + } +} diff --git a/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/JsonDeserializationContext.java b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/JsonDeserializationContext.java new file mode 100644 index 0000000..fb039b1 --- /dev/null +++ b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/JsonDeserializationContext.java @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2008 Google Inc. + * + * 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. + */ + +package com.google.gson285; + +import java.lang.reflect.Type; + +/** + * Context for deserialization that is passed to a custom deserializer during invocation of its + * {@link JsonDeserializer#deserialize(JsonElement, Type, JsonDeserializationContext)} + * method. + * + * @author Inderjeet Singh + * @author Joel Leitch + */ +public interface JsonDeserializationContext { + + /** + * Invokes default deserialization on the specified object. It should never be invoked on + * the element received as a parameter of the + * {@link JsonDeserializer#deserialize(JsonElement, Type, JsonDeserializationContext)} method. Doing + * so will result in an infinite loop since Gson will in-turn call the custom deserializer again. + * + * @param json the parse tree. + * @param typeOfT type of the expected return value. + * @param The type of the deserialized object. + * @return An object of type typeOfT. + * @throws JsonParseException if the parse tree does not contain expected data. + */ + public T deserialize(JsonElement json, Type typeOfT) throws JsonParseException; +} \ No newline at end of file diff --git a/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/JsonDeserializer.java b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/JsonDeserializer.java new file mode 100644 index 0000000..f08c6b9 --- /dev/null +++ b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/JsonDeserializer.java @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2008 Google Inc. + * + * 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. + */ + +package com.google.gson285; + +import java.lang.reflect.Type; + +/** + *

Interface representing a custom deserializer for Json. You should write a custom + * deserializer, if you are not happy with the default deserialization done by Gson. You will + * also need to register this deserializer through + * {@link GsonBuilder#registerTypeAdapter(Type, Object)}.

+ * + *

Let us look at example where defining a deserializer will be useful. The {@code Id} class + * defined below has two fields: {@code clazz} and {@code value}.

+ * + *
+ * public class Id<T> {
+ *   private final Class<T> clazz;
+ *   private final long value;
+ *   public Id(Class<T> clazz, long value) {
+ *     this.clazz = clazz;
+ *     this.value = value;
+ *   }
+ *   public long getValue() {
+ *     return value;
+ *   }
+ * }
+ * 
+ * + *

The default deserialization of {@code Id(com.foo.MyObject.class, 20L)} will require the + * Json string to be {"clazz":com.foo.MyObject,"value":20}. Suppose, you already know + * the type of the field that the {@code Id} will be deserialized into, and hence just want to + * deserialize it from a Json string {@code 20}. You can achieve that by writing a custom + * deserializer:

+ * + *
+ * class IdDeserializer implements JsonDeserializer<Id>() {
+ *   public Id deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
+ *       throws JsonParseException {
+ *     return new Id((Class)typeOfT, id.getValue());
+ *   }
+ * 
+ * + *

You will also need to register {@code IdDeserializer} with Gson as follows:

+ * + *
+ * Gson gson = new GsonBuilder().registerTypeAdapter(Id.class, new IdDeserializer()).create();
+ * 
+ * + *

New applications should prefer {@link TypeAdapter}, whose streaming API + * is more efficient than this interface's tree API. + * + * @author Inderjeet Singh + * @author Joel Leitch + * + * @param type for which the deserializer is being registered. It is possible that a + * deserializer may be asked to deserialize a specific generic type of the T. + */ +public interface JsonDeserializer { + + /** + * Gson invokes this call-back method during deserialization when it encounters a field of the + * specified type. + *

In the implementation of this call-back method, you should consider invoking + * {@link JsonDeserializationContext#deserialize(JsonElement, Type)} method to create objects + * for any non-trivial field of the returned object. However, you should never invoke it on the + * the same type passing {@code json} since that will cause an infinite loop (Gson will call your + * call-back method again). + * + * @param json The Json data being deserialized + * @param typeOfT The type of the Object to deserialize to + * @return a deserialized object of the specified type typeOfT which is a subclass of {@code T} + * @throws JsonParseException if json is not in the expected format of {@code typeofT} + */ + public T deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) + throws JsonParseException; +} diff --git a/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/JsonElement.java b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/JsonElement.java new file mode 100644 index 0000000..0341fe1 --- /dev/null +++ b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/JsonElement.java @@ -0,0 +1,335 @@ +/* + * Copyright (C) 2008 Google Inc. + * + * 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. + */ + +package com.google.gson285; + +import com.google.gson285.internal.Streams; +import com.google.gson285.stream.JsonWriter; +import java.io.IOException; +import java.io.StringWriter; +import java.math.BigDecimal; +import java.math.BigInteger; + +/** + * A class representing an element of Json. It could either be a {@link JsonObject}, a + * {@link JsonArray}, a {@link JsonPrimitive} or a {@link JsonNull}. + * + * @author Inderjeet Singh + * @author Joel Leitch + */ +public abstract class JsonElement { + /** + * Returns a deep copy of this element. Immutable elements like primitives + * and nulls are not copied. + * @since 2.8.2 + */ + public abstract JsonElement deepCopy(); + + /** + * provides check for verifying if this element is an array or not. + * + * @return true if this element is of type {@link JsonArray}, false otherwise. + */ + public boolean isJsonArray() { + return this instanceof JsonArray; + } + + /** + * provides check for verifying if this element is a Json object or not. + * + * @return true if this element is of type {@link JsonObject}, false otherwise. + */ + public boolean isJsonObject() { + return this instanceof JsonObject; + } + + /** + * provides check for verifying if this element is a primitive or not. + * + * @return true if this element is of type {@link JsonPrimitive}, false otherwise. + */ + public boolean isJsonPrimitive() { + return this instanceof JsonPrimitive; + } + + /** + * provides check for verifying if this element represents a null value or not. + * + * @return true if this element is of type {@link JsonNull}, false otherwise. + * @since 1.2 + */ + public boolean isJsonNull() { + return this instanceof JsonNull; + } + + /** + * convenience method to get this element as a {@link JsonObject}. If the element is of some + * other type, a {@link IllegalStateException} will result. Hence it is best to use this method + * after ensuring that this element is of the desired type by calling {@link #isJsonObject()} + * first. + * + * @return get this element as a {@link JsonObject}. + * @throws IllegalStateException if the element is of another type. + */ + public JsonObject getAsJsonObject() { + if (isJsonObject()) { + return (JsonObject) this; + } + throw new IllegalStateException("Not a JSON Object: " + this); + } + + /** + * convenience method to get this element as a {@link JsonArray}. If the element is of some + * other type, a {@link IllegalStateException} will result. Hence it is best to use this method + * after ensuring that this element is of the desired type by calling {@link #isJsonArray()} + * first. + * + * @return get this element as a {@link JsonArray}. + * @throws IllegalStateException if the element is of another type. + */ + public JsonArray getAsJsonArray() { + if (isJsonArray()) { + return (JsonArray) this; + } + throw new IllegalStateException("Not a JSON Array: " + this); + } + + /** + * convenience method to get this element as a {@link JsonPrimitive}. If the element is of some + * other type, a {@link IllegalStateException} will result. Hence it is best to use this method + * after ensuring that this element is of the desired type by calling {@link #isJsonPrimitive()} + * first. + * + * @return get this element as a {@link JsonPrimitive}. + * @throws IllegalStateException if the element is of another type. + */ + public JsonPrimitive getAsJsonPrimitive() { + if (isJsonPrimitive()) { + return (JsonPrimitive) this; + } + throw new IllegalStateException("Not a JSON Primitive: " + this); + } + + /** + * convenience method to get this element as a {@link JsonNull}. If the element is of some + * other type, a {@link IllegalStateException} will result. Hence it is best to use this method + * after ensuring that this element is of the desired type by calling {@link #isJsonNull()} + * first. + * + * @return get this element as a {@link JsonNull}. + * @throws IllegalStateException if the element is of another type. + * @since 1.2 + */ + public JsonNull getAsJsonNull() { + if (isJsonNull()) { + return (JsonNull) this; + } + throw new IllegalStateException("Not a JSON Null: " + this); + } + + /** + * convenience method to get this element as a boolean value. + * + * @return get this element as a primitive boolean value. + * @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid + * boolean value. + * @throws IllegalStateException if the element is of the type {@link JsonArray} but contains + * more than a single element. + */ + public boolean getAsBoolean() { + throw new UnsupportedOperationException(getClass().getSimpleName()); + } + + /** + * convenience method to get this element as a {@link Boolean} value. + * + * @return get this element as a {@link Boolean} value. + * @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid + * boolean value. + * @throws IllegalStateException if the element is of the type {@link JsonArray} but contains + * more than a single element. + */ + Boolean getAsBooleanWrapper() { + throw new UnsupportedOperationException(getClass().getSimpleName()); + } + + /** + * convenience method to get this element as a {@link Number}. + * + * @return get this element as a {@link Number}. + * @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid + * number. + * @throws IllegalStateException if the element is of the type {@link JsonArray} but contains + * more than a single element. + */ + public Number getAsNumber() { + throw new UnsupportedOperationException(getClass().getSimpleName()); + } + + /** + * convenience method to get this element as a string value. + * + * @return get this element as a string value. + * @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid + * string value. + * @throws IllegalStateException if the element is of the type {@link JsonArray} but contains + * more than a single element. + */ + public String getAsString() { + throw new UnsupportedOperationException(getClass().getSimpleName()); + } + + /** + * convenience method to get this element as a primitive double value. + * + * @return get this element as a primitive double value. + * @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid + * double value. + * @throws IllegalStateException if the element is of the type {@link JsonArray} but contains + * more than a single element. + */ + public double getAsDouble() { + throw new UnsupportedOperationException(getClass().getSimpleName()); + } + + /** + * convenience method to get this element as a primitive float value. + * + * @return get this element as a primitive float value. + * @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid + * float value. + * @throws IllegalStateException if the element is of the type {@link JsonArray} but contains + * more than a single element. + */ + public float getAsFloat() { + throw new UnsupportedOperationException(getClass().getSimpleName()); + } + + /** + * convenience method to get this element as a primitive long value. + * + * @return get this element as a primitive long value. + * @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid + * long value. + * @throws IllegalStateException if the element is of the type {@link JsonArray} but contains + * more than a single element. + */ + public long getAsLong() { + throw new UnsupportedOperationException(getClass().getSimpleName()); + } + + /** + * convenience method to get this element as a primitive integer value. + * + * @return get this element as a primitive integer value. + * @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid + * integer value. + * @throws IllegalStateException if the element is of the type {@link JsonArray} but contains + * more than a single element. + */ + public int getAsInt() { + throw new UnsupportedOperationException(getClass().getSimpleName()); + } + + /** + * convenience method to get this element as a primitive byte value. + * + * @return get this element as a primitive byte value. + * @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid + * byte value. + * @throws IllegalStateException if the element is of the type {@link JsonArray} but contains + * more than a single element. + * @since 1.3 + */ + public byte getAsByte() { + throw new UnsupportedOperationException(getClass().getSimpleName()); + } + + /** + * convenience method to get the first character of this element as a string or the first + * character of this array's first element as a string. + * + * @return the first character of the string. + * @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid + * string value. + * @throws IllegalStateException if the element is of the type {@link JsonArray} but contains + * more than a single element. + * @since 1.3 + * @deprecated This method is misleading, as it does not get this element as a char but rather as + * a string's first character. + */ + @Deprecated + public char getAsCharacter() { + throw new UnsupportedOperationException(getClass().getSimpleName()); + } + + /** + * convenience method to get this element as a {@link BigDecimal}. + * + * @return get this element as a {@link BigDecimal}. + * @throws ClassCastException if the element is of not a {@link JsonPrimitive}. + * * @throws NumberFormatException if the element is not a valid {@link BigDecimal}. + * @throws IllegalStateException if the element is of the type {@link JsonArray} but contains + * more than a single element. + * @since 1.2 + */ + public BigDecimal getAsBigDecimal() { + throw new UnsupportedOperationException(getClass().getSimpleName()); + } + + /** + * convenience method to get this element as a {@link BigInteger}. + * + * @return get this element as a {@link BigInteger}. + * @throws ClassCastException if the element is of not a {@link JsonPrimitive}. + * @throws NumberFormatException if the element is not a valid {@link BigInteger}. + * @throws IllegalStateException if the element is of the type {@link JsonArray} but contains + * more than a single element. + * @since 1.2 + */ + public BigInteger getAsBigInteger() { + throw new UnsupportedOperationException(getClass().getSimpleName()); + } + + /** + * convenience method to get this element as a primitive short value. + * + * @return get this element as a primitive short value. + * @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid + * short value. + * @throws IllegalStateException if the element is of the type {@link JsonArray} but contains + * more than a single element. + */ + public short getAsShort() { + throw new UnsupportedOperationException(getClass().getSimpleName()); + } + + /** + * Returns a String representation of this element. + */ + @Override + public String toString() { + try { + StringWriter stringWriter = new StringWriter(); + JsonWriter jsonWriter = new JsonWriter(stringWriter); + jsonWriter.setLenient(true); + Streams.write(this, jsonWriter); + return stringWriter.toString(); + } catch (IOException e) { + throw new AssertionError(e); + } + } +} diff --git a/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/JsonIOException.java b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/JsonIOException.java new file mode 100644 index 0000000..799b82b --- /dev/null +++ b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/JsonIOException.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2008 Google Inc. + * + * 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. + */ +package com.google.gson285; + +/** + * This exception is raised when Gson was unable to read an input stream + * or write to one. + * + * @author Inderjeet Singh + * @author Joel Leitch + */ +public final class JsonIOException extends JsonParseException { + private static final long serialVersionUID = 1L; + + public JsonIOException(String msg) { + super(msg); + } + + public JsonIOException(String msg, Throwable cause) { + super(msg, cause); + } + + /** + * Creates exception with the specified cause. Consider using + * {@link #JsonIOException(String, Throwable)} instead if you can describe what happened. + * + * @param cause root exception that caused this exception to be thrown. + */ + public JsonIOException(Throwable cause) { + super(cause); + } +} diff --git a/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/JsonNull.java b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/JsonNull.java new file mode 100644 index 0000000..ee5fcff --- /dev/null +++ b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/JsonNull.java @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2008 Google Inc. + * + * 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. + */ + +package com.google.gson285; + +/** + * A class representing a Json {@code null} value. + * + * @author Inderjeet Singh + * @author Joel Leitch + * @since 1.2 + */ +public final class JsonNull extends JsonElement { + /** + * singleton for JsonNull + * + * @since 1.8 + */ + public static final JsonNull INSTANCE = new JsonNull(); + + /** + * Creates a new JsonNull object. + * Deprecated since Gson version 1.8. Use {@link #INSTANCE} instead + */ + @Deprecated + public JsonNull() { + // Do nothing + } + + /** + * Returns the same instance since it is an immutable value + * @since 2.8.2 + */ + @Override + public JsonNull deepCopy() { + return INSTANCE; + } + + /** + * All instances of JsonNull have the same hash code since they are indistinguishable + */ + @Override + public int hashCode() { + return JsonNull.class.hashCode(); + } + + /** + * All instances of JsonNull are the same + */ + @Override + public boolean equals(Object other) { + return this == other || other instanceof JsonNull; + } +} diff --git a/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/JsonObject.java b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/JsonObject.java new file mode 100644 index 0000000..c9a89d2 --- /dev/null +++ b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/JsonObject.java @@ -0,0 +1,218 @@ +/* + * Copyright (C) 2008 Google Inc. + * + * 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. + */ + +package com.google.gson285; + +import com.google.gson285.internal.LinkedTreeMap; + +import java.util.Map; +import java.util.Set; + +/** + * A class representing an object type in Json. An object consists of name-value pairs where names + * are strings, and values are any other type of {@link JsonElement}. This allows for a creating a + * tree of JsonElements. The member elements of this object are maintained in order they were added. + * + * @author Inderjeet Singh + * @author Joel Leitch + */ +public final class JsonObject extends JsonElement { + private final LinkedTreeMap members = + new LinkedTreeMap(); + + /** + * Creates a deep copy of this element and all its children + * @since 2.8.2 + */ + @Override + public JsonObject deepCopy() { + JsonObject result = new JsonObject(); + for (Map.Entry entry : members.entrySet()) { + result.add(entry.getKey(), entry.getValue().deepCopy()); + } + return result; + } + + /** + * Adds a member, which is a name-value pair, to self. The name must be a String, but the value + * can be an arbitrary JsonElement, thereby allowing you to build a full tree of JsonElements + * rooted at this node. + * + * @param property name of the member. + * @param value the member object. + */ + public void add(String property, JsonElement value) { + if (value == null) { + value = JsonNull.INSTANCE; + } + members.put(property, value); + } + + /** + * Removes the {@code property} from this {@link JsonObject}. + * + * @param property name of the member that should be removed. + * @return the {@link JsonElement} object that is being removed. + * @since 1.3 + */ + public JsonElement remove(String property) { + return members.remove(property); + } + + /** + * Convenience method to add a primitive member. The specified value is converted to a + * JsonPrimitive of String. + * + * @param property name of the member. + * @param value the string value associated with the member. + */ + public void addProperty(String property, String value) { + add(property, createJsonElement(value)); + } + + /** + * Convenience method to add a primitive member. The specified value is converted to a + * JsonPrimitive of Number. + * + * @param property name of the member. + * @param value the number value associated with the member. + */ + public void addProperty(String property, Number value) { + add(property, createJsonElement(value)); + } + + /** + * Convenience method to add a boolean member. The specified value is converted to a + * JsonPrimitive of Boolean. + * + * @param property name of the member. + * @param value the number value associated with the member. + */ + public void addProperty(String property, Boolean value) { + add(property, createJsonElement(value)); + } + + /** + * Convenience method to add a char member. The specified value is converted to a + * JsonPrimitive of Character. + * + * @param property name of the member. + * @param value the number value associated with the member. + */ + public void addProperty(String property, Character value) { + add(property, createJsonElement(value)); + } + + /** + * Creates the proper {@link JsonElement} object from the given {@code value} object. + * + * @param value the object to generate the {@link JsonElement} for + * @return a {@link JsonPrimitive} if the {@code value} is not null, otherwise a {@link JsonNull} + */ + private JsonElement createJsonElement(Object value) { + return value == null ? JsonNull.INSTANCE : new JsonPrimitive(value); + } + + /** + * Returns a set of members of this object. The set is ordered, and the order is in which the + * elements were added. + * + * @return a set of members of this object. + */ + public Set> entrySet() { + return members.entrySet(); + } + + /** + * Returns a set of members key values. + * + * @return a set of member keys as Strings + * @since 2.8.1 + */ + public Set keySet() { + return members.keySet(); + } + + /** + * Returns the number of key/value pairs in the object. + * + * @return the number of key/value pairs in the object. + */ + public int size() { + return members.size(); + } + + /** + * Convenience method to check if a member with the specified name is present in this object. + * + * @param memberName name of the member that is being checked for presence. + * @return true if there is a member with the specified name, false otherwise. + */ + public boolean has(String memberName) { + return members.containsKey(memberName); + } + + /** + * Returns the member with the specified name. + * + * @param memberName name of the member that is being requested. + * @return the member matching the name. Null if no such member exists. + */ + public JsonElement get(String memberName) { + return members.get(memberName); + } + + /** + * Convenience method to get the specified member as a JsonPrimitive element. + * + * @param memberName name of the member being requested. + * @return the JsonPrimitive corresponding to the specified member. + */ + public JsonPrimitive getAsJsonPrimitive(String memberName) { + return (JsonPrimitive) members.get(memberName); + } + + /** + * Convenience method to get the specified member as a JsonArray. + * + * @param memberName name of the member being requested. + * @return the JsonArray corresponding to the specified member. + */ + public JsonArray getAsJsonArray(String memberName) { + return (JsonArray) members.get(memberName); + } + + /** + * Convenience method to get the specified member as a JsonObject. + * + * @param memberName name of the member being requested. + * @return the JsonObject corresponding to the specified member. + */ + public JsonObject getAsJsonObject(String memberName) { + return (JsonObject) members.get(memberName); + } + + @Override + public boolean equals(Object o) { + return (o == this) || (o instanceof JsonObject + && ((JsonObject) o).members.equals(members)); + } + + @Override + public int hashCode() { + return members.hashCode(); + } +} diff --git a/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/JsonParseException.java b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/JsonParseException.java new file mode 100644 index 0000000..b39c277 --- /dev/null +++ b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/JsonParseException.java @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2008 Google Inc. + * + * 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. + */ + +package com.google.gson285; + +/** + * This exception is raised if there is a serious issue that occurs during parsing of a Json + * string. One of the main usages for this class is for the Gson infrastructure. If the incoming + * Json is bad/malicious, an instance of this exception is raised. + * + *

This exception is a {@link RuntimeException} because it is exposed to the client. Using a + * {@link RuntimeException} avoids bad coding practices on the client side where they catch the + * exception and do nothing. It is often the case that you want to blow up if there is a parsing + * error (i.e. often clients do not know how to recover from a {@link JsonParseException}.

+ * + * @author Inderjeet Singh + * @author Joel Leitch + */ +public class JsonParseException extends RuntimeException { + static final long serialVersionUID = -4086729973971783390L; + + /** + * Creates exception with the specified message. If you are wrapping another exception, consider + * using {@link #JsonParseException(String, Throwable)} instead. + * + * @param msg error message describing a possible cause of this exception. + */ + public JsonParseException(String msg) { + super(msg); + } + + /** + * Creates exception with the specified message and cause. + * + * @param msg error message describing what happened. + * @param cause root exception that caused this exception to be thrown. + */ + public JsonParseException(String msg, Throwable cause) { + super(msg, cause); + } + + /** + * Creates exception with the specified cause. Consider using + * {@link #JsonParseException(String, Throwable)} instead if you can describe what happened. + * + * @param cause root exception that caused this exception to be thrown. + */ + public JsonParseException(Throwable cause) { + super(cause); + } +} diff --git a/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/JsonParser.java b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/JsonParser.java new file mode 100644 index 0000000..02413b2 --- /dev/null +++ b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/JsonParser.java @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2009 Google Inc. + * + * 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. + */ +package com.google.gson285; + +import java.io.IOException; +import java.io.Reader; +import java.io.StringReader; + +import com.google.gson285.internal.Streams; +import com.google.gson285.stream.JsonReader; +import com.google.gson285.stream.JsonToken; +import com.google.gson285.stream.MalformedJsonException; + +/** + * A parser to parse Json into a parse tree of {@link JsonElement}s + * + * @author Inderjeet Singh + * @author Joel Leitch + * @since 1.3 + */ +public final class JsonParser { + + /** + * Parses the specified JSON string into a parse tree + * + * @param json JSON text + * @return a parse tree of {@link JsonElement}s corresponding to the specified JSON + * @throws JsonParseException if the specified text is not valid JSON + * @since 1.3 + */ + public JsonElement parse(String json) throws JsonSyntaxException { + return parse(new StringReader(json)); + } + + /** + * Parses the specified JSON string into a parse tree + * + * @param json JSON text + * @return a parse tree of {@link JsonElement}s corresponding to the specified JSON + * @throws JsonParseException if the specified text is not valid JSON + * @since 1.3 + */ + public JsonElement parse(Reader json) throws JsonIOException, JsonSyntaxException { + try { + JsonReader jsonReader = new JsonReader(json); + JsonElement element = parse(jsonReader); + if (!element.isJsonNull() && jsonReader.peek() != JsonToken.END_DOCUMENT) { + throw new JsonSyntaxException("Did not consume the entire document."); + } + return element; + } catch (MalformedJsonException e) { + throw new JsonSyntaxException(e); + } catch (IOException e) { + throw new JsonIOException(e); + } catch (NumberFormatException e) { + throw new JsonSyntaxException(e); + } + } + + /** + * Returns the next value from the JSON stream as a parse tree. + * + * @throws JsonParseException if there is an IOException or if the specified + * text is not valid JSON + * @since 1.6 + */ + public JsonElement parse(JsonReader json) throws JsonIOException, JsonSyntaxException { + boolean lenient = json.isLenient(); + json.setLenient(true); + try { + return Streams.parse(json); + } catch (StackOverflowError e) { + throw new JsonParseException("Failed parsing JSON source: " + json + " to Json", e); + } catch (OutOfMemoryError e) { + throw new JsonParseException("Failed parsing JSON source: " + json + " to Json", e); + } finally { + json.setLenient(lenient); + } + } +} diff --git a/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/JsonPrimitive.java b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/JsonPrimitive.java new file mode 100644 index 0000000..0327582 --- /dev/null +++ b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/JsonPrimitive.java @@ -0,0 +1,345 @@ +/* + * Copyright (C) 2008 Google Inc. + * + * 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. + */ + +package com.google.gson285; + +import java.math.BigDecimal; +import java.math.BigInteger; + +import com.google.gson285.internal.$Gson$Preconditions; +import com.google.gson285.internal.LazilyParsedNumber; + +/** + * A class representing a Json primitive value. A primitive value + * is either a String, a Java primitive, or a Java primitive + * wrapper type. + * + * @author Inderjeet Singh + * @author Joel Leitch + */ +public final class JsonPrimitive extends JsonElement { + + private static final Class[] PRIMITIVE_TYPES = { int.class, long.class, short.class, + float.class, double.class, byte.class, boolean.class, char.class, Integer.class, Long.class, + Short.class, Float.class, Double.class, Byte.class, Boolean.class, Character.class }; + + private Object value; + + /** + * Create a primitive containing a boolean value. + * + * @param bool the value to create the primitive with. + */ + public JsonPrimitive(Boolean bool) { + setValue(bool); + } + + /** + * Create a primitive containing a {@link Number}. + * + * @param number the value to create the primitive with. + */ + public JsonPrimitive(Number number) { + setValue(number); + } + + /** + * Create a primitive containing a String value. + * + * @param string the value to create the primitive with. + */ + public JsonPrimitive(String string) { + setValue(string); + } + + /** + * Create a primitive containing a character. The character is turned into a one character String + * since Json only supports String. + * + * @param c the value to create the primitive with. + */ + public JsonPrimitive(Character c) { + setValue(c); + } + + /** + * Create a primitive using the specified Object. It must be an instance of {@link Number}, a + * Java primitive type, or a String. + * + * @param primitive the value to create the primitive with. + */ + JsonPrimitive(Object primitive) { + setValue(primitive); + } + + /** + * Returns the same value as primitives are immutable. + * @since 2.8.2 + */ + @Override + public JsonPrimitive deepCopy() { + return this; + } + + void setValue(Object primitive) { + if (primitive instanceof Character) { + // convert characters to strings since in JSON, characters are represented as a single + // character string + char c = ((Character) primitive).charValue(); + this.value = String.valueOf(c); + } else { + $Gson$Preconditions.checkArgument(primitive instanceof Number + || isPrimitiveOrString(primitive)); + this.value = primitive; + } + } + + /** + * Check whether this primitive contains a boolean value. + * + * @return true if this primitive contains a boolean value, false otherwise. + */ + public boolean isBoolean() { + return value instanceof Boolean; + } + + /** + * convenience method to get this element as a {@link Boolean}. + * + * @return get this element as a {@link Boolean}. + */ + @Override + Boolean getAsBooleanWrapper() { + return (Boolean) value; + } + + /** + * convenience method to get this element as a boolean value. + * + * @return get this element as a primitive boolean value. + */ + @Override + public boolean getAsBoolean() { + if (isBoolean()) { + return getAsBooleanWrapper().booleanValue(); + } else { + // Check to see if the value as a String is "true" in any case. + return Boolean.parseBoolean(getAsString()); + } + } + + /** + * Check whether this primitive contains a Number. + * + * @return true if this primitive contains a Number, false otherwise. + */ + public boolean isNumber() { + return value instanceof Number; + } + + /** + * convenience method to get this element as a Number. + * + * @return get this element as a Number. + * @throws NumberFormatException if the value contained is not a valid Number. + */ + @Override + public Number getAsNumber() { + return value instanceof String ? new LazilyParsedNumber((String) value) : (Number) value; + } + + /** + * Check whether this primitive contains a String value. + * + * @return true if this primitive contains a String value, false otherwise. + */ + public boolean isString() { + return value instanceof String; + } + + /** + * convenience method to get this element as a String. + * + * @return get this element as a String. + */ + @Override + public String getAsString() { + if (isNumber()) { + return getAsNumber().toString(); + } else if (isBoolean()) { + return getAsBooleanWrapper().toString(); + } else { + return (String) value; + } + } + + /** + * convenience method to get this element as a primitive double. + * + * @return get this element as a primitive double. + * @throws NumberFormatException if the value contained is not a valid double. + */ + @Override + public double getAsDouble() { + return isNumber() ? getAsNumber().doubleValue() : Double.parseDouble(getAsString()); + } + + /** + * convenience method to get this element as a {@link BigDecimal}. + * + * @return get this element as a {@link BigDecimal}. + * @throws NumberFormatException if the value contained is not a valid {@link BigDecimal}. + */ + @Override + public BigDecimal getAsBigDecimal() { + return value instanceof BigDecimal ? (BigDecimal) value : new BigDecimal(value.toString()); + } + + /** + * convenience method to get this element as a {@link BigInteger}. + * + * @return get this element as a {@link BigInteger}. + * @throws NumberFormatException if the value contained is not a valid {@link BigInteger}. + */ + @Override + public BigInteger getAsBigInteger() { + return value instanceof BigInteger ? + (BigInteger) value : new BigInteger(value.toString()); + } + + /** + * convenience method to get this element as a float. + * + * @return get this element as a float. + * @throws NumberFormatException if the value contained is not a valid float. + */ + @Override + public float getAsFloat() { + return isNumber() ? getAsNumber().floatValue() : Float.parseFloat(getAsString()); + } + + /** + * convenience method to get this element as a primitive long. + * + * @return get this element as a primitive long. + * @throws NumberFormatException if the value contained is not a valid long. + */ + @Override + public long getAsLong() { + return isNumber() ? getAsNumber().longValue() : Long.parseLong(getAsString()); + } + + /** + * convenience method to get this element as a primitive short. + * + * @return get this element as a primitive short. + * @throws NumberFormatException if the value contained is not a valid short value. + */ + @Override + public short getAsShort() { + return isNumber() ? getAsNumber().shortValue() : Short.parseShort(getAsString()); + } + + /** + * convenience method to get this element as a primitive integer. + * + * @return get this element as a primitive integer. + * @throws NumberFormatException if the value contained is not a valid integer. + */ + @Override + public int getAsInt() { + return isNumber() ? getAsNumber().intValue() : Integer.parseInt(getAsString()); + } + + @Override + public byte getAsByte() { + return isNumber() ? getAsNumber().byteValue() : Byte.parseByte(getAsString()); + } + + @Override + public char getAsCharacter() { + return getAsString().charAt(0); + } + + private static boolean isPrimitiveOrString(Object target) { + if (target instanceof String) { + return true; + } + + Class classOfPrimitive = target.getClass(); + for (Class standardPrimitive : PRIMITIVE_TYPES) { + if (standardPrimitive.isAssignableFrom(classOfPrimitive)) { + return true; + } + } + return false; + } + + @Override + public int hashCode() { + if (value == null) { + return 31; + } + // Using recommended hashing algorithm from Effective Java for longs and doubles + if (isIntegral(this)) { + long value = getAsNumber().longValue(); + return (int) (value ^ (value >>> 32)); + } + if (value instanceof Number) { + long value = Double.doubleToLongBits(getAsNumber().doubleValue()); + return (int) (value ^ (value >>> 32)); + } + return value.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null || getClass() != obj.getClass()) { + return false; + } + JsonPrimitive other = (JsonPrimitive)obj; + if (value == null) { + return other.value == null; + } + if (isIntegral(this) && isIntegral(other)) { + return getAsNumber().longValue() == other.getAsNumber().longValue(); + } + if (value instanceof Number && other.value instanceof Number) { + double a = getAsNumber().doubleValue(); + // Java standard types other than double return true for two NaN. So, need + // special handling for double. + double b = other.getAsNumber().doubleValue(); + return a == b || (Double.isNaN(a) && Double.isNaN(b)); + } + return value.equals(other.value); + } + + /** + * Returns true if the specified number is an integral type + * (Long, Integer, Short, Byte, BigInteger) + */ + private static boolean isIntegral(JsonPrimitive primitive) { + if (primitive.value instanceof Number) { + Number number = (Number) primitive.value; + return number instanceof BigInteger || number instanceof Long || number instanceof Integer + || number instanceof Short || number instanceof Byte; + } + return false; + } +} diff --git a/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/JsonSerializationContext.java b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/JsonSerializationContext.java new file mode 100644 index 0000000..f49d9bc --- /dev/null +++ b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/JsonSerializationContext.java @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2008 Google Inc. + * + * 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. + */ + +package com.google.gson285; + +import java.lang.reflect.Type; + +/** + * Context for serialization that is passed to a custom serializer during invocation of its + * {@link JsonSerializer#serialize(Object, Type, JsonSerializationContext)} method. + * + * @author Inderjeet Singh + * @author Joel Leitch + */ +public interface JsonSerializationContext { + + /** + * Invokes default serialization on the specified object. + * + * @param src the object that needs to be serialized. + * @return a tree of {@link JsonElement}s corresponding to the serialized form of {@code src}. + */ + public JsonElement serialize(Object src); + + /** + * Invokes default serialization on the specified object passing the specific type information. + * It should never be invoked on the element received as a parameter of the + * {@link JsonSerializer#serialize(Object, Type, JsonSerializationContext)} method. Doing + * so will result in an infinite loop since Gson will in-turn call the custom serializer again. + * + * @param src the object that needs to be serialized. + * @param typeOfSrc the actual genericized type of src object. + * @return a tree of {@link JsonElement}s corresponding to the serialized form of {@code src}. + */ + public JsonElement serialize(Object src, Type typeOfSrc); +} diff --git a/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/JsonSerializer.java b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/JsonSerializer.java new file mode 100644 index 0000000..f0d028d --- /dev/null +++ b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/JsonSerializer.java @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2008 Google Inc. + * + * 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. + */ + +package com.google.gson285; + +import java.lang.reflect.Type; + +/** + * Interface representing a custom serializer for Json. You should write a custom serializer, if + * you are not happy with the default serialization done by Gson. You will also need to register + * this serializer through {@link com.google.gson285.GsonBuilder#registerTypeAdapter(Type, Object)}. + * + *

Let us look at example where defining a serializer will be useful. The {@code Id} class + * defined below has two fields: {@code clazz} and {@code value}.

+ * + *

+ * public class Id<T> {
+ *   private final Class<T> clazz;
+ *   private final long value;
+ *
+ *   public Id(Class<T> clazz, long value) {
+ *     this.clazz = clazz;
+ *     this.value = value;
+ *   }
+ *
+ *   public long getValue() {
+ *     return value;
+ *   }
+ * }
+ * 

+ * + *

The default serialization of {@code Id(com.foo.MyObject.class, 20L)} will be + * {"clazz":com.foo.MyObject,"value":20}. Suppose, you just want the output to be + * the value instead, which is {@code 20} in this case. You can achieve that by writing a custom + * serializer:

+ * + *

+ * class IdSerializer implements JsonSerializer<Id>() {
+ *   public JsonElement serialize(Id id, Type typeOfId, JsonSerializationContext context) {
+ *     return new JsonPrimitive(id.getValue());
+ *   }
+ * }
+ * 

+ * + *

You will also need to register {@code IdSerializer} with Gson as follows:

+ *
+ * Gson gson = new GsonBuilder().registerTypeAdapter(Id.class, new IdSerializer()).create();
+ * 
+ * + *

New applications should prefer {@link TypeAdapter}, whose streaming API + * is more efficient than this interface's tree API. + * + * @author Inderjeet Singh + * @author Joel Leitch + * + * @param type for which the serializer is being registered. It is possible that a serializer + * may be asked to serialize a specific generic type of the T. + */ +public interface JsonSerializer { + + /** + * Gson invokes this call-back method during serialization when it encounters a field of the + * specified type. + * + *

In the implementation of this call-back method, you should consider invoking + * {@link JsonSerializationContext#serialize(Object, Type)} method to create JsonElements for any + * non-trivial field of the {@code src} object. However, you should never invoke it on the + * {@code src} object itself since that will cause an infinite loop (Gson will call your + * call-back method again).

+ * + * @param src the object that needs to be converted to Json. + * @param typeOfSrc the actual type (fully genericized version) of the source object. + * @return a JsonElement corresponding to the specified object. + */ + public JsonElement serialize(T src, Type typeOfSrc, JsonSerializationContext context); +} diff --git a/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/JsonStreamParser.java b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/JsonStreamParser.java new file mode 100644 index 0000000..0bbd53b --- /dev/null +++ b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/JsonStreamParser.java @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2009 Google Inc. + * + * 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. + */ +package com.google.gson285; + +import java.io.EOFException; +import java.io.IOException; +import java.io.Reader; +import java.io.StringReader; +import java.util.Iterator; +import java.util.NoSuchElementException; + +import com.google.gson285.internal.Streams; +import com.google.gson285.stream.JsonReader; +import com.google.gson285.stream.JsonToken; +import com.google.gson285.stream.MalformedJsonException; + +/** + * A streaming parser that allows reading of multiple {@link JsonElement}s from the specified reader + * asynchronously. + * + *

This class is conditionally thread-safe (see Item 70, Effective Java second edition). To + * properly use this class across multiple threads, you will need to add some external + * synchronization. For example: + * + *

+ * JsonStreamParser parser = new JsonStreamParser("['first'] {'second':10} 'third'");
+ * JsonElement element;
+ * synchronized (parser) {  // synchronize on an object shared by threads
+ *   if (parser.hasNext()) {
+ *     element = parser.next();
+ *   }
+ * }
+ * 
+ * + * @author Inderjeet Singh + * @author Joel Leitch + * @since 1.4 + */ +public final class JsonStreamParser implements Iterator { + private final JsonReader parser; + private final Object lock; + + /** + * @param json The string containing JSON elements concatenated to each other. + * @since 1.4 + */ + public JsonStreamParser(String json) { + this(new StringReader(json)); + } + + /** + * @param reader The data stream containing JSON elements concatenated to each other. + * @since 1.4 + */ + public JsonStreamParser(Reader reader) { + parser = new JsonReader(reader); + parser.setLenient(true); + lock = new Object(); + } + + /** + * Returns the next available {@link JsonElement} on the reader. Null if none available. + * + * @return the next available {@link JsonElement} on the reader. Null if none available. + * @throws JsonParseException if the incoming stream is malformed JSON. + * @since 1.4 + */ + public JsonElement next() throws JsonParseException { + if (!hasNext()) { + throw new NoSuchElementException(); + } + + try { + return Streams.parse(parser); + } catch (StackOverflowError e) { + throw new JsonParseException("Failed parsing JSON source to Json", e); + } catch (OutOfMemoryError e) { + throw new JsonParseException("Failed parsing JSON source to Json", e); + } catch (JsonParseException e) { + throw e.getCause() instanceof EOFException ? new NoSuchElementException() : e; + } + } + + /** + * Returns true if a {@link JsonElement} is available on the input for consumption + * @return true if a {@link JsonElement} is available on the input, false otherwise + * @since 1.4 + */ + public boolean hasNext() { + synchronized (lock) { + try { + return parser.peek() != JsonToken.END_DOCUMENT; + } catch (MalformedJsonException e) { + throw new JsonSyntaxException(e); + } catch (IOException e) { + throw new JsonIOException(e); + } + } + } + + /** + * This optional {@link Iterator} method is not relevant for stream parsing and hence is not + * implemented. + * @since 1.4 + */ + public void remove() { + throw new UnsupportedOperationException(); + } +} diff --git a/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/JsonSyntaxException.java b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/JsonSyntaxException.java new file mode 100644 index 0000000..a4a67a4 --- /dev/null +++ b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/JsonSyntaxException.java @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * 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. + */ +package com.google.gson285; + +/** + * This exception is raised when Gson attempts to read (or write) a malformed + * JSON element. + * + * @author Inderjeet Singh + * @author Joel Leitch + */ +public final class JsonSyntaxException extends JsonParseException { + + private static final long serialVersionUID = 1L; + + public JsonSyntaxException(String msg) { + super(msg); + } + + public JsonSyntaxException(String msg, Throwable cause) { + super(msg, cause); + } + + /** + * Creates exception with the specified cause. Consider using + * {@link #JsonSyntaxException(String, Throwable)} instead if you can + * describe what actually happened. + * + * @param cause root exception that caused this exception to be thrown. + */ + public JsonSyntaxException(Throwable cause) { + super(cause); + } +} diff --git a/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/LICENSE b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/LICENSE new file mode 100644 index 0000000..880f50a --- /dev/null +++ b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/LICENSE @@ -0,0 +1,206 @@ +Google GSon source code is available at: +https://github.com/google/gson + +Under the following licence: + + 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/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/LongSerializationPolicy.java b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/LongSerializationPolicy.java new file mode 100644 index 0000000..eee7e1e --- /dev/null +++ b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/LongSerializationPolicy.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2009 Google Inc. + * + * 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. + */ + +package com.google.gson285; + +/** + * Defines the expected format for a {@code long} or {@code Long} type when its serialized. + * + * @since 1.3 + * + * @author Inderjeet Singh + * @author Joel Leitch + */ +public enum LongSerializationPolicy { + /** + * This is the "default" serialization policy that will output a {@code long} object as a JSON + * number. For example, assume an object has a long field named "f" then the serialized output + * would be: + * {@code {"f":123}}. + */ + DEFAULT() { + @Override public JsonElement serialize(Long value) { + return new JsonPrimitive(value); + } + }, + + /** + * Serializes a long value as a quoted string. For example, assume an object has a long field + * named "f" then the serialized output would be: + * {@code {"f":"123"}}. + */ + STRING() { + @Override public JsonElement serialize(Long value) { + return new JsonPrimitive(String.valueOf(value)); + } + }; + + /** + * Serialize this {@code value} using this serialization policy. + * + * @param value the long value to be serialized into a {@link JsonElement} + * @return the serialized version of {@code value} + */ + public abstract JsonElement serialize(Long value); +} diff --git a/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/README.md b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/README.md new file mode 100644 index 0000000..a67bdb4 --- /dev/null +++ b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/README.md @@ -0,0 +1,72 @@ +# Gson + +Gson is a Java library that can be used to convert Java Objects into their JSON representation. It can also be used to convert a JSON string to an equivalent Java object. +Gson can work with arbitrary Java objects including pre-existing objects that you do not have source-code of. + +There are a few open-source projects that can convert Java objects to JSON. However, most of them require that you place Java annotations in your classes; something that you can not do if you do not have access to the source-code. Most also do not fully support the use of Java Generics. Gson considers both of these as very important design goals. + +### Goals + * Provide simple `toJson()` and `fromJson()` methods to convert Java objects to JSON and vice-versa + * Allow pre-existing unmodifiable objects to be converted to and from JSON + * Extensive support of Java Generics + * Allow custom representations for objects + * Support arbitrarily complex objects (with deep inheritance hierarchies and extensive use of generic types) + +### Download + +Gradle: +```gradle +dependencies { + implementation 'com.google.code.gson:gson:2.8.5' +} +``` + +Maven: +```xml + + com.google.code.gson + gson + 2.8.5 + +``` + +[Gson jar downloads](https://maven-badges.herokuapp.com/maven-central/com.google.code.gson/gson) are available from Maven Central. + +[![Build Status](https://travis-ci.org/google/gson.svg?branch=master)](https://travis-ci.org/google/gson) + +### Documentation + * [API Javadoc](http://www.javadoc.io/doc/com.google.code.gson/gson): Documentation for the current release + * [User guide](https://github.com/google/gson/blob/master/UserGuide.md): This guide contains examples on how to use Gson in your code. + * [Change log](https://github.com/google/gson/blob/master/CHANGELOG.md): Changes in the recent versions + * [Design document](https://github.com/google/gson/blob/master/GsonDesignDocument.md): This document discusses issues we faced while designing Gson. It also includes a comparison of Gson with other Java libraries that can be used for Json conversion + +Please use the 'gson' tag on StackOverflow or the [google-gson Google group](http://groups.google.com/group/google-gson) to discuss Gson or to post questions. + +### Related Content Created by Third Parties + * [Gson Tutorial](http://www.studytrails.com/java/json/java-google-json-introduction.jsp) by `StudyTrails` + * [Gson Tutorial Series](https://futurestud.io/tutorials/gson-getting-started-with-java-json-serialization-deserialization) by `Future Studio` + * [Gson API Report](https://abi-laboratory.pro/java/tracker/timeline/gson/) + +### License + +Gson is released under the [Apache 2.0 license](LICENSE). + +``` +Copyright 2008 Google Inc. + +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. +``` + +### Disclaimer + +This is not an officially supported Google product. diff --git a/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/TypeAdapter.java b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/TypeAdapter.java new file mode 100644 index 0000000..64569af --- /dev/null +++ b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/TypeAdapter.java @@ -0,0 +1,290 @@ +/* + * Copyright (C) 2011 Google Inc. + * + * 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. + */ + +package com.google.gson285; + +import com.google.gson285.internal.bind.JsonTreeWriter; +import com.google.gson285.internal.bind.JsonTreeReader; +import com.google.gson285.stream.JsonReader; +import com.google.gson285.stream.JsonToken; +import com.google.gson285.stream.JsonWriter; +import java.io.IOException; +import java.io.Reader; +import java.io.StringReader; +import java.io.StringWriter; +import java.io.Writer; + +/** + * Converts Java objects to and from JSON. + * + *

Defining a type's JSON form

+ * By default Gson converts application classes to JSON using its built-in type + * adapters. If Gson's default JSON conversion isn't appropriate for a type, + * extend this class to customize the conversion. Here's an example of a type + * adapter for an (X,Y) coordinate point:
   {@code
+ *
+ *   public class PointAdapter extends TypeAdapter {
+ *     public Point read(JsonReader reader) throws IOException {
+ *       if (reader.peek() == JsonToken.NULL) {
+ *         reader.nextNull();
+ *         return null;
+ *       }
+ *       String xy = reader.nextString();
+ *       String[] parts = xy.split(",");
+ *       int x = Integer.parseInt(parts[0]);
+ *       int y = Integer.parseInt(parts[1]);
+ *       return new Point(x, y);
+ *     }
+ *     public void write(JsonWriter writer, Point value) throws IOException {
+ *       if (value == null) {
+ *         writer.nullValue();
+ *         return;
+ *       }
+ *       String xy = value.getX() + "," + value.getY();
+ *       writer.value(xy);
+ *     }
+ *   }}
+ * With this type adapter installed, Gson will convert {@code Points} to JSON as + * strings like {@code "5,8"} rather than objects like {@code {"x":5,"y":8}}. In + * this case the type adapter binds a rich Java class to a compact JSON value. + * + *

The {@link #read(JsonReader) read()} method must read exactly one value + * and {@link #write(JsonWriter,Object) write()} must write exactly one value. + * For primitive types this is means readers should make exactly one call to + * {@code nextBoolean()}, {@code nextDouble()}, {@code nextInt()}, {@code + * nextLong()}, {@code nextString()} or {@code nextNull()}. Writers should make + * exactly one call to one of value() or nullValue(). + * For arrays, type adapters should start with a call to {@code beginArray()}, + * convert all elements, and finish with a call to {@code endArray()}. For + * objects, they should start with {@code beginObject()}, convert the object, + * and finish with {@code endObject()}. Failing to convert a value or converting + * too many values may cause the application to crash. + * + *

Type adapters should be prepared to read null from the stream and write it + * to the stream. Alternatively, they should use {@link #nullSafe()} method while + * registering the type adapter with Gson. If your {@code Gson} instance + * has been configured to {@link GsonBuilder#serializeNulls()}, these nulls will be + * written to the final document. Otherwise the value (and the corresponding name + * when writing to a JSON object) will be omitted automatically. In either case + * your type adapter must handle null. + * + *

To use a custom type adapter with Gson, you must register it with a + * {@link GsonBuilder}:

   {@code
+ *
+ *   GsonBuilder builder = new GsonBuilder();
+ *   builder.registerTypeAdapter(Point.class, new PointAdapter());
+ *   // if PointAdapter didn't check for nulls in its read/write methods, you should instead use
+ *   // builder.registerTypeAdapter(Point.class, new PointAdapter().nullSafe());
+ *   ...
+ *   Gson gson = builder.create();
+ * }
+ * + * @since 2.1 + */ +// non-Javadoc: +// +//

JSON Conversion

+//

A type adapter registered with Gson is automatically invoked while serializing +// or deserializing JSON. However, you can also use type adapters directly to serialize +// and deserialize JSON. Here is an example for deserialization:

   {@code
+//
+//   String json = "{'origin':'0,0','points':['1,2','3,4']}";
+//   TypeAdapter graphAdapter = gson.getAdapter(Graph.class);
+//   Graph graph = graphAdapter.fromJson(json);
+// }
+// And an example for serialization:
   {@code
+//
+//   Graph graph = new Graph(...);
+//   TypeAdapter graphAdapter = gson.getAdapter(Graph.class);
+//   String json = graphAdapter.toJson(graph);
+// }
+// +//

Type adapters are type-specific. For example, a {@code +// TypeAdapter} can convert {@code Date} instances to JSON and JSON to +// instances of {@code Date}, but cannot convert any other types. +// +public abstract class TypeAdapter { + + /** + * Writes one JSON value (an array, object, string, number, boolean or null) + * for {@code value}. + * + * @param value the Java object to write. May be null. + */ + public abstract void write(JsonWriter out, T value) throws IOException; + + /** + * Converts {@code value} to a JSON document and writes it to {@code out}. + * Unlike Gson's similar {@link Gson#toJson(JsonElement, Appendable) toJson} + * method, this write is strict. Create a {@link + * JsonWriter#setLenient(boolean) lenient} {@code JsonWriter} and call + * {@link #write(com.google.gson285.stream.JsonWriter, Object)} for lenient + * writing. + * + * @param value the Java object to convert. May be null. + * @since 2.2 + */ + public final void toJson(Writer out, T value) throws IOException { + JsonWriter writer = new JsonWriter(out); + write(writer, value); + } + + /** + * This wrapper method is used to make a type adapter null tolerant. In general, a + * type adapter is required to handle nulls in write and read methods. Here is how this + * is typically done:
+ *

   {@code
+   *
+   * Gson gson = new GsonBuilder().registerTypeAdapter(Foo.class,
+   *   new TypeAdapter() {
+   *     public Foo read(JsonReader in) throws IOException {
+   *       if (in.peek() == JsonToken.NULL) {
+   *         in.nextNull();
+   *         return null;
+   *       }
+   *       // read a Foo from in and return it
+   *     }
+   *     public void write(JsonWriter out, Foo src) throws IOException {
+   *       if (src == null) {
+   *         out.nullValue();
+   *         return;
+   *       }
+   *       // write src as JSON to out
+   *     }
+   *   }).create();
+   * }
+ * You can avoid this boilerplate handling of nulls by wrapping your type adapter with + * this method. Here is how we will rewrite the above example: + *
   {@code
+   *
+   * Gson gson = new GsonBuilder().registerTypeAdapter(Foo.class,
+   *   new TypeAdapter() {
+   *     public Foo read(JsonReader in) throws IOException {
+   *       // read a Foo from in and return it
+   *     }
+   *     public void write(JsonWriter out, Foo src) throws IOException {
+   *       // write src as JSON to out
+   *     }
+   *   }.nullSafe()).create();
+   * }
+ * Note that we didn't need to check for nulls in our type adapter after we used nullSafe. + */ + public final TypeAdapter nullSafe() { + return new TypeAdapter() { + @Override public void write(JsonWriter out, T value) throws IOException { + if (value == null) { + out.nullValue(); + } else { + TypeAdapter.this.write(out, value); + } + } + @Override public T read(JsonReader reader) throws IOException { + if (reader.peek() == JsonToken.NULL) { + reader.nextNull(); + return null; + } + return TypeAdapter.this.read(reader); + } + }; + } + + /** + * Converts {@code value} to a JSON document. Unlike Gson's similar {@link + * Gson#toJson(Object) toJson} method, this write is strict. Create a {@link + * JsonWriter#setLenient(boolean) lenient} {@code JsonWriter} and call + * {@link #write(com.google.gson285.stream.JsonWriter, Object)} for lenient + * writing. + * + * @param value the Java object to convert. May be null. + * @since 2.2 + */ + public final String toJson(T value) { + StringWriter stringWriter = new StringWriter(); + try { + toJson(stringWriter, value); + } catch (IOException e) { + throw new AssertionError(e); // No I/O writing to a StringWriter. + } + return stringWriter.toString(); + } + + /** + * Converts {@code value} to a JSON tree. + * + * @param value the Java object to convert. May be null. + * @return the converted JSON tree. May be {@link JsonNull}. + * @since 2.2 + */ + public final JsonElement toJsonTree(T value) { + try { + JsonTreeWriter jsonWriter = new JsonTreeWriter(); + write(jsonWriter, value); + return jsonWriter.get(); + } catch (IOException e) { + throw new JsonIOException(e); + } + } + + /** + * Reads one JSON value (an array, object, string, number, boolean or null) + * and converts it to a Java object. Returns the converted object. + * + * @return the converted Java object. May be null. + */ + public abstract T read(JsonReader in) throws IOException; + + /** + * Converts the JSON document in {@code in} to a Java object. Unlike Gson's + * similar {@link Gson#fromJson(java.io.Reader, Class) fromJson} method, this + * read is strict. Create a {@link JsonReader#setLenient(boolean) lenient} + * {@code JsonReader} and call {@link #read(JsonReader)} for lenient reading. + * + * @return the converted Java object. May be null. + * @since 2.2 + */ + public final T fromJson(Reader in) throws IOException { + JsonReader reader = new JsonReader(in); + return read(reader); + } + + /** + * Converts the JSON document in {@code json} to a Java object. Unlike Gson's + * similar {@link Gson#fromJson(String, Class) fromJson} method, this read is + * strict. Create a {@link JsonReader#setLenient(boolean) lenient} {@code + * JsonReader} and call {@link #read(JsonReader)} for lenient reading. + * + * @return the converted Java object. May be null. + * @since 2.2 + */ + public final T fromJson(String json) throws IOException { + return fromJson(new StringReader(json)); + } + + /** + * Converts {@code jsonTree} to a Java object. + * + * @param jsonTree the Java object to convert. May be {@link JsonNull}. + * @since 2.2 + */ + public final T fromJsonTree(JsonElement jsonTree) { + try { + JsonReader jsonReader = new JsonTreeReader(jsonTree); + return read(jsonReader); + } catch (IOException e) { + throw new JsonIOException(e); + } + } +} diff --git a/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/TypeAdapterFactory.java b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/TypeAdapterFactory.java new file mode 100644 index 0000000..e866f3b --- /dev/null +++ b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/TypeAdapterFactory.java @@ -0,0 +1,170 @@ +/* + * Copyright (C) 2011 Google Inc. + * + * 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. + */ + +package com.google.gson285; + +import com.google.gson285.reflect.TypeToken; + +/** + * Creates type adapters for set of related types. Type adapter factories are + * most useful when several types share similar structure in their JSON form. + * + *

Example: Converting enums to lowercase

+ * In this example, we implement a factory that creates type adapters for all + * enums. The type adapters will write enums in lowercase, despite the fact + * that they're defined in {@code CONSTANT_CASE} in the corresponding Java + * model:
   {@code
+ *
+ *   public class LowercaseEnumTypeAdapterFactory implements TypeAdapterFactory {
+ *     public  TypeAdapter create(Gson gson, TypeToken type) {
+ *       Class rawType = (Class) type.getRawType();
+ *       if (!rawType.isEnum()) {
+ *         return null;
+ *       }
+ *
+ *       final Map lowercaseToConstant = new HashMap();
+ *       for (T constant : rawType.getEnumConstants()) {
+ *         lowercaseToConstant.put(toLowercase(constant), constant);
+ *       }
+ *
+ *       return new TypeAdapter() {
+ *         public void write(JsonWriter out, T value) throws IOException {
+ *           if (value == null) {
+ *             out.nullValue();
+ *           } else {
+ *             out.value(toLowercase(value));
+ *           }
+ *         }
+ *
+ *         public T read(JsonReader reader) throws IOException {
+ *           if (reader.peek() == JsonToken.NULL) {
+ *             reader.nextNull();
+ *             return null;
+ *           } else {
+ *             return lowercaseToConstant.get(reader.nextString());
+ *           }
+ *         }
+ *       };
+ *     }
+ *
+ *     private String toLowercase(Object o) {
+ *       return o.toString().toLowerCase(Locale.US);
+ *     }
+ *   }
+ * }
+ * + *

Type adapter factories select which types they provide type adapters + * for. If a factory cannot support a given type, it must return null when + * that type is passed to {@link #create}. Factories should expect {@code + * create()} to be called on them for many types and should return null for + * most of those types. In the above example the factory returns null for + * calls to {@code create()} where {@code type} is not an enum. + * + *

A factory is typically called once per type, but the returned type + * adapter may be used many times. It is most efficient to do expensive work + * like reflection in {@code create()} so that the type adapter's {@code + * read()} and {@code write()} methods can be very fast. In this example the + * mapping from lowercase name to enum value is computed eagerly. + * + *

As with type adapters, factories must be registered with a {@link + * com.google.gson285.GsonBuilder} for them to take effect:

   {@code
+ *
+ *  GsonBuilder builder = new GsonBuilder();
+ *  builder.registerTypeAdapterFactory(new LowercaseEnumTypeAdapterFactory());
+ *  ...
+ *  Gson gson = builder.create();
+ * }
+ * If multiple factories support the same type, the factory registered earlier + * takes precedence. + * + *

Example: composing other type adapters

+ * In this example we implement a factory for Guava's {@code Multiset} + * collection type. The factory can be used to create type adapters for + * multisets of any element type: the type adapter for {@code + * Multiset} is different from the type adapter for {@code + * Multiset}. + * + *

The type adapter delegates to another type adapter for the + * multiset elements. It figures out the element type by reflecting on the + * multiset's type token. A {@code Gson} is passed in to {@code create} for + * just this purpose:

   {@code
+ *
+ *   public class MultisetTypeAdapterFactory implements TypeAdapterFactory {
+ *     public  TypeAdapter create(Gson gson, TypeToken typeToken) {
+ *       Type type = typeToken.getType();
+ *       if (typeToken.getRawType() != Multiset.class
+ *           || !(type instanceof ParameterizedType)) {
+ *         return null;
+ *       }
+ *
+ *       Type elementType = ((ParameterizedType) type).getActualTypeArguments()[0];
+ *       TypeAdapter elementAdapter = gson.getAdapter(TypeToken.get(elementType));
+ *       return (TypeAdapter) newMultisetAdapter(elementAdapter);
+ *     }
+ *
+ *     private  TypeAdapter> newMultisetAdapter(
+ *         final TypeAdapter elementAdapter) {
+ *       return new TypeAdapter>() {
+ *         public void write(JsonWriter out, Multiset value) throws IOException {
+ *           if (value == null) {
+ *             out.nullValue();
+ *             return;
+ *           }
+ *
+ *           out.beginArray();
+ *           for (Multiset.Entry entry : value.entrySet()) {
+ *             out.value(entry.getCount());
+ *             elementAdapter.write(out, entry.getElement());
+ *           }
+ *           out.endArray();
+ *         }
+ *
+ *         public Multiset read(JsonReader in) throws IOException {
+ *           if (in.peek() == JsonToken.NULL) {
+ *             in.nextNull();
+ *             return null;
+ *           }
+ *
+ *           Multiset result = LinkedHashMultiset.create();
+ *           in.beginArray();
+ *           while (in.hasNext()) {
+ *             int count = in.nextInt();
+ *             E element = elementAdapter.read(in);
+ *             result.add(element, count);
+ *           }
+ *           in.endArray();
+ *           return result;
+ *         }
+ *       };
+ *     }
+ *   }
+ * }
+ * Delegating from one type adapter to another is extremely powerful; it's + * the foundation of how Gson converts Java objects and collections. Whenever + * possible your factory should retrieve its delegate type adapter in the + * {@code create()} method; this ensures potentially-expensive type adapter + * creation happens only once. + * + * @since 2.1 + */ +public interface TypeAdapterFactory { + + /** + * Returns a type adapter for {@code type}, or null if this factory doesn't + * support {@code type}. + */ + TypeAdapter create(Gson gson, TypeToken type); +} diff --git a/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/annotations/Expose.java b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/annotations/Expose.java new file mode 100644 index 0000000..f9a923b --- /dev/null +++ b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/annotations/Expose.java @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2008 Google Inc. + * + * 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. + */ + +package com.google.gson285.annotations; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * An annotation that indicates this member should be exposed for JSON + * serialization or deserialization. + * + *

This annotation has no effect unless you build {@link com.google.gson285.Gson} + * with a {@link com.google.gson285.GsonBuilder} and invoke + * {@link com.google.gson285.GsonBuilder#excludeFieldsWithoutExposeAnnotation()} + * method.

+ * + *

Here is an example of how this annotation is meant to be used: + *

+ * public class User {
+ *   @Expose private String firstName;
+ *   @Expose(serialize = false) private String lastName;
+ *   @Expose (serialize = false, deserialize = false) private String emailAddress;
+ *   private String password;
+ * }
+ * 

+ * If you created Gson with {@code new Gson()}, the {@code toJson()} and {@code fromJson()} + * methods will use the {@code password} field along-with {@code firstName}, {@code lastName}, + * and {@code emailAddress} for serialization and deserialization. However, if you created Gson + * with {@code Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create()} + * then the {@code toJson()} and {@code fromJson()} methods of Gson will exclude the + * {@code password} field. This is because the {@code password} field is not marked with the + * {@code @Expose} annotation. Gson will also exclude {@code lastName} and {@code emailAddress} + * from serialization since {@code serialize} is set to {@code false}. Similarly, Gson will + * exclude {@code emailAddress} from deserialization since {@code deserialize} is set to false. + * + *

Note that another way to achieve the same effect would have been to just mark the + * {@code password} field as {@code transient}, and Gson would have excluded it even with default + * settings. The {@code @Expose} annotation is useful in a style of programming where you want to + * explicitly specify all fields that should get considered for serialization or deserialization. + * + * @author Inderjeet Singh + * @author Joel Leitch + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface Expose { + + /** + * If {@code true}, the field marked with this annotation is written out in the JSON while + * serializing. If {@code false}, the field marked with this annotation is skipped from the + * serialized output. Defaults to {@code true}. + * @since 1.4 + */ + public boolean serialize() default true; + + /** + * If {@code true}, the field marked with this annotation is deserialized from the JSON. + * If {@code false}, the field marked with this annotation is skipped during deserialization. + * Defaults to {@code true}. + * @since 1.4 + */ + public boolean deserialize() default true; +} diff --git a/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/annotations/JsonAdapter.java b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/annotations/JsonAdapter.java new file mode 100644 index 0000000..f12686f --- /dev/null +++ b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/annotations/JsonAdapter.java @@ -0,0 +1,104 @@ +/* + * Copyright (C) 2014 Google Inc. + * + * 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. + */ + +package com.google.gson285.annotations; + +import com.google.gson285.JsonDeserializer; +import com.google.gson285.JsonSerializer; +import com.google.gson285.TypeAdapter; +import com.google.gson285.TypeAdapterFactory; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * An annotation that indicates the Gson {@link TypeAdapter} to use with a class + * or field. + * + *

Here is an example of how this annotation is used:

+ *
+ * @JsonAdapter(UserJsonAdapter.class)
+ * public class User {
+ *   public final String firstName, lastName;
+ *   private User(String firstName, String lastName) {
+ *     this.firstName = firstName;
+ *     this.lastName = lastName;
+ *   }
+ * }
+ * public class UserJsonAdapter extends TypeAdapter<User> {
+ *   @Override public void write(JsonWriter out, User user) throws IOException {
+ *     // implement write: combine firstName and lastName into name
+ *     out.beginObject();
+ *     out.name("name");
+ *     out.value(user.firstName + " " + user.lastName);
+ *     out.endObject();
+ *     // implement the write method
+ *   }
+ *   @Override public User read(JsonReader in) throws IOException {
+ *     // implement read: split name into firstName and lastName
+ *     in.beginObject();
+ *     in.nextName();
+ *     String[] nameParts = in.nextString().split(" ");
+ *     in.endObject();
+ *     return new User(nameParts[0], nameParts[1]);
+ *   }
+ * }
+ * 
+ * + * Since User class specified UserJsonAdapter.class in @JsonAdapter annotation, it + * will automatically be invoked to serialize/deserialize User instances.
+ * + *

Here is an example of how to apply this annotation to a field. + *

+ * private static final class Gadget {
+ *   @JsonAdapter(UserJsonAdapter2.class)
+ *   final User user;
+ *   Gadget(User user) {
+ *     this.user = user;
+ *   }
+ * }
+ * 
+ * + * It's possible to specify different type adapters on a field, that + * field's type, and in the {@link com.google.gson285.GsonBuilder}. Field + * annotations take precedence over {@code GsonBuilder}-registered type + * adapters, which in turn take precedence over annotated types. + * + *

The class referenced by this annotation must be either a {@link + * TypeAdapter} or a {@link TypeAdapterFactory}, or must implement one + * or both of {@link JsonDeserializer} or {@link JsonSerializer}. + * Using {@link TypeAdapterFactory} makes it possible to delegate + * to the enclosing {@code Gson} instance. + * + * @since 2.3 + * + * @author Inderjeet Singh + * @author Joel Leitch + * @author Jesse Wilson + */ +// Note that the above example is taken from AdaptAnnotationTest. +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE, ElementType.FIELD}) +public @interface JsonAdapter { + + /** Either a {@link TypeAdapter} or {@link TypeAdapterFactory}, or one or both of {@link JsonDeserializer} or {@link JsonSerializer}. */ + Class value(); + + /** false, to be able to handle {@code null} values within the adapter, default value is true. */ + boolean nullSafe() default true; + +} diff --git a/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/annotations/SerializedName.java b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/annotations/SerializedName.java new file mode 100644 index 0000000..cabcd45 --- /dev/null +++ b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/annotations/SerializedName.java @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2008 Google Inc. + * + * 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. + */ + +package com.google.gson285.annotations; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * An annotation that indicates this member should be serialized to JSON with + * the provided name value as its field name. + * + *

This annotation will override any {@link com.google.gson285.FieldNamingPolicy}, including + * the default field naming policy, that may have been set on the {@link com.google.gson285.Gson} + * instance. A different naming policy can set using the {@code GsonBuilder} class. See + * {@link com.google.gson285.GsonBuilder#setFieldNamingPolicy(com.google.gson285.FieldNamingPolicy)} + * for more information.

+ * + *

Here is an example of how this annotation is meant to be used:

+ *
+ * public class MyClass {
+ *   @SerializedName("name") String a;
+ *   @SerializedName(value="name1", alternate={"name2", "name3"}) String b;
+ *   String c;
+ *
+ *   public MyClass(String a, String b, String c) {
+ *     this.a = a;
+ *     this.b = b;
+ *     this.c = c;
+ *   }
+ * }
+ * 
+ * + *

The following shows the output that is generated when serializing an instance of the + * above example class:

+ *
+ * MyClass target = new MyClass("v1", "v2", "v3");
+ * Gson gson = new Gson();
+ * String json = gson.toJson(target);
+ * System.out.println(json);
+ *
+ * ===== OUTPUT =====
+ * {"name":"v1","name1":"v2","c":"v3"}
+ * 
+ * + *

NOTE: The value you specify in this annotation must be a valid JSON field name.

+ * While deserializing, all values specified in the annotation will be deserialized into the field. + * For example: + *
+ *   MyClass target = gson.fromJson("{'name1':'v1'}", MyClass.class);
+ *   assertEquals("v1", target.b);
+ *   target = gson.fromJson("{'name2':'v2'}", MyClass.class);
+ *   assertEquals("v2", target.b);
+ *   target = gson.fromJson("{'name3':'v3'}", MyClass.class);
+ *   assertEquals("v3", target.b);
+ * 
+ * Note that MyClass.b is now deserialized from either name1, name2 or name3. + * + * @see com.google.gson285.FieldNamingPolicy + * + * @author Inderjeet Singh + * @author Joel Leitch + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.FIELD, ElementType.METHOD}) +public @interface SerializedName { + + /** + * @return the desired name of the field when it is serialized or deserialized + */ + String value(); + /** + * @return the alternative names of the field when it is deserialized + */ + String[] alternate() default {}; +} diff --git a/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/annotations/Since.java b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/annotations/Since.java new file mode 100644 index 0000000..1e47c39 --- /dev/null +++ b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/annotations/Since.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2008 Google Inc. + * + * 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. + */ + +package com.google.gson285.annotations; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * An annotation that indicates the version number since a member or a type has been present. + * This annotation is useful to manage versioning of your Json classes for a web-service. + * + *

+ * This annotation has no effect unless you build {@link com.google.gson285.Gson} with a + * {@link com.google.gson285.GsonBuilder} and invoke + * {@link com.google.gson285.GsonBuilder#setVersion(double)} method. + * + *

Here is an example of how this annotation is meant to be used:

+ *
+ * public class User {
+ *   private String firstName;
+ *   private String lastName;
+ *   @Since(1.0) private String emailAddress;
+ *   @Since(1.0) private String password;
+ *   @Since(1.1) private Address address;
+ * }
+ * 
+ * + *

If you created Gson with {@code new Gson()}, the {@code toJson()} and {@code fromJson()} + * methods will use all the fields for serialization and deserialization. However, if you created + * Gson with {@code Gson gson = new GsonBuilder().setVersion(1.0).create()} then the + * {@code toJson()} and {@code fromJson()} methods of Gson will exclude the {@code address} field + * since it's version number is set to {@code 1.1}.

+ * + * @author Inderjeet Singh + * @author Joel Leitch + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.FIELD, ElementType.TYPE}) +public @interface Since { + /** + * the value indicating a version number since this member + * or type has been present. + */ + double value(); +} diff --git a/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/annotations/Until.java b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/annotations/Until.java new file mode 100644 index 0000000..0c5aa41 --- /dev/null +++ b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/annotations/Until.java @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2008 Google Inc. + * + * 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. + */ + +package com.google.gson285.annotations; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * An annotation that indicates the version number until a member or a type should be present. + * Basically, if Gson is created with a version number that exceeds the value stored in the + * {@code Until} annotation then the field will be ignored from the JSON output. This annotation + * is useful to manage versioning of your JSON classes for a web-service. + * + *

+ * This annotation has no effect unless you build {@link com.google.gson285.Gson} with a + * {@link com.google.gson285.GsonBuilder} and invoke + * {@link com.google.gson285.GsonBuilder#setVersion(double)} method. + * + *

Here is an example of how this annotation is meant to be used:

+ *
+ * public class User {
+ *   private String firstName;
+ *   private String lastName;
+ *   @Until(1.1) private String emailAddress;
+ *   @Until(1.1) private String password;
+ * }
+ * 
+ * + *

If you created Gson with {@code new Gson()}, the {@code toJson()} and {@code fromJson()} + * methods will use all the fields for serialization and deserialization. However, if you created + * Gson with {@code Gson gson = new GsonBuilder().setVersion(1.2).create()} then the + * {@code toJson()} and {@code fromJson()} methods of Gson will exclude the {@code emailAddress} + * and {@code password} fields from the example above, because the version number passed to the + * GsonBuilder, {@code 1.2}, exceeds the version number set on the {@code Until} annotation, + * {@code 1.1}, for those fields. + * + * @author Inderjeet Singh + * @author Joel Leitch + * @since 1.3 + */ +@Documented +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.FIELD, ElementType.TYPE}) +public @interface Until { + + /** + * the value indicating a version number until this member + * or type should be ignored. + */ + double value(); +} diff --git a/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/annotations/package-info.java b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/annotations/package-info.java new file mode 100644 index 0000000..65d6a4b --- /dev/null +++ b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/annotations/package-info.java @@ -0,0 +1,6 @@ +/** + * This package provides annotations that can be used with {@link com.google.gson285.Gson}. + * + * @author Inderjeet Singh, Joel Leitch + */ +package com.google.gson285.annotations; \ No newline at end of file diff --git a/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/$Gson$Preconditions.java b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/$Gson$Preconditions.java new file mode 100644 index 0000000..a4e0da8 --- /dev/null +++ b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/$Gson$Preconditions.java @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2008 Google Inc. + * + * 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. + */ + +package com.google.gson285.internal; + +/** + * A simple utility class used to check method Preconditions. + * + *

+ * public long divideBy(long value) {
+ *   Preconditions.checkArgument(value != 0);
+ *   return this.value / value;
+ * }
+ * 
+ * + * @author Inderjeet Singh + * @author Joel Leitch + */ +public final class $Gson$Preconditions { + private $Gson$Preconditions() { + throw new UnsupportedOperationException(); + } + + public static T checkNotNull(T obj) { + if (obj == null) { + throw new NullPointerException(); + } + return obj; + } + + public static void checkArgument(boolean condition) { + if (!condition) { + throw new IllegalArgumentException(); + } + } +} diff --git a/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/$Gson$Types.java b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/$Gson$Types.java new file mode 100644 index 0000000..5e40d21 --- /dev/null +++ b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/$Gson$Types.java @@ -0,0 +1,610 @@ +/** + * Copyright (C) 2008 Google Inc. + * + * 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. + */ + +package com.google.gson285.internal; + +import java.io.Serializable; +import java.lang.reflect.Array; +import java.lang.reflect.GenericArrayType; +import java.lang.reflect.GenericDeclaration; +import java.lang.reflect.Modifier; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; +import java.lang.reflect.WildcardType; +import java.util.*; + +import static com.google.gson285.internal.$Gson$Preconditions.checkArgument; +import static com.google.gson285.internal.$Gson$Preconditions.checkNotNull; + +/** + * Static methods for working with types. + * + * @author Bob Lee + * @author Jesse Wilson + */ +public final class $Gson$Types { + static final Type[] EMPTY_TYPE_ARRAY = new Type[] {}; + + private $Gson$Types() { + throw new UnsupportedOperationException(); + } + + /** + * Returns a new parameterized type, applying {@code typeArguments} to + * {@code rawType} and enclosed by {@code ownerType}. + * + * @return a {@link java.io.Serializable serializable} parameterized type. + */ + public static ParameterizedType newParameterizedTypeWithOwner( + Type ownerType, Type rawType, Type... typeArguments) { + return new ParameterizedTypeImpl(ownerType, rawType, typeArguments); + } + + /** + * Returns an array type whose elements are all instances of + * {@code componentType}. + * + * @return a {@link java.io.Serializable serializable} generic array type. + */ + public static GenericArrayType arrayOf(Type componentType) { + return new GenericArrayTypeImpl(componentType); + } + + /** + * Returns a type that represents an unknown type that extends {@code bound}. + * For example, if {@code bound} is {@code CharSequence.class}, this returns + * {@code ? extends CharSequence}. If {@code bound} is {@code Object.class}, + * this returns {@code ?}, which is shorthand for {@code ? extends Object}. + */ + public static WildcardType subtypeOf(Type bound) { + Type[] upperBounds; + if (bound instanceof WildcardType) { + upperBounds = ((WildcardType) bound).getUpperBounds(); + } else { + upperBounds = new Type[] { bound }; + } + return new WildcardTypeImpl(upperBounds, EMPTY_TYPE_ARRAY); + } + + /** + * Returns a type that represents an unknown supertype of {@code bound}. For + * example, if {@code bound} is {@code String.class}, this returns {@code ? + * super String}. + */ + public static WildcardType supertypeOf(Type bound) { + Type[] lowerBounds; + if (bound instanceof WildcardType) { + lowerBounds = ((WildcardType) bound).getLowerBounds(); + } else { + lowerBounds = new Type[] { bound }; + } + return new WildcardTypeImpl(new Type[] { Object.class }, lowerBounds); + } + + /** + * Returns a type that is functionally equal but not necessarily equal + * according to {@link Object#equals(Object) Object.equals()}. The returned + * type is {@link java.io.Serializable}. + */ + public static Type canonicalize(Type type) { + if (type instanceof Class) { + Class c = (Class) type; + return c.isArray() ? new GenericArrayTypeImpl(canonicalize(c.getComponentType())) : c; + + } else if (type instanceof ParameterizedType) { + ParameterizedType p = (ParameterizedType) type; + return new ParameterizedTypeImpl(p.getOwnerType(), + p.getRawType(), p.getActualTypeArguments()); + + } else if (type instanceof GenericArrayType) { + GenericArrayType g = (GenericArrayType) type; + return new GenericArrayTypeImpl(g.getGenericComponentType()); + + } else if (type instanceof WildcardType) { + WildcardType w = (WildcardType) type; + return new WildcardTypeImpl(w.getUpperBounds(), w.getLowerBounds()); + + } else { + // type is either serializable as-is or unsupported + return type; + } + } + + public static Class getRawType(Type type) { + if (type instanceof Class) { + // type is a normal class. + return (Class) type; + + } else if (type instanceof ParameterizedType) { + ParameterizedType parameterizedType = (ParameterizedType) type; + + // I'm not exactly sure why getRawType() returns Type instead of Class. + // Neal isn't either but suspects some pathological case related + // to nested classes exists. + Type rawType = parameterizedType.getRawType(); + checkArgument(rawType instanceof Class); + return (Class) rawType; + + } else if (type instanceof GenericArrayType) { + Type componentType = ((GenericArrayType)type).getGenericComponentType(); + return Array.newInstance(getRawType(componentType), 0).getClass(); + + } else if (type instanceof TypeVariable) { + // we could use the variable's bounds, but that won't work if there are multiple. + // having a raw type that's more general than necessary is okay + return Object.class; + + } else if (type instanceof WildcardType) { + return getRawType(((WildcardType) type).getUpperBounds()[0]); + + } else { + String className = type == null ? "null" : type.getClass().getName(); + throw new IllegalArgumentException("Expected a Class, ParameterizedType, or " + + "GenericArrayType, but <" + type + "> is of type " + className); + } + } + + static boolean equal(Object a, Object b) { + return a == b || (a != null && a.equals(b)); + } + + /** + * Returns true if {@code a} and {@code b} are equal. + */ + public static boolean equals(Type a, Type b) { + if (a == b) { + // also handles (a == null && b == null) + return true; + + } else if (a instanceof Class) { + // Class already specifies equals(). + return a.equals(b); + + } else if (a instanceof ParameterizedType) { + if (!(b instanceof ParameterizedType)) { + return false; + } + + // TODO: save a .clone() call + ParameterizedType pa = (ParameterizedType) a; + ParameterizedType pb = (ParameterizedType) b; + return equal(pa.getOwnerType(), pb.getOwnerType()) + && pa.getRawType().equals(pb.getRawType()) + && Arrays.equals(pa.getActualTypeArguments(), pb.getActualTypeArguments()); + + } else if (a instanceof GenericArrayType) { + if (!(b instanceof GenericArrayType)) { + return false; + } + + GenericArrayType ga = (GenericArrayType) a; + GenericArrayType gb = (GenericArrayType) b; + return equals(ga.getGenericComponentType(), gb.getGenericComponentType()); + + } else if (a instanceof WildcardType) { + if (!(b instanceof WildcardType)) { + return false; + } + + WildcardType wa = (WildcardType) a; + WildcardType wb = (WildcardType) b; + return Arrays.equals(wa.getUpperBounds(), wb.getUpperBounds()) + && Arrays.equals(wa.getLowerBounds(), wb.getLowerBounds()); + + } else if (a instanceof TypeVariable) { + if (!(b instanceof TypeVariable)) { + return false; + } + TypeVariable va = (TypeVariable) a; + TypeVariable vb = (TypeVariable) b; + return va.getGenericDeclaration() == vb.getGenericDeclaration() + && va.getName().equals(vb.getName()); + + } else { + // This isn't a type we support. Could be a generic array type, wildcard type, etc. + return false; + } + } + + static int hashCodeOrZero(Object o) { + return o != null ? o.hashCode() : 0; + } + + public static String typeToString(Type type) { + return type instanceof Class ? ((Class) type).getName() : type.toString(); + } + + /** + * Returns the generic supertype for {@code supertype}. For example, given a class {@code + * IntegerSet}, the result for when supertype is {@code Set.class} is {@code Set} and the + * result when the supertype is {@code Collection.class} is {@code Collection}. + */ + static Type getGenericSupertype(Type context, Class rawType, Class toResolve) { + if (toResolve == rawType) { + return context; + } + + // we skip searching through interfaces if unknown is an interface + if (toResolve.isInterface()) { + Class[] interfaces = rawType.getInterfaces(); + for (int i = 0, length = interfaces.length; i < length; i++) { + if (interfaces[i] == toResolve) { + return rawType.getGenericInterfaces()[i]; + } else if (toResolve.isAssignableFrom(interfaces[i])) { + return getGenericSupertype(rawType.getGenericInterfaces()[i], interfaces[i], toResolve); + } + } + } + + // check our supertypes + if (!rawType.isInterface()) { + while (rawType != Object.class) { + Class rawSupertype = rawType.getSuperclass(); + if (rawSupertype == toResolve) { + return rawType.getGenericSuperclass(); + } else if (toResolve.isAssignableFrom(rawSupertype)) { + return getGenericSupertype(rawType.getGenericSuperclass(), rawSupertype, toResolve); + } + rawType = rawSupertype; + } + } + + // we can't resolve this further + return toResolve; + } + + /** + * Returns the generic form of {@code supertype}. For example, if this is {@code + * ArrayList}, this returns {@code Iterable} given the input {@code + * Iterable.class}. + * + * @param supertype a superclass of, or interface implemented by, this. + */ + static Type getSupertype(Type context, Class contextRawType, Class supertype) { + if (context instanceof WildcardType) { + // wildcards are useless for resolving supertypes. As the upper bound has the same raw type, use it instead + context = ((WildcardType)context).getUpperBounds()[0]; + } + checkArgument(supertype.isAssignableFrom(contextRawType)); + return resolve(context, contextRawType, + $Gson$Types.getGenericSupertype(context, contextRawType, supertype)); + } + + /** + * Returns the component type of this array type. + * @throws ClassCastException if this type is not an array. + */ + public static Type getArrayComponentType(Type array) { + return array instanceof GenericArrayType + ? ((GenericArrayType) array).getGenericComponentType() + : ((Class) array).getComponentType(); + } + + /** + * Returns the element type of this collection type. + * @throws IllegalArgumentException if this type is not a collection. + */ + public static Type getCollectionElementType(Type context, Class contextRawType) { + Type collectionType = getSupertype(context, contextRawType, Collection.class); + + if (collectionType instanceof WildcardType) { + collectionType = ((WildcardType)collectionType).getUpperBounds()[0]; + } + if (collectionType instanceof ParameterizedType) { + return ((ParameterizedType) collectionType).getActualTypeArguments()[0]; + } + return Object.class; + } + + /** + * Returns a two element array containing this map's key and value types in + * positions 0 and 1 respectively. + */ + public static Type[] getMapKeyAndValueTypes(Type context, Class contextRawType) { + /* + * Work around a problem with the declaration of java.util.Properties. That + * class should extend Hashtable, but it's declared to + * extend Hashtable. + */ + if (context == Properties.class) { + return new Type[] { String.class, String.class }; // TODO: test subclasses of Properties! + } + + Type mapType = getSupertype(context, contextRawType, Map.class); + // TODO: strip wildcards? + if (mapType instanceof ParameterizedType) { + ParameterizedType mapParameterizedType = (ParameterizedType) mapType; + return mapParameterizedType.getActualTypeArguments(); + } + return new Type[] { Object.class, Object.class }; + } + + public static Type resolve(Type context, Class contextRawType, Type toResolve) { + return resolve(context, contextRawType, toResolve, new HashSet()); + } + + private static Type resolve(Type context, Class contextRawType, Type toResolve, + Collection visitedTypeVariables) { + // this implementation is made a little more complicated in an attempt to avoid object-creation + while (true) { + if (toResolve instanceof TypeVariable) { + TypeVariable typeVariable = (TypeVariable) toResolve; + if (visitedTypeVariables.contains(typeVariable)) { + // cannot reduce due to infinite recursion + return toResolve; + } else { + visitedTypeVariables.add(typeVariable); + } + toResolve = resolveTypeVariable(context, contextRawType, typeVariable); + if (toResolve == typeVariable) { + return toResolve; + } + + } else if (toResolve instanceof Class && ((Class) toResolve).isArray()) { + Class original = (Class) toResolve; + Type componentType = original.getComponentType(); + Type newComponentType = resolve(context, contextRawType, componentType, visitedTypeVariables); + return componentType == newComponentType + ? original + : arrayOf(newComponentType); + + } else if (toResolve instanceof GenericArrayType) { + GenericArrayType original = (GenericArrayType) toResolve; + Type componentType = original.getGenericComponentType(); + Type newComponentType = resolve(context, contextRawType, componentType, visitedTypeVariables); + return componentType == newComponentType + ? original + : arrayOf(newComponentType); + + } else if (toResolve instanceof ParameterizedType) { + ParameterizedType original = (ParameterizedType) toResolve; + Type ownerType = original.getOwnerType(); + Type newOwnerType = resolve(context, contextRawType, ownerType, visitedTypeVariables); + boolean changed = newOwnerType != ownerType; + + Type[] args = original.getActualTypeArguments(); + for (int t = 0, length = args.length; t < length; t++) { + Type resolvedTypeArgument = resolve(context, contextRawType, args[t], visitedTypeVariables); + if (resolvedTypeArgument != args[t]) { + if (!changed) { + args = args.clone(); + changed = true; + } + args[t] = resolvedTypeArgument; + } + } + + return changed + ? newParameterizedTypeWithOwner(newOwnerType, original.getRawType(), args) + : original; + + } else if (toResolve instanceof WildcardType) { + WildcardType original = (WildcardType) toResolve; + Type[] originalLowerBound = original.getLowerBounds(); + Type[] originalUpperBound = original.getUpperBounds(); + + if (originalLowerBound.length == 1) { + Type lowerBound = resolve(context, contextRawType, originalLowerBound[0], visitedTypeVariables); + if (lowerBound != originalLowerBound[0]) { + return supertypeOf(lowerBound); + } + } else if (originalUpperBound.length == 1) { + Type upperBound = resolve(context, contextRawType, originalUpperBound[0], visitedTypeVariables); + if (upperBound != originalUpperBound[0]) { + return subtypeOf(upperBound); + } + } + return original; + + } else { + return toResolve; + } + } + } + + static Type resolveTypeVariable(Type context, Class contextRawType, TypeVariable unknown) { + Class declaredByRaw = declaringClassOf(unknown); + + // we can't reduce this further + if (declaredByRaw == null) { + return unknown; + } + + Type declaredBy = getGenericSupertype(context, contextRawType, declaredByRaw); + if (declaredBy instanceof ParameterizedType) { + int index = indexOf(declaredByRaw.getTypeParameters(), unknown); + return ((ParameterizedType) declaredBy).getActualTypeArguments()[index]; + } + + return unknown; + } + + private static int indexOf(Object[] array, Object toFind) { + for (int i = 0, length = array.length; i < length; i++) { + if (toFind.equals(array[i])) { + return i; + } + } + throw new NoSuchElementException(); + } + + /** + * Returns the declaring class of {@code typeVariable}, or {@code null} if it was not declared by + * a class. + */ + private static Class declaringClassOf(TypeVariable typeVariable) { + GenericDeclaration genericDeclaration = typeVariable.getGenericDeclaration(); + return genericDeclaration instanceof Class + ? (Class) genericDeclaration + : null; + } + + static void checkNotPrimitive(Type type) { + checkArgument(!(type instanceof Class) || !((Class) type).isPrimitive()); + } + + private static final class ParameterizedTypeImpl implements ParameterizedType, Serializable { + private final Type ownerType; + private final Type rawType; + private final Type[] typeArguments; + + public ParameterizedTypeImpl(Type ownerType, Type rawType, Type... typeArguments) { + // require an owner type if the raw type needs it + if (rawType instanceof Class) { + Class rawTypeAsClass = (Class) rawType; + boolean isStaticOrTopLevelClass = Modifier.isStatic(rawTypeAsClass.getModifiers()) + || rawTypeAsClass.getEnclosingClass() == null; + checkArgument(ownerType != null || isStaticOrTopLevelClass); + } + + this.ownerType = ownerType == null ? null : canonicalize(ownerType); + this.rawType = canonicalize(rawType); + this.typeArguments = typeArguments.clone(); + for (int t = 0, length = this.typeArguments.length; t < length; t++) { + checkNotNull(this.typeArguments[t]); + checkNotPrimitive(this.typeArguments[t]); + this.typeArguments[t] = canonicalize(this.typeArguments[t]); + } + } + + public Type[] getActualTypeArguments() { + return typeArguments.clone(); + } + + public Type getRawType() { + return rawType; + } + + public Type getOwnerType() { + return ownerType; + } + + @Override public boolean equals(Object other) { + return other instanceof ParameterizedType + && $Gson$Types.equals(this, (ParameterizedType) other); + } + + @Override public int hashCode() { + return Arrays.hashCode(typeArguments) + ^ rawType.hashCode() + ^ hashCodeOrZero(ownerType); + } + + @Override public String toString() { + int length = typeArguments.length; + if (length == 0) { + return typeToString(rawType); + } + + StringBuilder stringBuilder = new StringBuilder(30 * (length + 1)); + stringBuilder.append(typeToString(rawType)).append("<").append(typeToString(typeArguments[0])); + for (int i = 1; i < length; i++) { + stringBuilder.append(", ").append(typeToString(typeArguments[i])); + } + return stringBuilder.append(">").toString(); + } + + private static final long serialVersionUID = 0; + } + + private static final class GenericArrayTypeImpl implements GenericArrayType, Serializable { + private final Type componentType; + + public GenericArrayTypeImpl(Type componentType) { + this.componentType = canonicalize(componentType); + } + + public Type getGenericComponentType() { + return componentType; + } + + @Override public boolean equals(Object o) { + return o instanceof GenericArrayType + && $Gson$Types.equals(this, (GenericArrayType) o); + } + + @Override public int hashCode() { + return componentType.hashCode(); + } + + @Override public String toString() { + return typeToString(componentType) + "[]"; + } + + private static final long serialVersionUID = 0; + } + + /** + * The WildcardType interface supports multiple upper bounds and multiple + * lower bounds. We only support what the Java 6 language needs - at most one + * bound. If a lower bound is set, the upper bound must be Object.class. + */ + private static final class WildcardTypeImpl implements WildcardType, Serializable { + private final Type upperBound; + private final Type lowerBound; + + public WildcardTypeImpl(Type[] upperBounds, Type[] lowerBounds) { + checkArgument(lowerBounds.length <= 1); + checkArgument(upperBounds.length == 1); + + if (lowerBounds.length == 1) { + checkNotNull(lowerBounds[0]); + checkNotPrimitive(lowerBounds[0]); + checkArgument(upperBounds[0] == Object.class); + this.lowerBound = canonicalize(lowerBounds[0]); + this.upperBound = Object.class; + + } else { + checkNotNull(upperBounds[0]); + checkNotPrimitive(upperBounds[0]); + this.lowerBound = null; + this.upperBound = canonicalize(upperBounds[0]); + } + } + + public Type[] getUpperBounds() { + return new Type[] { upperBound }; + } + + public Type[] getLowerBounds() { + return lowerBound != null ? new Type[] { lowerBound } : EMPTY_TYPE_ARRAY; + } + + @Override public boolean equals(Object other) { + return other instanceof WildcardType + && $Gson$Types.equals(this, (WildcardType) other); + } + + @Override public int hashCode() { + // this equals Arrays.hashCode(getLowerBounds()) ^ Arrays.hashCode(getUpperBounds()); + return (lowerBound != null ? 31 + lowerBound.hashCode() : 1) + ^ (31 + upperBound.hashCode()); + } + + @Override public String toString() { + if (lowerBound != null) { + return "? super " + typeToString(lowerBound); + } else if (upperBound == Object.class) { + return "?"; + } else { + return "? extends " + typeToString(upperBound); + } + } + + private static final long serialVersionUID = 0; + } +} diff --git a/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/ConstructorConstructor.java b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/ConstructorConstructor.java new file mode 100644 index 0000000..0f953aa --- /dev/null +++ b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/ConstructorConstructor.java @@ -0,0 +1,238 @@ +/* + * Copyright (C) 2011 Google Inc. + * + * 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. + */ + +package com.google.gson285.internal; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.ArrayDeque; +import java.util.ArrayList; +import java.util.Collection; +import java.util.EnumSet; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Queue; +import java.util.Set; +import java.util.SortedMap; +import java.util.SortedSet; +import java.util.TreeMap; +import java.util.TreeSet; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.ConcurrentNavigableMap; +import java.util.concurrent.ConcurrentSkipListMap; + +import com.google.gson285.InstanceCreator; +import com.google.gson285.JsonIOException; +import com.google.gson285.internal.reflect.ReflectionAccessor; +import com.google.gson285.reflect.TypeToken; + +/** + * Returns a function that can construct an instance of a requested type. + */ +public final class ConstructorConstructor { + private final Map> instanceCreators; + private final ReflectionAccessor accessor = ReflectionAccessor.getInstance(); + + public ConstructorConstructor(Map> instanceCreators) { + this.instanceCreators = instanceCreators; + } + + public ObjectConstructor get(TypeToken typeToken) { + final Type type = typeToken.getType(); + final Class rawType = typeToken.getRawType(); + + // first try an instance creator + + @SuppressWarnings("unchecked") // types must agree + final InstanceCreator typeCreator = (InstanceCreator) instanceCreators.get(type); + if (typeCreator != null) { + return new ObjectConstructor() { + @Override public T construct() { + return typeCreator.createInstance(type); + } + }; + } + + // Next try raw type match for instance creators + @SuppressWarnings("unchecked") // types must agree + final InstanceCreator rawTypeCreator = + (InstanceCreator) instanceCreators.get(rawType); + if (rawTypeCreator != null) { + return new ObjectConstructor() { + @Override public T construct() { + return rawTypeCreator.createInstance(type); + } + }; + } + + ObjectConstructor defaultConstructor = newDefaultConstructor(rawType); + if (defaultConstructor != null) { + return defaultConstructor; + } + + ObjectConstructor defaultImplementation = newDefaultImplementationConstructor(type, rawType); + if (defaultImplementation != null) { + return defaultImplementation; + } + + // finally try unsafe + return newUnsafeAllocator(type, rawType); + } + + private ObjectConstructor newDefaultConstructor(Class rawType) { + try { + final Constructor constructor = rawType.getDeclaredConstructor(); + if (!constructor.isAccessible()) { + accessor.makeAccessible(constructor); + } + return new ObjectConstructor() { + @SuppressWarnings("unchecked") // T is the same raw type as is requested + @Override public T construct() { + try { + Object[] args = null; + return (T) constructor.newInstance(args); + } catch (InstantiationException e) { + // TODO: JsonParseException ? + throw new RuntimeException("Failed to invoke " + constructor + " with no args", e); + } catch (InvocationTargetException e) { + // TODO: don't wrap if cause is unchecked! + // TODO: JsonParseException ? + throw new RuntimeException("Failed to invoke " + constructor + " with no args", + e.getTargetException()); + } catch (IllegalAccessException e) { + throw new AssertionError(e); + } + } + }; + } catch (NoSuchMethodException e) { + return null; + } + } + + /** + * Constructors for common interface types like Map and List and their + * subtypes. + */ + @SuppressWarnings("unchecked") // use runtime checks to guarantee that 'T' is what it is + private ObjectConstructor newDefaultImplementationConstructor( + final Type type, Class rawType) { + if (Collection.class.isAssignableFrom(rawType)) { + if (SortedSet.class.isAssignableFrom(rawType)) { + return new ObjectConstructor() { + @Override public T construct() { + return (T) new TreeSet(); + } + }; + } else if (EnumSet.class.isAssignableFrom(rawType)) { + return new ObjectConstructor() { + @SuppressWarnings("rawtypes") + @Override public T construct() { + if (type instanceof ParameterizedType) { + Type elementType = ((ParameterizedType) type).getActualTypeArguments()[0]; + if (elementType instanceof Class) { + return (T) EnumSet.noneOf((Class)elementType); + } else { + throw new JsonIOException("Invalid EnumSet type: " + type.toString()); + } + } else { + throw new JsonIOException("Invalid EnumSet type: " + type.toString()); + } + } + }; + } else if (Set.class.isAssignableFrom(rawType)) { + return new ObjectConstructor() { + @Override public T construct() { + return (T) new LinkedHashSet(); + } + }; + } else if (Queue.class.isAssignableFrom(rawType)) { + return new ObjectConstructor() { + @Override public T construct() { + return (T) new ArrayDeque(); + } + }; + } else { + return new ObjectConstructor() { + @Override public T construct() { + return (T) new ArrayList(); + } + }; + } + } + + if (Map.class.isAssignableFrom(rawType)) { + if (ConcurrentNavigableMap.class.isAssignableFrom(rawType)) { + return new ObjectConstructor() { + @Override public T construct() { + return (T) new ConcurrentSkipListMap(); + } + }; + } else if (ConcurrentMap.class.isAssignableFrom(rawType)) { + return new ObjectConstructor() { + @Override public T construct() { + return (T) new ConcurrentHashMap(); + } + }; + } else if (SortedMap.class.isAssignableFrom(rawType)) { + return new ObjectConstructor() { + @Override public T construct() { + return (T) new TreeMap(); + } + }; + } else if (type instanceof ParameterizedType && !(String.class.isAssignableFrom( + TypeToken.get(((ParameterizedType) type).getActualTypeArguments()[0]).getRawType()))) { + return new ObjectConstructor() { + @Override public T construct() { + return (T) new LinkedHashMap(); + } + }; + } else { + return new ObjectConstructor() { + @Override public T construct() { + return (T) new LinkedTreeMap(); + } + }; + } + } + + return null; + } + + private ObjectConstructor newUnsafeAllocator( + final Type type, final Class rawType) { + return new ObjectConstructor() { + private final UnsafeAllocator unsafeAllocator = UnsafeAllocator.create(); + @SuppressWarnings("unchecked") + @Override public T construct() { + try { + Object newInstance = unsafeAllocator.newInstance(rawType); + return (T) newInstance; + } catch (Exception e) { + throw new RuntimeException(("Unable to invoke no-args constructor for " + type + ". " + + "Registering an InstanceCreator with Gson for this type may fix this problem."), e); + } + } + }; + } + + @Override public String toString() { + return instanceCreators.toString(); + } +} diff --git a/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/Excluder.java b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/Excluder.java new file mode 100644 index 0000000..9e780c6 --- /dev/null +++ b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/Excluder.java @@ -0,0 +1,260 @@ +/* + * Copyright (C) 2008 Google Inc. + * + * 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. + */ + +package com.google.gson285.internal; + +import com.google.gson285.ExclusionStrategy; +import com.google.gson285.FieldAttributes; +import com.google.gson285.Gson; +import com.google.gson285.TypeAdapter; +import com.google.gson285.TypeAdapterFactory; +import com.google.gson285.annotations.Expose; +import com.google.gson285.annotations.Since; +import com.google.gson285.annotations.Until; +import com.google.gson285.reflect.TypeToken; +import com.google.gson285.stream.JsonReader; +import com.google.gson285.stream.JsonWriter; +import java.io.IOException; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * This class selects which fields and types to omit. It is configurable, + * supporting version attributes {@link Since} and {@link Until}, modifiers, + * synthetic fields, anonymous and local classes, inner classes, and fields with + * the {@link Expose} annotation. + * + *

This class is a type adapter factory; types that are excluded will be + * adapted to null. It may delegate to another type adapter if only one + * direction is excluded. + * + * @author Joel Leitch + * @author Jesse Wilson + */ +public final class Excluder implements TypeAdapterFactory, Cloneable { + private static final double IGNORE_VERSIONS = -1.0d; + public static final Excluder DEFAULT = new Excluder(); + + private double version = IGNORE_VERSIONS; + private int modifiers = Modifier.TRANSIENT | Modifier.STATIC; + private boolean serializeInnerClasses = true; + private boolean requireExpose; + private List serializationStrategies = Collections.emptyList(); + private List deserializationStrategies = Collections.emptyList(); + + @Override protected Excluder clone() { + try { + return (Excluder) super.clone(); + } catch (CloneNotSupportedException e) { + throw new AssertionError(e); + } + } + + public Excluder withVersion(double ignoreVersionsAfter) { + Excluder result = clone(); + result.version = ignoreVersionsAfter; + return result; + } + + public Excluder withModifiers(int... modifiers) { + Excluder result = clone(); + result.modifiers = 0; + for (int modifier : modifiers) { + result.modifiers |= modifier; + } + return result; + } + + public Excluder disableInnerClassSerialization() { + Excluder result = clone(); + result.serializeInnerClasses = false; + return result; + } + + public Excluder excludeFieldsWithoutExposeAnnotation() { + Excluder result = clone(); + result.requireExpose = true; + return result; + } + + public Excluder withExclusionStrategy(ExclusionStrategy exclusionStrategy, + boolean serialization, boolean deserialization) { + Excluder result = clone(); + if (serialization) { + result.serializationStrategies = new ArrayList(serializationStrategies); + result.serializationStrategies.add(exclusionStrategy); + } + if (deserialization) { + result.deserializationStrategies + = new ArrayList(deserializationStrategies); + result.deserializationStrategies.add(exclusionStrategy); + } + return result; + } + + public TypeAdapter create(final Gson gson, final TypeToken type) { + Class rawType = type.getRawType(); + boolean excludeClass = excludeClassChecks(rawType); + + final boolean skipSerialize = excludeClass || excludeClassInStrategy(rawType, true); + final boolean skipDeserialize = excludeClass || excludeClassInStrategy(rawType, false); + + if (!skipSerialize && !skipDeserialize) { + return null; + } + + return new TypeAdapter() { + /** The delegate is lazily created because it may not be needed, and creating it may fail. */ + private TypeAdapter delegate; + + @Override public T read(JsonReader in) throws IOException { + if (skipDeserialize) { + in.skipValue(); + return null; + } + return delegate().read(in); + } + + @Override public void write(JsonWriter out, T value) throws IOException { + if (skipSerialize) { + out.nullValue(); + return; + } + delegate().write(out, value); + } + + private TypeAdapter delegate() { + TypeAdapter d = delegate; + return d != null + ? d + : (delegate = gson.getDelegateAdapter(Excluder.this, type)); + } + }; + } + + public boolean excludeField(Field field, boolean serialize) { + if ((modifiers & field.getModifiers()) != 0) { + return true; + } + + if (version != Excluder.IGNORE_VERSIONS + && !isValidVersion(field.getAnnotation(Since.class), field.getAnnotation(Until.class))) { + return true; + } + + if (field.isSynthetic()) { + return true; + } + + if (requireExpose) { + Expose annotation = field.getAnnotation(Expose.class); + if (annotation == null || (serialize ? !annotation.serialize() : !annotation.deserialize())) { + return true; + } + } + + if (!serializeInnerClasses && isInnerClass(field.getType())) { + return true; + } + + if (isAnonymousOrLocal(field.getType())) { + return true; + } + + List list = serialize ? serializationStrategies : deserializationStrategies; + if (!list.isEmpty()) { + FieldAttributes fieldAttributes = new FieldAttributes(field); + for (ExclusionStrategy exclusionStrategy : list) { + if (exclusionStrategy.shouldSkipField(fieldAttributes)) { + return true; + } + } + } + + return false; + } + + private boolean excludeClassChecks(Class clazz) { + if (version != Excluder.IGNORE_VERSIONS && !isValidVersion(clazz.getAnnotation(Since.class), clazz.getAnnotation(Until.class))) { + return true; + } + + if (!serializeInnerClasses && isInnerClass(clazz)) { + return true; + } + + if (isAnonymousOrLocal(clazz)) { + return true; + } + + return false; + } + + public boolean excludeClass(Class clazz, boolean serialize) { + return excludeClassChecks(clazz) || + excludeClassInStrategy(clazz, serialize); + } + + private boolean excludeClassInStrategy(Class clazz, boolean serialize) { + List list = serialize ? serializationStrategies : deserializationStrategies; + for (ExclusionStrategy exclusionStrategy : list) { + if (exclusionStrategy.shouldSkipClass(clazz)) { + return true; + } + } + return false; + } + + private boolean isAnonymousOrLocal(Class clazz) { + return !Enum.class.isAssignableFrom(clazz) + && (clazz.isAnonymousClass() || clazz.isLocalClass()); + } + + private boolean isInnerClass(Class clazz) { + return clazz.isMemberClass() && !isStatic(clazz); + } + + private boolean isStatic(Class clazz) { + return (clazz.getModifiers() & Modifier.STATIC) != 0; + } + + private boolean isValidVersion(Since since, Until until) { + return isValidSince(since) && isValidUntil(until); + } + + private boolean isValidSince(Since annotation) { + if (annotation != null) { + double annotationVersion = annotation.value(); + if (annotationVersion > version) { + return false; + } + } + return true; + } + + private boolean isValidUntil(Until annotation) { + if (annotation != null) { + double annotationVersion = annotation.value(); + if (annotationVersion <= version) { + return false; + } + } + return true; + } +} diff --git a/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/GsonBuildConfig.java b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/GsonBuildConfig.java new file mode 100644 index 0000000..67e4af4 --- /dev/null +++ b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/GsonBuildConfig.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2018 The Gson authors + * + * 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. + */ + +package com.google.gson285.internal; + +/** + * Build configuration for Gson. This file is automatically populated by + * templating-maven-plugin and .java/.class files are generated for use in Gson. + * + * @author Inderjeet Singh + */ +public final class GsonBuildConfig { + // Based on https://stackoverflow.com/questions/2469922/generate-a-version-java-file-in-maven + + /** This field is automatically populated by Maven when a build is triggered */ + public static final String VERSION = "${project.version}"; + + private GsonBuildConfig() { } +} diff --git a/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/JavaVersion.java b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/JavaVersion.java new file mode 100644 index 0000000..15ddb0e --- /dev/null +++ b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/JavaVersion.java @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2017 The Gson authors + * + * 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. + */ + +package com.google.gson285.internal; + +/** + * Utility to check the major Java version of the current JVM. + */ +public final class JavaVersion { + // Oracle defines naming conventions at http://www.oracle.com/technetwork/java/javase/versioning-naming-139433.html + // However, many alternate implementations differ. For example, Debian used 9-debian as the version string + + private static final int majorJavaVersion = determineMajorJavaVersion(); + + private static int determineMajorJavaVersion() { + String javaVersion = System.getProperty("java.version"); + return getMajorJavaVersion(javaVersion); + } + + // Visible for testing only + static int getMajorJavaVersion(String javaVersion) { + int version = parseDotted(javaVersion); + if (version == -1) { + version = extractBeginningInt(javaVersion); + } + if (version == -1) { + return 6; // Choose minimum supported JDK version as default + } + return version; + } + + // Parses both legacy 1.8 style and newer 9.0.4 style + private static int parseDotted(String javaVersion) { + try { + String[] parts = javaVersion.split("[._]"); + int firstVer = Integer.parseInt(parts[0]); + if (firstVer == 1 && parts.length > 1) { + return Integer.parseInt(parts[1]); + } else { + return firstVer; + } + } catch (NumberFormatException e) { + return -1; + } + } + + private static int extractBeginningInt(String javaVersion) { + try { + StringBuilder num = new StringBuilder(); + for (int i = 0; i < javaVersion.length(); ++i) { + char c = javaVersion.charAt(i); + if (Character.isDigit(c)) { + num.append(c); + } else { + break; + } + } + return Integer.parseInt(num.toString()); + } catch (NumberFormatException e) { + return -1; + } + } + + /** + * @return the major Java version, i.e. '8' for Java 1.8, '9' for Java 9 etc. + */ + public static int getMajorJavaVersion() { + return majorJavaVersion; + } + + /** + * @return {@code true} if the application is running on Java 9 or later; and {@code false} otherwise. + */ + public static boolean isJava9OrLater() { + return majorJavaVersion >= 9; + } + + private JavaVersion() { } +} diff --git a/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/JsonReaderInternalAccess.java b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/JsonReaderInternalAccess.java new file mode 100644 index 0000000..415dc58 --- /dev/null +++ b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/JsonReaderInternalAccess.java @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2011 Google Inc. + * + * 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. + */ + +package com.google.gson285.internal; + +import com.google.gson285.stream.JsonReader; +import java.io.IOException; + +/** + * Internal-only APIs of JsonReader available only to other classes in Gson. + */ +public abstract class JsonReaderInternalAccess { + public static JsonReaderInternalAccess INSTANCE; + + /** + * Changes the type of the current property name token to a string value. + */ + public abstract void promoteNameToValue(JsonReader reader) throws IOException; +} diff --git a/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/LazilyParsedNumber.java b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/LazilyParsedNumber.java new file mode 100644 index 0000000..5403a4f --- /dev/null +++ b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/LazilyParsedNumber.java @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2011 Google Inc. + * + * 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. + */ +package com.google.gson285.internal; + +import java.io.ObjectStreamException; +import java.math.BigDecimal; + +/** + * This class holds a number value that is lazily converted to a specific number type + * + * @author Inderjeet Singh + */ +public final class LazilyParsedNumber extends Number { + private final String value; + + /** @param value must not be null */ + public LazilyParsedNumber(String value) { + this.value = value; + } + + @Override + public int intValue() { + try { + return Integer.parseInt(value); + } catch (NumberFormatException e) { + try { + return (int) Long.parseLong(value); + } catch (NumberFormatException nfe) { + return new BigDecimal(value).intValue(); + } + } + } + + @Override + public long longValue() { + try { + return Long.parseLong(value); + } catch (NumberFormatException e) { + return new BigDecimal(value).longValue(); + } + } + + @Override + public float floatValue() { + return Float.parseFloat(value); + } + + @Override + public double doubleValue() { + return Double.parseDouble(value); + } + + @Override + public String toString() { + return value; + } + + /** + * If somebody is unlucky enough to have to serialize one of these, serialize + * it as a BigDecimal so that they won't need Gson on the other side to + * deserialize it. + */ + private Object writeReplace() throws ObjectStreamException { + return new BigDecimal(value); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof LazilyParsedNumber) { + LazilyParsedNumber other = (LazilyParsedNumber) obj; + return value == other.value || value.equals(other.value); + } + return false; + } +} diff --git a/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/LinkedHashTreeMap.java b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/LinkedHashTreeMap.java new file mode 100644 index 0000000..7021e26 --- /dev/null +++ b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/LinkedHashTreeMap.java @@ -0,0 +1,864 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * Copyright (C) 2012 Google Inc. + * + * 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. + */ + +package com.google.gson285.internal; + +import java.io.ObjectStreamException; +import java.io.Serializable; +import java.util.AbstractMap; +import java.util.AbstractSet; +import java.util.Arrays; +import java.util.Comparator; +import java.util.ConcurrentModificationException; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.NoSuchElementException; +import java.util.Set; + +/** + * A map of comparable keys to values. Unlike {@code TreeMap}, this class uses + * insertion order for iteration order. Comparison order is only used as an + * optimization for efficient insertion and removal. + * + *

This implementation was derived from Android 4.1's TreeMap and + * LinkedHashMap classes. + */ +public final class LinkedHashTreeMap extends AbstractMap implements Serializable { + @SuppressWarnings({ "unchecked", "rawtypes" }) // to avoid Comparable>> + private static final Comparator NATURAL_ORDER = new Comparator() { + public int compare(Comparable a, Comparable b) { + return a.compareTo(b); + } + }; + + Comparator comparator; + Node[] table; + final Node header; + int size = 0; + int modCount = 0; + int threshold; + + /** + * Create a natural order, empty tree map whose keys must be mutually + * comparable and non-null. + */ + @SuppressWarnings("unchecked") // unsafe! this assumes K is comparable + public LinkedHashTreeMap() { + this((Comparator) NATURAL_ORDER); + } + + /** + * Create a tree map ordered by {@code comparator}. This map's keys may only + * be null if {@code comparator} permits. + * + * @param comparator the comparator to order elements with, or {@code null} to + * use the natural ordering. + */ + @SuppressWarnings({ "unchecked", "rawtypes" }) // unsafe! if comparator is null, this assumes K is comparable + public LinkedHashTreeMap(Comparator comparator) { + this.comparator = comparator != null + ? comparator + : (Comparator) NATURAL_ORDER; + this.header = new Node(); + this.table = new Node[16]; // TODO: sizing/resizing policies + this.threshold = (table.length / 2) + (table.length / 4); // 3/4 capacity + } + + @Override public int size() { + return size; + } + + @Override public V get(Object key) { + Node node = findByObject(key); + return node != null ? node.value : null; + } + + @Override public boolean containsKey(Object key) { + return findByObject(key) != null; + } + + @Override public V put(K key, V value) { + if (key == null) { + throw new NullPointerException("key == null"); + } + Node created = find(key, true); + V result = created.value; + created.value = value; + return result; + } + + @Override public void clear() { + Arrays.fill(table, null); + size = 0; + modCount++; + + // Clear all links to help GC + Node header = this.header; + for (Node e = header.next; e != header; ) { + Node next = e.next; + e.next = e.prev = null; + e = next; + } + + header.next = header.prev = header; + } + + @Override public V remove(Object key) { + Node node = removeInternalByKey(key); + return node != null ? node.value : null; + } + + /** + * Returns the node at or adjacent to the given key, creating it if requested. + * + * @throws ClassCastException if {@code key} and the tree's keys aren't + * mutually comparable. + */ + Node find(K key, boolean create) { + Comparator comparator = this.comparator; + Node[] table = this.table; + int hash = secondaryHash(key.hashCode()); + int index = hash & (table.length - 1); + Node nearest = table[index]; + int comparison = 0; + + if (nearest != null) { + // Micro-optimization: avoid polymorphic calls to Comparator.compare(). + @SuppressWarnings("unchecked") // Throws a ClassCastException below if there's trouble. + Comparable comparableKey = (comparator == NATURAL_ORDER) + ? (Comparable) key + : null; + + while (true) { + comparison = (comparableKey != null) + ? comparableKey.compareTo(nearest.key) + : comparator.compare(key, nearest.key); + + // We found the requested key. + if (comparison == 0) { + return nearest; + } + + // If it exists, the key is in a subtree. Go deeper. + Node child = (comparison < 0) ? nearest.left : nearest.right; + if (child == null) { + break; + } + + nearest = child; + } + } + + // The key doesn't exist in this tree. + if (!create) { + return null; + } + + // Create the node and add it to the tree or the table. + Node header = this.header; + Node created; + if (nearest == null) { + // Check that the value is comparable if we didn't do any comparisons. + if (comparator == NATURAL_ORDER && !(key instanceof Comparable)) { + throw new ClassCastException(key.getClass().getName() + " is not Comparable"); + } + created = new Node(nearest, key, hash, header, header.prev); + table[index] = created; + } else { + created = new Node(nearest, key, hash, header, header.prev); + if (comparison < 0) { // nearest.key is higher + nearest.left = created; + } else { // comparison > 0, nearest.key is lower + nearest.right = created; + } + rebalance(nearest, true); + } + + if (size++ > threshold) { + doubleCapacity(); + } + modCount++; + + return created; + } + + @SuppressWarnings("unchecked") + Node findByObject(Object key) { + try { + return key != null ? find((K) key, false) : null; + } catch (ClassCastException e) { + return null; + } + } + + /** + * Returns this map's entry that has the same key and value as {@code + * entry}, or null if this map has no such entry. + * + *

This method uses the comparator for key equality rather than {@code + * equals}. If this map's comparator isn't consistent with equals (such as + * {@code String.CASE_INSENSITIVE_ORDER}), then {@code remove()} and {@code + * contains()} will violate the collections API. + */ + Node findByEntry(Entry entry) { + Node mine = findByObject(entry.getKey()); + boolean valuesEqual = mine != null && equal(mine.value, entry.getValue()); + return valuesEqual ? mine : null; + } + + private boolean equal(Object a, Object b) { + return a == b || (a != null && a.equals(b)); + } + + /** + * Applies a supplemental hash function to a given hashCode, which defends + * against poor quality hash functions. This is critical because HashMap + * uses power-of-two length hash tables, that otherwise encounter collisions + * for hashCodes that do not differ in lower or upper bits. + */ + private static int secondaryHash(int h) { + // Doug Lea's supplemental hash function + h ^= (h >>> 20) ^ (h >>> 12); + return h ^ (h >>> 7) ^ (h >>> 4); + } + + /** + * Removes {@code node} from this tree, rearranging the tree's structure as + * necessary. + * + * @param unlink true to also unlink this node from the iteration linked list. + */ + void removeInternal(Node node, boolean unlink) { + if (unlink) { + node.prev.next = node.next; + node.next.prev = node.prev; + node.next = node.prev = null; // Help the GC (for performance) + } + + Node left = node.left; + Node right = node.right; + Node originalParent = node.parent; + if (left != null && right != null) { + + /* + * To remove a node with both left and right subtrees, move an + * adjacent node from one of those subtrees into this node's place. + * + * Removing the adjacent node may change this node's subtrees. This + * node may no longer have two subtrees once the adjacent node is + * gone! + */ + + Node adjacent = (left.height > right.height) ? left.last() : right.first(); + removeInternal(adjacent, false); // takes care of rebalance and size-- + + int leftHeight = 0; + left = node.left; + if (left != null) { + leftHeight = left.height; + adjacent.left = left; + left.parent = adjacent; + node.left = null; + } + int rightHeight = 0; + right = node.right; + if (right != null) { + rightHeight = right.height; + adjacent.right = right; + right.parent = adjacent; + node.right = null; + } + adjacent.height = Math.max(leftHeight, rightHeight) + 1; + replaceInParent(node, adjacent); + return; + } else if (left != null) { + replaceInParent(node, left); + node.left = null; + } else if (right != null) { + replaceInParent(node, right); + node.right = null; + } else { + replaceInParent(node, null); + } + + rebalance(originalParent, false); + size--; + modCount++; + } + + Node removeInternalByKey(Object key) { + Node node = findByObject(key); + if (node != null) { + removeInternal(node, true); + } + return node; + } + + private void replaceInParent(Node node, Node replacement) { + Node parent = node.parent; + node.parent = null; + if (replacement != null) { + replacement.parent = parent; + } + + if (parent != null) { + if (parent.left == node) { + parent.left = replacement; + } else { + assert (parent.right == node); + parent.right = replacement; + } + } else { + int index = node.hash & (table.length - 1); + table[index] = replacement; + } + } + + /** + * Rebalances the tree by making any AVL rotations necessary between the + * newly-unbalanced node and the tree's root. + * + * @param insert true if the node was unbalanced by an insert; false if it + * was by a removal. + */ + private void rebalance(Node unbalanced, boolean insert) { + for (Node node = unbalanced; node != null; node = node.parent) { + Node left = node.left; + Node right = node.right; + int leftHeight = left != null ? left.height : 0; + int rightHeight = right != null ? right.height : 0; + + int delta = leftHeight - rightHeight; + if (delta == -2) { + Node rightLeft = right.left; + Node rightRight = right.right; + int rightRightHeight = rightRight != null ? rightRight.height : 0; + int rightLeftHeight = rightLeft != null ? rightLeft.height : 0; + + int rightDelta = rightLeftHeight - rightRightHeight; + if (rightDelta == -1 || (rightDelta == 0 && !insert)) { + rotateLeft(node); // AVL right right + } else { + assert (rightDelta == 1); + rotateRight(right); // AVL right left + rotateLeft(node); + } + if (insert) { + break; // no further rotations will be necessary + } + + } else if (delta == 2) { + Node leftLeft = left.left; + Node leftRight = left.right; + int leftRightHeight = leftRight != null ? leftRight.height : 0; + int leftLeftHeight = leftLeft != null ? leftLeft.height : 0; + + int leftDelta = leftLeftHeight - leftRightHeight; + if (leftDelta == 1 || (leftDelta == 0 && !insert)) { + rotateRight(node); // AVL left left + } else { + assert (leftDelta == -1); + rotateLeft(left); // AVL left right + rotateRight(node); + } + if (insert) { + break; // no further rotations will be necessary + } + + } else if (delta == 0) { + node.height = leftHeight + 1; // leftHeight == rightHeight + if (insert) { + break; // the insert caused balance, so rebalancing is done! + } + + } else { + assert (delta == -1 || delta == 1); + node.height = Math.max(leftHeight, rightHeight) + 1; + if (!insert) { + break; // the height hasn't changed, so rebalancing is done! + } + } + } + } + + /** + * Rotates the subtree so that its root's right child is the new root. + */ + private void rotateLeft(Node root) { + Node left = root.left; + Node pivot = root.right; + Node pivotLeft = pivot.left; + Node pivotRight = pivot.right; + + // move the pivot's left child to the root's right + root.right = pivotLeft; + if (pivotLeft != null) { + pivotLeft.parent = root; + } + + replaceInParent(root, pivot); + + // move the root to the pivot's left + pivot.left = root; + root.parent = pivot; + + // fix heights + root.height = Math.max(left != null ? left.height : 0, + pivotLeft != null ? pivotLeft.height : 0) + 1; + pivot.height = Math.max(root.height, + pivotRight != null ? pivotRight.height : 0) + 1; + } + + /** + * Rotates the subtree so that its root's left child is the new root. + */ + private void rotateRight(Node root) { + Node pivot = root.left; + Node right = root.right; + Node pivotLeft = pivot.left; + Node pivotRight = pivot.right; + + // move the pivot's right child to the root's left + root.left = pivotRight; + if (pivotRight != null) { + pivotRight.parent = root; + } + + replaceInParent(root, pivot); + + // move the root to the pivot's right + pivot.right = root; + root.parent = pivot; + + // fixup heights + root.height = Math.max(right != null ? right.height : 0, + pivotRight != null ? pivotRight.height : 0) + 1; + pivot.height = Math.max(root.height, + pivotLeft != null ? pivotLeft.height : 0) + 1; + } + + private EntrySet entrySet; + private KeySet keySet; + + @Override public Set> entrySet() { + EntrySet result = entrySet; + return result != null ? result : (entrySet = new EntrySet()); + } + + @Override public Set keySet() { + KeySet result = keySet; + return result != null ? result : (keySet = new KeySet()); + } + + static final class Node implements Entry { + Node parent; + Node left; + Node right; + Node next; + Node prev; + final K key; + final int hash; + V value; + int height; + + /** Create the header entry */ + Node() { + key = null; + hash = -1; + next = prev = this; + } + + /** Create a regular entry */ + Node(Node parent, K key, int hash, Node next, Node prev) { + this.parent = parent; + this.key = key; + this.hash = hash; + this.height = 1; + this.next = next; + this.prev = prev; + prev.next = this; + next.prev = this; + } + + public K getKey() { + return key; + } + + public V getValue() { + return value; + } + + public V setValue(V value) { + V oldValue = this.value; + this.value = value; + return oldValue; + } + + @SuppressWarnings("rawtypes") + @Override public boolean equals(Object o) { + if (o instanceof Entry) { + Entry other = (Entry) o; + return (key == null ? other.getKey() == null : key.equals(other.getKey())) + && (value == null ? other.getValue() == null : value.equals(other.getValue())); + } + return false; + } + + @Override public int hashCode() { + return (key == null ? 0 : key.hashCode()) + ^ (value == null ? 0 : value.hashCode()); + } + + @Override public String toString() { + return key + "=" + value; + } + + /** + * Returns the first node in this subtree. + */ + public Node first() { + Node node = this; + Node child = node.left; + while (child != null) { + node = child; + child = node.left; + } + return node; + } + + /** + * Returns the last node in this subtree. + */ + public Node last() { + Node node = this; + Node child = node.right; + while (child != null) { + node = child; + child = node.right; + } + return node; + } + } + + private void doubleCapacity() { + table = doubleCapacity(table); + threshold = (table.length / 2) + (table.length / 4); // 3/4 capacity + } + + /** + * Returns a new array containing the same nodes as {@code oldTable}, but with + * twice as many trees, each of (approximately) half the previous size. + */ + static Node[] doubleCapacity(Node[] oldTable) { + // TODO: don't do anything if we're already at MAX_CAPACITY + int oldCapacity = oldTable.length; + @SuppressWarnings("unchecked") // Arrays and generics don't get along. + Node[] newTable = new Node[oldCapacity * 2]; + AvlIterator iterator = new AvlIterator(); + AvlBuilder leftBuilder = new AvlBuilder(); + AvlBuilder rightBuilder = new AvlBuilder(); + + // Split each tree into two trees. + for (int i = 0; i < oldCapacity; i++) { + Node root = oldTable[i]; + if (root == null) { + continue; + } + + // Compute the sizes of the left and right trees. + iterator.reset(root); + int leftSize = 0; + int rightSize = 0; + for (Node node; (node = iterator.next()) != null; ) { + if ((node.hash & oldCapacity) == 0) { + leftSize++; + } else { + rightSize++; + } + } + + // Split the tree into two. + leftBuilder.reset(leftSize); + rightBuilder.reset(rightSize); + iterator.reset(root); + for (Node node; (node = iterator.next()) != null; ) { + if ((node.hash & oldCapacity) == 0) { + leftBuilder.add(node); + } else { + rightBuilder.add(node); + } + } + + // Populate the enlarged array with these new roots. + newTable[i] = leftSize > 0 ? leftBuilder.root() : null; + newTable[i + oldCapacity] = rightSize > 0 ? rightBuilder.root() : null; + } + return newTable; + } + + /** + * Walks an AVL tree in iteration order. Once a node has been returned, its + * left, right and parent links are no longer used. For this + * reason it is safe to transform these links as you walk a tree. + * + *

Warning: this iterator is destructive. It clears the + * parent node of all nodes in the tree. It is an error to make a partial + * iteration of a tree. + */ + static class AvlIterator { + /** This stack is a singly linked list, linked by the 'parent' field. */ + private Node stackTop; + + void reset(Node root) { + Node stackTop = null; + for (Node n = root; n != null; n = n.left) { + n.parent = stackTop; + stackTop = n; // Stack push. + } + this.stackTop = stackTop; + } + + public Node next() { + Node stackTop = this.stackTop; + if (stackTop == null) { + return null; + } + Node result = stackTop; + stackTop = result.parent; + result.parent = null; + for (Node n = result.right; n != null; n = n.left) { + n.parent = stackTop; + stackTop = n; // Stack push. + } + this.stackTop = stackTop; + return result; + } + } + + /** + * Builds AVL trees of a predetermined size by accepting nodes of increasing + * value. To use: + *

    + *
  1. Call {@link #reset} to initialize the target size size. + *
  2. Call {@link #add} size times with increasing values. + *
  3. Call {@link #root} to get the root of the balanced tree. + *
+ * + *

The returned tree will satisfy the AVL constraint: for every node + * N, the height of N.left and N.right is different by at + * most 1. It accomplishes this by omitting deepest-level leaf nodes when + * building trees whose size isn't a power of 2 minus 1. + * + *

Unlike rebuilding a tree from scratch, this approach requires no value + * comparisons. Using this class to create a tree of size S is + * {@code O(S)}. + */ + final static class AvlBuilder { + /** This stack is a singly linked list, linked by the 'parent' field. */ + private Node stack; + private int leavesToSkip; + private int leavesSkipped; + private int size; + + void reset(int targetSize) { + // compute the target tree size. This is a power of 2 minus one, like 15 or 31. + int treeCapacity = Integer.highestOneBit(targetSize) * 2 - 1; + leavesToSkip = treeCapacity - targetSize; + size = 0; + leavesSkipped = 0; + stack = null; + } + + void add(Node node) { + node.left = node.parent = node.right = null; + node.height = 1; + + // Skip a leaf if necessary. + if (leavesToSkip > 0 && (size & 1) == 0) { + size++; + leavesToSkip--; + leavesSkipped++; + } + + node.parent = stack; + stack = node; // Stack push. + size++; + + // Skip a leaf if necessary. + if (leavesToSkip > 0 && (size & 1) == 0) { + size++; + leavesToSkip--; + leavesSkipped++; + } + + /* + * Combine 3 nodes into subtrees whenever the size is one less than a + * multiple of 4. For example we combine the nodes A, B, C into a + * 3-element tree with B as the root. + * + * Combine two subtrees and a spare single value whenever the size is one + * less than a multiple of 8. For example at 8 we may combine subtrees + * (A B C) and (E F G) with D as the root to form ((A B C) D (E F G)). + * + * Just as we combine single nodes when size nears a multiple of 4, and + * 3-element trees when size nears a multiple of 8, we combine subtrees of + * size (N-1) whenever the total size is 2N-1 whenever N is a power of 2. + */ + for (int scale = 4; (size & scale - 1) == scale - 1; scale *= 2) { + if (leavesSkipped == 0) { + // Pop right, center and left, then make center the top of the stack. + Node right = stack; + Node center = right.parent; + Node left = center.parent; + center.parent = left.parent; + stack = center; + // Construct a tree. + center.left = left; + center.right = right; + center.height = right.height + 1; + left.parent = center; + right.parent = center; + } else if (leavesSkipped == 1) { + // Pop right and center, then make center the top of the stack. + Node right = stack; + Node center = right.parent; + stack = center; + // Construct a tree with no left child. + center.right = right; + center.height = right.height + 1; + right.parent = center; + leavesSkipped = 0; + } else if (leavesSkipped == 2) { + leavesSkipped = 0; + } + } + } + + Node root() { + Node stackTop = this.stack; + if (stackTop.parent != null) { + throw new IllegalStateException(); + } + return stackTop; + } + } + + private abstract class LinkedTreeMapIterator implements Iterator { + Node next = header.next; + Node lastReturned = null; + int expectedModCount = modCount; + + LinkedTreeMapIterator() { + } + + public final boolean hasNext() { + return next != header; + } + + final Node nextNode() { + Node e = next; + if (e == header) { + throw new NoSuchElementException(); + } + if (modCount != expectedModCount) { + throw new ConcurrentModificationException(); + } + next = e.next; + return lastReturned = e; + } + + public final void remove() { + if (lastReturned == null) { + throw new IllegalStateException(); + } + removeInternal(lastReturned, true); + lastReturned = null; + expectedModCount = modCount; + } + } + + final class EntrySet extends AbstractSet> { + @Override public int size() { + return size; + } + + @Override public Iterator> iterator() { + return new LinkedTreeMapIterator>() { + public Entry next() { + return nextNode(); + } + }; + } + + @Override public boolean contains(Object o) { + return o instanceof Entry && findByEntry((Entry) o) != null; + } + + @Override public boolean remove(Object o) { + if (!(o instanceof Entry)) { + return false; + } + + Node node = findByEntry((Entry) o); + if (node == null) { + return false; + } + removeInternal(node, true); + return true; + } + + @Override public void clear() { + LinkedHashTreeMap.this.clear(); + } + } + + final class KeySet extends AbstractSet { + @Override public int size() { + return size; + } + + @Override public Iterator iterator() { + return new LinkedTreeMapIterator() { + public K next() { + return nextNode().key; + } + }; + } + + @Override public boolean contains(Object o) { + return containsKey(o); + } + + @Override public boolean remove(Object key) { + return removeInternalByKey(key) != null; + } + + @Override public void clear() { + LinkedHashTreeMap.this.clear(); + } + } + + /** + * If somebody is unlucky enough to have to serialize one of these, serialize + * it as a LinkedHashMap so that they won't need Gson on the other side to + * deserialize it. Using serialization defeats our DoS defence, so most apps + * shouldn't use it. + */ + private Object writeReplace() throws ObjectStreamException { + return new LinkedHashMap(this); + } +} diff --git a/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/LinkedTreeMap.java b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/LinkedTreeMap.java new file mode 100644 index 0000000..6e09f46 --- /dev/null +++ b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/LinkedTreeMap.java @@ -0,0 +1,630 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * Copyright (C) 2012 Google Inc. + * + * 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. + */ + +package com.google.gson285.internal; + +import java.io.ObjectStreamException; +import java.io.Serializable; +import java.util.AbstractMap; +import java.util.AbstractSet; +import java.util.Comparator; +import java.util.ConcurrentModificationException; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.NoSuchElementException; +import java.util.Set; + +/** + * A map of comparable keys to values. Unlike {@code TreeMap}, this class uses + * insertion order for iteration order. Comparison order is only used as an + * optimization for efficient insertion and removal. + * + *

This implementation was derived from Android 4.1's TreeMap class. + */ +public final class LinkedTreeMap extends AbstractMap implements Serializable { + @SuppressWarnings({ "unchecked", "rawtypes" }) // to avoid Comparable>> + private static final Comparator NATURAL_ORDER = new Comparator() { + public int compare(Comparable a, Comparable b) { + return a.compareTo(b); + } + }; + + Comparator comparator; + Node root; + int size = 0; + int modCount = 0; + + // Used to preserve iteration order + final Node header = new Node(); + + /** + * Create a natural order, empty tree map whose keys must be mutually + * comparable and non-null. + */ + @SuppressWarnings("unchecked") // unsafe! this assumes K is comparable + public LinkedTreeMap() { + this((Comparator) NATURAL_ORDER); + } + + /** + * Create a tree map ordered by {@code comparator}. This map's keys may only + * be null if {@code comparator} permits. + * + * @param comparator the comparator to order elements with, or {@code null} to + * use the natural ordering. + */ + @SuppressWarnings({ "unchecked", "rawtypes" }) // unsafe! if comparator is null, this assumes K is comparable + public LinkedTreeMap(Comparator comparator) { + this.comparator = comparator != null + ? comparator + : (Comparator) NATURAL_ORDER; + } + + @Override public int size() { + return size; + } + + @Override public V get(Object key) { + Node node = findByObject(key); + return node != null ? node.value : null; + } + + @Override public boolean containsKey(Object key) { + return findByObject(key) != null; + } + + @Override public V put(K key, V value) { + if (key == null) { + throw new NullPointerException("key == null"); + } + Node created = find(key, true); + V result = created.value; + created.value = value; + return result; + } + + @Override public void clear() { + root = null; + size = 0; + modCount++; + + // Clear iteration order + Node header = this.header; + header.next = header.prev = header; + } + + @Override public V remove(Object key) { + Node node = removeInternalByKey(key); + return node != null ? node.value : null; + } + + /** + * Returns the node at or adjacent to the given key, creating it if requested. + * + * @throws ClassCastException if {@code key} and the tree's keys aren't + * mutually comparable. + */ + Node find(K key, boolean create) { + Comparator comparator = this.comparator; + Node nearest = root; + int comparison = 0; + + if (nearest != null) { + // Micro-optimization: avoid polymorphic calls to Comparator.compare(). + @SuppressWarnings("unchecked") // Throws a ClassCastException below if there's trouble. + Comparable comparableKey = (comparator == NATURAL_ORDER) + ? (Comparable) key + : null; + + while (true) { + comparison = (comparableKey != null) + ? comparableKey.compareTo(nearest.key) + : comparator.compare(key, nearest.key); + + // We found the requested key. + if (comparison == 0) { + return nearest; + } + + // If it exists, the key is in a subtree. Go deeper. + Node child = (comparison < 0) ? nearest.left : nearest.right; + if (child == null) { + break; + } + + nearest = child; + } + } + + // The key doesn't exist in this tree. + if (!create) { + return null; + } + + // Create the node and add it to the tree or the table. + Node header = this.header; + Node created; + if (nearest == null) { + // Check that the value is comparable if we didn't do any comparisons. + if (comparator == NATURAL_ORDER && !(key instanceof Comparable)) { + throw new ClassCastException(key.getClass().getName() + " is not Comparable"); + } + created = new Node(nearest, key, header, header.prev); + root = created; + } else { + created = new Node(nearest, key, header, header.prev); + if (comparison < 0) { // nearest.key is higher + nearest.left = created; + } else { // comparison > 0, nearest.key is lower + nearest.right = created; + } + rebalance(nearest, true); + } + size++; + modCount++; + + return created; + } + + @SuppressWarnings("unchecked") + Node findByObject(Object key) { + try { + return key != null ? find((K) key, false) : null; + } catch (ClassCastException e) { + return null; + } + } + + /** + * Returns this map's entry that has the same key and value as {@code + * entry}, or null if this map has no such entry. + * + *

This method uses the comparator for key equality rather than {@code + * equals}. If this map's comparator isn't consistent with equals (such as + * {@code String.CASE_INSENSITIVE_ORDER}), then {@code remove()} and {@code + * contains()} will violate the collections API. + */ + Node findByEntry(Entry entry) { + Node mine = findByObject(entry.getKey()); + boolean valuesEqual = mine != null && equal(mine.value, entry.getValue()); + return valuesEqual ? mine : null; + } + + private boolean equal(Object a, Object b) { + return a == b || (a != null && a.equals(b)); + } + + /** + * Removes {@code node} from this tree, rearranging the tree's structure as + * necessary. + * + * @param unlink true to also unlink this node from the iteration linked list. + */ + void removeInternal(Node node, boolean unlink) { + if (unlink) { + node.prev.next = node.next; + node.next.prev = node.prev; + } + + Node left = node.left; + Node right = node.right; + Node originalParent = node.parent; + if (left != null && right != null) { + + /* + * To remove a node with both left and right subtrees, move an + * adjacent node from one of those subtrees into this node's place. + * + * Removing the adjacent node may change this node's subtrees. This + * node may no longer have two subtrees once the adjacent node is + * gone! + */ + + Node adjacent = (left.height > right.height) ? left.last() : right.first(); + removeInternal(adjacent, false); // takes care of rebalance and size-- + + int leftHeight = 0; + left = node.left; + if (left != null) { + leftHeight = left.height; + adjacent.left = left; + left.parent = adjacent; + node.left = null; + } + + int rightHeight = 0; + right = node.right; + if (right != null) { + rightHeight = right.height; + adjacent.right = right; + right.parent = adjacent; + node.right = null; + } + + adjacent.height = Math.max(leftHeight, rightHeight) + 1; + replaceInParent(node, adjacent); + return; + } else if (left != null) { + replaceInParent(node, left); + node.left = null; + } else if (right != null) { + replaceInParent(node, right); + node.right = null; + } else { + replaceInParent(node, null); + } + + rebalance(originalParent, false); + size--; + modCount++; + } + + Node removeInternalByKey(Object key) { + Node node = findByObject(key); + if (node != null) { + removeInternal(node, true); + } + return node; + } + + private void replaceInParent(Node node, Node replacement) { + Node parent = node.parent; + node.parent = null; + if (replacement != null) { + replacement.parent = parent; + } + + if (parent != null) { + if (parent.left == node) { + parent.left = replacement; + } else { + assert (parent.right == node); + parent.right = replacement; + } + } else { + root = replacement; + } + } + + /** + * Rebalances the tree by making any AVL rotations necessary between the + * newly-unbalanced node and the tree's root. + * + * @param insert true if the node was unbalanced by an insert; false if it + * was by a removal. + */ + private void rebalance(Node unbalanced, boolean insert) { + for (Node node = unbalanced; node != null; node = node.parent) { + Node left = node.left; + Node right = node.right; + int leftHeight = left != null ? left.height : 0; + int rightHeight = right != null ? right.height : 0; + + int delta = leftHeight - rightHeight; + if (delta == -2) { + Node rightLeft = right.left; + Node rightRight = right.right; + int rightRightHeight = rightRight != null ? rightRight.height : 0; + int rightLeftHeight = rightLeft != null ? rightLeft.height : 0; + + int rightDelta = rightLeftHeight - rightRightHeight; + if (rightDelta == -1 || (rightDelta == 0 && !insert)) { + rotateLeft(node); // AVL right right + } else { + assert (rightDelta == 1); + rotateRight(right); // AVL right left + rotateLeft(node); + } + if (insert) { + break; // no further rotations will be necessary + } + + } else if (delta == 2) { + Node leftLeft = left.left; + Node leftRight = left.right; + int leftRightHeight = leftRight != null ? leftRight.height : 0; + int leftLeftHeight = leftLeft != null ? leftLeft.height : 0; + + int leftDelta = leftLeftHeight - leftRightHeight; + if (leftDelta == 1 || (leftDelta == 0 && !insert)) { + rotateRight(node); // AVL left left + } else { + assert (leftDelta == -1); + rotateLeft(left); // AVL left right + rotateRight(node); + } + if (insert) { + break; // no further rotations will be necessary + } + + } else if (delta == 0) { + node.height = leftHeight + 1; // leftHeight == rightHeight + if (insert) { + break; // the insert caused balance, so rebalancing is done! + } + + } else { + assert (delta == -1 || delta == 1); + node.height = Math.max(leftHeight, rightHeight) + 1; + if (!insert) { + break; // the height hasn't changed, so rebalancing is done! + } + } + } + } + + /** + * Rotates the subtree so that its root's right child is the new root. + */ + private void rotateLeft(Node root) { + Node left = root.left; + Node pivot = root.right; + Node pivotLeft = pivot.left; + Node pivotRight = pivot.right; + + // move the pivot's left child to the root's right + root.right = pivotLeft; + if (pivotLeft != null) { + pivotLeft.parent = root; + } + + replaceInParent(root, pivot); + + // move the root to the pivot's left + pivot.left = root; + root.parent = pivot; + + // fix heights + root.height = Math.max(left != null ? left.height : 0, + pivotLeft != null ? pivotLeft.height : 0) + 1; + pivot.height = Math.max(root.height, + pivotRight != null ? pivotRight.height : 0) + 1; + } + + /** + * Rotates the subtree so that its root's left child is the new root. + */ + private void rotateRight(Node root) { + Node pivot = root.left; + Node right = root.right; + Node pivotLeft = pivot.left; + Node pivotRight = pivot.right; + + // move the pivot's right child to the root's left + root.left = pivotRight; + if (pivotRight != null) { + pivotRight.parent = root; + } + + replaceInParent(root, pivot); + + // move the root to the pivot's right + pivot.right = root; + root.parent = pivot; + + // fixup heights + root.height = Math.max(right != null ? right.height : 0, + pivotRight != null ? pivotRight.height : 0) + 1; + pivot.height = Math.max(root.height, + pivotLeft != null ? pivotLeft.height : 0) + 1; + } + + private EntrySet entrySet; + private KeySet keySet; + + @Override public Set> entrySet() { + EntrySet result = entrySet; + return result != null ? result : (entrySet = new EntrySet()); + } + + @Override public Set keySet() { + KeySet result = keySet; + return result != null ? result : (keySet = new KeySet()); + } + + static final class Node implements Entry { + Node parent; + Node left; + Node right; + Node next; + Node prev; + final K key; + V value; + int height; + + /** Create the header entry */ + Node() { + key = null; + next = prev = this; + } + + /** Create a regular entry */ + Node(Node parent, K key, Node next, Node prev) { + this.parent = parent; + this.key = key; + this.height = 1; + this.next = next; + this.prev = prev; + prev.next = this; + next.prev = this; + } + + public K getKey() { + return key; + } + + public V getValue() { + return value; + } + + public V setValue(V value) { + V oldValue = this.value; + this.value = value; + return oldValue; + } + + @SuppressWarnings("rawtypes") + @Override public boolean equals(Object o) { + if (o instanceof Entry) { + Entry other = (Entry) o; + return (key == null ? other.getKey() == null : key.equals(other.getKey())) + && (value == null ? other.getValue() == null : value.equals(other.getValue())); + } + return false; + } + + @Override public int hashCode() { + return (key == null ? 0 : key.hashCode()) + ^ (value == null ? 0 : value.hashCode()); + } + + @Override public String toString() { + return key + "=" + value; + } + + /** + * Returns the first node in this subtree. + */ + public Node first() { + Node node = this; + Node child = node.left; + while (child != null) { + node = child; + child = node.left; + } + return node; + } + + /** + * Returns the last node in this subtree. + */ + public Node last() { + Node node = this; + Node child = node.right; + while (child != null) { + node = child; + child = node.right; + } + return node; + } + } + + private abstract class LinkedTreeMapIterator implements Iterator { + Node next = header.next; + Node lastReturned = null; + int expectedModCount = modCount; + + LinkedTreeMapIterator() { + } + + public final boolean hasNext() { + return next != header; + } + + final Node nextNode() { + Node e = next; + if (e == header) { + throw new NoSuchElementException(); + } + if (modCount != expectedModCount) { + throw new ConcurrentModificationException(); + } + next = e.next; + return lastReturned = e; + } + + public final void remove() { + if (lastReturned == null) { + throw new IllegalStateException(); + } + removeInternal(lastReturned, true); + lastReturned = null; + expectedModCount = modCount; + } + } + + class EntrySet extends AbstractSet> { + @Override public int size() { + return size; + } + + @Override public Iterator> iterator() { + return new LinkedTreeMapIterator>() { + public Entry next() { + return nextNode(); + } + }; + } + + @Override public boolean contains(Object o) { + return o instanceof Entry && findByEntry((Entry) o) != null; + } + + @Override public boolean remove(Object o) { + if (!(o instanceof Entry)) { + return false; + } + + Node node = findByEntry((Entry) o); + if (node == null) { + return false; + } + removeInternal(node, true); + return true; + } + + @Override public void clear() { + LinkedTreeMap.this.clear(); + } + } + + final class KeySet extends AbstractSet { + @Override public int size() { + return size; + } + + @Override public Iterator iterator() { + return new LinkedTreeMapIterator() { + public K next() { + return nextNode().key; + } + }; + } + + @Override public boolean contains(Object o) { + return containsKey(o); + } + + @Override public boolean remove(Object key) { + return removeInternalByKey(key) != null; + } + + @Override public void clear() { + LinkedTreeMap.this.clear(); + } + } + + /** + * If somebody is unlucky enough to have to serialize one of these, serialize + * it as a LinkedHashMap so that they won't need Gson on the other side to + * deserialize it. Using serialization defeats our DoS defence, so most apps + * shouldn't use it. + */ + private Object writeReplace() throws ObjectStreamException { + return new LinkedHashMap(this); + } +} diff --git a/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/ObjectConstructor.java b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/ObjectConstructor.java new file mode 100644 index 0000000..ed92650 --- /dev/null +++ b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/ObjectConstructor.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2008 Google Inc. + * + * 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. + */ + +package com.google.gson285.internal; + +/** + * Defines a generic object construction factory. The purpose of this class + * is to construct a default instance of a class that can be used for object + * navigation while deserialization from its JSON representation. + * + * @author Inderjeet Singh + * @author Joel Leitch + */ +public interface ObjectConstructor { + + /** + * Returns a new instance. + */ + public T construct(); +} \ No newline at end of file diff --git a/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/PreJava9DateFormatProvider.java b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/PreJava9DateFormatProvider.java new file mode 100644 index 0000000..5e5fd51 --- /dev/null +++ b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/PreJava9DateFormatProvider.java @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2017 The Gson authors + * + * 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. + */ +package com.google.gson285.internal; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Locale; + +/** + * Provides DateFormats for US locale with patterns which were the default ones before Java 9. + */ +public class PreJava9DateFormatProvider { + + /** + * Returns the same DateFormat as {@code DateFormat.getDateInstance(style, Locale.US)} in Java 8 or below. + */ + public static DateFormat getUSDateFormat(int style) { + return new SimpleDateFormat(getDateFormatPattern(style), Locale.US); + } + + /** + * Returns the same DateFormat as {@code DateFormat.getDateTimeInstance(dateStyle, timeStyle, Locale.US)} + * in Java 8 or below. + */ + public static DateFormat getUSDateTimeFormat(int dateStyle, int timeStyle) { + String pattern = getDatePartOfDateTimePattern(dateStyle) + " " + getTimePartOfDateTimePattern(timeStyle); + return new SimpleDateFormat(pattern, Locale.US); + } + + private static String getDateFormatPattern(int style) { + switch (style) { + case DateFormat.SHORT: + return "M/d/yy"; + case DateFormat.MEDIUM: + return "MMM d, y"; + case DateFormat.LONG: + return "MMMM d, y"; + case DateFormat.FULL: + return "EEEE, MMMM d, y"; + default: + throw new IllegalArgumentException("Unknown DateFormat style: " + style); + } + } + + private static String getDatePartOfDateTimePattern(int dateStyle) { + switch (dateStyle) { + case DateFormat.SHORT: + return "M/d/yy"; + case DateFormat.MEDIUM: + return "MMM d, yyyy"; + case DateFormat.LONG: + return "MMMM d, yyyy"; + case DateFormat.FULL: + return "EEEE, MMMM d, yyyy"; + default: + throw new IllegalArgumentException("Unknown DateFormat style: " + dateStyle); + } + } + + private static String getTimePartOfDateTimePattern(int timeStyle) { + switch (timeStyle) { + case DateFormat.SHORT: + return "h:mm a"; + case DateFormat.MEDIUM: + return "h:mm:ss a"; + case DateFormat.FULL: + case DateFormat.LONG: + return "h:mm:ss a z"; + default: + throw new IllegalArgumentException("Unknown DateFormat style: " + timeStyle); + } + } +} diff --git a/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/Primitives.java b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/Primitives.java new file mode 100644 index 0000000..0b021cb --- /dev/null +++ b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/Primitives.java @@ -0,0 +1,119 @@ +/* + * Copyright (C) 2008 Google Inc. + * + * 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. + */ + +package com.google.gson285.internal; + + +import java.lang.reflect.Type; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/** + * Contains static utility methods pertaining to primitive types and their + * corresponding wrapper types. + * + * @author Kevin Bourrillion + */ +public final class Primitives { + private Primitives() { + throw new UnsupportedOperationException(); + } + + /** A map from primitive types to their corresponding wrapper types. */ + private static final Map, Class> PRIMITIVE_TO_WRAPPER_TYPE; + + /** A map from wrapper types to their corresponding primitive types. */ + private static final Map, Class> WRAPPER_TO_PRIMITIVE_TYPE; + + // Sad that we can't use a BiMap. :( + + static { + Map, Class> primToWrap = new HashMap, Class>(16); + Map, Class> wrapToPrim = new HashMap, Class>(16); + + add(primToWrap, wrapToPrim, boolean.class, Boolean.class); + add(primToWrap, wrapToPrim, byte.class, Byte.class); + add(primToWrap, wrapToPrim, char.class, Character.class); + add(primToWrap, wrapToPrim, double.class, Double.class); + add(primToWrap, wrapToPrim, float.class, Float.class); + add(primToWrap, wrapToPrim, int.class, Integer.class); + add(primToWrap, wrapToPrim, long.class, Long.class); + add(primToWrap, wrapToPrim, short.class, Short.class); + add(primToWrap, wrapToPrim, void.class, Void.class); + + PRIMITIVE_TO_WRAPPER_TYPE = Collections.unmodifiableMap(primToWrap); + WRAPPER_TO_PRIMITIVE_TYPE = Collections.unmodifiableMap(wrapToPrim); + } + + private static void add(Map, Class> forward, + Map, Class> backward, Class key, Class value) { + forward.put(key, value); + backward.put(value, key); + } + + /** + * Returns true if this type is a primitive. + */ + public static boolean isPrimitive(Type type) { + return PRIMITIVE_TO_WRAPPER_TYPE.containsKey(type); + } + + /** + * Returns {@code true} if {@code type} is one of the nine + * primitive-wrapper types, such as {@link Integer}. + * + * @see Class#isPrimitive + */ + public static boolean isWrapperType(Type type) { + return WRAPPER_TO_PRIMITIVE_TYPE.containsKey( + $Gson$Preconditions.checkNotNull(type)); + } + + /** + * Returns the corresponding wrapper type of {@code type} if it is a primitive + * type; otherwise returns {@code type} itself. Idempotent. + *

+   *     wrap(int.class) == Integer.class
+   *     wrap(Integer.class) == Integer.class
+   *     wrap(String.class) == String.class
+   * 
+ */ + public static Class wrap(Class type) { + // cast is safe: long.class and Long.class are both of type Class + @SuppressWarnings("unchecked") + Class wrapped = (Class) PRIMITIVE_TO_WRAPPER_TYPE.get( + $Gson$Preconditions.checkNotNull(type)); + return (wrapped == null) ? type : wrapped; + } + + /** + * Returns the corresponding primitive type of {@code type} if it is a + * wrapper type; otherwise returns {@code type} itself. Idempotent. + *
+   *     unwrap(Integer.class) == int.class
+   *     unwrap(int.class) == int.class
+   *     unwrap(String.class) == String.class
+   * 
+ */ + public static Class unwrap(Class type) { + // cast is safe: long.class and Long.class are both of type Class + @SuppressWarnings("unchecked") + Class unwrapped = (Class) WRAPPER_TO_PRIMITIVE_TYPE.get( + $Gson$Preconditions.checkNotNull(type)); + return (unwrapped == null) ? type : unwrapped; + } +} diff --git a/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/Streams.java b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/Streams.java new file mode 100644 index 0000000..c0a2eef --- /dev/null +++ b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/Streams.java @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2010 Google Inc. + * + * 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. + */ + +package com.google.gson285.internal; + +import com.google.gson285.JsonElement; +import com.google.gson285.JsonIOException; +import com.google.gson285.JsonNull; +import com.google.gson285.JsonParseException; +import com.google.gson285.JsonSyntaxException; +import com.google.gson285.internal.bind.TypeAdapters; +import com.google.gson285.stream.JsonReader; +import com.google.gson285.stream.JsonWriter; +import com.google.gson285.stream.MalformedJsonException; +import java.io.EOFException; +import java.io.IOException; +import java.io.Writer; + +/** + * Reads and writes GSON parse trees over streams. + */ +public final class Streams { + private Streams() { + throw new UnsupportedOperationException(); + } + + /** + * Takes a reader in any state and returns the next value as a JsonElement. + */ + public static JsonElement parse(JsonReader reader) throws JsonParseException { + boolean isEmpty = true; + try { + reader.peek(); + isEmpty = false; + return TypeAdapters.JSON_ELEMENT.read(reader); + } catch (EOFException e) { + /* + * For compatibility with JSON 1.5 and earlier, we return a JsonNull for + * empty documents instead of throwing. + */ + if (isEmpty) { + return JsonNull.INSTANCE; + } + // The stream ended prematurely so it is likely a syntax error. + throw new JsonSyntaxException(e); + } catch (MalformedJsonException e) { + throw new JsonSyntaxException(e); + } catch (IOException e) { + throw new JsonIOException(e); + } catch (NumberFormatException e) { + throw new JsonSyntaxException(e); + } + } + + /** + * Writes the JSON element to the writer, recursively. + */ + public static void write(JsonElement element, JsonWriter writer) throws IOException { + TypeAdapters.JSON_ELEMENT.write(writer, element); + } + + public static Writer writerForAppendable(Appendable appendable) { + return appendable instanceof Writer ? (Writer) appendable : new AppendableWriter(appendable); + } + + /** + * Adapts an {@link Appendable} so it can be passed anywhere a {@link Writer} + * is used. + */ + private static final class AppendableWriter extends Writer { + private final Appendable appendable; + private final CurrentWrite currentWrite = new CurrentWrite(); + + AppendableWriter(Appendable appendable) { + this.appendable = appendable; + } + + @Override public void write(char[] chars, int offset, int length) throws IOException { + currentWrite.chars = chars; + appendable.append(currentWrite, offset, offset + length); + } + + @Override public void write(int i) throws IOException { + appendable.append((char) i); + } + + @Override public void flush() {} + @Override public void close() {} + + /** + * A mutable char sequence pointing at a single char[]. + */ + static class CurrentWrite implements CharSequence { + char[] chars; + public int length() { + return chars.length; + } + public char charAt(int i) { + return chars[i]; + } + public CharSequence subSequence(int start, int end) { + return new String(chars, start, end - start); + } + } + } + +} diff --git a/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/UnsafeAllocator.java b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/UnsafeAllocator.java new file mode 100644 index 0000000..05947b8 --- /dev/null +++ b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/UnsafeAllocator.java @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2011 Google Inc. + * + * 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. + */ + +package com.google.gson285.internal; + +import java.io.ObjectInputStream; +import java.io.ObjectStreamClass; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; + +/** + * Do sneaky things to allocate objects without invoking their constructors. + * + * @author Joel Leitch + * @author Jesse Wilson + */ +public abstract class UnsafeAllocator { + public abstract T newInstance(Class c) throws Exception; + + public static UnsafeAllocator create() { + // try JVM + // public class Unsafe { + // public Object allocateInstance(Class type); + // } + try { + Class unsafeClass = Class.forName("sun.misc.Unsafe"); + Field f = unsafeClass.getDeclaredField("theUnsafe"); + f.setAccessible(true); + final Object unsafe = f.get(null); + final Method allocateInstance = unsafeClass.getMethod("allocateInstance", Class.class); + return new UnsafeAllocator() { + @Override + @SuppressWarnings("unchecked") + public T newInstance(Class c) throws Exception { + assertInstantiable(c); + return (T) allocateInstance.invoke(unsafe, c); + } + }; + } catch (Exception ignored) { + } + + // try dalvikvm, post-gingerbread + // public class ObjectStreamClass { + // private static native int getConstructorId(Class c); + // private static native Object newInstance(Class instantiationClass, int methodId); + // } + try { + Method getConstructorId = ObjectStreamClass.class + .getDeclaredMethod("getConstructorId", Class.class); + getConstructorId.setAccessible(true); + final int constructorId = (Integer) getConstructorId.invoke(null, Object.class); + final Method newInstance = ObjectStreamClass.class + .getDeclaredMethod("newInstance", Class.class, int.class); + newInstance.setAccessible(true); + return new UnsafeAllocator() { + @Override + @SuppressWarnings("unchecked") + public T newInstance(Class c) throws Exception { + assertInstantiable(c); + return (T) newInstance.invoke(null, c, constructorId); + } + }; + } catch (Exception ignored) { + } + + // try dalvikvm, pre-gingerbread + // public class ObjectInputStream { + // private static native Object newInstance( + // Class instantiationClass, Class constructorClass); + // } + try { + final Method newInstance = ObjectInputStream.class + .getDeclaredMethod("newInstance", Class.class, Class.class); + newInstance.setAccessible(true); + return new UnsafeAllocator() { + @Override + @SuppressWarnings("unchecked") + public T newInstance(Class c) throws Exception { + assertInstantiable(c); + return (T) newInstance.invoke(null, c, Object.class); + } + }; + } catch (Exception ignored) { + } + + // give up + return new UnsafeAllocator() { + @Override + public T newInstance(Class c) { + throw new UnsupportedOperationException("Cannot allocate " + c); + } + }; + } + + /** + * Check if the class can be instantiated by unsafe allocator. If the instance has interface or abstract modifiers + * throw an {@link java.lang.UnsupportedOperationException} + * @param c instance of the class to be checked + */ + static void assertInstantiable(Class c) { + int modifiers = c.getModifiers(); + if (Modifier.isInterface(modifiers)) { + throw new UnsupportedOperationException("Interface can't be instantiated! Interface name: " + c.getName()); + } + if (Modifier.isAbstract(modifiers)) { + throw new UnsupportedOperationException("Abstract class can't be instantiated! Class name: " + c.getName()); + } + } +} diff --git a/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/bind/ArrayTypeAdapter.java b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/bind/ArrayTypeAdapter.java new file mode 100644 index 0000000..a9e5bed --- /dev/null +++ b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/bind/ArrayTypeAdapter.java @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2011 Google Inc. + * + * 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. + */ + +package com.google.gson285.internal.bind; + +import java.io.IOException; +import java.lang.reflect.Array; +import java.lang.reflect.GenericArrayType; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.List; + +import com.google.gson285.Gson; +import com.google.gson285.TypeAdapter; +import com.google.gson285.TypeAdapterFactory; +import com.google.gson285.internal.$Gson$Types; +import com.google.gson285.reflect.TypeToken; +import com.google.gson285.stream.JsonReader; +import com.google.gson285.stream.JsonToken; +import com.google.gson285.stream.JsonWriter; + +/** + * Adapt an array of objects. + */ +public final class ArrayTypeAdapter extends TypeAdapter { + public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() { + @SuppressWarnings({"unchecked", "rawtypes"}) + @Override public TypeAdapter create(Gson gson, TypeToken typeToken) { + Type type = typeToken.getType(); + if (!(type instanceof GenericArrayType || type instanceof Class && ((Class) type).isArray())) { + return null; + } + + Type componentType = $Gson$Types.getArrayComponentType(type); + TypeAdapter componentTypeAdapter = gson.getAdapter(TypeToken.get(componentType)); + return new ArrayTypeAdapter( + gson, componentTypeAdapter, $Gson$Types.getRawType(componentType)); + } + }; + + private final Class componentType; + private final TypeAdapter componentTypeAdapter; + + public ArrayTypeAdapter(Gson context, TypeAdapter componentTypeAdapter, Class componentType) { + this.componentTypeAdapter = + new TypeAdapterRuntimeTypeWrapper(context, componentTypeAdapter, componentType); + this.componentType = componentType; + } + + @Override public Object read(JsonReader in) throws IOException { + if (in.peek() == JsonToken.NULL) { + in.nextNull(); + return null; + } + + List list = new ArrayList(); + in.beginArray(); + while (in.hasNext()) { + E instance = componentTypeAdapter.read(in); + list.add(instance); + } + in.endArray(); + + int size = list.size(); + Object array = Array.newInstance(componentType, size); + for (int i = 0; i < size; i++) { + Array.set(array, i, list.get(i)); + } + return array; + } + + @SuppressWarnings("unchecked") + @Override public void write(JsonWriter out, Object array) throws IOException { + if (array == null) { + out.nullValue(); + return; + } + + out.beginArray(); + for (int i = 0, length = Array.getLength(array); i < length; i++) { + E value = (E) Array.get(array, i); + componentTypeAdapter.write(out, value); + } + out.endArray(); + } +} diff --git a/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/bind/CollectionTypeAdapterFactory.java b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/bind/CollectionTypeAdapterFactory.java new file mode 100644 index 0000000..388849e --- /dev/null +++ b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/bind/CollectionTypeAdapterFactory.java @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2011 Google Inc. + * + * 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. + */ + +package com.google.gson285.internal.bind; + +import com.google.gson285.Gson; +import com.google.gson285.TypeAdapter; +import com.google.gson285.TypeAdapterFactory; +import com.google.gson285.internal.$Gson$Types; +import com.google.gson285.internal.ConstructorConstructor; +import com.google.gson285.internal.ObjectConstructor; +import com.google.gson285.reflect.TypeToken; +import com.google.gson285.stream.JsonReader; +import com.google.gson285.stream.JsonToken; +import com.google.gson285.stream.JsonWriter; +import java.io.IOException; +import java.lang.reflect.Type; +import java.util.Collection; + +/** + * Adapt a homogeneous collection of objects. + */ +public final class CollectionTypeAdapterFactory implements TypeAdapterFactory { + private final ConstructorConstructor constructorConstructor; + + public CollectionTypeAdapterFactory(ConstructorConstructor constructorConstructor) { + this.constructorConstructor = constructorConstructor; + } + + @Override + public TypeAdapter create(Gson gson, TypeToken typeToken) { + Type type = typeToken.getType(); + + Class rawType = typeToken.getRawType(); + if (!Collection.class.isAssignableFrom(rawType)) { + return null; + } + + Type elementType = $Gson$Types.getCollectionElementType(type, rawType); + TypeAdapter elementTypeAdapter = gson.getAdapter(TypeToken.get(elementType)); + ObjectConstructor constructor = constructorConstructor.get(typeToken); + + @SuppressWarnings({"unchecked", "rawtypes"}) // create() doesn't define a type parameter + TypeAdapter result = new Adapter(gson, elementType, elementTypeAdapter, constructor); + return result; + } + + private static final class Adapter extends TypeAdapter> { + private final TypeAdapter elementTypeAdapter; + private final ObjectConstructor> constructor; + + public Adapter(Gson context, Type elementType, + TypeAdapter elementTypeAdapter, + ObjectConstructor> constructor) { + this.elementTypeAdapter = + new TypeAdapterRuntimeTypeWrapper(context, elementTypeAdapter, elementType); + this.constructor = constructor; + } + + @Override public Collection read(JsonReader in) throws IOException { + if (in.peek() == JsonToken.NULL) { + in.nextNull(); + return null; + } + + Collection collection = constructor.construct(); + in.beginArray(); + while (in.hasNext()) { + E instance = elementTypeAdapter.read(in); + collection.add(instance); + } + in.endArray(); + return collection; + } + + @Override public void write(JsonWriter out, Collection collection) throws IOException { + if (collection == null) { + out.nullValue(); + return; + } + + out.beginArray(); + for (E element : collection) { + elementTypeAdapter.write(out, element); + } + out.endArray(); + } + } +} diff --git a/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/bind/DateTypeAdapter.java b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/bind/DateTypeAdapter.java new file mode 100644 index 0000000..06d50d2 --- /dev/null +++ b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/bind/DateTypeAdapter.java @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2011 Google Inc. + * + * 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. + */ + +package com.google.gson285.internal.bind; + +import com.google.gson285.Gson; +import com.google.gson285.JsonSyntaxException; +import com.google.gson285.TypeAdapter; +import com.google.gson285.TypeAdapterFactory; +import com.google.gson285.internal.JavaVersion; +import com.google.gson285.internal.PreJava9DateFormatProvider; +import com.google.gson285.internal.bind.util.ISO8601Utils; +import com.google.gson285.reflect.TypeToken; +import com.google.gson285.stream.JsonReader; +import com.google.gson285.stream.JsonToken; +import com.google.gson285.stream.JsonWriter; + +import java.io.IOException; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.ParsePosition; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Locale; + +/** + * Adapter for Date. Although this class appears stateless, it is not. + * DateFormat captures its time zone and locale when it is created, which gives + * this class state. DateFormat isn't thread safe either, so this class has + * to synchronize its read and write methods. + */ +public final class DateTypeAdapter extends TypeAdapter { + public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() { + @SuppressWarnings("unchecked") // we use a runtime check to make sure the 'T's equal + @Override public TypeAdapter create(Gson gson, TypeToken typeToken) { + return typeToken.getRawType() == Date.class ? (TypeAdapter) new DateTypeAdapter() : null; + } + }; + + /** + * List of 1 or more different date formats used for de-serialization attempts. + * The first of them (default US format) is used for serialization as well. + */ + private final List dateFormats = new ArrayList(); + + public DateTypeAdapter() { + dateFormats.add(DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.US)); + if (!Locale.getDefault().equals(Locale.US)) { + dateFormats.add(DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT)); + } + if (JavaVersion.isJava9OrLater()) { + dateFormats.add(PreJava9DateFormatProvider.getUSDateTimeFormat(DateFormat.DEFAULT, DateFormat.DEFAULT)); + } + } + + @Override public Date read(JsonReader in) throws IOException { + if (in.peek() == JsonToken.NULL) { + in.nextNull(); + return null; + } + return deserializeToDate(in.nextString()); + } + + private synchronized Date deserializeToDate(String json) { + for (DateFormat dateFormat : dateFormats) { + try { + return dateFormat.parse(json); + } catch (ParseException ignored) {} + } + try { + return ISO8601Utils.parse(json, new ParsePosition(0)); + } catch (ParseException e) { + throw new JsonSyntaxException(json, e); + } + } + + @Override public synchronized void write(JsonWriter out, Date value) throws IOException { + if (value == null) { + out.nullValue(); + return; + } + String dateFormatAsString = dateFormats.get(0).format(value); + out.value(dateFormatAsString); + } + + +} diff --git a/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/bind/JsonAdapterAnnotationTypeAdapterFactory.java b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/bind/JsonAdapterAnnotationTypeAdapterFactory.java new file mode 100644 index 0000000..a2dd486 --- /dev/null +++ b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/bind/JsonAdapterAnnotationTypeAdapterFactory.java @@ -0,0 +1,83 @@ +/* + * Copyright (C) 2014 Google Inc. + * + * 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. + */ + +package com.google.gson285.internal.bind; + +import com.google.gson285.Gson; +import com.google.gson285.JsonDeserializer; +import com.google.gson285.JsonSerializer; +import com.google.gson285.TypeAdapter; +import com.google.gson285.TypeAdapterFactory; +import com.google.gson285.annotations.JsonAdapter; +import com.google.gson285.internal.ConstructorConstructor; +import com.google.gson285.reflect.TypeToken; + +/** + * Given a type T, looks for the annotation {@link JsonAdapter} and uses an instance of the + * specified class as the default type adapter. + * + * @since 2.3 + */ +public final class JsonAdapterAnnotationTypeAdapterFactory implements TypeAdapterFactory { + private final ConstructorConstructor constructorConstructor; + + public JsonAdapterAnnotationTypeAdapterFactory(ConstructorConstructor constructorConstructor) { + this.constructorConstructor = constructorConstructor; + } + + @SuppressWarnings("unchecked") + @Override + public TypeAdapter create(Gson gson, TypeToken targetType) { + Class rawType = targetType.getRawType(); + JsonAdapter annotation = rawType.getAnnotation(JsonAdapter.class); + if (annotation == null) { + return null; + } + return (TypeAdapter) getTypeAdapter(constructorConstructor, gson, targetType, annotation); + } + + @SuppressWarnings({ "unchecked", "rawtypes" }) // Casts guarded by conditionals. + TypeAdapter getTypeAdapter(ConstructorConstructor constructorConstructor, Gson gson, + TypeToken type, JsonAdapter annotation) { + Object instance = constructorConstructor.get(TypeToken.get(annotation.value())).construct(); + + TypeAdapter typeAdapter; + if (instance instanceof TypeAdapter) { + typeAdapter = (TypeAdapter) instance; + } else if (instance instanceof TypeAdapterFactory) { + typeAdapter = ((TypeAdapterFactory) instance).create(gson, type); + } else if (instance instanceof JsonSerializer || instance instanceof JsonDeserializer) { + JsonSerializer serializer = instance instanceof JsonSerializer + ? (JsonSerializer) instance + : null; + JsonDeserializer deserializer = instance instanceof JsonDeserializer + ? (JsonDeserializer) instance + : null; + typeAdapter = new TreeTypeAdapter(serializer, deserializer, gson, type, null); + } else { + throw new IllegalArgumentException("Invalid attempt to bind an instance of " + + instance.getClass().getName() + " as a @JsonAdapter for " + type.toString() + + ". @JsonAdapter value must be a TypeAdapter, TypeAdapterFactory," + + " JsonSerializer or JsonDeserializer."); + } + + if (typeAdapter != null && annotation.nullSafe()) { + typeAdapter = typeAdapter.nullSafe(); + } + + return typeAdapter; + } +} diff --git a/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/bind/JsonTreeReader.java b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/bind/JsonTreeReader.java new file mode 100644 index 0000000..7345a6f --- /dev/null +++ b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/bind/JsonTreeReader.java @@ -0,0 +1,320 @@ +/* + * Copyright (C) 2011 Google Inc. + * + * 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. + */ + +package com.google.gson285.internal.bind; + +import com.google.gson285.JsonArray; +import com.google.gson285.JsonElement; +import com.google.gson285.JsonNull; +import com.google.gson285.JsonObject; +import com.google.gson285.JsonPrimitive; +import com.google.gson285.stream.JsonReader; +import com.google.gson285.stream.JsonToken; +import java.io.IOException; +import java.io.Reader; +import java.util.Iterator; +import java.util.Map; + +/** + * This reader walks the elements of a JsonElement as if it was coming from a + * character stream. + * + * @author Jesse Wilson + */ +public final class JsonTreeReader extends JsonReader { + private static final Reader UNREADABLE_READER = new Reader() { + @Override public int read(char[] buffer, int offset, int count) throws IOException { + throw new AssertionError(); + } + @Override public void close() throws IOException { + throw new AssertionError(); + } + }; + private static final Object SENTINEL_CLOSED = new Object(); + + /* + * The nesting stack. Using a manual array rather than an ArrayList saves 20%. + */ + private Object[] stack = new Object[32]; + private int stackSize = 0; + + /* + * The path members. It corresponds directly to stack: At indices where the + * stack contains an object (EMPTY_OBJECT, DANGLING_NAME or NONEMPTY_OBJECT), + * pathNames contains the name at this scope. Where it contains an array + * (EMPTY_ARRAY, NONEMPTY_ARRAY) pathIndices contains the current index in + * that array. Otherwise the value is undefined, and we take advantage of that + * by incrementing pathIndices when doing so isn't useful. + */ + private String[] pathNames = new String[32]; + private int[] pathIndices = new int[32]; + + public JsonTreeReader(JsonElement element) { + super(UNREADABLE_READER); + push(element); + } + + @Override public void beginArray() throws IOException { + expect(JsonToken.BEGIN_ARRAY); + JsonArray array = (JsonArray) peekStack(); + push(array.iterator()); + pathIndices[stackSize - 1] = 0; + } + + @Override public void endArray() throws IOException { + expect(JsonToken.END_ARRAY); + popStack(); // empty iterator + popStack(); // array + if (stackSize > 0) { + pathIndices[stackSize - 1]++; + } + } + + @Override public void beginObject() throws IOException { + expect(JsonToken.BEGIN_OBJECT); + JsonObject object = (JsonObject) peekStack(); + push(object.entrySet().iterator()); + } + + @Override public void endObject() throws IOException { + expect(JsonToken.END_OBJECT); + popStack(); // empty iterator + popStack(); // object + if (stackSize > 0) { + pathIndices[stackSize - 1]++; + } + } + + @Override public boolean hasNext() throws IOException { + JsonToken token = peek(); + return token != JsonToken.END_OBJECT && token != JsonToken.END_ARRAY; + } + + @Override public JsonToken peek() throws IOException { + if (stackSize == 0) { + return JsonToken.END_DOCUMENT; + } + + Object o = peekStack(); + if (o instanceof Iterator) { + boolean isObject = stack[stackSize - 2] instanceof JsonObject; + Iterator iterator = (Iterator) o; + if (iterator.hasNext()) { + if (isObject) { + return JsonToken.NAME; + } else { + push(iterator.next()); + return peek(); + } + } else { + return isObject ? JsonToken.END_OBJECT : JsonToken.END_ARRAY; + } + } else if (o instanceof JsonObject) { + return JsonToken.BEGIN_OBJECT; + } else if (o instanceof JsonArray) { + return JsonToken.BEGIN_ARRAY; + } else if (o instanceof JsonPrimitive) { + JsonPrimitive primitive = (JsonPrimitive) o; + if (primitive.isString()) { + return JsonToken.STRING; + } else if (primitive.isBoolean()) { + return JsonToken.BOOLEAN; + } else if (primitive.isNumber()) { + return JsonToken.NUMBER; + } else { + throw new AssertionError(); + } + } else if (o instanceof JsonNull) { + return JsonToken.NULL; + } else if (o == SENTINEL_CLOSED) { + throw new IllegalStateException("JsonReader is closed"); + } else { + throw new AssertionError(); + } + } + + private Object peekStack() { + return stack[stackSize - 1]; + } + + private Object popStack() { + Object result = stack[--stackSize]; + stack[stackSize] = null; + return result; + } + + private void expect(JsonToken expected) throws IOException { + if (peek() != expected) { + throw new IllegalStateException( + "Expected " + expected + " but was " + peek() + locationString()); + } + } + + @Override public String nextName() throws IOException { + expect(JsonToken.NAME); + Iterator i = (Iterator) peekStack(); + Map.Entry entry = (Map.Entry) i.next(); + String result = (String) entry.getKey(); + pathNames[stackSize - 1] = result; + push(entry.getValue()); + return result; + } + + @Override public String nextString() throws IOException { + JsonToken token = peek(); + if (token != JsonToken.STRING && token != JsonToken.NUMBER) { + throw new IllegalStateException( + "Expected " + JsonToken.STRING + " but was " + token + locationString()); + } + String result = ((JsonPrimitive) popStack()).getAsString(); + if (stackSize > 0) { + pathIndices[stackSize - 1]++; + } + return result; + } + + @Override public boolean nextBoolean() throws IOException { + expect(JsonToken.BOOLEAN); + boolean result = ((JsonPrimitive) popStack()).getAsBoolean(); + if (stackSize > 0) { + pathIndices[stackSize - 1]++; + } + return result; + } + + @Override public void nextNull() throws IOException { + expect(JsonToken.NULL); + popStack(); + if (stackSize > 0) { + pathIndices[stackSize - 1]++; + } + } + + @Override public double nextDouble() throws IOException { + JsonToken token = peek(); + if (token != JsonToken.NUMBER && token != JsonToken.STRING) { + throw new IllegalStateException( + "Expected " + JsonToken.NUMBER + " but was " + token + locationString()); + } + double result = ((JsonPrimitive) peekStack()).getAsDouble(); + if (!isLenient() && (Double.isNaN(result) || Double.isInfinite(result))) { + throw new NumberFormatException("JSON forbids NaN and infinities: " + result); + } + popStack(); + if (stackSize > 0) { + pathIndices[stackSize - 1]++; + } + return result; + } + + @Override public long nextLong() throws IOException { + JsonToken token = peek(); + if (token != JsonToken.NUMBER && token != JsonToken.STRING) { + throw new IllegalStateException( + "Expected " + JsonToken.NUMBER + " but was " + token + locationString()); + } + long result = ((JsonPrimitive) peekStack()).getAsLong(); + popStack(); + if (stackSize > 0) { + pathIndices[stackSize - 1]++; + } + return result; + } + + @Override public int nextInt() throws IOException { + JsonToken token = peek(); + if (token != JsonToken.NUMBER && token != JsonToken.STRING) { + throw new IllegalStateException( + "Expected " + JsonToken.NUMBER + " but was " + token + locationString()); + } + int result = ((JsonPrimitive) peekStack()).getAsInt(); + popStack(); + if (stackSize > 0) { + pathIndices[stackSize - 1]++; + } + return result; + } + + @Override public void close() throws IOException { + stack = new Object[] { SENTINEL_CLOSED }; + stackSize = 1; + } + + @Override public void skipValue() throws IOException { + if (peek() == JsonToken.NAME) { + nextName(); + pathNames[stackSize - 2] = "null"; + } else { + popStack(); + if (stackSize > 0) { + pathNames[stackSize - 1] = "null"; + } + } + if (stackSize > 0) { + pathIndices[stackSize - 1]++; + } + } + + @Override public String toString() { + return getClass().getSimpleName(); + } + + public void promoteNameToValue() throws IOException { + expect(JsonToken.NAME); + Iterator i = (Iterator) peekStack(); + Map.Entry entry = (Map.Entry) i.next(); + push(entry.getValue()); + push(new JsonPrimitive((String) entry.getKey())); + } + + private void push(Object newTop) { + if (stackSize == stack.length) { + Object[] newStack = new Object[stackSize * 2]; + int[] newPathIndices = new int[stackSize * 2]; + String[] newPathNames = new String[stackSize * 2]; + System.arraycopy(stack, 0, newStack, 0, stackSize); + System.arraycopy(pathIndices, 0, newPathIndices, 0, stackSize); + System.arraycopy(pathNames, 0, newPathNames, 0, stackSize); + stack = newStack; + pathIndices = newPathIndices; + pathNames = newPathNames; + } + stack[stackSize++] = newTop; + } + + @Override public String getPath() { + StringBuilder result = new StringBuilder().append('$'); + for (int i = 0; i < stackSize; i++) { + if (stack[i] instanceof JsonArray) { + if (stack[++i] instanceof Iterator) { + result.append('[').append(pathIndices[i]).append(']'); + } + } else if (stack[i] instanceof JsonObject) { + if (stack[++i] instanceof Iterator) { + result.append('.'); + if (pathNames[i] != null) { + result.append(pathNames[i]); + } + } + } + } + return result.toString(); + } + + private String locationString() { + return " at path " + getPath(); + } +} diff --git a/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/bind/JsonTreeWriter.java b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/bind/JsonTreeWriter.java new file mode 100644 index 0000000..c7ca06f --- /dev/null +++ b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/bind/JsonTreeWriter.java @@ -0,0 +1,208 @@ +/* + * Copyright (C) 2011 Google Inc. + * + * 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. + */ + +package com.google.gson285.internal.bind; + +import com.google.gson285.JsonArray; +import com.google.gson285.JsonElement; +import com.google.gson285.JsonNull; +import com.google.gson285.JsonObject; +import com.google.gson285.JsonPrimitive; +import com.google.gson285.stream.JsonWriter; +import java.io.IOException; +import java.io.Writer; +import java.util.ArrayList; +import java.util.List; + +/** + * This writer creates a JsonElement. + */ +public final class JsonTreeWriter extends JsonWriter { + private static final Writer UNWRITABLE_WRITER = new Writer() { + @Override public void write(char[] buffer, int offset, int counter) { + throw new AssertionError(); + } + @Override public void flush() throws IOException { + throw new AssertionError(); + } + @Override public void close() throws IOException { + throw new AssertionError(); + } + }; + /** Added to the top of the stack when this writer is closed to cause following ops to fail. */ + private static final JsonPrimitive SENTINEL_CLOSED = new JsonPrimitive("closed"); + + /** The JsonElements and JsonArrays under modification, outermost to innermost. */ + private final List stack = new ArrayList(); + + /** The name for the next JSON object value. If non-null, the top of the stack is a JsonObject. */ + private String pendingName; + + /** the JSON element constructed by this writer. */ + private JsonElement product = JsonNull.INSTANCE; // TODO: is this really what we want?; + + public JsonTreeWriter() { + super(UNWRITABLE_WRITER); + } + + /** + * Returns the top level object produced by this writer. + */ + public JsonElement get() { + if (!stack.isEmpty()) { + throw new IllegalStateException("Expected one JSON element but was " + stack); + } + return product; + } + + private JsonElement peek() { + return stack.get(stack.size() - 1); + } + + private void put(JsonElement value) { + if (pendingName != null) { + if (!value.isJsonNull() || getSerializeNulls()) { + JsonObject object = (JsonObject) peek(); + object.add(pendingName, value); + } + pendingName = null; + } else if (stack.isEmpty()) { + product = value; + } else { + JsonElement element = peek(); + if (element instanceof JsonArray) { + ((JsonArray) element).add(value); + } else { + throw new IllegalStateException(); + } + } + } + + @Override public JsonWriter beginArray() throws IOException { + JsonArray array = new JsonArray(); + put(array); + stack.add(array); + return this; + } + + @Override public JsonWriter endArray() throws IOException { + if (stack.isEmpty() || pendingName != null) { + throw new IllegalStateException(); + } + JsonElement element = peek(); + if (element instanceof JsonArray) { + stack.remove(stack.size() - 1); + return this; + } + throw new IllegalStateException(); + } + + @Override public JsonWriter beginObject() throws IOException { + JsonObject object = new JsonObject(); + put(object); + stack.add(object); + return this; + } + + @Override public JsonWriter endObject() throws IOException { + if (stack.isEmpty() || pendingName != null) { + throw new IllegalStateException(); + } + JsonElement element = peek(); + if (element instanceof JsonObject) { + stack.remove(stack.size() - 1); + return this; + } + throw new IllegalStateException(); + } + + @Override public JsonWriter name(String name) throws IOException { + if (stack.isEmpty() || pendingName != null) { + throw new IllegalStateException(); + } + JsonElement element = peek(); + if (element instanceof JsonObject) { + pendingName = name; + return this; + } + throw new IllegalStateException(); + } + + @Override public JsonWriter value(String value) throws IOException { + if (value == null) { + return nullValue(); + } + put(new JsonPrimitive(value)); + return this; + } + + @Override public JsonWriter nullValue() throws IOException { + put(JsonNull.INSTANCE); + return this; + } + + @Override public JsonWriter value(boolean value) throws IOException { + put(new JsonPrimitive(value)); + return this; + } + + @Override public JsonWriter value(Boolean value) throws IOException { + if (value == null) { + return nullValue(); + } + put(new JsonPrimitive(value)); + return this; + } + + @Override public JsonWriter value(double value) throws IOException { + if (!isLenient() && (Double.isNaN(value) || Double.isInfinite(value))) { + throw new IllegalArgumentException("JSON forbids NaN and infinities: " + value); + } + put(new JsonPrimitive(value)); + return this; + } + + @Override public JsonWriter value(long value) throws IOException { + put(new JsonPrimitive(value)); + return this; + } + + @Override public JsonWriter value(Number value) throws IOException { + if (value == null) { + return nullValue(); + } + + if (!isLenient()) { + double d = value.doubleValue(); + if (Double.isNaN(d) || Double.isInfinite(d)) { + throw new IllegalArgumentException("JSON forbids NaN and infinities: " + value); + } + } + + put(new JsonPrimitive(value)); + return this; + } + + @Override public void flush() throws IOException { + } + + @Override public void close() throws IOException { + if (!stack.isEmpty()) { + throw new IOException("Incomplete document"); + } + stack.add(SENTINEL_CLOSED); + } +} diff --git a/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/bind/MapTypeAdapterFactory.java b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/bind/MapTypeAdapterFactory.java new file mode 100644 index 0000000..7f4060a --- /dev/null +++ b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/bind/MapTypeAdapterFactory.java @@ -0,0 +1,264 @@ +/* + * Copyright (C) 2011 Google Inc. + * + * 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. + */ + +package com.google.gson285.internal.bind; + +import com.google.gson285.Gson; +import com.google.gson285.JsonElement; +import com.google.gson285.JsonPrimitive; +import com.google.gson285.JsonSyntaxException; +import com.google.gson285.TypeAdapter; +import com.google.gson285.TypeAdapterFactory; +import com.google.gson285.internal.$Gson$Types; +import com.google.gson285.internal.ConstructorConstructor; +import com.google.gson285.internal.JsonReaderInternalAccess; +import com.google.gson285.internal.ObjectConstructor; +import com.google.gson285.internal.Streams; +import com.google.gson285.reflect.TypeToken; +import com.google.gson285.stream.JsonReader; +import com.google.gson285.stream.JsonToken; +import com.google.gson285.stream.JsonWriter; +import java.io.IOException; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * Adapts maps to either JSON objects or JSON arrays. + * + *

Maps as JSON objects

+ * For primitive keys or when complex map key serialization is not enabled, this + * converts Java {@link Map Maps} to JSON Objects. This requires that map keys + * can be serialized as strings; this is insufficient for some key types. For + * example, consider a map whose keys are points on a grid. The default JSON + * form encodes reasonably:
   {@code
+ *   Map original = new LinkedHashMap();
+ *   original.put(new Point(5, 6), "a");
+ *   original.put(new Point(8, 8), "b");
+ *   System.out.println(gson.toJson(original, type));
+ * }
+ * The above code prints this JSON object:
   {@code
+ *   {
+ *     "(5,6)": "a",
+ *     "(8,8)": "b"
+ *   }
+ * }
+ * But GSON is unable to deserialize this value because the JSON string name is + * just the {@link Object#toString() toString()} of the map key. Attempting to + * convert the above JSON to an object fails with a parse exception: + *
com.google.gson285.JsonParseException: Expecting object found: "(5,6)"
+ *   at com.google.gson285.JsonObjectDeserializationVisitor.visitFieldUsingCustomHandler
+ *   at com.google.gson285.ObjectNavigator.navigateClassFields
+ *   ...
+ * + *

Maps as JSON arrays

+ * An alternative approach taken by this type adapter when it is required and + * complex map key serialization is enabled is to encode maps as arrays of map + * entries. Each map entry is a two element array containing a key and a value. + * This approach is more flexible because any type can be used as the map's key; + * not just strings. But it's also less portable because the receiver of such + * JSON must be aware of the map entry convention. + * + *

Register this adapter when you are creating your GSON instance. + *

   {@code
+ *   Gson gson = new GsonBuilder()
+ *     .registerTypeAdapter(Map.class, new MapAsArrayTypeAdapter())
+ *     .create();
+ * }
+ * This will change the structure of the JSON emitted by the code above. Now we + * get an array. In this case the arrays elements are map entries: + *
   {@code
+ *   [
+ *     [
+ *       {
+ *         "x": 5,
+ *         "y": 6
+ *       },
+ *       "a",
+ *     ],
+ *     [
+ *       {
+ *         "x": 8,
+ *         "y": 8
+ *       },
+ *       "b"
+ *     ]
+ *   ]
+ * }
+ * This format will serialize and deserialize just fine as long as this adapter + * is registered. + */ +public final class MapTypeAdapterFactory implements TypeAdapterFactory { + private final ConstructorConstructor constructorConstructor; + final boolean complexMapKeySerialization; + + public MapTypeAdapterFactory(ConstructorConstructor constructorConstructor, + boolean complexMapKeySerialization) { + this.constructorConstructor = constructorConstructor; + this.complexMapKeySerialization = complexMapKeySerialization; + } + + @Override public TypeAdapter create(Gson gson, TypeToken typeToken) { + Type type = typeToken.getType(); + + Class rawType = typeToken.getRawType(); + if (!Map.class.isAssignableFrom(rawType)) { + return null; + } + + Class rawTypeOfSrc = $Gson$Types.getRawType(type); + Type[] keyAndValueTypes = $Gson$Types.getMapKeyAndValueTypes(type, rawTypeOfSrc); + TypeAdapter keyAdapter = getKeyAdapter(gson, keyAndValueTypes[0]); + TypeAdapter valueAdapter = gson.getAdapter(TypeToken.get(keyAndValueTypes[1])); + ObjectConstructor constructor = constructorConstructor.get(typeToken); + + @SuppressWarnings({"unchecked", "rawtypes"}) + // we don't define a type parameter for the key or value types + TypeAdapter result = new Adapter(gson, keyAndValueTypes[0], keyAdapter, + keyAndValueTypes[1], valueAdapter, constructor); + return result; + } + + /** + * Returns a type adapter that writes the value as a string. + */ + private TypeAdapter getKeyAdapter(Gson context, Type keyType) { + return (keyType == boolean.class || keyType == Boolean.class) + ? TypeAdapters.BOOLEAN_AS_STRING + : context.getAdapter(TypeToken.get(keyType)); + } + + private final class Adapter extends TypeAdapter> { + private final TypeAdapter keyTypeAdapter; + private final TypeAdapter valueTypeAdapter; + private final ObjectConstructor> constructor; + + public Adapter(Gson context, Type keyType, TypeAdapter keyTypeAdapter, + Type valueType, TypeAdapter valueTypeAdapter, + ObjectConstructor> constructor) { + this.keyTypeAdapter = + new TypeAdapterRuntimeTypeWrapper(context, keyTypeAdapter, keyType); + this.valueTypeAdapter = + new TypeAdapterRuntimeTypeWrapper(context, valueTypeAdapter, valueType); + this.constructor = constructor; + } + + @Override public Map read(JsonReader in) throws IOException { + JsonToken peek = in.peek(); + if (peek == JsonToken.NULL) { + in.nextNull(); + return null; + } + + Map map = constructor.construct(); + + if (peek == JsonToken.BEGIN_ARRAY) { + in.beginArray(); + while (in.hasNext()) { + in.beginArray(); // entry array + K key = keyTypeAdapter.read(in); + V value = valueTypeAdapter.read(in); + V replaced = map.put(key, value); + if (replaced != null) { + throw new JsonSyntaxException("duplicate key: " + key); + } + in.endArray(); + } + in.endArray(); + } else { + in.beginObject(); + while (in.hasNext()) { + JsonReaderInternalAccess.INSTANCE.promoteNameToValue(in); + K key = keyTypeAdapter.read(in); + V value = valueTypeAdapter.read(in); + V replaced = map.put(key, value); + if (replaced != null) { + throw new JsonSyntaxException("duplicate key: " + key); + } + } + in.endObject(); + } + return map; + } + + @Override public void write(JsonWriter out, Map map) throws IOException { + if (map == null) { + out.nullValue(); + return; + } + + if (!complexMapKeySerialization) { + out.beginObject(); + for (Map.Entry entry : map.entrySet()) { + out.name(String.valueOf(entry.getKey())); + valueTypeAdapter.write(out, entry.getValue()); + } + out.endObject(); + return; + } + + boolean hasComplexKeys = false; + List keys = new ArrayList(map.size()); + + List values = new ArrayList(map.size()); + for (Map.Entry entry : map.entrySet()) { + JsonElement keyElement = keyTypeAdapter.toJsonTree(entry.getKey()); + keys.add(keyElement); + values.add(entry.getValue()); + hasComplexKeys |= keyElement.isJsonArray() || keyElement.isJsonObject(); + } + + if (hasComplexKeys) { + out.beginArray(); + for (int i = 0, size = keys.size(); i < size; i++) { + out.beginArray(); // entry array + Streams.write(keys.get(i), out); + valueTypeAdapter.write(out, values.get(i)); + out.endArray(); + } + out.endArray(); + } else { + out.beginObject(); + for (int i = 0, size = keys.size(); i < size; i++) { + JsonElement keyElement = keys.get(i); + out.name(keyToString(keyElement)); + valueTypeAdapter.write(out, values.get(i)); + } + out.endObject(); + } + } + + private String keyToString(JsonElement keyElement) { + if (keyElement.isJsonPrimitive()) { + JsonPrimitive primitive = keyElement.getAsJsonPrimitive(); + if (primitive.isNumber()) { + return String.valueOf(primitive.getAsNumber()); + } else if (primitive.isBoolean()) { + return Boolean.toString(primitive.getAsBoolean()); + } else if (primitive.isString()) { + return primitive.getAsString(); + } else { + throw new AssertionError(); + } + } else if (keyElement.isJsonNull()) { + return "null"; + } else { + throw new AssertionError(); + } + } + } +} diff --git a/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/bind/ObjectTypeAdapter.java b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/bind/ObjectTypeAdapter.java new file mode 100644 index 0000000..8055ba0 --- /dev/null +++ b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/bind/ObjectTypeAdapter.java @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2011 Google Inc. + * + * 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. + */ + +package com.google.gson285.internal.bind; + +import com.google.gson285.Gson; +import com.google.gson285.TypeAdapter; +import com.google.gson285.TypeAdapterFactory; +import com.google.gson285.internal.LinkedTreeMap; +import com.google.gson285.reflect.TypeToken; +import com.google.gson285.stream.JsonReader; +import com.google.gson285.stream.JsonToken; +import com.google.gson285.stream.JsonWriter; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * Adapts types whose static type is only 'Object'. Uses getClass() on + * serialization and a primitive/Map/List on deserialization. + */ +public final class ObjectTypeAdapter extends TypeAdapter { + public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() { + @SuppressWarnings("unchecked") + @Override public TypeAdapter create(Gson gson, TypeToken type) { + if (type.getRawType() == Object.class) { + return (TypeAdapter) new ObjectTypeAdapter(gson); + } + return null; + } + }; + + private final Gson gson; + + ObjectTypeAdapter(Gson gson) { + this.gson = gson; + } + + @Override public Object read(JsonReader in) throws IOException { + JsonToken token = in.peek(); + switch (token) { + case BEGIN_ARRAY: + List list = new ArrayList(); + in.beginArray(); + while (in.hasNext()) { + list.add(read(in)); + } + in.endArray(); + return list; + + case BEGIN_OBJECT: + Map map = new LinkedTreeMap(); + in.beginObject(); + while (in.hasNext()) { + map.put(in.nextName(), read(in)); + } + in.endObject(); + return map; + + case STRING: + return in.nextString(); + + case NUMBER: + return in.nextDouble(); + + case BOOLEAN: + return in.nextBoolean(); + + case NULL: + in.nextNull(); + return null; + + default: + throw new IllegalStateException(); + } + } + + @SuppressWarnings("unchecked") + @Override public void write(JsonWriter out, Object value) throws IOException { + if (value == null) { + out.nullValue(); + return; + } + + TypeAdapter typeAdapter = (TypeAdapter) gson.getAdapter(value.getClass()); + if (typeAdapter instanceof ObjectTypeAdapter) { + out.beginObject(); + out.endObject(); + return; + } + + typeAdapter.write(out, value); + } +} diff --git a/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/bind/ReflectiveTypeAdapterFactory.java b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/bind/ReflectiveTypeAdapterFactory.java new file mode 100644 index 0000000..32e4279 --- /dev/null +++ b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/bind/ReflectiveTypeAdapterFactory.java @@ -0,0 +1,254 @@ +/* + * Copyright (C) 2011 Google Inc. + * + * 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. + */ + +package com.google.gson285.internal.bind; + +import com.google.gson285.FieldNamingStrategy; +import com.google.gson285.Gson; +import com.google.gson285.JsonSyntaxException; +import com.google.gson285.TypeAdapter; +import com.google.gson285.TypeAdapterFactory; +import com.google.gson285.annotations.JsonAdapter; +import com.google.gson285.annotations.SerializedName; +import com.google.gson285.internal.$Gson$Types; +import com.google.gson285.internal.ConstructorConstructor; +import com.google.gson285.internal.Excluder; +import com.google.gson285.internal.ObjectConstructor; +import com.google.gson285.internal.Primitives; +import com.google.gson285.internal.reflect.ReflectionAccessor; +import com.google.gson285.reflect.TypeToken; +import com.google.gson285.stream.JsonReader; +import com.google.gson285.stream.JsonToken; +import com.google.gson285.stream.JsonWriter; +import java.io.IOException; +import java.lang.reflect.Field; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +/** + * Type adapter that reflects over the fields and methods of a class. + */ +public final class ReflectiveTypeAdapterFactory implements TypeAdapterFactory { + private final ConstructorConstructor constructorConstructor; + private final FieldNamingStrategy fieldNamingPolicy; + private final Excluder excluder; + private final JsonAdapterAnnotationTypeAdapterFactory jsonAdapterFactory; + private final ReflectionAccessor accessor = ReflectionAccessor.getInstance(); + + public ReflectiveTypeAdapterFactory(ConstructorConstructor constructorConstructor, + FieldNamingStrategy fieldNamingPolicy, Excluder excluder, + JsonAdapterAnnotationTypeAdapterFactory jsonAdapterFactory) { + this.constructorConstructor = constructorConstructor; + this.fieldNamingPolicy = fieldNamingPolicy; + this.excluder = excluder; + this.jsonAdapterFactory = jsonAdapterFactory; + } + + public boolean excludeField(Field f, boolean serialize) { + return excludeField(f, serialize, excluder); + } + + static boolean excludeField(Field f, boolean serialize, Excluder excluder) { + return !excluder.excludeClass(f.getType(), serialize) && !excluder.excludeField(f, serialize); + } + + /** first element holds the default name */ + private List getFieldNames(Field f) { + SerializedName annotation = f.getAnnotation(SerializedName.class); + if (annotation == null) { + String name = fieldNamingPolicy.translateName(f); + return Collections.singletonList(name); + } + + String serializedName = annotation.value(); + String[] alternates = annotation.alternate(); + if (alternates.length == 0) { + return Collections.singletonList(serializedName); + } + + List fieldNames = new ArrayList(alternates.length + 1); + fieldNames.add(serializedName); + for (String alternate : alternates) { + fieldNames.add(alternate); + } + return fieldNames; + } + + @Override public TypeAdapter create(Gson gson, final TypeToken type) { + Class raw = type.getRawType(); + + if (!Object.class.isAssignableFrom(raw)) { + return null; // it's a primitive! + } + + ObjectConstructor constructor = constructorConstructor.get(type); + return new Adapter(constructor, getBoundFields(gson, type, raw)); + } + + private ReflectiveTypeAdapterFactory.BoundField createBoundField( + final Gson context, final Field field, final String name, + final TypeToken fieldType, boolean serialize, boolean deserialize) { + final boolean isPrimitive = Primitives.isPrimitive(fieldType.getRawType()); + // special casing primitives here saves ~5% on Android... + JsonAdapter annotation = field.getAnnotation(JsonAdapter.class); + TypeAdapter mapped = null; + if (annotation != null) { + mapped = jsonAdapterFactory.getTypeAdapter( + constructorConstructor, context, fieldType, annotation); + } + final boolean jsonAdapterPresent = mapped != null; + if (mapped == null) mapped = context.getAdapter(fieldType); + + final TypeAdapter typeAdapter = mapped; + return new ReflectiveTypeAdapterFactory.BoundField(name, serialize, deserialize) { + @SuppressWarnings({"unchecked", "rawtypes"}) // the type adapter and field type always agree + @Override void write(JsonWriter writer, Object value) + throws IOException, IllegalAccessException { + Object fieldValue = field.get(value); + TypeAdapter t = jsonAdapterPresent ? typeAdapter + : new TypeAdapterRuntimeTypeWrapper(context, typeAdapter, fieldType.getType()); + t.write(writer, fieldValue); + } + @Override void read(JsonReader reader, Object value) + throws IOException, IllegalAccessException { + Object fieldValue = typeAdapter.read(reader); + if (fieldValue != null || !isPrimitive) { + field.set(value, fieldValue); + } + } + @Override public boolean writeField(Object value) throws IOException, IllegalAccessException { + if (!serialized) return false; + Object fieldValue = field.get(value); + return fieldValue != value; // avoid recursion for example for Throwable.cause + } + }; + } + + private Map getBoundFields(Gson context, TypeToken type, Class raw) { + Map result = new LinkedHashMap(); + if (raw.isInterface()) { + return result; + } + + Type declaredType = type.getType(); + while (raw != Object.class) { + Field[] fields = raw.getDeclaredFields(); + for (Field field : fields) { + boolean serialize = excludeField(field, true); + boolean deserialize = excludeField(field, false); + if (!serialize && !deserialize) { + continue; + } + accessor.makeAccessible(field); + Type fieldType = $Gson$Types.resolve(type.getType(), raw, field.getGenericType()); + List fieldNames = getFieldNames(field); + BoundField previous = null; + for (int i = 0, size = fieldNames.size(); i < size; ++i) { + String name = fieldNames.get(i); + if (i != 0) serialize = false; // only serialize the default name + BoundField boundField = createBoundField(context, field, name, + TypeToken.get(fieldType), serialize, deserialize); + BoundField replaced = result.put(name, boundField); + if (previous == null) previous = replaced; + } + if (previous != null) { + throw new IllegalArgumentException(declaredType + + " declares multiple JSON fields named " + previous.name); + } + } + type = TypeToken.get($Gson$Types.resolve(type.getType(), raw, raw.getGenericSuperclass())); + raw = type.getRawType(); + } + return result; + } + + static abstract class BoundField { + final String name; + final boolean serialized; + final boolean deserialized; + + protected BoundField(String name, boolean serialized, boolean deserialized) { + this.name = name; + this.serialized = serialized; + this.deserialized = deserialized; + } + abstract boolean writeField(Object value) throws IOException, IllegalAccessException; + abstract void write(JsonWriter writer, Object value) throws IOException, IllegalAccessException; + abstract void read(JsonReader reader, Object value) throws IOException, IllegalAccessException; + } + + public static final class Adapter extends TypeAdapter { + private final ObjectConstructor constructor; + private final Map boundFields; + + Adapter(ObjectConstructor constructor, Map boundFields) { + this.constructor = constructor; + this.boundFields = boundFields; + } + + @Override public T read(JsonReader in) throws IOException { + if (in.peek() == JsonToken.NULL) { + in.nextNull(); + return null; + } + + T instance = constructor.construct(); + + try { + in.beginObject(); + while (in.hasNext()) { + String name = in.nextName(); + BoundField field = boundFields.get(name); + if (field == null || !field.deserialized) { + in.skipValue(); + } else { + field.read(in, instance); + } + } + } catch (IllegalStateException e) { + throw new JsonSyntaxException(e); + } catch (IllegalAccessException e) { + throw new AssertionError(e); + } + in.endObject(); + return instance; + } + + @Override public void write(JsonWriter out, T value) throws IOException { + if (value == null) { + out.nullValue(); + return; + } + + out.beginObject(); + try { + for (BoundField boundField : boundFields.values()) { + if (boundField.writeField(value)) { + out.name(boundField.name); + boundField.write(out, value); + } + } + } catch (IllegalAccessException e) { + throw new AssertionError(e); + } + out.endObject(); + } + } +} diff --git a/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/bind/SqlDateTypeAdapter.java b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/bind/SqlDateTypeAdapter.java new file mode 100644 index 0000000..736715d --- /dev/null +++ b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/bind/SqlDateTypeAdapter.java @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2011 Google Inc. + * + * 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. + */ + +package com.google.gson285.internal.bind; + +import com.google.gson285.Gson; +import com.google.gson285.JsonSyntaxException; +import com.google.gson285.TypeAdapter; +import com.google.gson285.TypeAdapterFactory; +import com.google.gson285.reflect.TypeToken; +import com.google.gson285.stream.JsonReader; +import com.google.gson285.stream.JsonToken; +import com.google.gson285.stream.JsonWriter; +import java.io.IOException; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; + +/** + * Adapter for java.sql.Date. Although this class appears stateless, it is not. + * DateFormat captures its time zone and locale when it is created, which gives + * this class state. DateFormat isn't thread safe either, so this class has + * to synchronize its read and write methods. + */ +public final class SqlDateTypeAdapter extends TypeAdapter { + public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() { + @SuppressWarnings("unchecked") // we use a runtime check to make sure the 'T's equal + @Override public TypeAdapter create(Gson gson, TypeToken typeToken) { + return typeToken.getRawType() == java.sql.Date.class + ? (TypeAdapter) new SqlDateTypeAdapter() : null; + } + }; + + private final DateFormat format = new SimpleDateFormat("MMM d, yyyy"); + + @Override + public synchronized java.sql.Date read(JsonReader in) throws IOException { + if (in.peek() == JsonToken.NULL) { + in.nextNull(); + return null; + } + try { + final long utilDate = format.parse(in.nextString()).getTime(); + return new java.sql.Date(utilDate); + } catch (ParseException e) { + throw new JsonSyntaxException(e); + } + } + + @Override + public synchronized void write(JsonWriter out, java.sql.Date value) throws IOException { + out.value(value == null ? null : format.format(value)); + } +} diff --git a/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/bind/TimeTypeAdapter.java b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/bind/TimeTypeAdapter.java new file mode 100644 index 0000000..79c807d --- /dev/null +++ b/datawedgeprofileintentswrapper/src/main/java/com/google/gson285/internal/bind/TimeTypeAdapter.java @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2011 Google Inc. + * + * 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. + */ + +package com.google.gson285.internal.bind; + +import com.google.gson285.Gson; +import com.google.gson285.JsonSyntaxException; +import com.google.gson285.TypeAdapter; +import com.google.gson285.TypeAdapterFactory; +import com.google.gson285.reflect.TypeToken; +import com.google.gson285.stream.JsonReader; +import com.google.gson285.stream.JsonToken; +import com.google.gson285.stream.JsonWriter; +import java.io.IOException; +import java.sql.Time; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; + +/** + * Adapter for Time. Although this class appears stateless, it is not. + * DateFormat captures its time zone and locale when it is created, which gives + * this class state. DateFormat isn't thread safe either, so this class has + * to synchronize its read and write methods. + */ +public final class TimeTypeAdapter extends TypeAdapter