Skip to content

Commit ad05056

Browse files
Fix for setLocation(null) + Kotlin update (#35)
* Fix: setLocation(null) should delete all known fields. + Unit Test * Removed debug println * Dependency updates * Target Android 35 * Bumped version
1 parent 2091090 commit ad05056

225 files changed

Lines changed: 321 additions & 266 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# XMP Core for Kotlin Multiplatform
22

3-
[![Kotlin](https://img.shields.io/badge/kotlin-2.1.0-blue.svg?logo=kotlin)](httpw://kotlinlang.org)
3+
[![Kotlin](https://img.shields.io/badge/kotlin-2.1.10-blue.svg?logo=kotlin)](httpw://kotlinlang.org)
44
![JVM](https://img.shields.io/badge/-JVM-gray.svg?style=flat)
55
![Android](https://img.shields.io/badge/-Android-gray.svg?style=flat)
66
![iOS](https://img.shields.io/badge/-iOS-gray.svg?style=flat)
@@ -20,7 +20,7 @@ It's part of [Ashampoo Photo Organizer](https://ashampoo.com/photo-organizer).
2020
## Installation
2121

2222
```
23-
implementation("com.ashampoo:xmpcore:1.5.0")
23+
implementation("com.ashampoo:xmpcore:1.5.1")
2424
```
2525

2626
## How to use

build.gradle.kts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.NativeBuildType
33
import org.jetbrains.kotlin.gradle.plugin.mpp.apple.XCFramework
44

55
plugins {
6-
kotlin("multiplatform") version "2.1.0"
6+
kotlin("multiplatform") version "2.1.10"
77
id("com.android.library") version "8.5.0"
88
id("maven-publish")
99
id("signing")
@@ -295,7 +295,7 @@ android {
295295

296296
namespace = "com.ashampoo.xmpcore"
297297

298-
compileSdk = 34
298+
compileSdk = 35
299299

300300
sourceSets["main"].res.srcDirs("src/commonMain/resources")
301301

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
distributionBase=GRADLE_USER_HOME
22
distributionPath=wrapper/dists
3-
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip
3+
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12.1-bin.zip
44
networkTimeout=10000
55
zipStoreBase=GRADLE_USER_HOME
66
zipStorePath=wrapper/dists

src/commonMain/kotlin/com/ashampoo/xmp/XMPMeta.kt

Lines changed: 30 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -2018,7 +2018,7 @@ public class XMPMeta internal constructor() {
20182018
}
20192019

20202020
/*
2021-
* For missing values fall back to the Photoshop namespace.
2021+
* For missing values fall back to older places.
20222022
*/
20232023

20242024
if (location.isNullOrBlank())
@@ -2062,21 +2062,28 @@ public class XMPMeta internal constructor() {
20622062
xmpLocation: XMPLocation?
20632063
) {
20642064

2065-
/* Delete existing entries, if any */
2065+
/* Delete existing entries */
2066+
20662067
deleteProperty(XMPConst.NS_IPTC_EXT, XMPConst.XMP_IPTC_EXT_LOCATION_SHOWN)
2068+
deleteProperty(XMPConst.NS_IPTC_CORE, "Location")
2069+
deleteProperty(XMPConst.NS_PHOTOSHOP, "City")
2070+
deleteProperty(XMPConst.NS_PHOTOSHOP, "State")
2071+
deleteProperty(XMPConst.NS_PHOTOSHOP, "Country")
20672072

20682073
if (xmpLocation == null)
20692074
return
20702075

2071-
/* Create a new array property. */
2076+
/*
2077+
* Write Iptc4xmpExt:LocationShown
2078+
*/
2079+
20722080
setProperty(
20732081
XMPConst.NS_IPTC_EXT,
20742082
XMPConst.XMP_IPTC_EXT_LOCATION_SHOWN,
20752083
null,
20762084
arrayOptions
20772085
)
20782086

2079-
/* Append empty entry */
20802087
appendArrayItem(
20812088
schemaNS = XMPConst.NS_IPTC_EXT,
20822089
arrayName = XMPConst.XMP_IPTC_EXT_LOCATION_SHOWN,
@@ -2112,8 +2119,7 @@ public class XMPMeta internal constructor() {
21122119
)
21132120
}
21142121

2115-
if (!xmpLocation.location.isNullOrBlank()) {
2116-
2122+
if (!xmpLocation.location.isNullOrBlank())
21172123
setStructField(
21182124
schemaNS = XMPConst.NS_IPTC_EXT,
21192125
structName = XMPConst.XMP_IPTC_EXT_LOCATION_SHOWN + "[1]",
@@ -2122,15 +2128,7 @@ public class XMPMeta internal constructor() {
21222128
fieldValue = xmpLocation.location
21232129
)
21242130

2125-
setProperty(
2126-
schemaNS = XMPConst.NS_IPTC_CORE,
2127-
propName = "Location",
2128-
propValue = xmpLocation.location
2129-
)
2130-
}
2131-
2132-
if (!xmpLocation.city.isNullOrBlank()) {
2133-
2131+
if (!xmpLocation.city.isNullOrBlank())
21342132
setStructField(
21352133
schemaNS = XMPConst.NS_IPTC_EXT,
21362134
structName = XMPConst.XMP_IPTC_EXT_LOCATION_SHOWN + "[1]",
@@ -2139,15 +2137,7 @@ public class XMPMeta internal constructor() {
21392137
fieldValue = xmpLocation.city
21402138
)
21412139

2142-
setProperty(
2143-
schemaNS = XMPConst.NS_PHOTOSHOP,
2144-
propName = "City",
2145-
propValue = xmpLocation.city
2146-
)
2147-
}
2148-
2149-
if (!xmpLocation.state.isNullOrBlank()) {
2150-
2140+
if (!xmpLocation.state.isNullOrBlank())
21512141
setStructField(
21522142
schemaNS = XMPConst.NS_IPTC_EXT,
21532143
structName = XMPConst.XMP_IPTC_EXT_LOCATION_SHOWN + "[1]",
@@ -2156,15 +2146,7 @@ public class XMPMeta internal constructor() {
21562146
fieldValue = xmpLocation.state
21572147
)
21582148

2159-
setProperty(
2160-
schemaNS = XMPConst.NS_PHOTOSHOP,
2161-
propName = "State",
2162-
propValue = xmpLocation.state
2163-
)
2164-
}
2165-
2166-
if (!xmpLocation.country.isNullOrBlank()) {
2167-
2149+
if (!xmpLocation.country.isNullOrBlank())
21682150
setStructField(
21692151
schemaNS = XMPConst.NS_IPTC_EXT,
21702152
structName = XMPConst.XMP_IPTC_EXT_LOCATION_SHOWN + "[1]",
@@ -2173,12 +2155,21 @@ public class XMPMeta internal constructor() {
21732155
fieldValue = xmpLocation.country
21742156
)
21752157

2176-
setProperty(
2177-
schemaNS = XMPConst.NS_PHOTOSHOP,
2178-
propName = "Country",
2179-
propValue = xmpLocation.country
2180-
)
2181-
}
2158+
/*
2159+
* Write older fields for completeness
2160+
*/
2161+
2162+
if (!xmpLocation.location.isNullOrBlank())
2163+
setProperty(XMPConst.NS_IPTC_CORE, "Location", xmpLocation.location)
2164+
2165+
if (!xmpLocation.city.isNullOrBlank())
2166+
setProperty(XMPConst.NS_PHOTOSHOP, "City", xmpLocation.city)
2167+
2168+
if (!xmpLocation.state.isNullOrBlank())
2169+
setProperty(XMPConst.NS_PHOTOSHOP, "State", xmpLocation.state)
2170+
2171+
if (!xmpLocation.country.isNullOrBlank())
2172+
setProperty(XMPConst.NS_PHOTOSHOP, "Country", xmpLocation.country)
21822173
}
21832174

21842175
public fun getTitle(): String? {

src/commonMain/kotlin/com/ashampoo/xmp/XMPVersionInfo.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ public object XMPVersionInfo {
99

1010
public const val MAJOR: Int = 1
1111
public const val MINOR: Int = 5
12-
public const val PATCH: Int = 0
12+
public const val PATCH: Int = 1
1313

1414
public const val VERSION_MESSAGE: String =
1515
"Ashampoo XMP Core $MAJOR.$MINOR.$PATCH"

src/commonTest/kotlin/com/ashampoo/xmp/ReadXmpTest.kt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -222,8 +222,6 @@ class ReadXmpTest {
222222
<?xpacket end="w"?>
223223
""".trimIndent()
224224

225-
println(testXmp)
226-
227225
val xmpMeta = XMPMetaFactory.parseFromString(testXmp)
228226

229227
assertEquals(

src/commonTest/kotlin/com/ashampoo/xmp/WriteXmpTest.kt

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,72 @@ class WriteXmpTest {
412412
)
413413
}
414414

415+
/**
416+
* Create an XMP only containing location info.
417+
*/
418+
@OptIn(ExperimentalStdlibApi::class)
419+
@Test
420+
fun testLocationRemovalXmp() {
421+
422+
/* language=XML */
423+
val originalXmp = """
424+
<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
425+
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="${XMPVersionInfo.VERSION_MESSAGE}">
426+
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
427+
<rdf:Description rdf:about=""
428+
xmlns:Iptc4xmpCore="http://iptc.org/std/Iptc4xmpCore/1.0/xmlns/"
429+
xmlns:Iptc4xmpExt="http://iptc.org/std/Iptc4xmpExt/2008-02-29/"
430+
xmlns:photoshop="http://ns.adobe.com/photoshop/1.0/"
431+
Iptc4xmpCore:Location="Schafjückenweg 2"
432+
photoshop:City="Rastede"
433+
photoshop:Country="Deutschland"
434+
photoshop:State="Niedersachsen">
435+
<Iptc4xmpExt:LocationShown>
436+
<rdf:Bag>
437+
<rdf:li>
438+
<rdf:Description
439+
Iptc4xmpExt:City="Rastede"
440+
Iptc4xmpExt:CountryName="Deutschland"
441+
Iptc4xmpExt:ProvinceState="Niedersachsen"
442+
Iptc4xmpExt:Sublocation="Schafjückenweg 2">
443+
<Iptc4xmpExt:LocationName>
444+
<rdf:Alt>
445+
<rdf:li xml:lang="x-default">Ashampoo GmbH &amp; Co. KG</rdf:li>
446+
</rdf:Alt>
447+
</Iptc4xmpExt:LocationName>
448+
</rdf:Description>
449+
</rdf:li>
450+
</rdf:Bag>
451+
</Iptc4xmpExt:LocationShown>
452+
</rdf:Description>
453+
</rdf:RDF>
454+
</x:xmpmeta>
455+
<?xpacket end="w"?>
456+
""".trimIndent()
457+
458+
val xmpMeta = XMPMetaFactory.parseFromString(originalXmp)
459+
460+
xmpMeta.setLocation(null)
461+
462+
val actualXmp = XMPMetaFactory.serializeToString(xmpMeta, xmpSerializeOptionsCompact)
463+
464+
/* language=XML */
465+
val expectedXmp = """
466+
<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
467+
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="${XMPVersionInfo.VERSION_MESSAGE}">
468+
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
469+
<rdf:Description rdf:about=""/>
470+
</rdf:RDF>
471+
</x:xmpmeta>
472+
<?xpacket end="w"?>
473+
""".trimIndent()
474+
475+
assertEquals(
476+
expected = expectedXmp,
477+
actual = actualXmp
478+
)
479+
}
480+
415481
/**
416482
* Create an XMP only containing title & description.
417483
*/
@@ -429,7 +495,7 @@ class WriteXmpTest {
429495
/* language=XML */
430496
val expectedXmp = """
431497
<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
432-
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Ashampoo XMP Core 1.5.0">
498+
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="${XMPVersionInfo.VERSION_MESSAGE}">
433499
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
434500
<rdf:Description rdf:about=""
435501
xmlns:dc="http://purl.org/dc/elements/1.1/">

src/commonTest/resources/com/ashampoo/xmp/sample_100_formatted_canonical.xmp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
2-
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Ashampoo XMP Core 1.5.0">
2+
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Ashampoo XMP Core 1.5.1">
33
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
44
<rdf:Description rdf:about=""
55
xmlns:MicrosoftPhoto_1_="http://ns.microsoft.com/photo/1.0"

src/commonTest/resources/com/ashampoo/xmp/sample_100_formatted_compact.xmp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
2-
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Ashampoo XMP Core 1.5.0">
2+
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Ashampoo XMP Core 1.5.1">
33
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
44
<rdf:Description rdf:about=""
55
xmlns:MicrosoftPhoto_1_="http://ns.microsoft.com/photo/1.0"

src/commonTest/resources/com/ashampoo/xmp/sample_101_formatted_canonical.xmp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
2-
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Ashampoo XMP Core 1.5.0">
2+
<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Ashampoo XMP Core 1.5.1">
33
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
44
<rdf:Description rdf:about=""
55
xmlns:xmp="http://ns.adobe.com/xap/1.0/"

0 commit comments

Comments
 (0)