From 9afa1c167c507ed4415ea5564861f5b6b5846e30 Mon Sep 17 00:00:00 2001 From: Stefan Oltmann Date: Thu, 2 May 2024 17:02:33 +0200 Subject: [PATCH] Enabled explicitApi() (#28) * Added language=XML comment to enabled IDEA syntax highlighting * Removed unused imports * Preparation for explicitApi() * Preparation for explicitApi() * Enabled explicitApi() * Fixed duplicated string * Moved internal classes into dedicated package * Moved internal classes into dedicated package * Added missing ResourcePath.js.kt * Imports organized * XMPNode: Removed useless "public" * Minor dependency update * Removed copyright header * Moved classes * Bump version to v1.3.0 * XMPValueType can be private * Improved QName.kt * Detekt issues * Detekt suppress --- README.md | 2 +- build.gradle.kts | 6 +- detekt.yml | 2 +- examples/xmpcore-java-sample/build.gradle | 2 +- .../build.gradle.kts | 2 +- .../src/main/kotlin/Main.kt | 1 + .../kotlin/com/ashampoo/xmp/QName.kt | 51 --- .../xmp/{properties => }/XMPAliasInfo.kt | 12 +- .../kotlin/com/ashampoo/xmp/XMPConst.kt | 194 +++++------ .../kotlin/com/ashampoo/xmp/XMPException.kt | 4 +- .../kotlin/com/ashampoo/xmp/XMPIterator.kt | 28 +- .../kotlin/com/ashampoo/xmp/XMPMeta.kt | 322 +++++++++--------- .../kotlin/com/ashampoo/xmp/XMPMetaFactory.kt | 14 +- .../kotlin/com/ashampoo/xmp/XMPPathFactory.kt | 34 +- .../xmp/{properties => }/XMPProperty.kt | 10 +- .../xmp/{properties => }/XMPPropertyInfo.kt | 8 +- .../kotlin/com/ashampoo/xmp/XMPRegionArea.kt | 2 +- .../com/ashampoo/xmp/XMPSchemaRegistry.kt | 53 +-- .../kotlin/com/ashampoo/xmp/XMPVersionInfo.kt | 13 +- .../ashampoo/xmp/{ => internal}/DomParser.kt | 7 +- .../xmp/{xpath => internal}/PathPosition.kt | 2 +- .../kotlin/com/ashampoo/xmp/internal/QName.kt | 44 +++ .../com/ashampoo/xmp/{ => internal}/Utils.kt | 6 +- .../XMPErrorConst.kt} | 4 +- .../xmp/{ => internal}/XMPMetaParser.kt | 6 +- .../ashampoo/xmp/{ => internal}/XMPNode.kt | 15 +- .../xmp/{ => internal}/XMPNodeUtils.kt | 48 +-- .../xmp/{ => internal}/XMPNormalizer.kt | 20 +- .../xmp/{xpath => internal}/XMPPath.kt | 4 +- .../xmp/{xpath => internal}/XMPPathParser.kt | 48 ++- .../xmp/{xpath => internal}/XMPPathSegment.kt | 4 +- .../xmp/{ => internal}/XMPRDFParser.kt | 101 +++--- .../xmp/{ => internal}/XMPRDFWriter.kt | 23 +- .../ashampoo/xmp/{ => internal}/XMPUtils.kt | 21 +- .../com/ashampoo/xmp/options/AliasOptions.kt | 29 +- .../ashampoo/xmp/options/IteratorOptions.kt | 20 +- .../com/ashampoo/xmp/options/Options.kt | 14 +- .../com/ashampoo/xmp/options/ParseOptions.kt | 16 +- .../ashampoo/xmp/options/PropertyOptions.kt | 68 ++-- .../ashampoo/xmp/options/SerializeOptions.kt | 34 +- .../kotlin/com/ashampoo/xmp/ReadXmpTest.kt | 1 + .../kotlin/com/ashampoo/xmp/ResourcePath.kt | 15 - .../kotlin/com/ashampoo/xmp/WriteXmpTest.kt | 1 + .../ashampoo/xmp/{ => internal}/UtilsTest.kt | 2 +- .../resources/com/ashampoo/xmp/empty.xmp | 2 +- .../resources/com/ashampoo/xmp/new.xmp | 2 +- .../resources/com/ashampoo/xmp/rating.xmp | 2 +- .../xmp/sample_100_formatted_canonical.xmp | 2 +- .../xmp/sample_100_formatted_compact.xmp | 2 +- .../xmp/sample_10_formatted_canonical.xmp | 2 +- .../xmp/sample_10_formatted_compact.xmp | 2 +- .../xmp/sample_11_formatted_canonical.xmp | 2 +- .../xmp/sample_11_formatted_compact.xmp | 2 +- .../xmp/sample_12_formatted_canonical.xmp | 2 +- .../xmp/sample_12_formatted_compact.xmp | 2 +- .../xmp/sample_13_formatted_canonical.xmp | 2 +- .../xmp/sample_13_formatted_compact.xmp | 2 +- .../xmp/sample_14_formatted_canonical.xmp | 2 +- .../xmp/sample_14_formatted_compact.xmp | 2 +- .../xmp/sample_15_formatted_canonical.xmp | 2 +- .../xmp/sample_15_formatted_compact.xmp | 2 +- .../xmp/sample_16_formatted_canonical.xmp | 2 +- .../xmp/sample_16_formatted_compact.xmp | 2 +- .../xmp/sample_17_formatted_canonical.xmp | 2 +- .../xmp/sample_17_formatted_compact.xmp | 2 +- .../xmp/sample_18_formatted_canonical.xmp | 2 +- .../xmp/sample_18_formatted_compact.xmp | 2 +- .../xmp/sample_19_formatted_canonical.xmp | 2 +- .../xmp/sample_19_formatted_compact.xmp | 2 +- .../xmp/sample_1_formatted_canonical.xmp | 2 +- .../xmp/sample_1_formatted_compact.xmp | 2 +- .../xmp/sample_20_formatted_canonical.xmp | 2 +- .../xmp/sample_20_formatted_compact.xmp | 2 +- .../xmp/sample_21_formatted_canonical.xmp | 2 +- .../xmp/sample_21_formatted_compact.xmp | 2 +- .../xmp/sample_22_formatted_canonical.xmp | 2 +- .../xmp/sample_22_formatted_compact.xmp | 2 +- .../xmp/sample_23_formatted_canonical.xmp | 2 +- .../xmp/sample_23_formatted_compact.xmp | 2 +- .../xmp/sample_24_formatted_canonical.xmp | 2 +- .../xmp/sample_24_formatted_compact.xmp | 2 +- .../xmp/sample_25_formatted_canonical.xmp | 2 +- .../xmp/sample_25_formatted_compact.xmp | 2 +- .../xmp/sample_26_formatted_canonical.xmp | 2 +- .../xmp/sample_26_formatted_compact.xmp | 2 +- .../xmp/sample_27_formatted_canonical.xmp | 2 +- .../xmp/sample_27_formatted_compact.xmp | 2 +- .../xmp/sample_28_formatted_canonical.xmp | 2 +- .../xmp/sample_28_formatted_compact.xmp | 2 +- .../xmp/sample_29_formatted_canonical.xmp | 2 +- .../xmp/sample_29_formatted_compact.xmp | 2 +- .../xmp/sample_2_formatted_canonical.xmp | 2 +- .../xmp/sample_2_formatted_compact.xmp | 2 +- .../xmp/sample_30_formatted_canonical.xmp | 2 +- .../xmp/sample_30_formatted_compact.xmp | 2 +- .../xmp/sample_31_formatted_canonical.xmp | 2 +- .../xmp/sample_31_formatted_compact.xmp | 2 +- .../xmp/sample_32_formatted_canonical.xmp | 2 +- .../xmp/sample_32_formatted_compact.xmp | 2 +- .../xmp/sample_33_formatted_canonical.xmp | 2 +- .../xmp/sample_33_formatted_compact.xmp | 2 +- .../xmp/sample_34_formatted_canonical.xmp | 2 +- .../xmp/sample_34_formatted_compact.xmp | 2 +- .../xmp/sample_35_formatted_canonical.xmp | 2 +- .../xmp/sample_35_formatted_compact.xmp | 2 +- .../xmp/sample_36_formatted_canonical.xmp | 2 +- .../xmp/sample_36_formatted_compact.xmp | 2 +- .../xmp/sample_37_formatted_canonical.xmp | 2 +- .../xmp/sample_37_formatted_compact.xmp | 2 +- .../xmp/sample_38_formatted_canonical.xmp | 2 +- .../xmp/sample_38_formatted_compact.xmp | 2 +- .../xmp/sample_39_formatted_canonical.xmp | 2 +- .../xmp/sample_39_formatted_compact.xmp | 2 +- .../xmp/sample_3_formatted_canonical.xmp | 2 +- .../xmp/sample_3_formatted_compact.xmp | 2 +- .../xmp/sample_40_formatted_canonical.xmp | 2 +- .../xmp/sample_40_formatted_compact.xmp | 2 +- .../xmp/sample_41_formatted_canonical.xmp | 2 +- .../xmp/sample_41_formatted_compact.xmp | 2 +- .../xmp/sample_42_formatted_canonical.xmp | 2 +- .../xmp/sample_42_formatted_compact.xmp | 2 +- .../xmp/sample_43_formatted_canonical.xmp | 2 +- .../xmp/sample_43_formatted_compact.xmp | 2 +- .../xmp/sample_44_formatted_canonical.xmp | 2 +- .../xmp/sample_44_formatted_compact.xmp | 2 +- .../xmp/sample_45_formatted_canonical.xmp | 2 +- .../xmp/sample_45_formatted_compact.xmp | 2 +- .../xmp/sample_46_formatted_canonical.xmp | 2 +- .../xmp/sample_46_formatted_compact.xmp | 2 +- .../xmp/sample_47_formatted_canonical.xmp | 2 +- .../xmp/sample_47_formatted_compact.xmp | 2 +- .../xmp/sample_48_formatted_canonical.xmp | 2 +- .../xmp/sample_48_formatted_compact.xmp | 2 +- .../xmp/sample_49_formatted_canonical.xmp | 2 +- .../xmp/sample_49_formatted_compact.xmp | 2 +- .../xmp/sample_4_formatted_canonical.xmp | 2 +- .../xmp/sample_4_formatted_compact.xmp | 2 +- .../xmp/sample_50_formatted_canonical.xmp | 2 +- .../xmp/sample_50_formatted_compact.xmp | 2 +- .../xmp/sample_51_formatted_canonical.xmp | 2 +- .../xmp/sample_51_formatted_compact.xmp | 2 +- .../xmp/sample_52_formatted_canonical.xmp | 2 +- .../xmp/sample_52_formatted_compact.xmp | 2 +- .../xmp/sample_53_formatted_canonical.xmp | 2 +- .../xmp/sample_53_formatted_compact.xmp | 2 +- .../xmp/sample_54_formatted_canonical.xmp | 2 +- .../xmp/sample_54_formatted_compact.xmp | 2 +- .../xmp/sample_55_formatted_canonical.xmp | 2 +- .../xmp/sample_55_formatted_compact.xmp | 2 +- .../xmp/sample_56_formatted_canonical.xmp | 2 +- .../xmp/sample_56_formatted_compact.xmp | 2 +- .../xmp/sample_57_formatted_canonical.xmp | 2 +- .../xmp/sample_57_formatted_compact.xmp | 2 +- .../xmp/sample_58_formatted_canonical.xmp | 2 +- .../xmp/sample_58_formatted_compact.xmp | 2 +- .../xmp/sample_59_formatted_canonical.xmp | 2 +- .../xmp/sample_59_formatted_compact.xmp | 2 +- .../xmp/sample_5_formatted_canonical.xmp | 2 +- .../xmp/sample_5_formatted_compact.xmp | 2 +- .../xmp/sample_60_formatted_canonical.xmp | 2 +- .../xmp/sample_60_formatted_compact.xmp | 2 +- .../xmp/sample_61_formatted_canonical.xmp | 2 +- .../xmp/sample_61_formatted_compact.xmp | 2 +- .../xmp/sample_62_formatted_canonical.xmp | 2 +- .../xmp/sample_62_formatted_compact.xmp | 2 +- .../xmp/sample_63_formatted_canonical.xmp | 2 +- .../xmp/sample_63_formatted_compact.xmp | 2 +- .../xmp/sample_64_formatted_canonical.xmp | 2 +- .../xmp/sample_64_formatted_compact.xmp | 2 +- .../xmp/sample_65_formatted_canonical.xmp | 2 +- .../xmp/sample_65_formatted_compact.xmp | 2 +- .../xmp/sample_66_formatted_canonical.xmp | 2 +- .../xmp/sample_66_formatted_compact.xmp | 2 +- .../xmp/sample_67_formatted_canonical.xmp | 2 +- .../xmp/sample_67_formatted_compact.xmp | 2 +- .../xmp/sample_68_formatted_canonical.xmp | 2 +- .../xmp/sample_68_formatted_compact.xmp | 2 +- .../xmp/sample_69_formatted_canonical.xmp | 2 +- .../xmp/sample_69_formatted_compact.xmp | 2 +- .../xmp/sample_6_formatted_canonical.xmp | 2 +- .../xmp/sample_6_formatted_compact.xmp | 2 +- .../xmp/sample_70_formatted_canonical.xmp | 2 +- .../xmp/sample_70_formatted_compact.xmp | 2 +- .../xmp/sample_71_formatted_canonical.xmp | 2 +- .../xmp/sample_71_formatted_compact.xmp | 2 +- .../xmp/sample_72_formatted_canonical.xmp | 2 +- .../xmp/sample_72_formatted_compact.xmp | 2 +- .../xmp/sample_73_formatted_canonical.xmp | 2 +- .../xmp/sample_73_formatted_compact.xmp | 2 +- .../xmp/sample_74_formatted_canonical.xmp | 2 +- .../xmp/sample_74_formatted_compact.xmp | 2 +- .../xmp/sample_75_formatted_canonical.xmp | 2 +- .../xmp/sample_75_formatted_compact.xmp | 2 +- .../xmp/sample_76_formatted_canonical.xmp | 2 +- .../xmp/sample_76_formatted_compact.xmp | 2 +- .../xmp/sample_77_formatted_canonical.xmp | 2 +- .../xmp/sample_77_formatted_compact.xmp | 2 +- .../xmp/sample_78_formatted_canonical.xmp | 2 +- .../xmp/sample_78_formatted_compact.xmp | 2 +- .../xmp/sample_79_formatted_canonical.xmp | 2 +- .../xmp/sample_79_formatted_compact.xmp | 2 +- .../xmp/sample_7_formatted_canonical.xmp | 2 +- .../xmp/sample_7_formatted_compact.xmp | 2 +- .../xmp/sample_80_formatted_canonical.xmp | 2 +- .../xmp/sample_80_formatted_compact.xmp | 2 +- .../xmp/sample_81_formatted_canonical.xmp | 2 +- .../xmp/sample_81_formatted_compact.xmp | 2 +- .../xmp/sample_82_formatted_canonical.xmp | 2 +- .../xmp/sample_82_formatted_compact.xmp | 2 +- .../xmp/sample_83_formatted_canonical.xmp | 2 +- .../xmp/sample_83_formatted_compact.xmp | 2 +- .../xmp/sample_84_formatted_canonical.xmp | 2 +- .../xmp/sample_84_formatted_compact.xmp | 2 +- .../xmp/sample_85_formatted_canonical.xmp | 2 +- .../xmp/sample_85_formatted_compact.xmp | 2 +- .../xmp/sample_86_formatted_canonical.xmp | 2 +- .../xmp/sample_86_formatted_compact.xmp | 2 +- .../xmp/sample_87_formatted_canonical.xmp | 2 +- .../xmp/sample_87_formatted_compact.xmp | 2 +- .../xmp/sample_88_formatted_canonical.xmp | 2 +- .../xmp/sample_88_formatted_compact.xmp | 2 +- .../xmp/sample_89_formatted_canonical.xmp | 2 +- .../xmp/sample_89_formatted_compact.xmp | 2 +- .../xmp/sample_8_formatted_canonical.xmp | 2 +- .../xmp/sample_8_formatted_compact.xmp | 2 +- .../xmp/sample_90_formatted_canonical.xmp | 2 +- .../xmp/sample_90_formatted_compact.xmp | 2 +- .../xmp/sample_91_formatted_canonical.xmp | 2 +- .../xmp/sample_91_formatted_compact.xmp | 2 +- .../xmp/sample_92_formatted_canonical.xmp | 2 +- .../xmp/sample_92_formatted_compact.xmp | 2 +- .../xmp/sample_93_formatted_canonical.xmp | 2 +- .../xmp/sample_93_formatted_compact.xmp | 2 +- .../xmp/sample_94_formatted_canonical.xmp | 2 +- .../xmp/sample_94_formatted_compact.xmp | 2 +- .../xmp/sample_95_formatted_canonical.xmp | 2 +- .../xmp/sample_95_formatted_compact.xmp | 2 +- .../xmp/sample_96_formatted_canonical.xmp | 2 +- .../xmp/sample_96_formatted_compact.xmp | 2 +- .../xmp/sample_97_formatted_canonical.xmp | 2 +- .../xmp/sample_97_formatted_compact.xmp | 2 +- .../xmp/sample_98_formatted_canonical.xmp | 2 +- .../xmp/sample_98_formatted_compact.xmp | 2 +- .../xmp/sample_99_formatted_canonical.xmp | 2 +- .../xmp/sample_99_formatted_compact.xmp | 2 +- .../xmp/sample_9_formatted_canonical.xmp | 2 +- .../xmp/sample_9_formatted_compact.xmp | 2 +- .../resources/com/ashampoo/xmp/updated.xmp | 2 +- .../com/ashampoo/xmp/ResourcePath.js.kt | 3 + src/posixMain/kotlin/com/ashampoo/xmp/Main.kt | 2 +- 250 files changed, 868 insertions(+), 858 deletions(-) delete mode 100644 src/commonMain/kotlin/com/ashampoo/xmp/QName.kt rename src/commonMain/kotlin/com/ashampoo/xmp/{properties => }/XMPAliasInfo.kt (83%) rename src/commonMain/kotlin/com/ashampoo/xmp/{properties => }/XMPProperty.kt (83%) rename src/commonMain/kotlin/com/ashampoo/xmp/{properties => }/XMPPropertyInfo.kt (88%) rename src/commonMain/kotlin/com/ashampoo/xmp/{ => internal}/DomParser.kt (92%) rename src/commonMain/kotlin/com/ashampoo/xmp/{xpath => internal}/PathPosition.kt (96%) create mode 100644 src/commonMain/kotlin/com/ashampoo/xmp/internal/QName.kt rename src/commonMain/kotlin/com/ashampoo/xmp/{ => internal}/Utils.kt (99%) rename src/commonMain/kotlin/com/ashampoo/xmp/{XMPError.kt => internal/XMPErrorConst.kt} (94%) rename src/commonMain/kotlin/com/ashampoo/xmp/{ => internal}/XMPMetaParser.kt (97%) rename src/commonMain/kotlin/com/ashampoo/xmp/{ => internal}/XMPNode.kt (96%) rename src/commonMain/kotlin/com/ashampoo/xmp/{ => internal}/XMPNodeUtils.kt (95%) rename src/commonMain/kotlin/com/ashampoo/xmp/{ => internal}/XMPNormalizer.kt (97%) rename src/commonMain/kotlin/com/ashampoo/xmp/{xpath => internal}/XMPPath.kt (97%) rename src/commonMain/kotlin/com/ashampoo/xmp/{xpath => internal}/XMPPathParser.kt (94%) rename src/commonMain/kotlin/com/ashampoo/xmp/{xpath => internal}/XMPPathSegment.kt (94%) rename src/commonMain/kotlin/com/ashampoo/xmp/{ => internal}/XMPRDFParser.kt (94%) rename src/commonMain/kotlin/com/ashampoo/xmp/{ => internal}/XMPRDFWriter.kt (98%) rename src/commonMain/kotlin/com/ashampoo/xmp/{ => internal}/XMPUtils.kt (83%) rename src/commonTest/kotlin/com/ashampoo/xmp/{ => internal}/UtilsTest.kt (98%) create mode 100644 src/jsTest/kotlin/com/ashampoo/xmp/ResourcePath.js.kt diff --git a/README.md b/README.md index 9d9609d..2f8f65e 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ It's part of [Ashampoo Photo Organizer](https://ashampoo.com/photo-organizer). ## Installation ``` -implementation("com.ashampoo:xmpcore:1.2.2") +implementation("com.ashampoo:xmpcore:1.3.0") ``` ## How to use diff --git a/build.gradle.kts b/build.gradle.kts index a41bc62..008fe86 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,5 +1,3 @@ -import org.jetbrains.kotlin.gradle.dsl.KotlinJvmProjectExtension -import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType import org.jetbrains.kotlin.gradle.plugin.mpp.NativeBuildType import org.jetbrains.kotlin.gradle.plugin.mpp.apple.XCFramework import org.jetbrains.kotlin.gradle.targets.js.dsl.ExperimentalWasmDsl @@ -14,7 +12,7 @@ plugins { id("org.jetbrains.kotlinx.kover") version "0.6.1" id("com.asarkar.gradle.build-time-tracker") version "4.3.0" id("me.qoomon.git-versioning") version "6.4.3" - id("com.goncalossilva.resources") version "0.4.0" + id("com.goncalossilva.resources") version "0.4.1" id("com.github.ben-manes.versions") version "0.51.0" id("org.jetbrains.dokka") version "1.9.20" } @@ -111,6 +109,8 @@ dependencies { kotlin { + explicitApi() + androidTarget { compilations.all { diff --git a/detekt.yml b/detekt.yml index bda8fd9..32bbb3d 100644 --- a/detekt.yml +++ b/detekt.yml @@ -676,7 +676,7 @@ style: RedundantHigherOrderMapUsage: active: true RedundantVisibilityModifierRule: - active: true + active: false # explicitApiMode ReturnCount: active: false # results in bad style max: 2 diff --git a/examples/xmpcore-java-sample/build.gradle b/examples/xmpcore-java-sample/build.gradle index 98c7d92..5d64c69 100644 --- a/examples/xmpcore-java-sample/build.gradle +++ b/examples/xmpcore-java-sample/build.gradle @@ -10,7 +10,7 @@ repositories { } dependencies { - implementation 'com.ashampoo:xmpcore:1.2.2' + implementation 'com.ashampoo:xmpcore:1.3.0' } // Needed to make it work for the Gradle java plugin diff --git a/examples/xmpcore-kotlin-jvm-sample/build.gradle.kts b/examples/xmpcore-kotlin-jvm-sample/build.gradle.kts index 6181696..e9af068 100644 --- a/examples/xmpcore-kotlin-jvm-sample/build.gradle.kts +++ b/examples/xmpcore-kotlin-jvm-sample/build.gradle.kts @@ -10,5 +10,5 @@ repositories { } dependencies { - implementation("com.ashampoo:xmpcore:1.2.1") + implementation("com.ashampoo:xmpcore:1.3.0") } diff --git a/examples/xmpcore-kotlin-jvm-sample/src/main/kotlin/Main.kt b/examples/xmpcore-kotlin-jvm-sample/src/main/kotlin/Main.kt index 0d933e1..505e43f 100644 --- a/examples/xmpcore-kotlin-jvm-sample/src/main/kotlin/Main.kt +++ b/examples/xmpcore-kotlin-jvm-sample/src/main/kotlin/Main.kt @@ -40,6 +40,7 @@ fun main() { println("---") println(xmp) + /* language=XML */ val oldXmp = """ diff --git a/src/commonMain/kotlin/com/ashampoo/xmp/QName.kt b/src/commonMain/kotlin/com/ashampoo/xmp/QName.kt deleted file mode 100644 index e776a56..0000000 --- a/src/commonMain/kotlin/com/ashampoo/xmp/QName.kt +++ /dev/null @@ -1,51 +0,0 @@ -// ================================================================================================= -// ADOBE SYSTEMS INCORPORATED -// Copyright 2006 Adobe Systems Incorporated -// All Rights Reserved -// -// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms -// of the Adobe license agreement accompanying it. -// ================================================================================================= -package com.ashampoo.xmp - -class QName { - - /** - * XML namespace prefix - */ - var prefix: String? = null - private set - - /** - * XML localname - */ - var localName: String? = null - private set - - /** - * Splits a qname into prefix and localname. - * - * @param qname a QName - */ - constructor(qname: String) { - - val colon = qname.indexOf(':') - - if (colon >= 0) { - prefix = qname.substring(0, colon) - localName = qname.substring(colon + 1) - } else { - prefix = "" - localName = qname - } - } - - constructor(prefix: String?, localName: String?) { - this.prefix = prefix - this.localName = localName - } - - fun hasPrefix(): Boolean = - prefix != null && prefix!!.isNotEmpty() - -} diff --git a/src/commonMain/kotlin/com/ashampoo/xmp/properties/XMPAliasInfo.kt b/src/commonMain/kotlin/com/ashampoo/xmp/XMPAliasInfo.kt similarity index 83% rename from src/commonMain/kotlin/com/ashampoo/xmp/properties/XMPAliasInfo.kt rename to src/commonMain/kotlin/com/ashampoo/xmp/XMPAliasInfo.kt index e87d028..788b761 100644 --- a/src/commonMain/kotlin/com/ashampoo/xmp/properties/XMPAliasInfo.kt +++ b/src/commonMain/kotlin/com/ashampoo/xmp/XMPAliasInfo.kt @@ -6,29 +6,29 @@ // NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms // of the Adobe license agreement accompanying it. // ================================================================================================= -package com.ashampoo.xmp.properties +package com.ashampoo.xmp import com.ashampoo.xmp.options.AliasOptions /** * This interface is used to return info about an alias. */ -interface XMPAliasInfo { +public interface XMPAliasInfo { /** * @return Returns the namespace URI for the base property. */ - fun getNamespace(): String + public fun getNamespace(): String /** * @return Returns the default prefix for the given base property. */ - fun getPrefix(): String + public fun getPrefix(): String /** * @return Returns the path of the base property. */ - fun getPropName(): String + public fun getPropName(): String /** * @return Returns the kind of the alias. This can be a direct alias @@ -37,6 +37,6 @@ interface XMPAliasInfo { * (ARRAY_ALTERNATE) or to an alternate text array * (ARRAY_ALT_TEXT). */ - fun getAliasForm(): AliasOptions + public fun getAliasForm(): AliasOptions } diff --git a/src/commonMain/kotlin/com/ashampoo/xmp/XMPConst.kt b/src/commonMain/kotlin/com/ashampoo/xmp/XMPConst.kt index e647de0..a70159f 100644 --- a/src/commonMain/kotlin/com/ashampoo/xmp/XMPConst.kt +++ b/src/commonMain/kotlin/com/ashampoo/xmp/XMPConst.kt @@ -11,215 +11,215 @@ package com.ashampoo.xmp /** * Common constants for the XMP Toolkit. */ -object XMPConst { +public object XMPConst { /** * The XML namespace for XML. */ - const val NS_XML: String = "http://www.w3.org/XML/1998/namespace" + public const val NS_XML: String = "http://www.w3.org/XML/1998/namespace" /** * The XML namespace for RDF. */ - const val NS_RDF: String = "http://www.w3.org/1999/02/22-rdf-syntax-ns#" + public const val NS_RDF: String = "http://www.w3.org/1999/02/22-rdf-syntax-ns#" /** * The XML namespace for the Dublin Core schema. */ - const val NS_DC: String = "http://purl.org/dc/elements/1.1/" + public const val NS_DC: String = "http://purl.org/dc/elements/1.1/" /** * The XML namespace for the IPTC Core schema. */ - const val NS_IPTC_CORE: String = "http://iptc.org/std/Iptc4xmpCore/1.0/xmlns/" + public const val NS_IPTC_CORE: String = "http://iptc.org/std/Iptc4xmpCore/1.0/xmlns/" /** * The XML namespace for the IPTC Extension schema. */ - const val NS_IPTC_EXT: String = "http://iptc.org/std/Iptc4xmpExt/2008-02-29/" + public const val NS_IPTC_EXT: String = "http://iptc.org/std/Iptc4xmpExt/2008-02-29/" /** * The XML namespace for the DICOM medical schema. */ - const val NS_DICOM: String = "http://ns.adobe.com/DICOM/" + public const val NS_DICOM: String = "http://ns.adobe.com/DICOM/" /** * The XML namespace for the PLUS (Picture Licensing Universal System, http://www.useplus.org) */ - const val NS_PLUS: String = "http://ns.useplus.org/ldf/xmp/1.0/" + public const val NS_PLUS: String = "http://ns.useplus.org/ldf/xmp/1.0/" - const val NS_MWG_RS: String = "http://www.metadataworkinggroup.com/schemas/regions/" + public const val NS_MWG_RS: String = "http://www.metadataworkinggroup.com/schemas/regions/" /** * The XML namespace Adobe XMP Metadata. */ - const val NS_X: String = "adobe:ns:meta/" + public const val NS_X: String = "adobe:ns:meta/" - const val NS_IX: String = "http://ns.adobe.com/iX/1.0/" + public const val NS_IX: String = "http://ns.adobe.com/iX/1.0/" /** * The XML namespace for the XMP "basic" schema. */ - const val NS_XMP: String = "http://ns.adobe.com/xap/1.0/" + public const val NS_XMP: String = "http://ns.adobe.com/xap/1.0/" /** * The XML namespace for the XMP copyright schema. */ - const val NS_XMP_RIGHTS: String = "http://ns.adobe.com/xap/1.0/rights/" + public const val NS_XMP_RIGHTS: String = "http://ns.adobe.com/xap/1.0/rights/" /** * The XML namespace for the XMP digital asset management schema. */ - const val NS_XMP_MM: String = "http://ns.adobe.com/xap/1.0/mm/" + public const val NS_XMP_MM: String = "http://ns.adobe.com/xap/1.0/mm/" - const val NS_XMP_BJ: String = "http://ns.adobe.com/xap/1.0/bj/" + public const val NS_XMP_BJ: String = "http://ns.adobe.com/xap/1.0/bj/" - const val NS_XMP_NOTE: String = "http://ns.adobe.com/xmp/note/" + public const val NS_XMP_NOTE: String = "http://ns.adobe.com/xmp/note/" - const val NS_PDF: String = "http://ns.adobe.com/pdf/1.3/" + public const val NS_PDF: String = "http://ns.adobe.com/pdf/1.3/" - const val NS_PDFX: String = "http://ns.adobe.com/pdfx/1.3/" + public const val NS_PDFX: String = "http://ns.adobe.com/pdfx/1.3/" - const val NS_PDFX_ID: String = "http://www.npes.org/pdfx/ns/id/" + public const val NS_PDFX_ID: String = "http://www.npes.org/pdfx/ns/id/" - const val NS_PDFA_SCHEMA: String = "http://www.aiim.org/pdfa/ns/schema#" + public const val NS_PDFA_SCHEMA: String = "http://www.aiim.org/pdfa/ns/schema#" - const val NS_PDFA_PROPERTY: String = "http://www.aiim.org/pdfa/ns/property#" + public const val NS_PDFA_PROPERTY: String = "http://www.aiim.org/pdfa/ns/property#" - const val NS_PDFA_TYPE: String = "http://www.aiim.org/pdfa/ns/type#" + public const val NS_PDFA_TYPE: String = "http://www.aiim.org/pdfa/ns/type#" - const val NS_PDFA_FIELD: String = "http://www.aiim.org/pdfa/ns/field#" + public const val NS_PDFA_FIELD: String = "http://www.aiim.org/pdfa/ns/field#" - const val NS_PDFA_ID: String = "http://www.aiim.org/pdfa/ns/id/" + public const val NS_PDFA_ID: String = "http://www.aiim.org/pdfa/ns/id/" - const val NS_PDFA_EXTENSION: String = "http://www.aiim.org/pdfa/ns/extension/" + public const val NS_PDFA_EXTENSION: String = "http://www.aiim.org/pdfa/ns/extension/" /** * The XML namespace for the Photoshop Album schema. */ - const val NS_PS_ALBUM: String = "http://ns.adobe.com/album/1.0/" + public const val NS_PS_ALBUM: String = "http://ns.adobe.com/album/1.0/" /** * The XML namespace for Adobe's EXIF schema. */ - const val NS_EXIF: String = "http://ns.adobe.com/exif/1.0/" + public const val NS_EXIF: String = "http://ns.adobe.com/exif/1.0/" /** * NS for the CIPA XMP for Exif document v1.1 */ - const val NS_EXIF_CIPA: String = "http://cipa.jp/exif/1.0/" + public const val NS_EXIF_CIPA: String = "http://cipa.jp/exif/1.0/" - const val NS_EXIF_AUX: String = "http://ns.adobe.com/exif/1.0/aux/" + public const val NS_EXIF_AUX: String = "http://ns.adobe.com/exif/1.0/aux/" - const val NS_TIFF: String = "http://ns.adobe.com/tiff/1.0/" + public const val NS_TIFF: String = "http://ns.adobe.com/tiff/1.0/" - const val NS_PNG: String = "http://ns.adobe.com/png/1.0/" + public const val NS_PNG: String = "http://ns.adobe.com/png/1.0/" - const val NS_JPEG: String = "http://ns.adobe.com/jpeg/1.0/" + public const val NS_JPEG: String = "http://ns.adobe.com/jpeg/1.0/" - const val NS_JP2K: String = "http://ns.adobe.com/jp2k/1.0/" + public const val NS_JP2K: String = "http://ns.adobe.com/jp2k/1.0/" - const val NS_CAMERA_RAW: String = "http://ns.adobe.com/camera-raw-settings/1.0/" + public const val NS_CAMERA_RAW: String = "http://ns.adobe.com/camera-raw-settings/1.0/" - const val NS_ADOBE_STOCK_PHOTO: String = "http://ns.adobe.com/StockPhoto/1.0/" + public const val NS_ADOBE_STOCK_PHOTO: String = "http://ns.adobe.com/StockPhoto/1.0/" - const val NS_CREATOR_ATOM: String = "http://ns.adobe.com/creatorAtom/1.0/" + public const val NS_CREATOR_ATOM: String = "http://ns.adobe.com/creatorAtom/1.0/" - const val NS_ASF: String = "http://ns.adobe.com/asf/1.0/" + public const val NS_ASF: String = "http://ns.adobe.com/asf/1.0/" - const val NS_WAV: String = "http://ns.adobe.com/xmp/wav/1.0/" + public const val NS_WAV: String = "http://ns.adobe.com/xmp/wav/1.0/" /** * BExt Schema */ - const val NS_BWF: String = "http://ns.adobe.com/bwf/bext/1.0/" + public const val NS_BWF: String = "http://ns.adobe.com/bwf/bext/1.0/" /** * RIFF Info Schema */ - const val NS_RIFF_INFO: String = "http://ns.adobe.com/riff/info/" + public const val NS_RIFF_INFO: String = "http://ns.adobe.com/riff/info/" - const val NS_SCRIPT: String = "http://ns.adobe.com/xmp/1.0/Script/" + public const val NS_SCRIPT: String = "http://ns.adobe.com/xmp/1.0/Script/" /** * Transform XMP */ - const val NS_TRANSFORM_XMP: String = "http://ns.adobe.com/TransformXMP/" + public const val NS_TRANSFORM_XMP: String = "http://ns.adobe.com/TransformXMP/" /** * Adobe Flash SWF */ - const val NS_SWF: String = "http://ns.adobe.com/swf/1.0/" + public const val NS_SWF: String = "http://ns.adobe.com/swf/1.0/" // XMP namespaces that are Adobe private - const val NS_DM: String = "http://ns.adobe.com/xmp/1.0/DynamicMedia/" + public const val NS_DM: String = "http://ns.adobe.com/xmp/1.0/DynamicMedia/" - const val NS_TRANSIENT: String = "http://ns.adobe.com/xmp/transient/1.0/" + public const val NS_TRANSIENT: String = "http://ns.adobe.com/xmp/transient/1.0/" /** * legacy Dublin Core NS, will be converted to NS_DC */ - const val NS_DC_DEPRECATED: String = "http://purl.org/dc/1.1/" + public const val NS_DC_DEPRECATED: String = "http://purl.org/dc/1.1/" // Namespaces of products - const val NS_ASHAMPOO: String = "http://ns.ashampoo.com/xmp/1.0/" - const val NS_ACDSEE: String = "http://ns.acdsee.com/iptc/1.0/" - const val NS_DIGIKAM: String = "http://www.digikam.org/ns/1.0/" - const val NS_MYLIO: String = "http://ns.mylollc.com/MyloEdit/" - const val NS_NARRATIVE: String = "http://ns.narrative.so/narrative_select/1.0/" - const val NS_MICROSOFT_PHOTO: String = "http://ns.microsoft.com/photo/1.0/" - const val NS_LIGHTROOM: String = "http://ns.adobe.com/lightroom/1.0/" - const val NS_PHOTOSHOP: String = "http://ns.adobe.com/photoshop/1.0/" + public const val NS_ASHAMPOO: String = "http://ns.ashampoo.com/xmp/1.0/" + public const val NS_ACDSEE: String = "http://ns.acdsee.com/iptc/1.0/" + public const val NS_DIGIKAM: String = "http://www.digikam.org/ns/1.0/" + public const val NS_MYLIO: String = "http://ns.mylollc.com/MyloEdit/" + public const val NS_NARRATIVE: String = "http://ns.narrative.so/narrative_select/1.0/" + public const val NS_MICROSOFT_PHOTO: String = "http://ns.microsoft.com/photo/1.0/" + public const val NS_LIGHTROOM: String = "http://ns.adobe.com/lightroom/1.0/" + public const val NS_PHOTOSHOP: String = "http://ns.adobe.com/photoshop/1.0/" // XML namespace constants for qualifiers and structured property fields. /** * The XML namespace for qualifiers of the xmp:Identifier property. */ - const val TYPE_IDENTIFIERQUAL: String = "http://ns.adobe.com/xmp/Identifier/qual/1.0/" + public const val TYPE_IDENTIFIERQUAL: String = "http://ns.adobe.com/xmp/Identifier/qual/1.0/" /** * The XML namespace for fields of the Dimensions type. */ - const val TYPE_DIMENSIONS: String = "http://ns.adobe.com/xap/1.0/sType/Dimensions#" + public const val TYPE_DIMENSIONS: String = "http://ns.adobe.com/xap/1.0/sType/Dimensions#" - const val TYPE_AREA: String = "http://ns.adobe.com/xmp/sType/Area#" + public const val TYPE_AREA: String = "http://ns.adobe.com/xmp/sType/Area#" - const val TYPE_TEXT: String = "http://ns.adobe.com/xap/1.0/t/" + public const val TYPE_TEXT: String = "http://ns.adobe.com/xap/1.0/t/" - const val TYPE_PAGED_FILE: String = "http://ns.adobe.com/xap/1.0/t/pg/" + public const val TYPE_PAGED_FILE: String = "http://ns.adobe.com/xap/1.0/t/pg/" - const val TYPE_GRAPHICS: String = "http://ns.adobe.com/xap/1.0/g/" + public const val TYPE_GRAPHICS: String = "http://ns.adobe.com/xap/1.0/g/" /** * The XML namespace for fields of a graphical image. Used for the Thumbnail type. */ - const val TYPE_IMAGE: String = "http://ns.adobe.com/xap/1.0/g/img/" + public const val TYPE_IMAGE: String = "http://ns.adobe.com/xap/1.0/g/img/" - const val TYPE_FONT: String = "http://ns.adobe.com/xap/1.0/sType/Font#" + public const val TYPE_FONT: String = "http://ns.adobe.com/xap/1.0/sType/Font#" /** * The XML namespace for fields of the ResourceEvent type. */ - const val TYPE_RESOURCE_EVENT: String = "http://ns.adobe.com/xap/1.0/sType/ResourceEvent#" + public const val TYPE_RESOURCE_EVENT: String = "http://ns.adobe.com/xap/1.0/sType/ResourceEvent#" /** * The XML namespace for fields of the ResourceRef type. */ - const val TYPE_RESOURCE_REF: String = "http://ns.adobe.com/xap/1.0/sType/ResourceRef#" + public const val TYPE_RESOURCE_REF: String = "http://ns.adobe.com/xap/1.0/sType/ResourceRef#" /** * The XML namespace for fields of the Version type. */ - const val TYPE_ST_VERSION: String = "http://ns.adobe.com/xap/1.0/sType/Version#" + public const val TYPE_ST_VERSION: String = "http://ns.adobe.com/xap/1.0/sType/Version#" /** * The XML namespace for fields of the JobRef type. */ - const val TYPE_ST_JOB: String = "http://ns.adobe.com/xap/1.0/sType/Job#" + public const val TYPE_ST_JOB: String = "http://ns.adobe.com/xap/1.0/sType/Job#" - const val TYPE_MANIFEST_ITEM: String = "http://ns.adobe.com/xap/1.0/sType/ManifestItem#" + public const val TYPE_MANIFEST_ITEM: String = "http://ns.adobe.com/xap/1.0/sType/ManifestItem#" // --------------------------------------------------------------------------------------------- // Basic types and constants @@ -228,86 +228,86 @@ object XMPConst { * The canonical true string value for Booleans in serialized XMP. Code that converts from the * string to a bool should be case-insensitive, and even allow "1". */ - const val TRUE_STRING: String = "True" + public const val TRUE_STRING: String = "True" /** * The canonical false string value for Booleans in serialized XMP. Code that converts from the * string to a bool should be case-insensitive, and even allow "0". */ - const val FALSE_STRING: String = "False" + public const val FALSE_STRING: String = "False" /** * Index that has the meaning to be always the last item in an array. */ - const val ARRAY_LAST_ITEM: Int = -1 + public const val ARRAY_LAST_ITEM: Int = -1 /** * Node name of an array item. */ - const val ARRAY_ITEM_NAME: String = "[]" + public const val ARRAY_ITEM_NAME: String = "[]" /** * The x-default string for localized properties */ - const val X_DEFAULT: String = "x-default" + public const val X_DEFAULT: String = "x-default" /** * xml:lang qualfifier */ - const val XML_LANG: String = "xml:lang" + public const val XML_LANG: String = "xml:lang" /** * rdf:type qualfifier */ - const val RDF_TYPE: String = "rdf:type" + public const val RDF_TYPE: String = "rdf:type" /** * Processing Instruction (PI) for xmp packet */ - const val XMP_PI: String = "xpacket" + public const val XMP_PI: String = "xpacket" /** * XMP meta tag version new */ - const val TAG_XMPMETA: String = "xmpmeta" + public const val TAG_XMPMETA: String = "xmpmeta" /** * XMP meta tag version old */ - const val TAG_XAPMETA: String = "xapmeta" + public const val TAG_XAPMETA: String = "xapmeta" /** GPSVersionID as written by default by ExifTool. */ - const val DEFAULT_GPS_VERSION_ID = "2.3.0.0" + public const val DEFAULT_GPS_VERSION_ID: String = "2.3.0.0" - const val XMP_DC_SUBJECT: String = "subject" + public const val XMP_DC_SUBJECT: String = "subject" - const val XMP_ACDSEE_KEYWORDS: String = "keywords" + public const val XMP_ACDSEE_KEYWORDS: String = "keywords" - const val XMP_IPTC_EXT_PERSON_IN_IMAGE: String = "PersonInImage" + public const val XMP_IPTC_EXT_PERSON_IN_IMAGE: String = "PersonInImage" - const val XMP_MWG_RS_TYPE_FACE: String = "Face" - const val XMP_MWG_RS_REGION_LIST: String = "Regions/mwg-rs:RegionList" - const val XMP_MWG_RS_APPLIED_TO_DIMENSIONS: String = "Regions/mwg-rs:AppliedToDimensions" + public const val XMP_MWG_RS_TYPE_FACE: String = "Face" + public const val XMP_MWG_RS_REGION_LIST: String = "Regions/mwg-rs:RegionList" + public const val XMP_MWG_RS_APPLIED_TO_DIMENSIONS: String = "Regions/mwg-rs:AppliedToDimensions" /* xmpDM:pick="1" or xmpDM:pick="0" */ - const val FLAGGED_TAG_ADOBE_NAME: String = "pick" - const val FLAGGED_TAG_ADOBE_TRUE: String = "1" - const val FLAGGED_TAG_ADOBE_FALSE: String = "0" + public const val FLAGGED_TAG_ADOBE_NAME: String = "pick" + public const val FLAGGED_TAG_ADOBE_TRUE: String = "1" + public const val FLAGGED_TAG_ADOBE_FALSE: String = "0" /* True or False */ - const val FLAGGED_TAG_ACDSEE_NAME: String = "tagged" - const val FLAGGED_TAG_ACDSEE_TRUE: String = TRUE_STRING - const val FLAGGED_TAG_ACDSEE_FALSE: String = FALSE_STRING + public const val FLAGGED_TAG_ACDSEE_NAME: String = "tagged" + public const val FLAGGED_TAG_ACDSEE_TRUE: String = TRUE_STRING + public const val FLAGGED_TAG_ACDSEE_FALSE: String = FALSE_STRING /* MY:flag="true" or MY:flag="false" */ - const val FLAGGED_TAG_MYLIO_NAME: String = "flag" - const val FLAGGED_TAG_MYLIO_TRUE: String = "true" - const val FLAGGED_TAG_MYLIO_FALSE: String = "false" + public const val FLAGGED_TAG_MYLIO_NAME: String = "flag" + public const val FLAGGED_TAG_MYLIO_TRUE: String = "true" + public const val FLAGGED_TAG_MYLIO_FALSE: String = "false" /* narrative:Tagged="True" or narrative:Tagged="False" */ - const val FLAGGED_TAG_NARRATIVE_NAME: String = "Tagged" - const val FLAGGED_TAG_NARRATIVE_TRUE: String = TRUE_STRING - const val FLAGGED_TAG_NARRATIVE_FALSE: String = FALSE_STRING + public const val FLAGGED_TAG_NARRATIVE_NAME: String = "Tagged" + public const val FLAGGED_TAG_NARRATIVE_TRUE: String = TRUE_STRING + public const val FLAGGED_TAG_NARRATIVE_FALSE: String = FALSE_STRING - const val XMP_ASHAMPOO_ALBUMS: String = "albums" + public const val XMP_ASHAMPOO_ALBUMS: String = "albums" } diff --git a/src/commonMain/kotlin/com/ashampoo/xmp/XMPException.kt b/src/commonMain/kotlin/com/ashampoo/xmp/XMPException.kt index c2542e3..1149469 100644 --- a/src/commonMain/kotlin/com/ashampoo/xmp/XMPException.kt +++ b/src/commonMain/kotlin/com/ashampoo/xmp/XMPException.kt @@ -11,8 +11,8 @@ package com.ashampoo.xmp /** * This exception wraps all errors that occur in the XMP Toolkit. */ -class XMPException( +public class XMPException( message: String, - val errorCode: Int, + public val errorCode: Int, cause: Throwable? = null ) : Exception(message, cause) diff --git a/src/commonMain/kotlin/com/ashampoo/xmp/XMPIterator.kt b/src/commonMain/kotlin/com/ashampoo/xmp/XMPIterator.kt index d964ca3..e29868e 100644 --- a/src/commonMain/kotlin/com/ashampoo/xmp/XMPIterator.kt +++ b/src/commonMain/kotlin/com/ashampoo/xmp/XMPIterator.kt @@ -8,13 +8,15 @@ // ================================================================================================= package com.ashampoo.xmp -import com.ashampoo.xmp.XMPNodeUtils.findNode -import com.ashampoo.xmp.XMPNodeUtils.findSchemaNode +import com.ashampoo.xmp.internal.QName +import com.ashampoo.xmp.internal.XMPErrorConst +import com.ashampoo.xmp.internal.XMPNode +import com.ashampoo.xmp.internal.XMPNodeUtils.findNode +import com.ashampoo.xmp.internal.XMPNodeUtils.findSchemaNode import com.ashampoo.xmp.options.IteratorOptions import com.ashampoo.xmp.options.PropertyOptions -import com.ashampoo.xmp.properties.XMPPropertyInfo -import com.ashampoo.xmp.xpath.XMPPath -import com.ashampoo.xmp.xpath.XMPPathParser.expandXPath +import com.ashampoo.xmp.internal.XMPPath +import com.ashampoo.xmp.internal.XMPPathParser.expandXPath /** * Interface for the `XMPMeta` iteration services. @@ -66,7 +68,7 @@ import com.ashampoo.xmp.xpath.XMPPathParser.expandXPath * a `NoSuchElementException` if there are no more properties to * return. */ -class XMPIterator( +public class XMPIterator( xmp: XMPMeta, schemaNS: String?, propPath: String?, @@ -151,7 +153,7 @@ class XMPIterator( // !baseSchema && baseProperty // No schema but property provided -> error - throw XMPException("Schema namespace URI is required", XMPError.BADSCHEMA) + throw XMPException("Schema namespace URI is required", XMPErrorConst.BADSCHEMA) } } @@ -173,7 +175,7 @@ class XMPIterator( * Skip the subtree below the current node when `next()` is * called. */ - fun skipSubtree() { + public fun skipSubtree() { skipSubtree = true } @@ -181,7 +183,7 @@ class XMPIterator( * Skip the subtree below and remaining siblings of the current node when * `next()` is called. */ - fun skipSiblings() { + public fun skipSiblings() { skipSubtree() skipSiblings = true } @@ -437,8 +439,8 @@ class XMPIterator( if (node.options.isSchemaNode()) return baseNS - // determine namespace of leaf node - val qname = QName(node.name!!) + /* determine namespace of leaf node */ + val qname = QName.parse(node.name!!) return XMPSchemaRegistry.getNamespaceURI(qname.prefix!!)!! } @@ -449,7 +451,7 @@ class XMPIterator( override fun getOptions(): PropertyOptions = node.options - // the language is not reported + /* the language is not reported */ override fun getLanguage(): String? = null } } @@ -521,7 +523,7 @@ class XMPIterator( } } - companion object { + private companion object { /** * iteration state diff --git a/src/commonMain/kotlin/com/ashampoo/xmp/XMPMeta.kt b/src/commonMain/kotlin/com/ashampoo/xmp/XMPMeta.kt index dd27e15..05a5355 100644 --- a/src/commonMain/kotlin/com/ashampoo/xmp/XMPMeta.kt +++ b/src/commonMain/kotlin/com/ashampoo/xmp/XMPMeta.kt @@ -8,31 +8,32 @@ // ================================================================================================= package com.ashampoo.xmp -import com.ashampoo.xmp.Utils.normalizeLangValue import com.ashampoo.xmp.XMPConst.NS_MWG_RS import com.ashampoo.xmp.XMPConst.XMP_MWG_RS_APPLIED_TO_DIMENSIONS import com.ashampoo.xmp.XMPConst.XMP_MWG_RS_REGION_LIST -import com.ashampoo.xmp.XMPNodeUtils.appendLangItem -import com.ashampoo.xmp.XMPNodeUtils.chooseLocalizedText -import com.ashampoo.xmp.XMPNodeUtils.deleteNode -import com.ashampoo.xmp.XMPNodeUtils.findNode -import com.ashampoo.xmp.XMPNodeUtils.setNodeValue -import com.ashampoo.xmp.XMPNodeUtils.verifySetOptions -import com.ashampoo.xmp.XMPNormalizer.normalize import com.ashampoo.xmp.XMPPathFactory.composeArrayItemPath import com.ashampoo.xmp.XMPPathFactory.composeQualifierPath import com.ashampoo.xmp.XMPPathFactory.composeStructFieldPath -import com.ashampoo.xmp.XMPUtils.convertToBoolean -import com.ashampoo.xmp.XMPUtils.convertToDouble -import com.ashampoo.xmp.XMPUtils.convertToInteger -import com.ashampoo.xmp.XMPUtils.convertToLong -import com.ashampoo.xmp.XMPUtils.decodeBase64 +import com.ashampoo.xmp.internal.Utils.normalizeLangValue +import com.ashampoo.xmp.internal.XMPErrorConst +import com.ashampoo.xmp.internal.XMPNode +import com.ashampoo.xmp.internal.XMPNodeUtils +import com.ashampoo.xmp.internal.XMPNodeUtils.appendLangItem +import com.ashampoo.xmp.internal.XMPNodeUtils.chooseLocalizedText +import com.ashampoo.xmp.internal.XMPNodeUtils.deleteNode +import com.ashampoo.xmp.internal.XMPNodeUtils.findNode +import com.ashampoo.xmp.internal.XMPNodeUtils.setNodeValue +import com.ashampoo.xmp.internal.XMPNodeUtils.verifySetOptions +import com.ashampoo.xmp.internal.XMPNormalizer.normalize +import com.ashampoo.xmp.internal.XMPUtils.convertToBoolean +import com.ashampoo.xmp.internal.XMPUtils.convertToDouble +import com.ashampoo.xmp.internal.XMPUtils.convertToInteger +import com.ashampoo.xmp.internal.XMPUtils.convertToLong +import com.ashampoo.xmp.internal.XMPUtils.decodeBase64 import com.ashampoo.xmp.options.IteratorOptions import com.ashampoo.xmp.options.ParseOptions import com.ashampoo.xmp.options.PropertyOptions -import com.ashampoo.xmp.properties.XMPProperty -import com.ashampoo.xmp.properties.XMPPropertyInfo -import com.ashampoo.xmp.xpath.XMPPathParser.expandXPath +import com.ashampoo.xmp.internal.XMPPathParser.expandXPath /** * This class represents the set of XMP metadata as a DOM representation. It has methods to read and @@ -40,12 +41,12 @@ import com.ashampoo.xmp.xpath.XMPPathParser.expandXPath * to a String. */ @Suppress("TooManyFunctions") -class XMPMeta { +public class XMPMeta internal constructor() { /** * root of the metadata tree */ - var root: XMPNode + internal var root: XMPNode = XMPNode(null, null, PropertyOptions()) private set /** @@ -55,17 +56,6 @@ class XMPMeta { private val arrayOptions = PropertyOptions().setArray(true) - /** - * Constructor for an empty metadata object. - */ - constructor() { - this.root = XMPNode(null, null, PropertyOptions()) - } - - constructor(tree: XMPNode) { - this.root = tree - } - // --------------------------------------------------------------------------------------------- // Basic property manipulation functions @@ -97,16 +87,16 @@ class XMPMeta { * @return Returns a `XMPProperty` containing the value and the options or `null` * if the property does not exist. */ - fun getProperty(schemaNS: String, propName: String): XMPProperty? = + public fun getProperty(schemaNS: String, propName: String): XMPProperty? = getProperty(schemaNS, propName, XMPValueType.STRING) private fun getProperty(schemaNS: String, propName: String, valueType: XMPValueType): XMPProperty? { if (schemaNS.isEmpty()) - throw XMPException(XMPError.EMPTY_SCHEMA_TEXT, XMPError.BADPARAM) + throw XMPException(XMPErrorConst.EMPTY_SCHEMA_TEXT, XMPErrorConst.BADPARAM) if (propName.isEmpty()) - throw XMPException(XMPError.EMPTY_PROPERTY_NAME_TEXT, XMPError.BADPARAM) + throw XMPException(XMPErrorConst.EMPTY_PROPERTY_NAME_TEXT, XMPErrorConst.BADPARAM) val propNode = findNode( xmpTree = this.root, @@ -116,7 +106,7 @@ class XMPMeta { ) ?: return null if (valueType != XMPValueType.STRING && propNode.options.isCompositeProperty()) - throw XMPException("Property must be simple when a value type is requested", XMPError.BADXPATH) + throw XMPException("Property must be simple when a value type is requested", XMPErrorConst.BADXPATH) val value = evaluateNodeValue(valueType, propNode) @@ -179,13 +169,13 @@ class XMPMeta { * @return Returns a `XMPProperty` containing the value and the options or * `null` if the property does not exist. */ - fun getArrayItem(schemaNS: String, arrayName: String, itemIndex: Int): XMPProperty? { + public fun getArrayItem(schemaNS: String, arrayName: String, itemIndex: Int): XMPProperty? { if (schemaNS.isEmpty()) - throw XMPException(XMPError.EMPTY_SCHEMA_TEXT, XMPError.BADPARAM) + throw XMPException(XMPErrorConst.EMPTY_SCHEMA_TEXT, XMPErrorConst.BADPARAM) if (arrayName.isEmpty()) - throw XMPException(XMPError.EMPTY_ARRAY_NAME_TEXT, XMPError.BADPARAM) + throw XMPException(XMPErrorConst.EMPTY_ARRAY_NAME_TEXT, XMPErrorConst.BADPARAM) val itemPath = composeArrayItemPath(arrayName, itemIndex) @@ -201,19 +191,19 @@ class XMPMeta { * Has the same namespace prefix usage as propName in `getProperty()`. * @return Returns the number of items in the array. */ - fun countArrayItems(schemaNS: String, arrayName: String): Int { + public fun countArrayItems(schemaNS: String, arrayName: String): Int { if (schemaNS.isEmpty()) - throw XMPException(XMPError.EMPTY_SCHEMA_TEXT, XMPError.BADPARAM) + throw XMPException(XMPErrorConst.EMPTY_SCHEMA_TEXT, XMPErrorConst.BADPARAM) if (arrayName.isEmpty()) - throw XMPException(XMPError.EMPTY_ARRAY_NAME_TEXT, XMPError.BADPARAM) + throw XMPException(XMPErrorConst.EMPTY_ARRAY_NAME_TEXT, XMPErrorConst.BADPARAM) val arrayPath = expandXPath(schemaNS, arrayName) val arrayNode = findNode(this.root, arrayPath, false, null) ?: return 0 if (!arrayNode.options.isArray()) - throw XMPException("The named property is not an array", XMPError.BADXPATH) + throw XMPException("The named property is not an array", XMPErrorConst.BADXPATH) return arrayNode.getChildrenLength() } @@ -240,7 +230,7 @@ class XMPMeta { * `null` if the property does not exist. Arrays and non-leaf levels of * structs do not have values. */ - fun getStructField( + public fun getStructField( schemaNS: String, structName: String, fieldNS: String, @@ -250,10 +240,10 @@ class XMPMeta { /* Note that fieldNS and fieldName are checked inside composeStructFieldPath */ if (schemaNS.isEmpty()) - throw XMPException(XMPError.EMPTY_SCHEMA_TEXT, XMPError.BADPARAM) + throw XMPException(XMPErrorConst.EMPTY_SCHEMA_TEXT, XMPErrorConst.BADPARAM) if (structName.isEmpty()) - throw XMPException(XMPError.EMPTY_ARRAY_NAME_TEXT, XMPError.BADPARAM) + throw XMPException(XMPErrorConst.EMPTY_ARRAY_NAME_TEXT, XMPErrorConst.BADPARAM) val fieldPath = structName + composeStructFieldPath(fieldNS, fieldName) @@ -290,7 +280,7 @@ class XMPMeta { * The value of the qualifier is only set if it has one (Arrays and non-leaf levels of * structs do not have values). */ - fun getQualifier( + public fun getQualifier( schemaNS: String, propName: String, qualNS: String, @@ -299,10 +289,10 @@ class XMPMeta { // qualNS and qualName are checked inside composeQualfierPath if (schemaNS.isEmpty()) - throw XMPException(XMPError.EMPTY_SCHEMA_TEXT, XMPError.BADPARAM) + throw XMPException(XMPErrorConst.EMPTY_SCHEMA_TEXT, XMPErrorConst.BADPARAM) if (propName.isEmpty()) - throw XMPException(XMPError.EMPTY_PROPERTY_NAME_TEXT, XMPError.BADPARAM) + throw XMPException(XMPErrorConst.EMPTY_PROPERTY_NAME_TEXT, XMPErrorConst.BADPARAM) val qualPath = propName + composeQualifierPath(qualNS, qualName) @@ -339,7 +329,7 @@ class XMPMeta { * @param options Option flags describing the property. See the earlier description. */ @kotlin.jvm.JvmOverloads - fun setProperty( + public fun setProperty( schemaNS: String, propName: String, propValue: Any?, @@ -347,10 +337,10 @@ class XMPMeta { ) { if (schemaNS.isEmpty()) - throw XMPException(XMPError.EMPTY_SCHEMA_TEXT, XMPError.BADPARAM) + throw XMPException(XMPErrorConst.EMPTY_SCHEMA_TEXT, XMPErrorConst.BADPARAM) if (propName.isEmpty()) - throw XMPException(XMPError.EMPTY_PROPERTY_NAME_TEXT, XMPError.BADPARAM) + throw XMPException(XMPErrorConst.EMPTY_PROPERTY_NAME_TEXT, XMPErrorConst.BADPARAM) val verifiedOptions = verifySetOptions(options, propValue) @@ -359,7 +349,7 @@ class XMPMeta { xpath = expandXPath(schemaNS, propName), createNodes = true, leafOptions = verifySetOptions(options, propValue) - ) ?: throw XMPException("Specified property does not exist", XMPError.BADXPATH) + ) ?: throw XMPException("Specified property does not exist", XMPErrorConst.BADXPATH) setNode(propNode, propValue, verifiedOptions, false) } @@ -391,13 +381,13 @@ class XMPMeta { } else { if (value != null && value.toString().isNotEmpty()) - throw XMPException("Composite nodes can't have values", XMPError.BADXPATH) + throw XMPException("Composite nodes can't have values", XMPErrorConst.BADXPATH) // Can't change an array to a struct, or vice versa. if (node.options.getOptions() and compositeMask != 0 && newOptions.getOptions() and compositeMask != node.options.getOptions() and compositeMask ) - throw XMPException("Requested and existing composite form mismatch", XMPError.BADXPATH) + throw XMPException("Requested and existing composite form mismatch", XMPErrorConst.BADXPATH) node.removeChildren() } @@ -421,7 +411,7 @@ class XMPMeta { * @param options the set options for the item. */ @kotlin.jvm.JvmOverloads - fun setArrayItem( + public fun setArrayItem( schemaNS: String, arrayName: String, itemIndex: Int, @@ -430,17 +420,17 @@ class XMPMeta { ) { if (schemaNS.isEmpty()) - throw XMPException(XMPError.EMPTY_SCHEMA_TEXT, XMPError.BADPARAM) + throw XMPException(XMPErrorConst.EMPTY_SCHEMA_TEXT, XMPErrorConst.BADPARAM) if (arrayName.isEmpty()) - throw XMPException(XMPError.EMPTY_ARRAY_NAME_TEXT, XMPError.BADPARAM) + throw XMPException(XMPErrorConst.EMPTY_ARRAY_NAME_TEXT, XMPErrorConst.BADPARAM) // Just lookup, don't try to create. val arrayPath = expandXPath(schemaNS, arrayName) val arrayNode = findNode(this.root, arrayPath, false, null) if (arrayNode == null) - throw XMPException("Specified array does not exist", XMPError.BADXPATH) + throw XMPException("Specified array does not exist", XMPErrorConst.BADXPATH) doSetArrayItem(arrayNode, itemIndex, itemValue, options, false) } @@ -462,7 +452,7 @@ class XMPMeta { * @param options the set options that decide about the kind of the node. */ @kotlin.jvm.JvmOverloads - fun insertArrayItem( + public fun insertArrayItem( schemaNS: String, arrayName: String, itemIndex: Int, @@ -471,17 +461,17 @@ class XMPMeta { ) { if (schemaNS.isEmpty()) - throw XMPException(XMPError.EMPTY_SCHEMA_TEXT, XMPError.BADPARAM) + throw XMPException(XMPErrorConst.EMPTY_SCHEMA_TEXT, XMPErrorConst.BADPARAM) if (arrayName.isEmpty()) - throw XMPException(XMPError.EMPTY_ARRAY_NAME_TEXT, XMPError.BADPARAM) + throw XMPException(XMPErrorConst.EMPTY_ARRAY_NAME_TEXT, XMPErrorConst.BADPARAM) // Just lookup, don't try to create. val arrayPath = expandXPath(schemaNS, arrayName) val arrayNode = findNode(this.root, arrayPath, false, null) if (arrayNode == null) - throw XMPException("Specified array does not exist", XMPError.BADXPATH) + throw XMPException("Specified array does not exist", XMPErrorConst.BADXPATH) doSetArrayItem(arrayNode, itemIndex, itemValue, options, true) } @@ -511,7 +501,7 @@ class XMPMeta { * @param itemOptions Option flags describing the item to append ([PropertyOptions]) */ @kotlin.jvm.JvmOverloads - fun appendArrayItem( + public fun appendArrayItem( schemaNS: String, arrayName: String, arrayOptions: PropertyOptions = PropertyOptions(), @@ -520,13 +510,13 @@ class XMPMeta { ) { if (schemaNS.isEmpty()) - throw XMPException(XMPError.EMPTY_SCHEMA_TEXT, XMPError.BADPARAM) + throw XMPException(XMPErrorConst.EMPTY_SCHEMA_TEXT, XMPErrorConst.BADPARAM) if (arrayName.isEmpty()) - throw XMPException(XMPError.EMPTY_ARRAY_NAME_TEXT, XMPError.BADPARAM) + throw XMPException(XMPErrorConst.EMPTY_ARRAY_NAME_TEXT, XMPErrorConst.BADPARAM) if (!arrayOptions.isOnlyArrayOptions()) - throw XMPException("Only array form flags allowed for arrayOptions", XMPError.BADOPTIONS) + throw XMPException("Only array form flags allowed for arrayOptions", XMPErrorConst.BADOPTIONS) // Check if array options are set correctly. val verifiedArrayOptions = verifySetOptions(arrayOptions, null) @@ -542,7 +532,7 @@ class XMPMeta { // The array exists, make sure the form is compatible. Zero arrayForm means take what exists. if (!arrayNode.options.isArray()) - throw XMPException("The named property is not an array", XMPError.BADXPATH) + throw XMPException("The named property is not an array", XMPErrorConst.BADXPATH) } else { @@ -552,12 +542,12 @@ class XMPMeta { arrayNode = findNode(this.root, arrayPath, true, verifiedArrayOptions) if (arrayNode == null) - throw XMPException("Failure creating array node", XMPError.BADXPATH) + throw XMPException("Failure creating array node", XMPErrorConst.BADXPATH) } else { // array options missing - throw XMPException("Explicit arrayOptions required to create new array", XMPError.BADOPTIONS) + throw XMPException("Explicit arrayOptions required to create new array", XMPErrorConst.BADOPTIONS) } } @@ -604,7 +594,7 @@ class XMPMeta { setNode(itemNode, itemValue, verifiedItemOptions, false) } else { - throw XMPException("Array index out of bounds", XMPError.BADINDEX) + throw XMPException("Array index out of bounds", XMPErrorConst.BADINDEX) } } @@ -627,7 +617,7 @@ class XMPMeta { * @param options Option flags describing the field. See the earlier description. */ @kotlin.jvm.JvmOverloads - fun setStructField( + public fun setStructField( schemaNS: String, structName: String, fieldNS: String, @@ -637,10 +627,10 @@ class XMPMeta { ) { if (schemaNS.isEmpty()) - throw XMPException(XMPError.EMPTY_SCHEMA_TEXT, XMPError.BADPARAM) + throw XMPException(XMPErrorConst.EMPTY_SCHEMA_TEXT, XMPErrorConst.BADPARAM) if (structName.isEmpty()) - throw XMPException(XMPError.EMPTY_ARRAY_NAME_TEXT, XMPError.BADPARAM) + throw XMPException(XMPErrorConst.EMPTY_ARRAY_NAME_TEXT, XMPErrorConst.BADPARAM) val fieldPath = structName + composeStructFieldPath(fieldNS, fieldName) @@ -671,7 +661,7 @@ class XMPMeta { * @param options Option flags describing the qualifier. See the earlier description. */ @kotlin.jvm.JvmOverloads - fun setQualifier( + public fun setQualifier( schemaNS: String, propName: String, qualNS: String, @@ -681,13 +671,13 @@ class XMPMeta { ) { if (schemaNS.isEmpty()) - throw XMPException(XMPError.EMPTY_SCHEMA_TEXT, XMPError.BADPARAM) + throw XMPException(XMPErrorConst.EMPTY_SCHEMA_TEXT, XMPErrorConst.BADPARAM) if (propName.isEmpty()) - throw XMPException(XMPError.EMPTY_PROPERTY_NAME_TEXT, XMPError.BADPARAM) + throw XMPException(XMPErrorConst.EMPTY_PROPERTY_NAME_TEXT, XMPErrorConst.BADPARAM) if (!doesPropertyExist(schemaNS, propName)) - throw XMPException("Specified property does not exist!", XMPError.BADXPATH) + throw XMPException("Specified property does not exist!", XMPErrorConst.BADXPATH) val qualPath = propName + composeQualifierPath(qualNS, qualName) @@ -705,13 +695,13 @@ class XMPMeta { * @param schemaNS The namespace URI for the property. Has the same usage as in `getProperty()`. * @param propName The name of the property. Has the same usage as in getProperty. */ - fun deleteProperty(schemaNS: String, propName: String) { + public fun deleteProperty(schemaNS: String, propName: String) { if (schemaNS.isEmpty()) - throw XMPException(XMPError.EMPTY_SCHEMA_TEXT, XMPError.BADPARAM) + throw XMPException(XMPErrorConst.EMPTY_SCHEMA_TEXT, XMPErrorConst.BADPARAM) if (propName.isEmpty()) - throw XMPException("Can't delete empty property name.", XMPError.BADPARAM) + throw XMPException("Can't delete empty property name.", XMPErrorConst.BADPARAM) val propNode = findNode( xmpTree = this.root, @@ -735,13 +725,13 @@ class XMPMeta { * constant `XMPConst.ARRAY_LAST_ITEM` always refers to the last * existing array item. */ - fun deleteArrayItem(schemaNS: String, arrayName: String, itemIndex: Int) { + public fun deleteArrayItem(schemaNS: String, arrayName: String, itemIndex: Int) { if (schemaNS.isEmpty()) - throw XMPException(XMPError.EMPTY_SCHEMA_TEXT, XMPError.BADPARAM) + throw XMPException(XMPErrorConst.EMPTY_SCHEMA_TEXT, XMPErrorConst.BADPARAM) if (arrayName.isEmpty()) - throw XMPException(XMPError.EMPTY_ARRAY_NAME_TEXT, XMPError.BADPARAM) + throw XMPException(XMPErrorConst.EMPTY_ARRAY_NAME_TEXT, XMPErrorConst.BADPARAM) val itemPath = composeArrayItemPath(arrayName, itemIndex) @@ -762,7 +752,7 @@ class XMPMeta { * `null` or the empty string. Has the same namespace prefix usage as the * structName parameter. */ - fun deleteStructField( + public fun deleteStructField( schemaNS: String, structName: String, fieldNS: String, @@ -772,10 +762,10 @@ class XMPMeta { // fieldNS and fieldName are checked inside composeStructFieldPath if (schemaNS.isEmpty()) - throw XMPException(XMPError.EMPTY_SCHEMA_TEXT, XMPError.BADPARAM) + throw XMPException(XMPErrorConst.EMPTY_SCHEMA_TEXT, XMPErrorConst.BADPARAM) if (structName.isEmpty()) - throw XMPException(XMPError.EMPTY_ARRAY_NAME_TEXT, XMPError.BADPARAM) + throw XMPException(XMPErrorConst.EMPTY_ARRAY_NAME_TEXT, XMPErrorConst.BADPARAM) val fieldPath = structName + composeStructFieldPath(fieldNS, fieldName) @@ -795,14 +785,14 @@ class XMPMeta { * `null` or the empty string. Has the same namespace prefix usage as the * propName parameter. */ - fun deleteQualifier(schemaNS: String, propName: String, qualNS: String, qualName: String) { + public fun deleteQualifier(schemaNS: String, propName: String, qualNS: String, qualName: String) { // Note: qualNS and qualName are checked inside composeQualfierPath if (schemaNS.isEmpty()) - throw XMPException(XMPError.EMPTY_SCHEMA_TEXT, XMPError.BADPARAM) + throw XMPException(XMPErrorConst.EMPTY_SCHEMA_TEXT, XMPErrorConst.BADPARAM) if (propName.isEmpty()) - throw XMPException(XMPError.EMPTY_PROPERTY_NAME_TEXT, XMPError.BADPARAM) + throw XMPException(XMPErrorConst.EMPTY_PROPERTY_NAME_TEXT, XMPErrorConst.BADPARAM) val qualPath = propName + composeQualifierPath(qualNS, qualName) @@ -816,13 +806,13 @@ class XMPMeta { * @param propName The name of the property. Has the same usage as in `getProperty()`. * @return Returns true if the property exists. */ - fun doesPropertyExist(schemaNS: String, propName: String): Boolean { + public fun doesPropertyExist(schemaNS: String, propName: String): Boolean { if (schemaNS.isEmpty()) - throw XMPException(XMPError.EMPTY_SCHEMA_TEXT, XMPError.BADPARAM) + throw XMPException(XMPErrorConst.EMPTY_SCHEMA_TEXT, XMPErrorConst.BADPARAM) if (propName.isEmpty()) - throw XMPException(XMPError.EMPTY_PROPERTY_NAME_TEXT, XMPError.BADPARAM) + throw XMPException(XMPErrorConst.EMPTY_PROPERTY_NAME_TEXT, XMPErrorConst.BADPARAM) val propNode = findNode( xmpTree = this.root, @@ -846,13 +836,13 @@ class XMPMeta { * existing array item. * @return Returns `true` if the array exists, `false` otherwise. */ - fun doesArrayItemExist(schemaNS: String, arrayName: String, itemIndex: Int): Boolean { + public fun doesArrayItemExist(schemaNS: String, arrayName: String, itemIndex: Int): Boolean { if (schemaNS.isEmpty()) - throw XMPException(XMPError.EMPTY_SCHEMA_TEXT, XMPError.BADPARAM) + throw XMPException(XMPErrorConst.EMPTY_SCHEMA_TEXT, XMPErrorConst.BADPARAM) if (arrayName.isEmpty()) - throw XMPException(XMPError.EMPTY_ARRAY_NAME_TEXT, XMPError.BADPARAM) + throw XMPException(XMPErrorConst.EMPTY_ARRAY_NAME_TEXT, XMPErrorConst.BADPARAM) val path = composeArrayItemPath(arrayName, itemIndex) @@ -873,7 +863,7 @@ class XMPMeta { * Has the same namespace prefix usage as the structName parameter. * @return Returns true if the field exists. */ - fun doesStructFieldExist( + public fun doesStructFieldExist( schemaNS: String, structName: String, fieldNS: String, @@ -883,10 +873,10 @@ class XMPMeta { // fieldNS and fieldName are checked inside composeStructFieldPath() if (schemaNS.isEmpty()) - throw XMPException(XMPError.EMPTY_SCHEMA_TEXT, XMPError.BADPARAM) + throw XMPException(XMPErrorConst.EMPTY_SCHEMA_TEXT, XMPErrorConst.BADPARAM) if (structName.isEmpty()) - throw XMPException(XMPError.EMPTY_ARRAY_NAME_TEXT, XMPError.BADPARAM) + throw XMPException(XMPErrorConst.EMPTY_ARRAY_NAME_TEXT, XMPErrorConst.BADPARAM) val path = composeStructFieldPath(fieldNS, fieldName) @@ -906,7 +896,7 @@ class XMPMeta { * propName parameter. * @return Returns true if the qualifier exists. */ - fun doesQualifierExist( + public fun doesQualifierExist( schemaNS: String, propName: String, qualNS: String, @@ -916,10 +906,10 @@ class XMPMeta { // qualNS and qualName are checked inside composeQualifierPath() if (schemaNS.isEmpty()) - throw XMPException(XMPError.EMPTY_SCHEMA_TEXT, XMPError.BADPARAM) + throw XMPException(XMPErrorConst.EMPTY_SCHEMA_TEXT, XMPErrorConst.BADPARAM) if (propName.isEmpty()) - throw XMPException(XMPError.EMPTY_PROPERTY_NAME_TEXT, XMPError.BADPARAM) + throw XMPException(XMPErrorConst.EMPTY_PROPERTY_NAME_TEXT, XMPErrorConst.BADPARAM) val path = composeQualifierPath(qualNS, qualName) @@ -986,7 +976,7 @@ class XMPMeta { * the options if an appropriate alternate collection item exists, `null` * if the property does not exist. */ - fun getLocalizedText( + public fun getLocalizedText( schemaNS: String, altTextName: String, genericLang: String?, @@ -994,13 +984,13 @@ class XMPMeta { ): XMPProperty? { if (schemaNS.isEmpty()) - throw XMPException(XMPError.EMPTY_SCHEMA_TEXT, XMPError.BADPARAM) + throw XMPException(XMPErrorConst.EMPTY_SCHEMA_TEXT, XMPErrorConst.BADPARAM) if (altTextName.isEmpty()) - throw XMPException(XMPError.EMPTY_ARRAY_NAME_TEXT, XMPError.BADPARAM) + throw XMPException(XMPErrorConst.EMPTY_ARRAY_NAME_TEXT, XMPErrorConst.BADPARAM) if (specificLang.isEmpty()) - throw XMPException("Empty specific language", XMPError.BADPARAM) + throw XMPException("Empty specific language", XMPErrorConst.BADPARAM) val normalizedGenericLang = genericLang?.let { normalizeLangValue(it) } val normalizedSpecificLang = normalizeLangValue(specificLang) @@ -1064,7 +1054,7 @@ class XMPMeta { * value for the appropriate array item. * @param options Option flags, none are defined at present. */ - fun setLocalizedText( + public fun setLocalizedText( schemaNS: String, altTextName: String, genericLang: String?, @@ -1073,13 +1063,13 @@ class XMPMeta { ) { if (schemaNS.isEmpty()) - throw XMPException(XMPError.EMPTY_SCHEMA_TEXT, XMPError.BADPARAM) + throw XMPException(XMPErrorConst.EMPTY_SCHEMA_TEXT, XMPErrorConst.BADPARAM) if (altTextName.isEmpty()) - throw XMPException(XMPError.EMPTY_ARRAY_NAME_TEXT, XMPError.BADPARAM) + throw XMPException(XMPErrorConst.EMPTY_ARRAY_NAME_TEXT, XMPErrorConst.BADPARAM) if (specificLang.isEmpty()) - throw XMPException("Empty specific language", XMPError.BADPARAM) + throw XMPException("Empty specific language", XMPErrorConst.BADPARAM) val normalizedGenericLang = genericLang?.let { normalizeLangValue(it) } val normalizedSpecificLang = normalizeLangValue(specificLang) @@ -1097,14 +1087,14 @@ class XMPMeta { if (arrayNode == null) { - throw XMPException("Failed to find or create array node", XMPError.BADXPATH) + throw XMPException("Failed to find or create array node", XMPErrorConst.BADXPATH) } else if (!arrayNode.options.isArrayAltText()) { if (!arrayNode.hasChildren() && arrayNode.options.isArrayAlternate()) arrayNode.options.setArrayAltText(true) else - throw XMPException("Specified property is no alt-text array", XMPError.BADXPATH) + throw XMPException("Specified property is no alt-text array", XMPErrorConst.BADXPATH) } // Make sure the x-default item, if any, is first. @@ -1114,7 +1104,7 @@ class XMPMeta { for (item in arrayNode.iterateChildren()) { if (!item.hasQualifier() || XMPConst.XML_LANG != item.getQualifier(1).name) - throw XMPException("Language qualifier must be first", XMPError.BADXPATH) + throw XMPException("Language qualifier must be first", XMPErrorConst.BADXPATH) if (XMPConst.X_DEFAULT == item.getQualifier(1).value) { xdItem = item @@ -1210,7 +1200,7 @@ class XMPMeta { } else -> // does not happen under normal circumstances - throw XMPException("Unexpected result from ChooseLocalizedText", XMPError.INTERNALFAILURE) + throw XMPException("Unexpected result from ChooseLocalizedText", XMPErrorConst.INTERNALFAILURE) } // Add an x-default at the front if needed. @@ -1231,7 +1221,7 @@ class XMPMeta { * @param propName The name of the property. Has the same usage as in `getProperty()`. * @return Returns a `Boolean` value or `null` if the property does not exist. */ - fun getPropertyBoolean(schemaNS: String, propName: String): Boolean? = + public fun getPropertyBoolean(schemaNS: String, propName: String): Boolean? = getPropertyObject(schemaNS, propName, XMPValueType.BOOLEAN) as? Boolean /** @@ -1241,7 +1231,7 @@ class XMPMeta { * @param propName The name of the property. Has the same usage as in `getProperty()`. * @return Returns an `Integer` value or `null` if the property does not exist. */ - fun getPropertyInteger(schemaNS: String, propName: String): Int? = + public fun getPropertyInteger(schemaNS: String, propName: String): Int? = getPropertyObject(schemaNS, propName, XMPValueType.INTEGER) as? Int /** @@ -1251,7 +1241,7 @@ class XMPMeta { * @param propName The name of the property. Has the same usage as in `getProperty()`. * @return Returns a `Long` value or `null` if the property does not exist. */ - fun getPropertyLong(schemaNS: String, propName: String): Long? = + public fun getPropertyLong(schemaNS: String, propName: String): Long? = getPropertyObject(schemaNS, propName, XMPValueType.LONG) as? Long /** @@ -1261,7 +1251,7 @@ class XMPMeta { * @param propName The name of the property. Has the same usage as in `getProperty()`. * @return Returns a `Double` value or `null` if the property does not exist. */ - fun getPropertyDouble(schemaNS: String, propName: String): Double? = + public fun getPropertyDouble(schemaNS: String, propName: String): Double? = getPropertyObject(schemaNS, propName, XMPValueType.DOUBLE) as? Double /** @@ -1272,7 +1262,7 @@ class XMPMeta { * @return Returns a `byte[]`-array contained the decoded base64 value or `null` if the property does * not exist. */ - fun getPropertyBase64(schemaNS: String, propName: String): ByteArray? = + public fun getPropertyBase64(schemaNS: String, propName: String): ByteArray? = getPropertyObject(schemaNS, propName, XMPValueType.BASE64) as? ByteArray /** @@ -1285,7 +1275,7 @@ class XMPMeta { * @param propName The name of the property. Has the same usage as in `getProperty()`. * @return Returns a `String` value or `null` if the property does not exist. */ - fun getPropertyString(schemaNS: String, propName: String): String? = + public fun getPropertyString(schemaNS: String, propName: String): String? = getPropertyObject(schemaNS, propName, XMPValueType.STRING) as? String /** @@ -1294,10 +1284,10 @@ class XMPMeta { private fun getPropertyObject(schemaNS: String, propName: String, valueType: XMPValueType): Any? { if (schemaNS.isEmpty()) - throw XMPException(XMPError.EMPTY_SCHEMA_TEXT, XMPError.BADPARAM) + throw XMPException(XMPErrorConst.EMPTY_SCHEMA_TEXT, XMPErrorConst.BADPARAM) if (propName.isEmpty()) - throw XMPException(XMPError.EMPTY_PROPERTY_NAME_TEXT, XMPError.BADPARAM) + throw XMPException(XMPErrorConst.EMPTY_PROPERTY_NAME_TEXT, XMPErrorConst.BADPARAM) val propNode = findNode( xmpTree = this.root, @@ -1307,7 +1297,7 @@ class XMPMeta { ) ?: return null if (valueType != XMPValueType.STRING && propNode.options.isCompositeProperty()) - throw XMPException("Property must be simple when a value type is requested", XMPError.BADXPATH) + throw XMPException("Property must be simple when a value type is requested", XMPErrorConst.BADXPATH) return evaluateNodeValue(valueType, propNode) } @@ -1321,12 +1311,12 @@ class XMPMeta { * @param options options of the property to set (optional). */ @kotlin.jvm.JvmOverloads - fun setPropertyBoolean( + public fun setPropertyBoolean( schemaNS: String, propName: String, propValue: Boolean, options: PropertyOptions = PropertyOptions() - ) = setProperty( + ): Unit = setProperty( schemaNS, propName, if (propValue) XMPConst.TRUE_STRING else XMPConst.FALSE_STRING, @@ -1342,12 +1332,12 @@ class XMPMeta { * @param options options of the property to set (optional). */ @kotlin.jvm.JvmOverloads - fun setPropertyInteger( + public fun setPropertyInteger( schemaNS: String, propName: String, propValue: Int, options: PropertyOptions = PropertyOptions() - ) = setProperty(schemaNS, propName, propValue, options) + ): Unit = setProperty(schemaNS, propName, propValue, options) /** * Convenience method to set a property to a literal `long` value. @@ -1358,12 +1348,12 @@ class XMPMeta { * @param options options of the property to set (optional). */ @kotlin.jvm.JvmOverloads - fun setPropertyLong( + public fun setPropertyLong( schemaNS: String, propName: String, propValue: Long, options: PropertyOptions = PropertyOptions() - ) = setProperty(schemaNS, propName, propValue, options) + ): Unit = setProperty(schemaNS, propName, propValue, options) /** * Convenience method to set a property to a literal `double` value. @@ -1374,12 +1364,12 @@ class XMPMeta { * @param options options of the property to set (optional). */ @kotlin.jvm.JvmOverloads - fun setPropertyDouble( + public fun setPropertyDouble( schemaNS: String, propName: String, propValue: Double, options: PropertyOptions = PropertyOptions() - ) = setProperty(schemaNS, propName, propValue, options) + ): Unit = setProperty(schemaNS, propName, propValue, options) /** * Convenience method to set a property from a binary `byte[]`-array, @@ -1391,19 +1381,19 @@ class XMPMeta { * @param options options of the property to set (optional). */ @kotlin.jvm.JvmOverloads - fun setPropertyBase64( + public fun setPropertyBase64( schemaNS: String, propName: String, propValue: ByteArray, options: PropertyOptions = PropertyOptions() - ) = setProperty(schemaNS, propName, propValue, options) + ): Unit = setProperty(schemaNS, propName, propValue, options) /** * Constructs an iterator for the properties within this XMP object. * * @return Returns an `XMPIterator`. */ - fun iterator(): XMPIterator = + public fun iterator(): XMPIterator = iterator(IteratorOptions()) /** @@ -1412,7 +1402,7 @@ class XMPMeta { * @param options Option flags to control the iteration. * @return Returns an `XMPIterator`. */ - fun iterator(options: IteratorOptions): XMPIterator = + public fun iterator(options: IteratorOptions): XMPIterator = iterator(null, null, options) /** @@ -1427,7 +1417,7 @@ class XMPMeta { * @param options Option flags to control the iteration. See [IteratorOptions] for details. * @return Returns an `XMPIterator` for this `XMPMeta`-object considering the given options. */ - fun iterator( + public fun iterator( schemaNS: String?, propName: String?, options: IteratorOptions @@ -1440,13 +1430,13 @@ class XMPMeta { * * @return Returns the name of the XMP object. */ - fun getObjectName(): String = + public fun getObjectName(): String = root.name ?: "" /** * @param name Sets the name of the XMP object. */ - fun setObjectName(name: String) { + public fun setObjectName(name: String) { root.name = name } @@ -1457,13 +1447,13 @@ class XMPMeta { * 'encoding="XXX"'. If the parsed packet has not been wrapped into an xpacket, * `null` is returned. */ - fun getPacketHeader(): String? = + public fun getPacketHeader(): String? = packetHeader /** * Sets the packetHeader attributes, only used by the parser. */ - fun setPacketHeader(packetHeader: String?) { + public fun setPacketHeader(packetHeader: String?) { this.packetHeader = packetHeader } @@ -1476,7 +1466,7 @@ class XMPMeta { * * Qualifier are sorted, with the exception of "xml:lang" and/or "rdf:type" * that stay at the top of the list in that order. */ - fun sort() = + public fun sort(): Unit = root.sort() /** @@ -1486,10 +1476,10 @@ class XMPMeta { * *Note:* It does no harm to call this method to an already normalized xmp object. * It was a PDF/A requirement to get hand on the unnormalized `XMPMeta` object. */ - fun normalize(options: ParseOptions) = + public fun normalize(options: ParseOptions): XMPMeta = normalize(this, options) - fun printAllToConsole() { + public fun printAllToConsole() { val iterator: XMPIterator = iterator() @@ -1509,34 +1499,34 @@ class XMPMeta { */ /** Returns the ISO date string */ - fun getDateTimeOriginal(): String? = + public fun getDateTimeOriginal(): String? = getPropertyString(XMPConst.NS_EXIF, "DateTimeOriginal") - fun setDateTimeOriginal(isoDate: String) = + public fun setDateTimeOriginal(isoDate: String): Unit = setProperty(XMPConst.NS_EXIF, "DateTimeOriginal", isoDate) - fun deleteDateTimeOriginal() = + public fun deleteDateTimeOriginal(): Unit = deleteProperty(XMPConst.NS_EXIF, "DateTimeOriginal") - fun getOrientation(): Int? = + public fun getOrientation(): Int? = getPropertyInteger(XMPConst.NS_TIFF, "Orientation") - fun setOrientation(orientation: Int) = + public fun setOrientation(orientation: Int): Unit = setPropertyInteger(XMPConst.NS_TIFF, "Orientation", orientation) - fun getRating(): Int? = + public fun getRating(): Int? = getPropertyInteger(XMPConst.NS_XMP, "Rating") - fun setRating(rating: Int) = + public fun setRating(rating: Int): Unit = setPropertyInteger(XMPConst.NS_XMP, "Rating", rating) - fun getGpsLatitude(): String? = + public fun getGpsLatitude(): String? = getPropertyString(XMPConst.NS_EXIF, "GPSLatitude") - fun getGpsLongitude(): String? = + public fun getGpsLongitude(): String? = getPropertyString(XMPConst.NS_EXIF, "GPSLongitude") - fun setGpsCoordinates( + public fun setGpsCoordinates( latitudeDdm: String, longitudeDdm: String ) { @@ -1548,7 +1538,7 @@ class XMPMeta { setProperty(XMPConst.NS_EXIF, "GPSLongitude", longitudeDdm) } - fun deleteGpsCoordinates() { + public fun deleteGpsCoordinates() { deleteProperty(XMPConst.NS_EXIF, "GPSVersionID") deleteProperty(XMPConst.NS_EXIF, "GPSLatitude") @@ -1558,7 +1548,7 @@ class XMPMeta { /** * Check for common used fields if they have a positive flagged value. */ - fun isFlagged(): Boolean = + public fun isFlagged(): Boolean = getPropertyBoolean(XMPConst.NS_DM, XMPConst.FLAGGED_TAG_ADOBE_NAME) == true || getPropertyBoolean(XMPConst.NS_ACDSEE, XMPConst.FLAGGED_TAG_ACDSEE_NAME) == true || getPropertyBoolean(XMPConst.NS_MYLIO, XMPConst.FLAGGED_TAG_MYLIO_NAME) == true || @@ -1567,7 +1557,7 @@ class XMPMeta { /** * Sets flagged/tagged/picked marker for standard schema and other commonly used fields by popular tools. */ - fun setFlagged(flagged: Boolean) { + public fun setFlagged(flagged: Boolean) { /* Set the standard schema */ setProperty( @@ -1610,7 +1600,7 @@ class XMPMeta { /** * Gets the regular keywords specified by XMP standard. */ - fun getKeywords(): Set { + public fun getKeywords(): Set { val subjectCount = countArrayItems(XMPConst.NS_DC, XMPConst.XMP_DC_SUBJECT) @@ -1632,7 +1622,7 @@ class XMPMeta { return keywords } - fun setKeywords(keywords: Set) { + public fun setKeywords(keywords: Set) { /* Delete existing entries, if any */ deleteProperty(XMPConst.NS_DC, XMPConst.XMP_DC_SUBJECT) @@ -1661,7 +1651,7 @@ class XMPMeta { * Gets ACDSee keywords from the ACDSee namespace. * This can be used as an alternative if the regular keyword property is empty. */ - fun getAcdSeeKeywords(): Set { + public fun getAcdSeeKeywords(): Set { val propertyExists = doesPropertyExist(XMPConst.NS_ACDSEE, XMPConst.XMP_ACDSEE_KEYWORDS) @@ -1688,7 +1678,7 @@ class XMPMeta { return keywords } - fun getFaces(): Map { + public fun getFaces(): Map { val regionListExists = doesPropertyExist(XMPConst.NS_MWG_RS, XMP_MWG_RS_REGION_LIST) @@ -1730,11 +1720,11 @@ class XMPMeta { return faces } - fun setFaces( + public fun setFaces( faces: Map, widthPx: Int, heightPx: Int - ) { + ): Unit { /* Delete existing entries, if any */ deleteProperty(NS_MWG_RS, "Regions") @@ -1845,7 +1835,7 @@ class XMPMeta { } } - fun getPersonsInImage(): Set { + public fun getPersonsInImage(): Set { val personsInImageCount = countArrayItems(XMPConst.NS_IPTC_EXT, XMPConst.XMP_IPTC_EXT_PERSON_IN_IMAGE) @@ -1869,7 +1859,9 @@ class XMPMeta { return personsInImage } - fun setPersonsInImage(personsInImage: Set) { + public fun setPersonsInImage( + personsInImage: Set + ): Unit { /* Delete existing entries, if any */ deleteProperty(XMPConst.NS_IPTC_EXT, XMPConst.XMP_IPTC_EXT_PERSON_IN_IMAGE) @@ -1897,7 +1889,7 @@ class XMPMeta { /** * Get album names */ - fun getAlbums(): Set { + public fun getAlbums(): Set { val subjectCount = countArrayItems(XMPConst.NS_ASHAMPOO, XMPConst.XMP_ASHAMPOO_ALBUMS) @@ -1919,7 +1911,9 @@ class XMPMeta { return keywords } - fun setAlbums(albums: Set) { + public fun setAlbums( + albums: Set + ) { /* Delete existing entries, if any */ deleteProperty(XMPConst.NS_ASHAMPOO, XMPConst.XMP_ASHAMPOO_ALBUMS) @@ -1944,7 +1938,7 @@ class XMPMeta { ) } - internal enum class XMPValueType { + private enum class XMPValueType { STRING, BOOLEAN, diff --git a/src/commonMain/kotlin/com/ashampoo/xmp/XMPMetaFactory.kt b/src/commonMain/kotlin/com/ashampoo/xmp/XMPMetaFactory.kt index c408ca7..f3d6b21 100644 --- a/src/commonMain/kotlin/com/ashampoo/xmp/XMPMetaFactory.kt +++ b/src/commonMain/kotlin/com/ashampoo/xmp/XMPMetaFactory.kt @@ -8,27 +8,29 @@ // ================================================================================================= package com.ashampoo.xmp +import com.ashampoo.xmp.internal.XMPMetaParser +import com.ashampoo.xmp.internal.XMPRDFWriter import com.ashampoo.xmp.options.ParseOptions import com.ashampoo.xmp.options.SerializeOptions /** * Creates `XMPMeta`-instances from an `InputStream` */ -object XMPMetaFactory { +public object XMPMetaFactory { @kotlin.jvm.JvmStatic - val schemaRegistry = XMPSchemaRegistry + public val schemaRegistry: XMPSchemaRegistry = XMPSchemaRegistry @kotlin.jvm.JvmStatic - val versionInfo = XMPVersionInfo + public val versionInfo: XMPVersionInfo = XMPVersionInfo @kotlin.jvm.JvmStatic - fun create(): XMPMeta = XMPMeta() + public fun create(): XMPMeta = XMPMeta() @kotlin.jvm.JvmStatic @kotlin.jvm.JvmOverloads @Throws(XMPException::class) - fun parseFromString( + public fun parseFromString( packet: String, options: ParseOptions? = null ): XMPMeta = @@ -37,7 +39,7 @@ object XMPMetaFactory { @kotlin.jvm.JvmStatic @kotlin.jvm.JvmOverloads @Throws(XMPException::class) - fun serializeToString( + public fun serializeToString( xmp: XMPMeta, options: SerializeOptions? = null ): String { diff --git a/src/commonMain/kotlin/com/ashampoo/xmp/XMPPathFactory.kt b/src/commonMain/kotlin/com/ashampoo/xmp/XMPPathFactory.kt index 2e3fbd2..b36b76a 100644 --- a/src/commonMain/kotlin/com/ashampoo/xmp/XMPPathFactory.kt +++ b/src/commonMain/kotlin/com/ashampoo/xmp/XMPPathFactory.kt @@ -8,8 +8,10 @@ // ================================================================================================= package com.ashampoo.xmp -import com.ashampoo.xmp.xpath.XMPPath -import com.ashampoo.xmp.xpath.XMPPathParser +import com.ashampoo.xmp.internal.Utils +import com.ashampoo.xmp.internal.XMPErrorConst +import com.ashampoo.xmp.internal.XMPPath +import com.ashampoo.xmp.internal.XMPPathParser /** * Utility services for the metadata object. It has only public static functions, you cannot create @@ -33,7 +35,7 @@ import com.ashampoo.xmp.xpath.XMPPathParser * * *Note:* These methods are much simpler than in the C++-API, they don't check the given path or array indices. */ -object XMPPathFactory { +public object XMPPathFactory { /** * Compose the path expression for an item in an array. @@ -47,7 +49,7 @@ object XMPPathFactory { * "i" is the decimal representation of itemIndex. */ @kotlin.jvm.JvmStatic - fun composeArrayItemPath(arrayName: String, itemIndex: Int): String { + public fun composeArrayItemPath(arrayName: String, itemIndex: Int): String { if (itemIndex > 0) return "$arrayName[$itemIndex]" @@ -55,7 +57,7 @@ object XMPPathFactory { if (itemIndex == XMPConst.ARRAY_LAST_ITEM) return "$arrayName[last()]" - throw XMPException("Array index must be larger than zero", XMPError.BADINDEX) + throw XMPException("Array index must be larger than zero", XMPErrorConst.BADINDEX) } /** @@ -70,18 +72,18 @@ object XMPPathFactory { * schemaNS and "fNS" is the prefix for fieldNS. */ @kotlin.jvm.JvmStatic - fun composeStructFieldPath(fieldNS: String, fieldName: String): String { + public fun composeStructFieldPath(fieldNS: String, fieldName: String): String { if (fieldNS.isEmpty()) - throw XMPException("Empty field namespace URI", XMPError.BADSCHEMA) + throw XMPException("Empty field namespace URI", XMPErrorConst.BADSCHEMA) if (fieldName.isEmpty()) - throw XMPException("Empty field name", XMPError.BADXPATH) + throw XMPException("Empty field name", XMPErrorConst.BADXPATH) val fieldPath = XMPPathParser.expandXPath(fieldNS, fieldName) if (fieldPath.size() != 2) - throw XMPException("The field name must be simple", XMPError.BADXPATH) + throw XMPException("The field name must be simple", XMPErrorConst.BADXPATH) return '/'.toString() + fieldPath.getSegment(XMPPath.STEP_ROOT_PROP).name } @@ -98,18 +100,18 @@ object XMPPathFactory { * schemaNS and "qNS" is the prefix for qualNS. */ @kotlin.jvm.JvmStatic - fun composeQualifierPath(qualNS: String, qualName: String): String { + public fun composeQualifierPath(qualNS: String, qualName: String): String { if (qualNS.isEmpty()) - throw XMPException("Empty qualifier namespace URI", XMPError.BADSCHEMA) + throw XMPException("Empty qualifier namespace URI", XMPErrorConst.BADSCHEMA) if (qualName.isEmpty()) - throw XMPException("Empty qualifier name", XMPError.BADXPATH) + throw XMPException("Empty qualifier name", XMPErrorConst.BADXPATH) val qualPath = XMPPathParser.expandXPath(qualNS, qualName) if (qualPath.size() != 2) - throw XMPException("The qualifier name must be simple", XMPError.BADXPATH) + throw XMPException("The qualifier name must be simple", XMPErrorConst.BADXPATH) return "/?" + qualPath.getSegment(XMPPath.STEP_ROOT_PROP).name } @@ -135,7 +137,7 @@ object XMPPathFactory { * ns:arrayName[@xml:lang='langName'], where * "ns" is the prefix for schemaNS. */ - fun composeLangSelector(arrayName: String, langName: String): String = + public fun composeLangSelector(arrayName: String, langName: String): String = arrayName + "[?xml:lang=\"" + Utils.normalizeLangValue(langName) + "\"]" /** @@ -160,7 +162,7 @@ object XMPPathFactory { * ns:arrayName[fNS:fieldName='fieldValue'], where "ns" is the * prefix for schemaNS and "fNS" is the prefix for fieldNS. */ - fun composeFieldSelector( + public fun composeFieldSelector( arrayName: String, fieldNS: String?, fieldName: String?, @@ -170,7 +172,7 @@ object XMPPathFactory { val fieldPath = XMPPathParser.expandXPath(fieldNS, fieldName) if (fieldPath.size() != 2) - throw XMPException("The fieldName name must be simple", XMPError.BADXPATH) + throw XMPException("The fieldName name must be simple", XMPErrorConst.BADXPATH) return arrayName + '[' + fieldPath.getSegment(XMPPath.STEP_ROOT_PROP).name + "=\"" + fieldValue + "\"]" diff --git a/src/commonMain/kotlin/com/ashampoo/xmp/properties/XMPProperty.kt b/src/commonMain/kotlin/com/ashampoo/xmp/XMPProperty.kt similarity index 83% rename from src/commonMain/kotlin/com/ashampoo/xmp/properties/XMPProperty.kt rename to src/commonMain/kotlin/com/ashampoo/xmp/XMPProperty.kt index ebc50a8..3c7ed12 100644 --- a/src/commonMain/kotlin/com/ashampoo/xmp/properties/XMPProperty.kt +++ b/src/commonMain/kotlin/com/ashampoo/xmp/XMPProperty.kt @@ -6,30 +6,30 @@ // NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms // of the Adobe license agreement accompanying it. // ================================================================================================= -package com.ashampoo.xmp.properties +package com.ashampoo.xmp import com.ashampoo.xmp.options.PropertyOptions /** * This interface is used to return a text property together with its and options. */ -interface XMPProperty { +public interface XMPProperty { /** * @return Returns the value of the property. */ - fun getValue(): String? + public fun getValue(): String? /** * @return Returns the options of the property. */ - fun getOptions(): PropertyOptions + public fun getOptions(): PropertyOptions /** * Only set by {@link XMPMeta.getLocalizedText}. * * @return Returns the language of the alt-text item. */ - fun getLanguage(): String? + public fun getLanguage(): String? } diff --git a/src/commonMain/kotlin/com/ashampoo/xmp/properties/XMPPropertyInfo.kt b/src/commonMain/kotlin/com/ashampoo/xmp/XMPPropertyInfo.kt similarity index 88% rename from src/commonMain/kotlin/com/ashampoo/xmp/properties/XMPPropertyInfo.kt rename to src/commonMain/kotlin/com/ashampoo/xmp/XMPPropertyInfo.kt index df1c7d0..7387143 100644 --- a/src/commonMain/kotlin/com/ashampoo/xmp/properties/XMPPropertyInfo.kt +++ b/src/commonMain/kotlin/com/ashampoo/xmp/XMPPropertyInfo.kt @@ -6,7 +6,7 @@ // NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms // of the Adobe license agreement accompanying it. // ================================================================================================= -package com.ashampoo.xmp.properties +package com.ashampoo.xmp import com.ashampoo.xmp.options.PropertyOptions @@ -14,17 +14,17 @@ import com.ashampoo.xmp.options.PropertyOptions * This interface is used to return a property together with its path and namespace. * It is returned when properties are iterated with the XMPIterator. */ -interface XMPPropertyInfo : XMPProperty { +public interface XMPPropertyInfo : XMPProperty { /** * @return Returns the namespace of the property */ - fun getNamespace(): String + public fun getNamespace(): String /** * @return Returns the path of the property, but only if returned by the iterator. */ - fun getPath(): String + public fun getPath(): String /** * @return Returns the value of the property. diff --git a/src/commonMain/kotlin/com/ashampoo/xmp/XMPRegionArea.kt b/src/commonMain/kotlin/com/ashampoo/xmp/XMPRegionArea.kt index 7848e46..0a34230 100644 --- a/src/commonMain/kotlin/com/ashampoo/xmp/XMPRegionArea.kt +++ b/src/commonMain/kotlin/com/ashampoo/xmp/XMPRegionArea.kt @@ -9,7 +9,7 @@ package com.ashampoo.xmp /** As used in XMP-mwg-rs */ -data class XMPRegionArea( +public data class XMPRegionArea( val xPos: Double, val yPos: Double, val width: Double, diff --git a/src/commonMain/kotlin/com/ashampoo/xmp/XMPSchemaRegistry.kt b/src/commonMain/kotlin/com/ashampoo/xmp/XMPSchemaRegistry.kt index 4251264..f89f9bf 100644 --- a/src/commonMain/kotlin/com/ashampoo/xmp/XMPSchemaRegistry.kt +++ b/src/commonMain/kotlin/com/ashampoo/xmp/XMPSchemaRegistry.kt @@ -8,9 +8,10 @@ // ================================================================================================= package com.ashampoo.xmp -import com.ashampoo.xmp.Utils.isXMLNameNS +import com.ashampoo.xmp.internal.Utils.isXMLNameNS +import com.ashampoo.xmp.internal.XMPErrorConst +import com.ashampoo.xmp.internal.XMPNodeUtils import com.ashampoo.xmp.options.AliasOptions -import com.ashampoo.xmp.properties.XMPAliasInfo /** * The schema registry keeps track of all namespaces and aliases used in the XMP @@ -41,7 +42,7 @@ import com.ashampoo.xmp.properties.XMPAliasInfo * There is only one single instance used by the toolkit. */ @Suppress("TooManyFunctions") -object XMPSchemaRegistry { +public object XMPSchemaRegistry { /** * a map from a namespace URI to its registered prefix @@ -98,21 +99,21 @@ object XMPSchemaRegistry { * @return Returns the registered prefix for this URI, is equal to the suggestedPrefix if the * namespace hasn't been registered before, otherwise the existing prefix. */ - fun registerNamespace(namespaceURI: String, suggestedPrefix: String): String { + public fun registerNamespace(namespaceURI: String, suggestedPrefix: String): String { var actualSuggestedPrefix = suggestedPrefix if (namespaceURI.isEmpty()) - throw XMPException(XMPError.EMPTY_SCHEMA_TEXT, XMPError.BADPARAM) + throw XMPException(XMPErrorConst.EMPTY_SCHEMA_TEXT, XMPErrorConst.BADPARAM) if (actualSuggestedPrefix.isEmpty()) - throw XMPException("Empty prefix", XMPError.BADPARAM) + throw XMPException("Empty prefix", XMPErrorConst.BADPARAM) if (actualSuggestedPrefix[actualSuggestedPrefix.length - 1] != ':') actualSuggestedPrefix += ':' if (!isXMLNameNS(actualSuggestedPrefix.substring(0, actualSuggestedPrefix.length - 1))) - throw XMPException("The prefix is a bad XML name", XMPError.BADXML) + throw XMPException("The prefix is a bad XML name", XMPErrorConst.BADXML) val registeredPrefix = namespaceToPrefixMap[namespaceURI] val registeredNS = prefixToNamespaceMap[actualSuggestedPrefix] @@ -153,7 +154,7 @@ object XMPSchemaRegistry { * @param namespaceURI The URI for the namespace. Must not be null or the empty string. * @return Returns the prefix registered for this namespace URI or null. */ - fun getNamespacePrefix(namespaceURI: String): String? = + public fun getNamespacePrefix(namespaceURI: String): String? = namespaceToPrefixMap[namespaceURI] /** @@ -164,7 +165,7 @@ object XMPSchemaRegistry { * @param namespacePrefix The prefix for the namespace. Must not be null or the empty string. * @return Returns the URI registered for this prefix or null. */ - fun getNamespaceURI(namespacePrefix: String): String? { + public fun getNamespaceURI(namespacePrefix: String): String? { var actualNamespacePrefix = namespacePrefix @@ -178,7 +179,7 @@ object XMPSchemaRegistry { * @return Returns the registered prefix/namespace-pairs as map, where the keys are the * namespaces and the values are the prefixes. */ - fun getNamespaces(): Map = + public fun getNamespaces(): Map = namespaceToPrefixMap /** @@ -189,7 +190,7 @@ object XMPSchemaRegistry { * * @param namespaceURI The URI for the namespace. */ - fun deleteNamespace(namespaceURI: String) { + public fun deleteNamespace(namespaceURI: String): Unit { val prefixToDelete = getNamespacePrefix(namespaceURI) ?: return @@ -197,7 +198,7 @@ object XMPSchemaRegistry { prefixToNamespaceMap.remove(prefixToDelete) } - fun getPrefixes(): Map = + public fun getPrefixes(): Map = prefixToNamespaceMap /** @@ -297,7 +298,7 @@ object XMPSchemaRegistry { * @return Returns the `XMPAliasInfo` for the given alias namespace and property * or `null` if there is no such alias. */ - fun resolveAlias(aliasNS: String, aliasProp: String): XMPAliasInfo? { + public fun resolveAlias(aliasNS: String, aliasProp: String): XMPAliasInfo? { val aliasPrefix = getNamespacePrefix(aliasNS) ?: return null @@ -311,7 +312,7 @@ object XMPSchemaRegistry { * @return Returns if an alias definition for the given qname to another * schema and property is registered. */ - fun findAlias(qname: String): XMPAliasInfo? = + public fun findAlias(qname: String): XMPAliasInfo? = aliasMap[qname] /** @@ -321,7 +322,7 @@ object XMPSchemaRegistry { * @param aliasNS a schema namespace URI * @return Returns all alias infos from aliases that are contained in the provided namespace. */ - fun findAliases(aliasNS: String): Set { + public fun findAliases(aliasNS: String): Set { val prefix = getNamespacePrefix(aliasNS) @@ -373,7 +374,7 @@ object XMPSchemaRegistry { * an array or not (see [AliasOptions]). */ @Suppress("ThrowsCount") - fun registerAlias( + public fun registerAlias( aliasNS: String, aliasProp: String, actualNS: String, @@ -382,16 +383,16 @@ object XMPSchemaRegistry { ) { if (aliasNS.isEmpty()) - throw XMPException(XMPError.EMPTY_SCHEMA_TEXT, XMPError.BADPARAM) + throw XMPException(XMPErrorConst.EMPTY_SCHEMA_TEXT, XMPErrorConst.BADPARAM) if (aliasProp.isEmpty()) - throw XMPException(XMPError.EMPTY_PROPERTY_NAME_TEXT, XMPError.BADPARAM) + throw XMPException(XMPErrorConst.EMPTY_PROPERTY_NAME_TEXT, XMPErrorConst.BADPARAM) if (actualNS.isEmpty()) - throw XMPException(XMPError.EMPTY_SCHEMA_TEXT, XMPError.BADPARAM) + throw XMPException(XMPErrorConst.EMPTY_SCHEMA_TEXT, XMPErrorConst.BADPARAM) if (actualProp.isEmpty()) - throw XMPException(XMPError.EMPTY_PROPERTY_NAME_TEXT, XMPError.BADPARAM) + throw XMPException(XMPErrorConst.EMPTY_PROPERTY_NAME_TEXT, XMPErrorConst.BADPARAM) // Fix the alias options val aliasOpts = if (aliasForm != null) @@ -405,25 +406,25 @@ object XMPSchemaRegistry { AliasOptions() if (simpleProperyPattern.matches(aliasProp) || simpleProperyPattern.matches(actualProp)) - throw XMPException("Alias and actual property names must be simple", XMPError.BADXPATH) + throw XMPException("Alias and actual property names must be simple", XMPErrorConst.BADXPATH) // check if both namespaces are registered val aliasPrefix = getNamespacePrefix(aliasNS) val actualPrefix = getNamespacePrefix(actualNS) if (aliasPrefix == null) - throw XMPException("Alias namespace is not registered", XMPError.BADSCHEMA) + throw XMPException("Alias namespace is not registered", XMPErrorConst.BADSCHEMA) else if (actualPrefix == null) - throw XMPException("Actual namespace is not registered", XMPError.BADSCHEMA) + throw XMPException("Actual namespace is not registered", XMPErrorConst.BADSCHEMA) val key = aliasPrefix + aliasProp // check if alias is already existing if (aliasMap.containsKey(key)) - throw XMPException("Alias is already existing", XMPError.BADPARAM) + throw XMPException("Alias is already existing", XMPErrorConst.BADPARAM) else if (aliasMap.containsKey(actualPrefix + actualProp)) throw XMPException( - "Actual property is already an alias, use the base property", XMPError.BADPARAM + "Actual property is already an alias, use the base property", XMPErrorConst.BADPARAM ) val aliasInfo: XMPAliasInfo = object : XMPAliasInfo { @@ -447,7 +448,7 @@ object XMPSchemaRegistry { * @return Returns the registered aliases as map, where the key is the "qname" (prefix and name) * and the value an `XMPAliasInfo`-object. */ - fun getAliases(): Map = + public fun getAliases(): Map = aliasMap /** diff --git a/src/commonMain/kotlin/com/ashampoo/xmp/XMPVersionInfo.kt b/src/commonMain/kotlin/com/ashampoo/xmp/XMPVersionInfo.kt index a99f2a2..5568e5c 100644 --- a/src/commonMain/kotlin/com/ashampoo/xmp/XMPVersionInfo.kt +++ b/src/commonMain/kotlin/com/ashampoo/xmp/XMPVersionInfo.kt @@ -5,14 +5,15 @@ package com.ashampoo.xmp * (which it is based on), but under it's real name and version number. */ @Suppress("MagicNumber") -object XMPVersionInfo { +public object XMPVersionInfo { - const val MAJOR: Int = 1 - const val MINOR: Int = 2 - const val PATCH: Int = 2 + public const val MAJOR: Int = 1 + public const val MINOR: Int = 3 + public const val PATCH: Int = 0 - const val VERSION_MESSAGE = "Ashampoo XMP Core $MAJOR.$MINOR.$PATCH" + public const val VERSION_MESSAGE: String = + "Ashampoo XMP Core $MAJOR.$MINOR.$PATCH" - const val DEBUG: Boolean = false + public const val DEBUG: Boolean = false } diff --git a/src/commonMain/kotlin/com/ashampoo/xmp/DomParser.kt b/src/commonMain/kotlin/com/ashampoo/xmp/internal/DomParser.kt similarity index 92% rename from src/commonMain/kotlin/com/ashampoo/xmp/DomParser.kt rename to src/commonMain/kotlin/com/ashampoo/xmp/internal/DomParser.kt index 594a0b0..4002d1b 100644 --- a/src/commonMain/kotlin/com/ashampoo/xmp/DomParser.kt +++ b/src/commonMain/kotlin/com/ashampoo/xmp/internal/DomParser.kt @@ -1,12 +1,13 @@ -package com.ashampoo.xmp +package com.ashampoo.xmp.internal +import com.ashampoo.xmp.XMPException import nl.adaptivity.xmlutil.DomWriter import nl.adaptivity.xmlutil.EventType import nl.adaptivity.xmlutil.dom.Document import nl.adaptivity.xmlutil.writeCurrent import nl.adaptivity.xmlutil.xmlStreaming -object DomParser { +internal object DomParser { private const val RDF_RDF_END = "" @@ -46,7 +47,7 @@ object DomParser { return writer.target } catch (ex: Exception) { - throw XMPException("Error reading the XML file: ${ex.message}", XMPError.BADSTREAM, ex) + throw XMPException("Error reading the XML file: ${ex.message}", XMPErrorConst.BADSTREAM, ex) } } } diff --git a/src/commonMain/kotlin/com/ashampoo/xmp/xpath/PathPosition.kt b/src/commonMain/kotlin/com/ashampoo/xmp/internal/PathPosition.kt similarity index 96% rename from src/commonMain/kotlin/com/ashampoo/xmp/xpath/PathPosition.kt rename to src/commonMain/kotlin/com/ashampoo/xmp/internal/PathPosition.kt index c9b0049..f262a12 100644 --- a/src/commonMain/kotlin/com/ashampoo/xmp/xpath/PathPosition.kt +++ b/src/commonMain/kotlin/com/ashampoo/xmp/internal/PathPosition.kt @@ -6,7 +6,7 @@ // NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms // of the Adobe license agreement accompanying it. // ================================================================================================= -package com.ashampoo.xmp.xpath +package com.ashampoo.xmp.internal /** * This objects contains all needed char positions to parse. diff --git a/src/commonMain/kotlin/com/ashampoo/xmp/internal/QName.kt b/src/commonMain/kotlin/com/ashampoo/xmp/internal/QName.kt new file mode 100644 index 0000000..8d51ac7 --- /dev/null +++ b/src/commonMain/kotlin/com/ashampoo/xmp/internal/QName.kt @@ -0,0 +1,44 @@ +// ================================================================================================= +// ADOBE SYSTEMS INCORPORATED +// Copyright 2006 Adobe Systems Incorporated +// All Rights Reserved +// +// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms +// of the Adobe license agreement accompanying it. +// ================================================================================================= +package com.ashampoo.xmp.internal + +internal data class QName( + /** XML namespace prefix */ + val prefix: String?, + /** XML localname */ + val localName: String +) { + + val hasPrefix: Boolean = + prefix != null && prefix.isNotEmpty() + + companion object { + + /** + * Splits a qname into prefix and localname. + * + * @param qname a QName + */ + fun parse(qname: String): QName { + + val colon = qname.indexOf(':') + + return if (colon >= 0) + QName( + prefix = qname.substring(0, colon), + localName = qname.substring(colon + 1) + ) + else + QName( + prefix = null, + localName = qname + ) + } + } +} diff --git a/src/commonMain/kotlin/com/ashampoo/xmp/Utils.kt b/src/commonMain/kotlin/com/ashampoo/xmp/internal/Utils.kt similarity index 99% rename from src/commonMain/kotlin/com/ashampoo/xmp/Utils.kt rename to src/commonMain/kotlin/com/ashampoo/xmp/internal/Utils.kt index 3204243..fcae8e8 100644 --- a/src/commonMain/kotlin/com/ashampoo/xmp/Utils.kt +++ b/src/commonMain/kotlin/com/ashampoo/xmp/internal/Utils.kt @@ -6,12 +6,14 @@ // NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms // of the Adobe license agreement accompanying it. // ================================================================================================= -package com.ashampoo.xmp +package com.ashampoo.xmp.internal + +import com.ashampoo.xmp.XMPConst /** * Utility functions for the XMPToolkit implementation. */ -object Utils { +internal object Utils { /** * segments of a UUID diff --git a/src/commonMain/kotlin/com/ashampoo/xmp/XMPError.kt b/src/commonMain/kotlin/com/ashampoo/xmp/internal/XMPErrorConst.kt similarity index 94% rename from src/commonMain/kotlin/com/ashampoo/xmp/XMPError.kt rename to src/commonMain/kotlin/com/ashampoo/xmp/internal/XMPErrorConst.kt index fcae525..f072367 100644 --- a/src/commonMain/kotlin/com/ashampoo/xmp/XMPError.kt +++ b/src/commonMain/kotlin/com/ashampoo/xmp/internal/XMPErrorConst.kt @@ -6,9 +6,9 @@ // NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms // of the Adobe license agreement accompanying it. // ================================================================================================= -package com.ashampoo.xmp +package com.ashampoo.xmp.internal -object XMPError { +internal object XMPErrorConst { const val EMPTY_ARRAY_NAME_TEXT: String = "Empty array name" const val EMPTY_SCHEMA_TEXT: String = "Empty schema namespace URI" diff --git a/src/commonMain/kotlin/com/ashampoo/xmp/XMPMetaParser.kt b/src/commonMain/kotlin/com/ashampoo/xmp/internal/XMPMetaParser.kt similarity index 97% rename from src/commonMain/kotlin/com/ashampoo/xmp/XMPMetaParser.kt rename to src/commonMain/kotlin/com/ashampoo/xmp/internal/XMPMetaParser.kt index eafef81..c800500 100644 --- a/src/commonMain/kotlin/com/ashampoo/xmp/XMPMetaParser.kt +++ b/src/commonMain/kotlin/com/ashampoo/xmp/internal/XMPMetaParser.kt @@ -6,9 +6,11 @@ // NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms // of the Adobe license agreement accompanying it. // ================================================================================================= -package com.ashampoo.xmp +package com.ashampoo.xmp.internal -import com.ashampoo.xmp.XMPNormalizer.normalize +import com.ashampoo.xmp.XMPConst +import com.ashampoo.xmp.XMPMeta +import com.ashampoo.xmp.internal.XMPNormalizer.normalize import com.ashampoo.xmp.options.ParseOptions import nl.adaptivity.xmlutil.dom.Element import nl.adaptivity.xmlutil.dom.Node diff --git a/src/commonMain/kotlin/com/ashampoo/xmp/XMPNode.kt b/src/commonMain/kotlin/com/ashampoo/xmp/internal/XMPNode.kt similarity index 96% rename from src/commonMain/kotlin/com/ashampoo/xmp/XMPNode.kt rename to src/commonMain/kotlin/com/ashampoo/xmp/internal/XMPNode.kt index e4fe0c1..70ebd95 100644 --- a/src/commonMain/kotlin/com/ashampoo/xmp/XMPNode.kt +++ b/src/commonMain/kotlin/com/ashampoo/xmp/internal/XMPNode.kt @@ -6,15 +6,16 @@ // NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms // of the Adobe license agreement accompanying it. // ================================================================================================= -package com.ashampoo.xmp +package com.ashampoo.xmp.internal +import com.ashampoo.xmp.XMPConst import com.ashampoo.xmp.options.PropertyOptions /** * A node in the internally XMP tree, which can be a schema node, a property node, an array node, * an array item, a struct node or a qualifier node (without '?'). */ -class XMPNode( +internal class XMPNode( /** * name of the node, contains different information depending of the node kind @@ -33,16 +34,16 @@ class XMPNode( ) : Comparable { - var parent: XMPNode? = null + internal var parent: XMPNode? = null private var children: MutableList? = null private var qualifier: MutableList? = null /* Internal processing options */ - var isImplicit = false - var hasAliases = false - var isAlias = false - var hasValueChild = false + var isImplicit: Boolean = false + var hasAliases: Boolean = false + var isAlias: Boolean = false + var hasValueChild: Boolean = false fun clear() { name = null diff --git a/src/commonMain/kotlin/com/ashampoo/xmp/XMPNodeUtils.kt b/src/commonMain/kotlin/com/ashampoo/xmp/internal/XMPNodeUtils.kt similarity index 95% rename from src/commonMain/kotlin/com/ashampoo/xmp/XMPNodeUtils.kt rename to src/commonMain/kotlin/com/ashampoo/xmp/internal/XMPNodeUtils.kt index 550ded9..b9aa76a 100644 --- a/src/commonMain/kotlin/com/ashampoo/xmp/XMPNodeUtils.kt +++ b/src/commonMain/kotlin/com/ashampoo/xmp/internal/XMPNodeUtils.kt @@ -6,21 +6,23 @@ // NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms // of the Adobe license agreement accompanying it. // ================================================================================================= -package com.ashampoo.xmp - -import com.ashampoo.xmp.Utils.normalizeLangValue -import com.ashampoo.xmp.Utils.replaceControlCharsWithSpace -import com.ashampoo.xmp.Utils.splitNameAndValue -import com.ashampoo.xmp.XMPUtils.encodeBase64 +package com.ashampoo.xmp.internal + +import com.ashampoo.xmp.XMPConst +import com.ashampoo.xmp.XMPException +import com.ashampoo.xmp.XMPSchemaRegistry +import com.ashampoo.xmp.internal.Utils.normalizeLangValue +import com.ashampoo.xmp.internal.Utils.replaceControlCharsWithSpace +import com.ashampoo.xmp.internal.Utils.splitNameAndValue +import com.ashampoo.xmp.internal.XMPUtils.encodeBase64 import com.ashampoo.xmp.options.AliasOptions import com.ashampoo.xmp.options.PropertyOptions -import com.ashampoo.xmp.xpath.XMPPath -import com.ashampoo.xmp.xpath.XMPPathSegment /** * Utilities for `XMPNode`. */ -object XMPNodeUtils { +@Suppress("TooManyFunctions") +internal object XMPNodeUtils { const val CLT_NO_VALUES = 0 @@ -78,7 +80,7 @@ object XMPNodeUtils { prefix = if (!suggestedPrefix.isNullOrEmpty()) XMPSchemaRegistry.registerNamespace(namespaceURI, suggestedPrefix) else - throw XMPException("Unregistered schema namespace URI", XMPError.BADSCHEMA) + throw XMPException("Unregistered schema namespace URI", XMPErrorConst.BADSCHEMA) } schemaNode.value = prefix @@ -100,11 +102,11 @@ object XMPNodeUtils { !parent.isImplicit -> throw XMPException( - "Named children only allowed for schemas and structs: $childName", XMPError.BADXPATH + "Named children only allowed for schemas and structs: $childName", XMPErrorConst.BADXPATH ) parent.options.isArray() -> - throw XMPException("Named children not allowed for arrays: $childName", XMPError.BADXPATH) + throw XMPException("Named children not allowed for arrays: $childName", XMPErrorConst.BADXPATH) createNodes -> parent.options.setStruct(true) @@ -146,7 +148,7 @@ object XMPNodeUtils { ): XMPNode? { if (xpath == null || xpath.size() == 0) - throw XMPException("Empty XMPPath", XMPError.BADXPATH) + throw XMPException("Empty XMPPath", XMPErrorConst.BADXPATH) // Root of implicitly created subtree to possible delete it later. // Valid only if leaf is new. @@ -284,7 +286,7 @@ object XMPNodeUtils { options.setArray(true) if (options.isCompositeProperty() && itemValue != null && itemValue.toString().isNotEmpty()) - throw XMPException("Structs and arrays can't have values", XMPError.BADOPTIONS) + throw XMPException("Structs and arrays can't have values", XMPErrorConst.BADOPTIONS) options.assertConsistency(options.getOptions()) @@ -344,7 +346,7 @@ object XMPNodeUtils { // This is an array indexing step. First get the index, then get the node. if (!parentNode.options.isArray()) - throw XMPException("Indexing applied to non-array", XMPError.BADXPATH) + throw XMPException("Indexing applied to non-array", XMPErrorConst.BADXPATH) val index = when (stepKind) { @@ -375,7 +377,7 @@ object XMPNodeUtils { else -> throw XMPException( "Unknown array indexing step in FollowXPathStep", - XMPError.INTERNALFAILURE + XMPErrorConst.INTERNALFAILURE ) } @@ -425,10 +427,10 @@ object XMPNodeUtils { index = innerSegment.toInt() if (index < 1) - throw XMPException("Array index must be larger than zero", XMPError.BADXPATH) + throw XMPException("Array index must be larger than zero", XMPErrorConst.BADXPATH) } catch (ex: NumberFormatException) { - throw XMPException("Array index not digits.", XMPError.BADXPATH, ex) + throw XMPException("Array index not digits.", XMPErrorConst.BADXPATH, ex) } if (createNodes && index == arrayNode.getChildrenLength() + 1) { @@ -464,7 +466,7 @@ object XMPNodeUtils { val currItem = arrayNode.getChild(index) if (!currItem.options.isStruct()) - throw XMPException("Field selector must be used on array of struct", XMPError.BADXPATH) + throw XMPException("Field selector must be used on array of struct", XMPErrorConst.BADXPATH) @Suppress("LoopWithTooManyJumpStatements") for (childIndex in 1..currItem.getChildrenLength()) { @@ -623,7 +625,7 @@ object XMPNodeUtils { // See if the array has the right form. Allow empty alt arrays, that is what parsing returns. if (!arrayNode.options.isArrayAltText()) - throw XMPException("Localized text array is not alt-text", XMPError.BADXPATH) + throw XMPException("Localized text array is not alt-text", XMPErrorConst.BADXPATH) else if (!arrayNode.hasChildren()) return arrayOf(CLT_NO_VALUES, null) @@ -640,9 +642,9 @@ object XMPNodeUtils { // perform some checks on the current item if (currItem.options.isCompositeProperty()) - throw XMPException("Alt-text array item is not simple", XMPError.BADXPATH) + throw XMPException("Alt-text array item is not simple", XMPErrorConst.BADXPATH) else if (!currItem.hasQualifier() || XMPConst.XML_LANG != currItem.getQualifier(1).name) - throw XMPException("Alt-text array item has no language qualifier", XMPError.BADXPATH) + throw XMPException("Alt-text array item has no language qualifier", XMPErrorConst.BADXPATH) val currLang = currItem.getQualifier(1).value @@ -690,7 +692,7 @@ object XMPNodeUtils { fun lookupLanguageItem(arrayNode: XMPNode?, language: String): Int { if (!arrayNode!!.options.isArray()) - throw XMPException("Language item must be used on array", XMPError.BADXPATH) + throw XMPException("Language item must be used on array", XMPErrorConst.BADXPATH) for (index in 1..arrayNode.getChildrenLength()) { diff --git a/src/commonMain/kotlin/com/ashampoo/xmp/XMPNormalizer.kt b/src/commonMain/kotlin/com/ashampoo/xmp/internal/XMPNormalizer.kt similarity index 97% rename from src/commonMain/kotlin/com/ashampoo/xmp/XMPNormalizer.kt rename to src/commonMain/kotlin/com/ashampoo/xmp/internal/XMPNormalizer.kt index 8c589d8..7b32df2 100644 --- a/src/commonMain/kotlin/com/ashampoo/xmp/XMPNormalizer.kt +++ b/src/commonMain/kotlin/com/ashampoo/xmp/internal/XMPNormalizer.kt @@ -6,19 +6,23 @@ // NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms // of the Adobe license agreement accompanying it. // ================================================================================================= -package com.ashampoo.xmp +package com.ashampoo.xmp.internal -import com.ashampoo.xmp.Utils.checkUUIDFormat +import com.ashampoo.xmp.XMPConst +import com.ashampoo.xmp.XMPException +import com.ashampoo.xmp.XMPMeta +import com.ashampoo.xmp.XMPSchemaRegistry +import com.ashampoo.xmp.internal.Utils.checkUUIDFormat import com.ashampoo.xmp.options.ParseOptions import com.ashampoo.xmp.options.PropertyOptions -import com.ashampoo.xmp.xpath.XMPPathParser.expandXPath +import com.ashampoo.xmp.internal.XMPPathParser.expandXPath internal object XMPNormalizer { /** * caches the correct dc-property array forms */ - private val dcArrayForms: Map = createDCArrays() + private val dcArrayForms = createDCArrays() /** * Normalizes a raw parsed XMPMeta-Object @@ -68,7 +72,7 @@ internal object XMPNormalizer { val idNode = XMPNodeUtils.findNode(tree, path, true, null) if (idNode == null) - throw XMPException("Failure creating xmpMM:InstanceID", XMPError.INTERNALFAILURE) + throw XMPException("Failure creating xmpMM:InstanceID", XMPErrorConst.INTERNALFAILURE) /* Clobber any existing xmpMM:InstanceID */ idNode.options = PropertyOptions() @@ -366,7 +370,7 @@ internal object XMPNormalizer { // *** Allow x-default. if (childNode.options.hasLanguage()) - throw XMPException("Alias to x-default already has a language qualifier", XMPError.BADXMP) + throw XMPException("Alias to x-default already has a language qualifier", XMPErrorConst.BADXMP) val langQual = XMPNode(XMPConst.XML_LANG, XMPConst.X_DEFAULT) @@ -417,7 +421,7 @@ internal object XMPNormalizer { ) { if (aliasNode.value != baseNode.value || aliasNode.getChildrenLength() != baseNode.getChildrenLength()) - throw XMPException("Mismatch between alias and base nodes", XMPError.BADXMP) + throw XMPException("Mismatch between alias and base nodes", XMPErrorConst.BADXMP) if (!outerCall && ( @@ -426,7 +430,7 @@ internal object XMPNormalizer { aliasNode.getQualifierLength() != baseNode.getQualifierLength() ) ) - throw XMPException("Mismatch between alias and base nodes", XMPError.BADXMP) + throw XMPException("Mismatch between alias and base nodes", XMPErrorConst.BADXMP) run { val an = aliasNode.iterateChildren() diff --git a/src/commonMain/kotlin/com/ashampoo/xmp/xpath/XMPPath.kt b/src/commonMain/kotlin/com/ashampoo/xmp/internal/XMPPath.kt similarity index 97% rename from src/commonMain/kotlin/com/ashampoo/xmp/xpath/XMPPath.kt rename to src/commonMain/kotlin/com/ashampoo/xmp/internal/XMPPath.kt index 95a4027..3ceeba8 100644 --- a/src/commonMain/kotlin/com/ashampoo/xmp/xpath/XMPPath.kt +++ b/src/commonMain/kotlin/com/ashampoo/xmp/internal/XMPPath.kt @@ -6,12 +6,12 @@ // NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms // of the Adobe license agreement accompanying it. // ================================================================================================= -package com.ashampoo.xmp.xpath +package com.ashampoo.xmp.internal /** * Representates an XMP XMPPath with segment accessor methods. */ -class XMPPath { +internal class XMPPath { private val segments = mutableListOf() diff --git a/src/commonMain/kotlin/com/ashampoo/xmp/xpath/XMPPathParser.kt b/src/commonMain/kotlin/com/ashampoo/xmp/internal/XMPPathParser.kt similarity index 94% rename from src/commonMain/kotlin/com/ashampoo/xmp/xpath/XMPPathParser.kt rename to src/commonMain/kotlin/com/ashampoo/xmp/internal/XMPPathParser.kt index 54aff91..36d5eb9 100644 --- a/src/commonMain/kotlin/com/ashampoo/xmp/xpath/XMPPathParser.kt +++ b/src/commonMain/kotlin/com/ashampoo/xmp/internal/XMPPathParser.kt @@ -6,17 +6,15 @@ // NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms // of the Adobe license agreement accompanying it. // ================================================================================================= -package com.ashampoo.xmp.xpath +package com.ashampoo.xmp.internal -import com.ashampoo.xmp.Utils -import com.ashampoo.xmp.XMPError import com.ashampoo.xmp.XMPException import com.ashampoo.xmp.XMPMetaFactory.schemaRegistry /** * Parser for XMP XPaths. */ -object XMPPathParser { +internal object XMPPathParser { /** * Split an XMPPath expression apart at the conceptual steps, adding the @@ -42,7 +40,7 @@ object XMPPathParser { fun expandXPath(schemaNS: String?, path: String?): XMPPath { if (schemaNS == null || path == null) - throw XMPException("Parameter must not be null", XMPError.BADPARAM) + throw XMPException("Parameter must not be null", XMPErrorConst.BADPARAM) val expandedXPath = XMPPath() @@ -85,7 +83,7 @@ object XMPPathParser { segment.name = "?" + segment.name!!.substring(1) if ("?xml:lang" != segment.name) - throw XMPException("Only xml:lang allowed with '@'", XMPError.BADXPATH) + throw XMPException("Only xml:lang allowed with '@'", XMPErrorConst.BADXPATH) } if (segment.name!![0] == '?') { @@ -104,7 +102,7 @@ object XMPPathParser { segment.name = "[?" + segment.name!!.substring(2) if (!segment.name!!.startsWith("[?xml:lang=")) - throw XMPException("Only xml:lang allowed with '@'", XMPError.BADXPATH) + throw XMPException("Only xml:lang allowed with '@'", XMPErrorConst.BADXPATH) } if (segment.name!![1] == '?') { @@ -131,7 +129,7 @@ object XMPPathParser { pos.stepBegin++ if (pos.stepBegin >= path.length) - throw XMPException("Empty XMPPath segment", XMPError.BADXPATH) + throw XMPException("Empty XMPPath segment", XMPErrorConst.BADXPATH) } if (path[pos.stepBegin] == '*') { @@ -140,7 +138,7 @@ object XMPPathParser { pos.stepBegin++ if (pos.stepBegin >= path.length || path[pos.stepBegin] != '[') - throw XMPException("Missing '[' after '*'", XMPError.BADXPATH) + throw XMPException("Missing '[' after '*'", XMPErrorConst.BADXPATH) } } @@ -154,7 +152,7 @@ object XMPPathParser { pos.nameEnd = pos.stepEnd if (pos.stepEnd == pos.stepBegin) - throw XMPException("Empty XMPPath segment", XMPError.BADXPATH) + throw XMPException("Empty XMPPath segment", XMPErrorConst.BADXPATH) return XMPPathSegment( pos.path!!.substring(pos.stepBegin, pos.stepEnd), @@ -193,12 +191,12 @@ object XMPPathParser { pos.stepEnd++ if (pos.stepEnd >= pos.path!!.length) - throw XMPException("Missing ']' or '=' for array index", XMPError.BADXPATH) + throw XMPException("Missing ']' or '=' for array index", XMPErrorConst.BADXPATH) if (pos.path!![pos.stepEnd] == ']') { if ("[last()" != pos.path!!.substring(pos.stepBegin, pos.stepEnd)) - throw XMPException("Invalid non-numeric array index", XMPError.BADXPATH) + throw XMPException("Invalid non-numeric array index", XMPErrorConst.BADXPATH) segment = XMPPathSegment(null, XMPPath.ARRAY_LAST_STEP) @@ -213,7 +211,7 @@ object XMPPathParser { val quote = pos.path!![pos.stepEnd] if (quote != '\'' && quote != '"') - throw XMPException("Invalid quote in array selector", XMPError.BADXPATH) + throw XMPException("Invalid quote in array selector", XMPErrorConst.BADXPATH) /* Absorb the leading quote */ pos.stepEnd++ @@ -233,7 +231,7 @@ object XMPPathParser { } if (pos.stepEnd >= pos.path!!.length) - throw XMPException("No terminating quote for array selector", XMPError.BADXPATH) + throw XMPException("No terminating quote for array selector", XMPErrorConst.BADXPATH) /* Absorb the trailing quote. */ pos.stepEnd++ @@ -244,7 +242,7 @@ object XMPPathParser { } if (pos.stepEnd >= pos.path!!.length || pos.path!![pos.stepEnd] != ']') - throw XMPException("Missing ']' for array index", XMPError.BADXPATH) + throw XMPException("Missing ']' for array index", XMPErrorConst.BADXPATH) pos.stepEnd++ @@ -263,7 +261,7 @@ object XMPPathParser { pos.stepEnd++ if (pos.stepEnd == pos.stepBegin) - throw XMPException("Empty initial XMPPath step", XMPError.BADXPATH) + throw XMPException("Empty initial XMPPath step", XMPErrorConst.BADXPATH) val rootProp = verifyXPathRoot(schemaNS, pos.path!!.substring(pos.stepBegin, pos.stepEnd)) val aliasInfo = schemaRegistry.findAlias(rootProp) @@ -333,11 +331,11 @@ object XMPPathParser { if (regURI != null) return - throw XMPException("Unknown namespace prefix for qualified name", XMPError.BADXPATH) + throw XMPException("Unknown namespace prefix for qualified name", XMPErrorConst.BADXPATH) } } - throw XMPException("Ill-formed qualified name: $qualName", XMPError.BADXPATH) + throw XMPException("Ill-formed qualified name: $qualName", XMPErrorConst.BADXPATH) } /** @@ -346,7 +344,7 @@ object XMPPathParser { private fun verifySimpleXMLName(name: String) { if (!Utils.isXMLName(name)) - throw XMPException("Bad XML name", XMPError.BADXPATH) + throw XMPException("Bad XML name", XMPErrorConst.BADXPATH) } /** @@ -360,19 +358,19 @@ object XMPPathParser { /* Do some basic checks on the URI and name. Try to look up the URI. See if the name is qualified. */ if (schemaNS.isNullOrEmpty()) - throw XMPException("Schema namespace URI is required", XMPError.BADSCHEMA) + throw XMPException("Schema namespace URI is required", XMPErrorConst.BADSCHEMA) if (rootProp[0] == '?' || rootProp[0] == '@') throw XMPException( "Top level name must not be a qualifier, but was '$rootProp'", - XMPError.BADXPATH + XMPErrorConst.BADXPATH ) if (rootProp.indexOf('/') >= 0 || rootProp.indexOf('[') >= 0) - throw XMPException("Top level name must be simple, but was '$rootProp'", XMPError.BADXPATH) + throw XMPException("Top level name must be simple, but was '$rootProp'", XMPErrorConst.BADXPATH) var prefix = schemaRegistry.getNamespacePrefix(schemaNS) - ?: throw XMPException("Unregistered schema namespace URI: $schemaNS", XMPError.BADSCHEMA) + ?: throw XMPException("Unregistered schema namespace URI: $schemaNS", XMPErrorConst.BADSCHEMA) /* Verify the various URI and prefix combinations. Initialize the expanded XMPPath. */ val colonPos = rootProp.indexOf(':') @@ -400,10 +398,10 @@ object XMPPathParser { prefix = rootProp.substring(0, colonPos + 1) val regPrefix = schemaRegistry.getNamespacePrefix(schemaNS) - ?: throw XMPException("Unknown schema namespace prefix", XMPError.BADSCHEMA) + ?: throw XMPException("Unknown schema namespace prefix", XMPErrorConst.BADSCHEMA) if (prefix != regPrefix) - throw XMPException("Schema namespace URI and prefix mismatch", XMPError.BADSCHEMA) + throw XMPException("Schema namespace URI and prefix mismatch", XMPErrorConst.BADSCHEMA) rootProp } diff --git a/src/commonMain/kotlin/com/ashampoo/xmp/xpath/XMPPathSegment.kt b/src/commonMain/kotlin/com/ashampoo/xmp/internal/XMPPathSegment.kt similarity index 94% rename from src/commonMain/kotlin/com/ashampoo/xmp/xpath/XMPPathSegment.kt rename to src/commonMain/kotlin/com/ashampoo/xmp/internal/XMPPathSegment.kt index e86343a..7a427f5 100644 --- a/src/commonMain/kotlin/com/ashampoo/xmp/xpath/XMPPathSegment.kt +++ b/src/commonMain/kotlin/com/ashampoo/xmp/internal/XMPPathSegment.kt @@ -6,12 +6,12 @@ // NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms // of the Adobe license agreement accompanying it. // ================================================================================================= -package com.ashampoo.xmp.xpath +package com.ashampoo.xmp.internal /** * A segment of a parsed `XMPPath`. */ -class XMPPathSegment { +internal class XMPPathSegment { /** * name of the path segment diff --git a/src/commonMain/kotlin/com/ashampoo/xmp/XMPRDFParser.kt b/src/commonMain/kotlin/com/ashampoo/xmp/internal/XMPRDFParser.kt similarity index 94% rename from src/commonMain/kotlin/com/ashampoo/xmp/XMPRDFParser.kt rename to src/commonMain/kotlin/com/ashampoo/xmp/internal/XMPRDFParser.kt index 993fdfc..c5248fa 100644 --- a/src/commonMain/kotlin/com/ashampoo/xmp/XMPRDFParser.kt +++ b/src/commonMain/kotlin/com/ashampoo/xmp/internal/XMPRDFParser.kt @@ -6,14 +6,19 @@ // NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms // of the Adobe license agreement accompanying it. // ================================================================================================= -package com.ashampoo.xmp +package com.ashampoo.xmp.internal +import com.ashampoo.xmp.XMPConst +import com.ashampoo.xmp.XMPException +import com.ashampoo.xmp.XMPMeta +import com.ashampoo.xmp.XMPSchemaRegistry import com.ashampoo.xmp.options.ParseOptions import com.ashampoo.xmp.options.PropertyOptions import nl.adaptivity.xmlutil.dom.Attr import nl.adaptivity.xmlutil.dom.Element import nl.adaptivity.xmlutil.dom.Node import nl.adaptivity.xmlutil.dom.NodeConsts +import nl.adaptivity.xmlutil.dom.ProcessingInstruction import nl.adaptivity.xmlutil.dom.Text import nl.adaptivity.xmlutil.dom.attributes import nl.adaptivity.xmlutil.dom.childNodes @@ -97,6 +102,8 @@ internal object XMPRDFParser { */ const val DEFAULT_PREFIX = "_dflt" + const val XMLNS = "xmlns" + /** * The main parsing method. The XML tree is walked through from the root node and and XMP tree * is created. This is a raw parse, the normalisation of the XMP tree happens outside. @@ -121,15 +128,15 @@ internal object XMPRDFParser { fun parseRdfRoot(xmp: XMPMeta, rdfRdfNode: Node, options: ParseOptions) { if (rdfRdfNode.nodeName != "rdf:RDF") - throw XMPException("Root node should be of type rdf:RDF", XMPError.BADRDF) + throw XMPException("Root node should be of type rdf:RDF", XMPErrorConst.BADRDF) if (rdfRdfNode.nodeType != NodeConsts.ELEMENT_NODE) - throw XMPException("Root node must be of element type.", XMPError.BADRDF) + throw XMPException("Root node must be of element type.", XMPErrorConst.BADRDF) rdfRdfNode as Element if (rdfRdfNode.attributes.length == 0) - throw XMPException("Illegal: rdf:RDF node has no attributes", XMPError.BADRDF) + throw XMPException("Illegal: rdf:RDF node has no attributes", XMPErrorConst.BADRDF) for (index in 0 until rdfRdfNode.childNodes.length) { @@ -167,10 +174,10 @@ internal object XMPRDFParser { val nodeTerm = getRDFTermKind(xmlNode) if (nodeTerm != RDFTERM_DESCRIPTION && nodeTerm != RDFTERM_OTHER) - throw XMPException("Node element must be rdf:Description or typed node", XMPError.BADRDF) + throw XMPException("Node element must be rdf:Description or typed node", XMPErrorConst.BADRDF) if (isTopLevel && nodeTerm == RDFTERM_OTHER) - throw XMPException("Top level typed node not allowed", XMPError.BADXMP) + throw XMPException("Top level typed node not allowed", XMPErrorConst.BADXMP) parseRdfNodeElementAttrs(xmp, xmpParent, xmlNode, isTopLevel) parseRdfPropertyElementList(xmp, xmpParent, xmlNode, isTopLevel, options) @@ -206,7 +213,7 @@ internal object XMPRDFParser { // quick hack, ns declarations do not appear in C++ // ignore "ID" without namespace - if ("xmlns" == attribute.prefix || attribute.prefix == null && "xmlns" == attribute.nodeName) + if (XMLNS == attribute.prefix || attribute.prefix == null && XMLNS == attribute.nodeName) continue val attrTerm = getRDFTermKind(attribute) @@ -216,7 +223,7 @@ internal object XMPRDFParser { RDFTERM_ID, RDFTERM_NODE_ID, RDFTERM_ABOUT -> { if (exclusiveAttrs > 0) - throw XMPException("Mutally exclusive about, ID, nodeID attributes", XMPError.BADRDF) + throw XMPException("Mutally exclusive about, ID, nodeID attributes", XMPErrorConst.BADRDF) exclusiveAttrs++ @@ -229,7 +236,7 @@ internal object XMPRDFParser { if (xmpParent.name != null && xmpParent.name!!.isNotEmpty()) { if (xmpParent.name != attribute.value) - throw XMPException("Mismatched top level rdf:about values", XMPError.BADXMP) + throw XMPException("Mismatched top level rdf:about values", XMPErrorConst.BADXMP) } else { xmpParent.name = attribute.value @@ -240,7 +247,7 @@ internal object XMPRDFParser { RDFTERM_OTHER -> addChildNode(xmp, xmpParent, attribute, attribute.value, isTopLevel) - else -> throw XMPException("Invalid nodeElement attribute", XMPError.BADRDF) + else -> throw XMPException("Invalid nodeElement attribute", XMPErrorConst.BADRDF) } } } @@ -272,7 +279,7 @@ internal object XMPRDFParser { continue if (currChild.nodeType != NodeConsts.ELEMENT_NODE) - throw XMPException("Expected property element node not found", XMPError.BADRDF) + throw XMPException("Expected property element node not found", XMPErrorConst.BADRDF) parseRdfPropertyElement(xmp, xmpParent, currChild as Element, isTopLevel, options) } @@ -343,7 +350,7 @@ internal object XMPRDFParser { val nodeTerm = getRDFTermKind(xmlNode) if (!isPropertyElementName(nodeTerm)) - throw XMPException("Invalid property element name", XMPError.BADRDF) + throw XMPException("Invalid property element name", XMPErrorConst.BADRDF) // remove the namespace-definitions from the list val attributes = xmlNode.attributes @@ -354,7 +361,7 @@ internal object XMPRDFParser { val attribute = attributes.item(index) as Attr - if ("xmlns" == attribute.prefix || attribute.prefix == null && "xmlns" == attribute.nodeName) { + if (XMLNS == attribute.prefix || attribute.prefix == null && XMLNS == attribute.nodeName) { if (nsAttrs == null) nsAttrs = mutableListOf() @@ -401,16 +408,16 @@ internal object XMPRDFParser { parseEmptyPropertyElement(xmp, xmpParent, xmlNode, isTopLevel) "Literal" == attrValue -> - throw XMPException("Literal property element not allowed", XMPError.BADXMP) + throw XMPException("Literal property element not allowed", XMPErrorConst.BADXMP) "Resource" == attrValue -> parseTypeResourcePropertyElement(xmp, xmpParent, xmlNode, isTopLevel, options) "Collection" == attrValue -> - throw XMPException("Collection property element forbidden", XMPError.BADXMP) + throw XMPException("Collection property element forbidden", XMPErrorConst.BADXMP) else -> - throw XMPException("Other property element not allowed", XMPError.BADXMP) + throw XMPException("Other property element not allowed", XMPErrorConst.BADXMP) } return @@ -472,7 +479,7 @@ internal object XMPRDFParser { val attribute = xmlNode.attributes.item(index) as Attr - if ("xmlns" == attribute.prefix || attribute.prefix == null && "xmlns" == attribute.nodeName) + if (XMLNS == attribute.prefix || attribute.prefix == null && XMLNS == attribute.nodeName) continue if (XMPConst.XML_LANG == attribute.nodeName) @@ -480,7 +487,7 @@ internal object XMPRDFParser { else if ("ID" == attribute.localName && XMPConst.NS_RDF == attribute.namespaceURI) continue else - throw XMPException("Invalid attribute for resource property element", XMPError.BADRDF) + throw XMPException("Invalid attribute for resource property element", XMPErrorConst.BADRDF) } // walk through the children @@ -519,7 +526,7 @@ internal object XMPRDFParser { var typeName = currentChild.namespaceURI ?: throw XMPException( - "All XML elements must be in a namespace", XMPError.BADXMP + "All XML elements must be in a namespace", XMPErrorConst.BADXMP ) typeName += ":$localName" @@ -540,17 +547,17 @@ internal object XMPRDFParser { } else if (found) { // found second child element - throw XMPException("Invalid child of resource property element", XMPError.BADRDF) + throw XMPException("Invalid child of resource property element", XMPErrorConst.BADRDF) } else { throw XMPException( - "Children of resource property element must be XML elements", XMPError.BADRDF + "Children of resource property element must be XML elements", XMPErrorConst.BADRDF ) } } } if (!found) - throw XMPException("Missing child of resource property element", XMPError.BADRDF) + throw XMPException("Missing child of resource property element", XMPErrorConst.BADRDF) } /** @@ -576,7 +583,7 @@ internal object XMPRDFParser { val attribute = xmlNode.attributes.item(index) as Attr - if ("xmlns" == attribute.prefix || attribute.prefix == null && "xmlns" == attribute.nodeName) + if (XMLNS == attribute.prefix || attribute.prefix == null && XMLNS == attribute.nodeName) continue if (XMPConst.XML_LANG == attribute.nodeName) @@ -587,7 +594,7 @@ internal object XMPRDFParser { ) continue else - throw XMPException("Invalid attribute for literal property element", XMPError.BADRDF) + throw XMPException("Invalid attribute for literal property element", XMPErrorConst.BADRDF) } var textValue = "" @@ -597,7 +604,7 @@ internal object XMPRDFParser { val child = xmlNode.childNodes.item(index) if (child?.nodeType != NodeConsts.TEXT_NODE) - throw XMPException("Invalid child of literal property element", XMPError.BADRDF) + throw XMPException("Invalid child of literal property element", XMPErrorConst.BADRDF) child as Text @@ -634,7 +641,7 @@ internal object XMPRDFParser { val attribute = xmlNode.attributes.item(index) as Attr - if ("xmlns" == attribute.prefix || attribute.prefix == null && "xmlns" == attribute.nodeName) + if (XMLNS == attribute.prefix || attribute.prefix == null && XMLNS == attribute.nodeName) continue if (XMPConst.XML_LANG == attribute.nodeName) { @@ -646,7 +653,7 @@ internal object XMPRDFParser { continue // The caller ensured the value is "Resource". Ignore all rdf:ID attributes. } else { throw XMPException( - "Invalid attribute for ParseTypeResource property element", XMPError.BADRDF + "Invalid attribute for ParseTypeResource property element", XMPErrorConst.BADRDF ) } } @@ -703,7 +710,7 @@ internal object XMPRDFParser { if (xmlNode.childNodes.length > 0) throw XMPException( - "Nested content not allowed with rdf:resource or property attributes", XMPError.BADRDF + "Nested content not allowed with rdf:resource or property attributes", XMPErrorConst.BADRDF ) /* First figure out what XMP this maps to and remember the XML node for a simple value. */ @@ -711,7 +718,7 @@ internal object XMPRDFParser { val attribute = xmlNode.attributes.item(index) as Attr - if ("xmlns" == attribute.prefix || attribute.prefix == null && "xmlns" == attribute.nodeName) + if (XMLNS == attribute.prefix || attribute.prefix == null && XMLNS == attribute.nodeName) continue val attrTerm = getRDFTermKind(attribute) @@ -733,12 +740,12 @@ internal object XMPRDFParser { if (hasNodeIDAttr) { throw XMPException( "Empty property element can't have both rdf:resource and rdf:nodeID", - XMPError.BADRDF + XMPErrorConst.BADRDF ) } else if (hasValueAttr) { throw XMPException( "Empty property element can't have both rdf:value and rdf:resource", - XMPError.BADXMP + XMPErrorConst.BADXMP ) } @@ -753,7 +760,7 @@ internal object XMPRDFParser { if (hasResourceAttr) { throw XMPException( "Empty property element can't have both rdf:resource and rdf:nodeID", - XMPError.BADRDF + XMPErrorConst.BADRDF ) } @@ -767,7 +774,7 @@ internal object XMPRDFParser { if (hasResourceAttr) { throw XMPException( "Empty property element can't have both rdf:value and rdf:resource", - XMPError.BADXMP + XMPErrorConst.BADXMP ) } @@ -784,7 +791,7 @@ internal object XMPRDFParser { else -> throw XMPException( "Unrecognized attribute of empty property element: $attrTerm", - XMPError.BADRDF + XMPErrorConst.BADRDF ) } } @@ -803,7 +810,7 @@ internal object XMPRDFParser { val valueNodeValue = when { valueNode == null -> null valueNode.nodeType == NodeConsts.ATTRIBUTE_NODE -> (valueNode as Attr).value - else -> throw XMPException("Unknown node type ${xmlNode.nodeType}", XMPError.BADXMP) + else -> throw XMPException("Unknown node type ${xmlNode.nodeType}", XMPErrorConst.BADXMP) } childNode.value = valueNodeValue ?: "" @@ -822,8 +829,8 @@ internal object XMPRDFParser { val attribute = xmlNode.attributes.item(index) as Attr if ( - attribute === valueNode || "xmlns" == attribute.prefix || - attribute.prefix == null && "xmlns" == attribute.nodeName + attribute === valueNode || XMLNS == attribute.prefix || + attribute.prefix == null && XMLNS == attribute.nodeName ) continue // Skip the rdf:value or rdf:resource attribute holding the value. @@ -854,7 +861,7 @@ internal object XMPRDFParser { else -> throw XMPException( "Unrecognized attribute of empty property element: $attrTerm", - XMPError.BADRDF + XMPErrorConst.BADRDF ) } } @@ -872,13 +879,13 @@ internal object XMPRDFParser { var namespace = when { xmlNode.nodeType == NodeConsts.ELEMENT_NODE -> (xmlNode as Element).namespaceURI xmlNode.nodeType == NodeConsts.ATTRIBUTE_NODE -> (xmlNode as Attr).namespaceURI - else -> throw XMPException("Unknown node type ${xmlNode.nodeType}", XMPError.BADXMP) + else -> throw XMPException("Unknown node type ${xmlNode.nodeType}", XMPErrorConst.BADXMP) } if (namespace.isNullOrEmpty()) throw XMPException( "XML namespace required for all elements and attributes: $xmlNode", - XMPError.BADRDF + XMPErrorConst.BADRDF ) /* Fix a legacy DC namespace */ @@ -892,7 +899,7 @@ internal object XMPRDFParser { val xmlNodePrefix = when { xmlNode.nodeType == NodeConsts.ELEMENT_NODE -> (xmlNode as Element).prefix xmlNode.nodeType == NodeConsts.ATTRIBUTE_NODE -> (xmlNode as Attr).prefix - else -> throw XMPException("Unknown node type ${xmlNode.nodeType}", XMPError.BADXMP) + else -> throw XMPException("Unknown node type ${xmlNode.nodeType}", XMPErrorConst.BADXMP) } prefix = if (xmlNodePrefix != null) @@ -906,7 +913,7 @@ internal object XMPRDFParser { val xmlNodeLocalName = when { xmlNode.nodeType == NodeConsts.ELEMENT_NODE -> (xmlNode as Element).localName xmlNode.nodeType == NodeConsts.ATTRIBUTE_NODE -> (xmlNode as Attr).localName - else -> throw XMPException("Unknown node type ${xmlNode.nodeType}", XMPError.BADXMP) + else -> throw XMPException("Unknown node type ${xmlNode.nodeType}", XMPErrorConst.BADXMP) } val childName = prefix + xmlNodeLocalName @@ -962,7 +969,7 @@ internal object XMPRDFParser { if (isValueNode) { if (isTopLevel || !actualXmpParent.options.isStruct()) - throw XMPException("Misplaced rdf:value element", XMPError.BADRDF) + throw XMPException("Misplaced rdf:value element", XMPErrorConst.BADRDF) actualXmpParent.hasValueChild = true } @@ -975,10 +982,10 @@ internal object XMPRDFParser { newChild.name = XMPConst.ARRAY_ITEM_NAME !isParentArray && isArrayItem -> - throw XMPException("Misplaced rdf:li element", XMPError.BADRDF) + throw XMPException("Misplaced rdf:li element", XMPErrorConst.BADRDF) isParentArray && !isArrayItem -> - throw XMPException("Arrays cannot have arbitrary child names", XMPError.BADRDF) + throw XMPException("Arrays cannot have arbitrary child names", XMPErrorConst.BADRDF) } return newChild @@ -1025,7 +1032,7 @@ internal object XMPRDFParser { if (valueNode.options.hasLanguage()) { if (xmpParent.options.hasLanguage()) - throw XMPException("Redundant xml:lang for rdf:value element", XMPError.BADXMP) + throw XMPException("Redundant xml:lang for rdf:value element", XMPErrorConst.BADXMP) val langQual = valueNode.getQualifier(1) @@ -1130,7 +1137,7 @@ internal object XMPRDFParser { val namespace = when { node.nodeType == NodeConsts.ELEMENT_NODE -> (node as Element).namespaceURI node.nodeType == NodeConsts.ATTRIBUTE_NODE -> (node as Attr).namespaceURI - else -> throw XMPException("Unknown Node ${node.nodeType}", XMPError.BADXMP) + else -> throw XMPException("Unknown Node ${node.nodeType}", XMPErrorConst.BADXMP) } /* diff --git a/src/commonMain/kotlin/com/ashampoo/xmp/XMPRDFWriter.kt b/src/commonMain/kotlin/com/ashampoo/xmp/internal/XMPRDFWriter.kt similarity index 98% rename from src/commonMain/kotlin/com/ashampoo/xmp/XMPRDFWriter.kt rename to src/commonMain/kotlin/com/ashampoo/xmp/internal/XMPRDFWriter.kt index deb1e79..81cc9a8 100644 --- a/src/commonMain/kotlin/com/ashampoo/xmp/XMPRDFWriter.kt +++ b/src/commonMain/kotlin/com/ashampoo/xmp/internal/XMPRDFWriter.kt @@ -6,9 +6,14 @@ // NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms // of the Adobe license agreement accompanying it. // ================================================================================================= -package com.ashampoo.xmp - -import com.ashampoo.xmp.Utils.escapeXML +package com.ashampoo.xmp.internal + +import com.ashampoo.xmp.XMPConst +import com.ashampoo.xmp.XMPException +import com.ashampoo.xmp.XMPMeta +import com.ashampoo.xmp.XMPSchemaRegistry +import com.ashampoo.xmp.XMPVersionInfo +import com.ashampoo.xmp.internal.Utils.escapeXML import com.ashampoo.xmp.options.SerializeOptions /** @@ -73,7 +78,7 @@ internal object XMPRDFWriter { return sb.toString() } catch (ex: Exception) { - throw XMPException("Error writing the XMP", XMPError.UNKNOWN, ex) + throw XMPException("Error writing the XMP", XMPErrorConst.UNKNOWN, ex) } } @@ -467,7 +472,7 @@ internal object XMPRDFWriter { } if (hasRDFResourceQual && hasElemFields) - throw XMPException("Can't mix rdf:resource qualifier and element fields", XMPError.BADRDF) + throw XMPException("Can't mix rdf:resource qualifier and element fields", XMPErrorConst.BADRDF) when { @@ -634,9 +639,9 @@ internal object XMPRDFWriter { if (actualNamespace == null) { // prefix contains qname, extract prefix and lookup namespace with prefix - val qname = QName(actualPrefix) + val qname = QName.parse(actualPrefix) - if (!qname.hasPrefix()) + if (!qname.hasPrefix) return actualPrefix = qname.prefix!! @@ -773,7 +778,7 @@ internal object XMPRDFWriter { // ! The value is output by a recursive call ON THE SAME NODE with // emitAsRDFValue set. if (hasRDFResourceQual) - throw XMPException("Can't mix rdf:resource and general qualifiers", XMPError.BADRDF) + throw XMPException("Can't mix rdf:resource and general qualifiers", XMPErrorConst.BADRDF) // Change serialization to canonical format with inner rdf:Description-tag // depending on option @@ -943,7 +948,7 @@ internal object XMPRDFWriter { for (child in node.getChildren()) { if (!canBeRDFAttrProp(child)) - throw XMPException("Can't mix rdf:resource and complex fields", XMPError.BADRDF) + throw XMPException("Can't mix rdf:resource and complex fields", XMPErrorConst.BADRDF) sb.append(XMP_DEFAULT_NEWLINE) writeIndent(sb, actualIndent + 1) diff --git a/src/commonMain/kotlin/com/ashampoo/xmp/XMPUtils.kt b/src/commonMain/kotlin/com/ashampoo/xmp/internal/XMPUtils.kt similarity index 83% rename from src/commonMain/kotlin/com/ashampoo/xmp/XMPUtils.kt rename to src/commonMain/kotlin/com/ashampoo/xmp/internal/XMPUtils.kt index 4c4897d..ed2e394 100644 --- a/src/commonMain/kotlin/com/ashampoo/xmp/XMPUtils.kt +++ b/src/commonMain/kotlin/com/ashampoo/xmp/internal/XMPUtils.kt @@ -6,8 +6,9 @@ // NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms // of the Adobe license agreement accompanying it. // ================================================================================================= -package com.ashampoo.xmp +package com.ashampoo.xmp.internal +import com.ashampoo.xmp.XMPException import kotlin.io.encoding.Base64 import kotlin.io.encoding.ExperimentalEncodingApi @@ -15,7 +16,7 @@ import kotlin.io.encoding.ExperimentalEncodingApi * Utility methods for XMP. I included only those that are different from the * Java default conversion utilities. */ -object XMPUtils { +internal object XMPUtils { /** * Convert from string to Boolean. @@ -33,7 +34,7 @@ object XMPUtils { fun convertToBoolean(value: String?): Boolean { if (value.isNullOrEmpty()) - throw XMPException(XMPError.EMPTY_CONVERT_STRING_TEXT, XMPError.BADVALUE) + throw XMPException(XMPErrorConst.EMPTY_CONVERT_STRING_TEXT, XMPErrorConst.BADVALUE) val valueLowercase = value.lowercase() @@ -55,7 +56,7 @@ object XMPUtils { try { if (rawValue.isNullOrEmpty()) - throw XMPException(XMPError.EMPTY_CONVERT_STRING_TEXT, XMPError.BADVALUE) + throw XMPException(XMPErrorConst.EMPTY_CONVERT_STRING_TEXT, XMPErrorConst.BADVALUE) return if (rawValue.startsWith("0x")) rawValue.substring(2).toInt(16) @@ -63,7 +64,7 @@ object XMPUtils { rawValue.toInt() } catch (ex: NumberFormatException) { - throw XMPException("Invalid integer string", XMPError.BADVALUE, ex) + throw XMPException("Invalid integer string", XMPErrorConst.BADVALUE, ex) } } @@ -73,7 +74,7 @@ object XMPUtils { try { if (rawValue.isNullOrEmpty()) - throw XMPException(XMPError.EMPTY_CONVERT_STRING_TEXT, XMPError.BADVALUE) + throw XMPException(XMPErrorConst.EMPTY_CONVERT_STRING_TEXT, XMPErrorConst.BADVALUE) return if (rawValue.startsWith("0x")) rawValue.substring(2).toLong(16) @@ -81,7 +82,7 @@ object XMPUtils { rawValue.toLong() } catch (ex: NumberFormatException) { - throw XMPException("Invalid long string", XMPError.BADVALUE, ex) + throw XMPException("Invalid long string", XMPErrorConst.BADVALUE, ex) } } @@ -91,12 +92,12 @@ object XMPUtils { try { if (rawValue.isNullOrEmpty()) - throw XMPException(XMPError.EMPTY_CONVERT_STRING_TEXT, XMPError.BADVALUE) + throw XMPException(XMPErrorConst.EMPTY_CONVERT_STRING_TEXT, XMPErrorConst.BADVALUE) return rawValue.toDouble() } catch (ex: NumberFormatException) { - throw XMPException("Invalid double string", XMPError.BADVALUE, ex) + throw XMPException("Invalid double string", XMPErrorConst.BADVALUE, ex) } } @@ -114,7 +115,7 @@ object XMPUtils { return Base64.decode(base64String.encodeToByteArray()) } catch (ex: Throwable) { - throw XMPException("Invalid base64 string", XMPError.BADVALUE, ex) + throw XMPException("Invalid base64 string", XMPErrorConst.BADVALUE, ex) } } } diff --git a/src/commonMain/kotlin/com/ashampoo/xmp/options/AliasOptions.kt b/src/commonMain/kotlin/com/ashampoo/xmp/options/AliasOptions.kt index 17f6cb4..809783f 100644 --- a/src/commonMain/kotlin/com/ashampoo/xmp/options/AliasOptions.kt +++ b/src/commonMain/kotlin/com/ashampoo/xmp/options/AliasOptions.kt @@ -11,48 +11,49 @@ package com.ashampoo.xmp.options /** * Options for XMPSchemaRegistry#registerAlias. */ -class AliasOptions : Options { +@Suppress("TooManyFunctions") +public class AliasOptions : Options { - constructor() : super() + public constructor() : super() - constructor(options: Int) : super(options) + internal constructor(options: Int) : super(options) - fun isSimple(): Boolean = + public fun isSimple(): Boolean = getOptions() == PROP_DIRECT - fun isArray(): Boolean = + public fun isArray(): Boolean = getOption(PROP_ARRAY) - fun setArray(value: Boolean): AliasOptions { + public fun setArray(value: Boolean): AliasOptions { setOption(PROP_ARRAY, value) return this } - fun isArrayOrdered(): Boolean = + public fun isArrayOrdered(): Boolean = getOption(PROP_ARRAY_ORDERED) - fun setArrayOrdered(value: Boolean): AliasOptions { + public fun setArrayOrdered(value: Boolean): AliasOptions { setOption(PROP_ARRAY or PROP_ARRAY_ORDERED, value) return this } - fun isArrayAlternate(): Boolean = + public fun isArrayAlternate(): Boolean = getOption(PROP_ARRAY_ALTERNATE) - fun setArrayAlternate(value: Boolean): AliasOptions { + public fun setArrayAlternate(value: Boolean): AliasOptions { setOption(PROP_ARRAY or PROP_ARRAY_ORDERED or PROP_ARRAY_ALTERNATE, value) return this } - fun isArrayAltText(): Boolean = + public fun isArrayAltText(): Boolean = getOption(PROP_ARRAY_ALT_TEXT) - fun setArrayAltText(value: Boolean): AliasOptions { + public fun setArrayAltText(value: Boolean): AliasOptions { setOption(PROP_ARRAY or PROP_ARRAY_ORDERED or PROP_ARRAY_ALTERNATE or PROP_ARRAY_ALT_TEXT, value) return this } - fun toPropertyOptions(): PropertyOptions = + public fun toPropertyOptions(): PropertyOptions = PropertyOptions(getOptions()) protected override fun defineOptionName(option: Int): String? { @@ -69,7 +70,7 @@ class AliasOptions : Options { protected override fun getValidOptions(): Int = PROP_DIRECT or PROP_ARRAY or PROP_ARRAY_ORDERED or PROP_ARRAY_ALTERNATE or PROP_ARRAY_ALT_TEXT - companion object { + internal companion object { const val PROP_DIRECT = 0 diff --git a/src/commonMain/kotlin/com/ashampoo/xmp/options/IteratorOptions.kt b/src/commonMain/kotlin/com/ashampoo/xmp/options/IteratorOptions.kt index 254062e..d95f724 100644 --- a/src/commonMain/kotlin/com/ashampoo/xmp/options/IteratorOptions.kt +++ b/src/commonMain/kotlin/com/ashampoo/xmp/options/IteratorOptions.kt @@ -11,30 +11,30 @@ package com.ashampoo.xmp.options /** * Options for XMPIterator construction. */ -class IteratorOptions : Options() { +public class IteratorOptions : Options() { /** * @return Returns whether the option is set. */ - fun isJustChildren(): Boolean = + public fun isJustChildren(): Boolean = getOption(JUST_CHILDREN) /** * @return Returns whether the option is set. */ - fun isJustLeafname(): Boolean = + public fun isJustLeafname(): Boolean = getOption(JUST_LEAFNAME) /** * @return Returns whether the option is set. */ - fun isJustLeafnodes(): Boolean = + public fun isJustLeafnodes(): Boolean = getOption(JUST_LEAFNODES) /** * @return Returns whether the option is set. */ - fun isOmitQualifiers(): Boolean = + public fun isOmitQualifiers(): Boolean = getOption(OMIT_QUALIFIERS) /** @@ -43,7 +43,7 @@ class IteratorOptions : Options() { * @param value the value to set * @return Returns the instance to call more set-methods. */ - fun setJustChildren(value: Boolean): IteratorOptions { + public fun setJustChildren(value: Boolean): IteratorOptions { setOption(JUST_CHILDREN, value) return this } @@ -54,7 +54,7 @@ class IteratorOptions : Options() { * @param value the value to set * @return Returns the instance to call more set-methods. */ - fun setJustLeafname(value: Boolean): IteratorOptions { + public fun setJustLeafname(value: Boolean): IteratorOptions { setOption(JUST_LEAFNAME, value) return this } @@ -65,7 +65,7 @@ class IteratorOptions : Options() { * @param value the value to set * @return Returns the instance to call more set-methods. */ - fun setJustLeafnodes(value: Boolean): IteratorOptions { + public fun setJustLeafnodes(value: Boolean): IteratorOptions { setOption(JUST_LEAFNODES, value) return this } @@ -76,7 +76,7 @@ class IteratorOptions : Options() { * @param value the value to set * @return Returns the instance to call more set-methods. */ - fun setOmitQualifiers(value: Boolean): IteratorOptions { + public fun setOmitQualifiers(value: Boolean): IteratorOptions { setOption(OMIT_QUALIFIERS, value) return this } @@ -103,7 +103,7 @@ class IteratorOptions : Options() { /** * Just do the immediate children of the root, default is subtree. */ - companion object { + internal companion object { const val JUST_CHILDREN = 0x0100 diff --git a/src/commonMain/kotlin/com/ashampoo/xmp/options/Options.kt b/src/commonMain/kotlin/com/ashampoo/xmp/options/Options.kt index 67b82c4..c023494 100644 --- a/src/commonMain/kotlin/com/ashampoo/xmp/options/Options.kt +++ b/src/commonMain/kotlin/com/ashampoo/xmp/options/Options.kt @@ -8,14 +8,14 @@ // ================================================================================================= package com.ashampoo.xmp.options -import com.ashampoo.xmp.XMPError import com.ashampoo.xmp.XMPException +import com.ashampoo.xmp.internal.XMPErrorConst /** * The base class for a collection of 32 flag bits. Individual flags are defined as enum value bit * masks. Inheriting classes add convenience accessor methods. */ -abstract class Options { +public abstract class Options { /** * the internal int containing all options @@ -48,7 +48,7 @@ abstract class Options { * @param optionBits the binary bit or bits that shall be set to the given value * @param value the boolean value to set */ - fun setOption(optionBits: Int, value: Boolean) { + public fun setOption(optionBits: Int, value: Boolean) { this.valueBits = if (value) this.valueBits or optionBits else @@ -60,9 +60,9 @@ abstract class Options { * * @return Returns the options. */ - fun getOptions(): Int = valueBits + public fun getOptions(): Int = valueBits - fun setOptions(options: Int) { + public fun setOptions(options: Int) { assertOptionsValid(options) @@ -99,7 +99,7 @@ abstract class Options { * @param options the bitmask to check. * */ - protected open fun assertConsistency(options: Int) = Unit // empty, no checks + protected open fun assertConsistency(options: Int): Unit = Unit // empty, no checks /** * Checks options before they are set. @@ -113,7 +113,7 @@ abstract class Options { if (invalidOptions != 0) throw XMPException( "The option bit(s) 0x" + invalidOptions.toString(16) + " + are invalid!", - XMPError.BADOPTIONS + XMPErrorConst.BADOPTIONS ) assertConsistency(options) diff --git a/src/commonMain/kotlin/com/ashampoo/xmp/options/ParseOptions.kt b/src/commonMain/kotlin/com/ashampoo/xmp/options/ParseOptions.kt index 5bfa40b..fb5ed8d 100644 --- a/src/commonMain/kotlin/com/ashampoo/xmp/options/ParseOptions.kt +++ b/src/commonMain/kotlin/com/ashampoo/xmp/options/ParseOptions.kt @@ -11,19 +11,19 @@ package com.ashampoo.xmp.options /** * Options for [XMPMetaFactory.parse]. */ -class ParseOptions : Options() { +public class ParseOptions : Options() { /** * @return Returns the requireXMPMeta. */ - fun getRequireXMPMeta(): Boolean = + public fun getRequireXMPMeta(): Boolean = getOption(REQUIRE_XMP_META) /** * @param value the value to set * @return Returns the instance to call more set-methods. */ - fun setRequireXMPMeta(value: Boolean): ParseOptions { + public fun setRequireXMPMeta(value: Boolean): ParseOptions { setOption(REQUIRE_XMP_META, value) return this } @@ -31,14 +31,14 @@ class ParseOptions : Options() { /** * @return Returns the strictAliasing. */ - fun getStrictAliasing(): Boolean = + public fun getStrictAliasing(): Boolean = getOption(STRICT_ALIASING) /** * @param value the value to set * @return Returns the instance to call more set-methods. */ - fun setStrictAliasing(value: Boolean): ParseOptions { + public fun setStrictAliasing(value: Boolean): ParseOptions { setOption(STRICT_ALIASING, value) return this } @@ -47,7 +47,7 @@ class ParseOptions : Options() { * @param value the value to set * @return Returns the instance to call more set-methods. */ - fun setOmitNormalization(value: Boolean): ParseOptions { + public fun setOmitNormalization(value: Boolean): ParseOptions { setOption(OMIT_NORMALIZATION, value) return this } @@ -55,7 +55,7 @@ class ParseOptions : Options() { /** * @return Returns the option "omit normalization". */ - fun getOmitNormalization(): Boolean = + public fun getOmitNormalization(): Boolean = getOption(OMIT_NORMALIZATION) /** @@ -79,7 +79,7 @@ class ParseOptions : Options() { /** * Require a surrounding "x:xmpmeta" element in the xml-document. */ - companion object { + internal companion object { const val REQUIRE_XMP_META = 0x0001 diff --git a/src/commonMain/kotlin/com/ashampoo/xmp/options/PropertyOptions.kt b/src/commonMain/kotlin/com/ashampoo/xmp/options/PropertyOptions.kt index b5d8e90..8e7c07b 100644 --- a/src/commonMain/kotlin/com/ashampoo/xmp/options/PropertyOptions.kt +++ b/src/commonMain/kotlin/com/ashampoo/xmp/options/PropertyOptions.kt @@ -8,19 +8,19 @@ // ================================================================================================= package com.ashampoo.xmp.options -import com.ashampoo.xmp.XMPError import com.ashampoo.xmp.XMPException +import com.ashampoo.xmp.internal.XMPErrorConst /** * The property flags are used when properties are fetched from the `XMPMeta`-object * and provide more detailed information about the property. */ -class PropertyOptions : Options { +public class PropertyOptions : Options { /** * Default constructor */ - constructor() + public constructor() /** * Intialization constructor @@ -28,19 +28,19 @@ class PropertyOptions : Options { * @param options the initialization options * */ - constructor(options: Int) : super(options) + internal constructor(options: Int) : super(options) /** * @return Return whether the property value is a URI. It is serialized to RDF using the * rdf:resource attribute. Not mandatory for URIs, but considered RDF-savvy. */ - fun isURI(): Boolean = getOption(URI) + public fun isURI(): Boolean = getOption(URI) /** * @param value the value to set * @return Returns this to enable cascaded options. */ - fun setURI(value: Boolean): PropertyOptions { + public fun setURI(value: Boolean): PropertyOptions { setOption(URI, value) return this } @@ -50,14 +50,14 @@ class PropertyOptions : Options { * attribute, an rdf:type property, or a general qualifier. See the * introductory discussion of qualified properties for more information. */ - fun hasQualifiers(): Boolean = + public fun hasQualifiers(): Boolean = getOption(HAS_QUALIFIERS) /** * @param value the value to set * @return Returns this to enable cascaded options. */ - fun setHasQualifiers(value: Boolean): PropertyOptions { + public fun setHasQualifiers(value: Boolean): PropertyOptions { setOption(HAS_QUALIFIERS, value) return this } @@ -68,14 +68,14 @@ class PropertyOptions : Options { * the qualifier's subtree. Qualifiers may have arbitrary structure, and may even have * qualifiers. */ - fun isQualifier(): Boolean = + public fun isQualifier(): Boolean = getOption(QUALIFIER) /** * @param value the value to set * @return Returns this to enable cascaded options. */ - fun setQualifier(value: Boolean): PropertyOptions { + public fun setQualifier(value: Boolean): PropertyOptions { setOption(QUALIFIER, value) return this } @@ -83,14 +83,14 @@ class PropertyOptions : Options { /** * @return Return whether this property has an xml:lang qualifier. */ - fun hasLanguage(): Boolean = + public fun hasLanguage(): Boolean = getOption(HAS_LANGUAGE) /** * @param value the value to set * @return Returns this to enable cascaded options. */ - fun setHasLanguage(value: Boolean): PropertyOptions { + public fun setHasLanguage(value: Boolean): PropertyOptions { setOption(HAS_LANGUAGE, value) return this } @@ -98,14 +98,14 @@ class PropertyOptions : Options { /** * @return Return whether this property has an rdf:type qualifier. */ - fun hasType(): Boolean = + public fun hasType(): Boolean = getOption(HAS_TYPE) /** * @param value the value to set * @return Returns this to enable cascaded options. */ - fun setHasType(value: Boolean): PropertyOptions { + public fun setHasType(value: Boolean): PropertyOptions { setOption(HAS_TYPE, value) return this } @@ -113,14 +113,14 @@ class PropertyOptions : Options { /** * @return Return whether this property contains nested fields. */ - fun isStruct(): Boolean = + public fun isStruct(): Boolean = getOption(STRUCT) /** * @param value the value to set * @return Returns this to enable cascaded options. */ - fun setStruct(value: Boolean): PropertyOptions { + public fun setStruct(value: Boolean): PropertyOptions { setOption(STRUCT, value) return this } @@ -129,14 +129,14 @@ class PropertyOptions : Options { * @return Return whether this property is an array. By itself this indicates a general * unordered array. It is serialized using an rdf:Bag container. */ - fun isArray(): Boolean = + public fun isArray(): Boolean = getOption(ARRAY) /** * @param value the value to set * @return Returns this to enable cascaded options. */ - fun setArray(value: Boolean): PropertyOptions { + public fun setArray(value: Boolean): PropertyOptions { setOption(ARRAY, value) return this } @@ -145,14 +145,14 @@ class PropertyOptions : Options { * @return Return whether this property is an ordered array. Appears in conjunction with * getPropValueIsArray(). It is serialized using an rdf:Seq container. */ - fun isArrayOrdered(): Boolean = + public fun isArrayOrdered(): Boolean = getOption(ARRAY_ORDERED) /** * @param value the value to set * @return Returns this to enable cascaded options. */ - fun setArrayOrdered(value: Boolean): PropertyOptions { + public fun setArrayOrdered(value: Boolean): PropertyOptions { setOption(ARRAY_ORDERED, value) return this } @@ -161,14 +161,14 @@ class PropertyOptions : Options { * @return Return whether this property is an alternative array. Appears in conjunction with * getPropValueIsArray(). It is serialized using an rdf:Alt container. */ - fun isArrayAlternate(): Boolean = + public fun isArrayAlternate(): Boolean = getOption(ARRAY_ALTERNATE) /** * @param value the value to set * @return Returns this to enable cascaded options. */ - fun setArrayAlternate(value: Boolean): PropertyOptions { + public fun setArrayAlternate(value: Boolean): PropertyOptions { setOption(ARRAY_ALTERNATE, value) return this } @@ -178,14 +178,14 @@ class PropertyOptions : Options { * getPropArrayIsAlternate(). It is serialized using an rdf:Alt container. * Each array element is a simple property with an xml:lang attribute. */ - fun isArrayAltText(): Boolean = + public fun isArrayAltText(): Boolean = getOption(ARRAY_ALT_TEXT) /** * @param value the value to set * @return Returns this to enable cascaded options. */ - fun setArrayAltText(value: Boolean): PropertyOptions { + public fun setArrayAltText(value: Boolean): PropertyOptions { setOption(ARRAY_ALT_TEXT, value) return this } @@ -193,14 +193,14 @@ class PropertyOptions : Options { /** * @return Returns whether the SCHEMA_NODE option is set. */ - fun isSchemaNode(): Boolean = + public fun isSchemaNode(): Boolean = getOption(SCHEMA_NODE) /** * @param value the option DELETE_EXISTING to set * @return Returns this to enable cascaded options. */ - fun setSchemaNode(value: Boolean): PropertyOptions { + public fun setSchemaNode(value: Boolean): PropertyOptions { setOption(SCHEMA_NODE, value) return this } @@ -208,13 +208,13 @@ class PropertyOptions : Options { /** * @return Returns whether the property is of composite type - an array or a struct. */ - fun isCompositeProperty(): Boolean = + public fun isCompositeProperty(): Boolean = getOptions() and (ARRAY or STRUCT) > 0 /** * @return Returns whether the property is of composite type - an array or a struct. */ - fun isSimple(): Boolean = + public fun isSimple(): Boolean = getOptions() and (ARRAY or STRUCT) == 0 /** @@ -223,7 +223,7 @@ class PropertyOptions : Options { * @param options other options * @return Returns true if the array options of the sets are equal. */ - fun equalArrayTypes(options: PropertyOptions): Boolean = + public fun equalArrayTypes(options: PropertyOptions): Boolean = isArray() == options.isArray() && isArrayOrdered() == options.isArrayOrdered() && isArrayAlternate() == options.isArrayAlternate() && @@ -235,14 +235,14 @@ class PropertyOptions : Options { * * @param options other options */ - fun mergeWith(options: PropertyOptions) { + public fun mergeWith(options: PropertyOptions) { setOptions(getOptions() or options.getOptions()) } /** * @return Returns true if only array options are set. */ - fun isOnlyArrayOptions(): Boolean = + public fun isOnlyArrayOptions(): Boolean = getOptions() and (ARRAY or ARRAY_ORDERED or ARRAY_ALTERNATE or ARRAY_ALT_TEXT).inv() == 0 /** @@ -282,12 +282,12 @@ class PropertyOptions : Options { public override fun assertConsistency(options: Int) { if (options and STRUCT > 0 && options and ARRAY > 0) - throw XMPException("IsStruct and IsArray options are mutually exclusive", XMPError.BADOPTIONS) + throw XMPException("IsStruct and IsArray options are mutually exclusive", XMPErrorConst.BADOPTIONS) else if (options and URI > 0 && options and (ARRAY or STRUCT) > 0) - throw XMPException("Structs and arrays can't have \"value\" options", XMPError.BADOPTIONS) + throw XMPException("Structs and arrays can't have \"value\" options", XMPErrorConst.BADOPTIONS) } - companion object { + internal companion object { /** * diff --git a/src/commonMain/kotlin/com/ashampoo/xmp/options/SerializeOptions.kt b/src/commonMain/kotlin/com/ashampoo/xmp/options/SerializeOptions.kt index 18755f4..edf204a 100644 --- a/src/commonMain/kotlin/com/ashampoo/xmp/options/SerializeOptions.kt +++ b/src/commonMain/kotlin/com/ashampoo/xmp/options/SerializeOptions.kt @@ -11,12 +11,12 @@ package com.ashampoo.xmp.options /** * Options for [XMPMetaFactory.serializeToBuffer]. */ -class SerializeOptions : Options { +public class SerializeOptions : Options { /** * Default constructor. */ - constructor() + public constructor() /** * Constructor using inital options @@ -24,76 +24,76 @@ class SerializeOptions : Options { * @param options the inital options * */ - constructor(options: Int) : super(options) + internal constructor(options: Int) : super(options) - fun getOmitPacketWrapper(): Boolean = + public fun getOmitPacketWrapper(): Boolean = getOption(OMIT_PACKET_WRAPPER) /** * @param value the value to set * @return Returns the instance to call more set-methods. */ - fun setOmitPacketWrapper(value: Boolean): SerializeOptions { + public fun setOmitPacketWrapper(value: Boolean): SerializeOptions { setOption(OMIT_PACKET_WRAPPER, value) return this } - fun getOmitXmpMetaElement(): Boolean = + public fun getOmitXmpMetaElement(): Boolean = getOption(OMIT_XMPMETA_ELEMENT) /** * @param value the value to set * @return Returns the instance to call more set-methods. */ - fun setOmitXmpMetaElement(value: Boolean): SerializeOptions { + public fun setOmitXmpMetaElement(value: Boolean): SerializeOptions { setOption(OMIT_XMPMETA_ELEMENT, value) return this } - fun getReadOnlyPacket(): Boolean = + public fun getReadOnlyPacket(): Boolean = getOption(READONLY_PACKET) /** * @param value the value to set * @return Returns the instance to call more set-methods. */ - fun setReadOnlyPacket(value: Boolean): SerializeOptions { + public fun setReadOnlyPacket(value: Boolean): SerializeOptions { setOption(READONLY_PACKET, value) return this } - fun getUseCompactFormat(): Boolean = + public fun getUseCompactFormat(): Boolean = getOption(USE_COMPACT_FORMAT) /** * @param value the value to set * @return Returns the instance to call more set-methods. */ - fun setUseCompactFormat(value: Boolean): SerializeOptions { + public fun setUseCompactFormat(value: Boolean): SerializeOptions { setOption(USE_COMPACT_FORMAT, value) return this } - fun getUseCanonicalFormat(): Boolean = + public fun getUseCanonicalFormat(): Boolean = getOption(USE_CANONICAL_FORMAT) /** * @param value the value to set * @return Returns the instance to call more set-methods. */ - fun setUseCanonicalFormat(value: Boolean): SerializeOptions { + public fun setUseCanonicalFormat(value: Boolean): SerializeOptions { setOption(USE_CANONICAL_FORMAT, value) return this } - fun getSort(): Boolean = + public fun getSort(): Boolean = getOption(SORT) /** * @param value the value to set * @return Returns the instance to call more set-methods. */ - fun setSort(value: Boolean): SerializeOptions { + public fun setSort(value: Boolean): SerializeOptions { setOption(SORT, value) return this } @@ -101,7 +101,7 @@ class SerializeOptions : Options { /** * @return Returns clone of this SerializeOptions-object with the same options set. */ - fun clone(): SerializeOptions = + public fun clone(): SerializeOptions = SerializeOptions(getOptions()) /** @@ -124,7 +124,7 @@ class SerializeOptions : Options { override fun getValidOptions(): Int = OMIT_PACKET_WRAPPER or READONLY_PACKET or USE_COMPACT_FORMAT or OMIT_XMPMETA_ELEMENT or SORT - companion object { + internal companion object { /** * Omit the XML packet wrapper. diff --git a/src/commonTest/kotlin/com/ashampoo/xmp/ReadXmpTest.kt b/src/commonTest/kotlin/com/ashampoo/xmp/ReadXmpTest.kt index 68a691b..e262d80 100644 --- a/src/commonTest/kotlin/com/ashampoo/xmp/ReadXmpTest.kt +++ b/src/commonTest/kotlin/com/ashampoo/xmp/ReadXmpTest.kt @@ -13,6 +13,7 @@ class ReadXmpTest { @Test fun testReadXmp() { + /* language=XML */ val testXmp = """ - + diff --git a/src/commonTest/resources/com/ashampoo/xmp/new.xmp b/src/commonTest/resources/com/ashampoo/xmp/new.xmp index f2bda6f..90ec790 100644 --- a/src/commonTest/resources/com/ashampoo/xmp/new.xmp +++ b/src/commonTest/resources/com/ashampoo/xmp/new.xmp @@ -1,5 +1,5 @@ - + - + - + - + - + - + - + - + - + - + - + diff --git a/src/commonTest/resources/com/ashampoo/xmp/sample_13_formatted_compact.xmp b/src/commonTest/resources/com/ashampoo/xmp/sample_13_formatted_compact.xmp index 14cc05d..ad869ad 100644 --- a/src/commonTest/resources/com/ashampoo/xmp/sample_13_formatted_compact.xmp +++ b/src/commonTest/resources/com/ashampoo/xmp/sample_13_formatted_compact.xmp @@ -1,5 +1,5 @@ - + - + diff --git a/src/commonTest/resources/com/ashampoo/xmp/sample_14_formatted_compact.xmp b/src/commonTest/resources/com/ashampoo/xmp/sample_14_formatted_compact.xmp index 8cb3172..1783e27 100644 --- a/src/commonTest/resources/com/ashampoo/xmp/sample_14_formatted_compact.xmp +++ b/src/commonTest/resources/com/ashampoo/xmp/sample_14_formatted_compact.xmp @@ -1,5 +1,5 @@ - + - + diff --git a/src/commonTest/resources/com/ashampoo/xmp/sample_15_formatted_compact.xmp b/src/commonTest/resources/com/ashampoo/xmp/sample_15_formatted_compact.xmp index caf0530..4e3cbd6 100644 --- a/src/commonTest/resources/com/ashampoo/xmp/sample_15_formatted_compact.xmp +++ b/src/commonTest/resources/com/ashampoo/xmp/sample_15_formatted_compact.xmp @@ -1,5 +1,5 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + diff --git a/src/commonTest/resources/com/ashampoo/xmp/sample_31_formatted_compact.xmp b/src/commonTest/resources/com/ashampoo/xmp/sample_31_formatted_compact.xmp index 8cb3172..1783e27 100644 --- a/src/commonTest/resources/com/ashampoo/xmp/sample_31_formatted_compact.xmp +++ b/src/commonTest/resources/com/ashampoo/xmp/sample_31_formatted_compact.xmp @@ -1,5 +1,5 @@ - + - + - + - + - + - + diff --git a/src/commonTest/resources/com/ashampoo/xmp/sample_34_formatted_compact.xmp b/src/commonTest/resources/com/ashampoo/xmp/sample_34_formatted_compact.xmp index 8cb3172..1783e27 100644 --- a/src/commonTest/resources/com/ashampoo/xmp/sample_34_formatted_compact.xmp +++ b/src/commonTest/resources/com/ashampoo/xmp/sample_34_formatted_compact.xmp @@ -1,5 +1,5 @@ - + - + - + - + - + - + - + - + - + - + diff --git a/src/commonTest/resources/com/ashampoo/xmp/sample_39_formatted_compact.xmp b/src/commonTest/resources/com/ashampoo/xmp/sample_39_formatted_compact.xmp index 14cc05d..ad869ad 100644 --- a/src/commonTest/resources/com/ashampoo/xmp/sample_39_formatted_compact.xmp +++ b/src/commonTest/resources/com/ashampoo/xmp/sample_39_formatted_compact.xmp @@ -1,5 +1,5 @@ - + - + - + - + - + - + diff --git a/src/commonTest/resources/com/ashampoo/xmp/sample_41_formatted_compact.xmp b/src/commonTest/resources/com/ashampoo/xmp/sample_41_formatted_compact.xmp index 14cc05d..ad869ad 100644 --- a/src/commonTest/resources/com/ashampoo/xmp/sample_41_formatted_compact.xmp +++ b/src/commonTest/resources/com/ashampoo/xmp/sample_41_formatted_compact.xmp @@ -1,5 +1,5 @@ - + - + - + - + diff --git a/src/commonTest/resources/com/ashampoo/xmp/sample_43_formatted_compact.xmp b/src/commonTest/resources/com/ashampoo/xmp/sample_43_formatted_compact.xmp index 901f1cf..2414867 100644 --- a/src/commonTest/resources/com/ashampoo/xmp/sample_43_formatted_compact.xmp +++ b/src/commonTest/resources/com/ashampoo/xmp/sample_43_formatted_compact.xmp @@ -1,5 +1,5 @@ - + - + diff --git a/src/commonTest/resources/com/ashampoo/xmp/sample_44_formatted_compact.xmp b/src/commonTest/resources/com/ashampoo/xmp/sample_44_formatted_compact.xmp index 2b48f84..5bef245 100644 --- a/src/commonTest/resources/com/ashampoo/xmp/sample_44_formatted_compact.xmp +++ b/src/commonTest/resources/com/ashampoo/xmp/sample_44_formatted_compact.xmp @@ -1,5 +1,5 @@ - + - + - + - + - + - + - + - + - + - + diff --git a/src/commonTest/resources/com/ashampoo/xmp/sample_49_formatted_compact.xmp b/src/commonTest/resources/com/ashampoo/xmp/sample_49_formatted_compact.xmp index 8cb3172..1783e27 100644 --- a/src/commonTest/resources/com/ashampoo/xmp/sample_49_formatted_compact.xmp +++ b/src/commonTest/resources/com/ashampoo/xmp/sample_49_formatted_compact.xmp @@ -1,5 +1,5 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + ) { +public fun main(args: Array) { if (args.size != 1) { println("USAGE: Must be called with one argument.")