diff --git a/modules/charon-core/src/main/java/org/wso2/charon3/core/attributes/AbstractAttribute.java b/modules/charon-core/src/main/java/org/wso2/charon3/core/attributes/AbstractAttribute.java index 5f4274f85..3eb292a00 100644 --- a/modules/charon-core/src/main/java/org/wso2/charon3/core/attributes/AbstractAttribute.java +++ b/modules/charon-core/src/main/java/org/wso2/charon3/core/attributes/AbstractAttribute.java @@ -15,6 +15,7 @@ */ package org.wso2.charon3.core.attributes; +import org.json.JSONObject; import org.wso2.charon3.core.schema.SCIMDefinitions; import java.util.HashMap; @@ -48,6 +49,7 @@ public abstract class AbstractAttribute implements Attribute { protected SCIMDefinitions.Uniqueness uniqueness; //A container to hold custom attribute properties. protected Map additionalAttributeProperties = new HashMap<>(); + protected Map additionalAttributeJSONProperties = new HashMap<>(); public String getURI() { return uri; } @@ -145,4 +147,24 @@ public String removeAttributeProperty(String propertyName) { return additionalAttributeProperties.remove(propertyName); } + + public Map getAttributeJSONProperties() { + + return additionalAttributeJSONProperties; + } + + public JSONObject getAttributeJSONProperty(String propertyName) { + + return additionalAttributeJSONProperties.get(propertyName); + } + + public void addAttributeJSONProperty(String propertyName, JSONObject jsonObject) { + + this.additionalAttributeJSONProperties.put(propertyName, jsonObject); + } + + public JSONObject removeAttributeJSONProperty(String propertyName) { + + return additionalAttributeJSONProperties.remove(propertyName); + } } diff --git a/modules/charon-core/src/main/java/org/wso2/charon3/core/attributes/Attribute.java b/modules/charon-core/src/main/java/org/wso2/charon3/core/attributes/Attribute.java index 43acf9e04..709f41134 100644 --- a/modules/charon-core/src/main/java/org/wso2/charon3/core/attributes/Attribute.java +++ b/modules/charon-core/src/main/java/org/wso2/charon3/core/attributes/Attribute.java @@ -15,6 +15,7 @@ */ package org.wso2.charon3.core.attributes; +import org.json.JSONObject; import org.wso2.charon3.core.exceptions.CharonException; import org.wso2.charon3.core.schema.SCIMDefinitions; @@ -62,4 +63,14 @@ public default Map getAttributeProperties() { throw new UnsupportedOperationException(); } + + public default Map getAttributeJSONProperties() { + + throw new UnsupportedOperationException(); + } + + public default JSONObject getAttributeJSONProperty(String propertyName) { + + throw new UnsupportedOperationException(); + } } diff --git a/modules/charon-core/src/main/java/org/wso2/charon3/core/encoder/JSONEncoder.java b/modules/charon-core/src/main/java/org/wso2/charon3/core/encoder/JSONEncoder.java index 338712a1f..a410aabec 100644 --- a/modules/charon-core/src/main/java/org/wso2/charon3/core/encoder/JSONEncoder.java +++ b/modules/charon-core/src/main/java/org/wso2/charon3/core/encoder/JSONEncoder.java @@ -233,6 +233,11 @@ public JSONObject encodeBasicAttributeSchema(Attribute attribute) throws JSONExc attributeSchema.put(entry.getKey(), entry.getValue()); } + Map customJSONProperties = attribute.getAttributeJSONProperties(); + for (Map.Entry entry: customJSONProperties.entrySet()) { + attributeSchema.put(entry.getKey(), entry.getValue()); + } + return attributeSchema; } diff --git a/modules/charon-core/src/test/java/org/wso2/charon3/core/encoder/JsonEncoderTest.java b/modules/charon-core/src/test/java/org/wso2/charon3/core/encoder/JsonEncoderTest.java new file mode 100644 index 000000000..183277c3f --- /dev/null +++ b/modules/charon-core/src/test/java/org/wso2/charon3/core/encoder/JsonEncoderTest.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2025, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.charon3.core.encoder; + +import org.json.JSONObject; +import org.testng.Assert; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; +import org.wso2.charon3.core.attributes.AbstractAttribute; +import org.wso2.charon3.core.attributes.SimpleAttribute; +import org.wso2.charon3.core.schema.SCIMDefinitions; + +/** + * Test class for JSONEncoder. + */ +public class JsonEncoderTest { + + private JSONEncoder jsonEncoder; + + @BeforeMethod + public void setUp() { + + jsonEncoder = new JSONEncoder(); + } + + @Test + public void testEncodeBasicAttributeSchema() { + + AbstractAttribute attribute = new SimpleAttribute("test", null); + attribute.setType(SCIMDefinitions.DataType.STRING); + attribute.setMultiValued(false); + attribute.setDescription("Test Description"); + attribute.setRequired(true); + attribute.setCaseExact(true); + attribute.setReturned(SCIMDefinitions.Returned.DEFAULT); + attribute.setMutability(SCIMDefinitions.Mutability.READ_WRITE); + attribute.setURI("testURI"); + attribute.setUniqueness(SCIMDefinitions.Uniqueness.NONE); + attribute.addAttributeProperty("custom1", "value1"); + + JSONObject testJsonObject = new JSONObject(); + testJsonObject.put("key1", "value1"); + attribute.addAttributeJSONProperty("json1", testJsonObject); + attribute.addAttributeJSONProperty("json2", new JSONObject()); + attribute.removeAttributeJSONProperty("json2"); + + JSONObject responseJson = jsonEncoder.encodeBasicAttributeSchema(attribute); + + // Assert. + Assert.assertEquals(responseJson.get("name"), "test"); + Assert.assertEquals(responseJson.get("type"), SCIMDefinitions.DataType.STRING); + Assert.assertEquals(responseJson.get("multiValued"), false); + Assert.assertEquals(responseJson.get("description"), "Test Description"); + Assert.assertEquals(responseJson.get("required"), true); + Assert.assertEquals(responseJson.get("caseExact"), true); + Assert.assertEquals(responseJson.get("mutability"), SCIMDefinitions.Mutability.READ_WRITE); + Assert.assertEquals(responseJson.get("returned"), SCIMDefinitions.Returned.DEFAULT); + Assert.assertEquals(responseJson.get("uniqueness"), SCIMDefinitions.Uniqueness.NONE); + + Assert.assertEquals(responseJson.get("custom1"), "value1"); + + JSONObject customJson = responseJson.getJSONObject("json1"); + Assert.assertEquals(customJson.get("key1"), "value1"); + + Assert.assertTrue(attribute.getAttributeJSONProperties().containsKey("json1")); + Assert.assertFalse(attribute.getAttributeJSONProperties().containsKey("json2")); + Assert.assertEquals(attribute.getAttributeJSONProperty("json1"), testJsonObject); + } +} diff --git a/modules/charon-core/src/test/resources/testng.xml b/modules/charon-core/src/test/resources/testng.xml index 704ca559d..a7a87babd 100644 --- a/modules/charon-core/src/test/resources/testng.xml +++ b/modules/charon-core/src/test/resources/testng.xml @@ -26,6 +26,7 @@ +