Skip to content

Commit

Permalink
Fixing serialization of raw values (storing type information).
Browse files Browse the repository at this point in the history
(cherry picked from commit fac31fc)
  • Loading branch information
mederly committed Oct 9, 2017
1 parent 94399e5 commit 6d00fea
Show file tree
Hide file tree
Showing 8 changed files with 290 additions and 8 deletions.
Expand Up @@ -1514,6 +1514,7 @@ public static void copyDefinition(Containerable aClone, Containerable original,
}
}

@Override
public QName getTypeName() {
return getComplexTypeDefinition() != null ? getComplexTypeDefinition().getTypeName() : null;
}
Expand Down
Expand Up @@ -26,6 +26,7 @@
import org.jetbrains.annotations.Nullable;
import org.w3c.dom.Element;

import javax.xml.namespace.QName;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
Expand Down Expand Up @@ -497,4 +498,9 @@ public static PrismContainerValue<?> getParentContainerValue(PrismValue value) {
public PrismContainerValue<?> getParentContainerValue() {
return getParentContainerValue(this);
}

public QName getTypeName() {
ItemDefinition definition = getDefinition();
return definition != null ? definition.getTypeName() : null;
}
}
Expand Up @@ -390,6 +390,11 @@ && getSchemaRegistry().findTypeDefinitionByType(typeName, TypeDefinition.class)

// TODO shouldn't we use here the same approach as above?
private void setExplicitTypeDeclarationIfNeeded(XNode node, Method getter, Object getterResult, QName typeName) {
if (typeName == null) {
// the idea is not to overwrite pre-existing explicit type declaration with null value
// TODO reconsider
return;
}
Class getterReturnType = getter.getReturnType();
Class getterType = null;
if (Collection.class.isAssignableFrom(getterReturnType)) {
Expand Down
Expand Up @@ -45,6 +45,9 @@ public class RawType implements Serializable, Cloneable, Equals, Revivable {
*/
private PrismValue parsed;

private QName explicitTypeName;
private boolean explicitTypeDeclaration;

public RawType(PrismContext prismContext) {
Validate.notNull(prismContext, "prismContext is not set - perhaps a forgotten call to adopt() somewhere?");
this.prismContext = prismContext;
Expand All @@ -53,11 +56,19 @@ public RawType(PrismContext prismContext) {
public RawType(XNode xnode, @NotNull PrismContext prismContext) {
this(prismContext);
this.xnode = xnode;
if (xnode != null) {
this.explicitTypeName = xnode.getTypeQName();
this.explicitTypeDeclaration = xnode.isExplicitTypeDeclaration();
}
}

public RawType(PrismValue parsed, @NotNull PrismContext prismContext) {
this.prismContext = prismContext;
this.parsed = parsed;
if (parsed != null && parsed.getTypeName() != null) {
this.explicitTypeName = parsed.getTypeName();
this.explicitTypeDeclaration = true;
}
}

@Override
Expand Down Expand Up @@ -191,7 +202,10 @@ public XNode serializeToXNode() throws SchemaException {
return xnode;
} else if (parsed != null) {
checkPrismContext();
return prismContext.xnodeSerializer().root(new QName("dummy")).serialize(parsed).getSubnode();
XNode rv = prismContext.xnodeSerializer().root(new QName("dummy")).serialize(parsed).getSubnode();
rv.setTypeQName(explicitTypeName);
rv.setExplicitTypeDeclaration(explicitTypeDeclaration);
return rv;
} else {
return null; // or an exception here?
}
Expand All @@ -206,6 +220,8 @@ public RawType clone() {
} else if (parsed != null) {
clone.parsed = parsed.clone();
}
clone.explicitTypeName = explicitTypeName;
clone.explicitTypeDeclaration = explicitTypeDeclaration;
return clone;
}

Expand Down Expand Up @@ -234,6 +250,7 @@ public boolean equals(Object obj) {
} else {
return xnodeSerializationsAreEqual(other);
}
// TODO explicit type declaration? (probably should be ignored as it is now)
}

private boolean xnodeSerializationsAreEqual(RawType other) {
Expand Down
Expand Up @@ -16,13 +16,7 @@

package com.evolveum.midpoint.schema;

import com.evolveum.midpoint.prism.PrismContainer;
import com.evolveum.midpoint.prism.PrismContainerValue;
import com.evolveum.midpoint.prism.PrismContext;
import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.prism.PrismObjectDefinition;
import com.evolveum.midpoint.prism.PrismProperty;
import com.evolveum.midpoint.prism.PrismPropertyValue;
import com.evolveum.midpoint.prism.*;
import com.evolveum.midpoint.prism.delta.ObjectDelta;
import com.evolveum.midpoint.prism.util.PrismAsserts;
import com.evolveum.midpoint.prism.util.PrismTestUtil;
Expand Down
@@ -0,0 +1,192 @@
/*
* Copyright (c) 2010-2017 Evolveum
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.evolveum.midpoint.schema;

import com.evolveum.midpoint.prism.Item;
import com.evolveum.midpoint.prism.PrismContext;
import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.prism.delta.ObjectDelta;
import com.evolveum.midpoint.prism.util.PrismAsserts;
import com.evolveum.midpoint.prism.util.PrismTestUtil;
import com.evolveum.midpoint.prism.xnode.RootXNode;
import com.evolveum.midpoint.schema.constants.MidPointConstants;
import com.evolveum.midpoint.util.PrettyPrinter;
import com.evolveum.midpoint.util.exception.SchemaException;
import com.evolveum.midpoint.xml.ns._public.common.common_3.TaskType;
import com.evolveum.midpoint.xml.ns._public.model.scripting_3.ExecuteScriptType;
import com.evolveum.prism.xml.ns._public.types_3.RawType;
import org.testng.annotations.BeforeSuite;
import org.testng.annotations.Test;
import org.xml.sax.SAXException;

import javax.xml.namespace.QName;
import java.io.File;
import java.io.IOException;

import static org.testng.AssertJUnit.assertTrue;

/**
* @author semancik
*
*/
public class TestParseTaskBulkAction2 {

public static final File TASK_FILE = new File("src/test/resources/common/task-bulk-action-2.xml");

@BeforeSuite
public void setup() throws SchemaException, SAXException, IOException {
PrettyPrinter.setDefaultNamespacePrefix(MidPointConstants.NS_MIDPOINT_PUBLIC_PREFIX);
PrismTestUtil.resetPrismContext(MidPointPrismContextFactory.FACTORY);
}

@Test
public void testParseTaskFileToXNode() throws Exception {
System.out.println("===[ testParseTaskFileToXNode ]===");

// GIVEN
PrismContext prismContext = PrismTestUtil.getPrismContext();

// WHEN
RootXNode node = prismContext.parserFor(TASK_FILE).xml().parseToXNode();

// THEN
System.out.println("Parsed task (XNode):");
System.out.println(node.debugDump());

System.out.println("XML -> XNode -> JSON:\n" + prismContext.jsonSerializer().serialize(node));
System.out.println("XML -> XNode -> YAML:\n" + prismContext.yamlSerializer().serialize(node));
}

@Test
public void testParseTaskFile() throws Exception {
System.out.println("===[ testParseTaskFile ]===");

// GIVEN
PrismContext prismContext = PrismTestUtil.getPrismContext();

// WHEN
PrismObject<TaskType> task = prismContext.parserFor(TASK_FILE).xml().parse();

// THEN
System.out.println("Parsed task:");
System.out.println(task.debugDump());

assertTask(task);

Item executeScriptItem = task.findExtensionItem(new QName("executeScript"));
ExecuteScriptType executeScript = (ExecuteScriptType) executeScriptItem.getRealValue();
Object o = executeScript.getInput().getValue().get(0);
System.out.println(o);
assertTrue("Raw value is not parsed", o instanceof RawType && ((RawType) o).getAlreadyParsedValue() != null);
}

@Test
public void testParseTaskRoundtrip() throws Exception {
System.out.println("===[ testParseTaskRoundtrip ]===");

// GIVEN
PrismContext prismContext = PrismTestUtil.getPrismContext();

PrismObject<TaskType> task = prismContext.parseObject(TASK_FILE);

System.out.println("Parsed task:");
System.out.println(task.debugDump());

assertTask(task);

// SERIALIZE

String serializedTask = prismContext.serializeObjectToString(task, PrismContext.LANG_XML);

System.out.println("serialized task:");
System.out.println(serializedTask);

// RE-PARSE

RootXNode reparsedToXNode = prismContext.parserFor(serializedTask).xml().parseToXNode();
System.out.println("Re-parsed task (to XNode):");
System.out.println(reparsedToXNode.debugDump());

// real reparse

PrismObject<TaskType> reparsedTask = prismContext.parseObject(serializedTask);

System.out.println("Re-parsed task:");
System.out.println(reparsedTask.debugDump());

// Cannot assert here. It will cause parsing of some of the raw values and diff will fail
assertTask(reparsedTask);

ObjectDelta<TaskType> objectDelta = task.diff(reparsedTask);
System.out.println("Delta:");
System.out.println(objectDelta.debugDump());
assertTrue("Delta is not empty", objectDelta.isEmpty());

PrismAsserts.assertEquivalent("Task re-parsed equivalence", task, reparsedTask);

Item executeScriptItem = reparsedTask.findExtensionItem(new QName("executeScript"));
ExecuteScriptType executeScript = (ExecuteScriptType) executeScriptItem.getRealValue();
Object o = executeScript.getInput().getValue().get(0);
System.out.println(o);
assertTrue("Raw value is not parsed", o instanceof RawType && ((RawType) o).getAlreadyParsedValue() != null);
}


private void assertTask(PrismObject<TaskType> task) {

task.checkConsistence();

// assertEquals("Wrong oid", "44444444-4444-4444-4444-000000001111", task.getOid());
// PrismObjectDefinition<TaskType> usedDefinition = task.getDefinition();
// assertNotNull("No task definition", usedDefinition);
// PrismAsserts.assertObjectDefinition(usedDefinition, new QName(SchemaConstantsGenerated.NS_COMMON, "task"),
// TaskType.COMPLEX_TYPE, TaskType.class);
// assertEquals("Wrong class in task", TaskType.class, task.getCompileTimeClass());
// TaskType taskType = task.asObjectable();
// assertNotNull("asObjectable resulted in null", taskType);
//
// assertPropertyValue(task, "name", PrismTestUtil.createPolyString("Task2"));
// assertPropertyDefinition(task, "name", PolyStringType.COMPLEX_TYPE, 0, 1);
//
// assertPropertyValue(task, "taskIdentifier", "44444444-4444-4444-4444-000000001111");
// assertPropertyDefinition(task, "taskIdentifier", DOMUtil.XSD_STRING, 0, 1);
//
// assertPropertyDefinition(task, "executionStatus", JAXBUtil.getTypeQName(TaskExecutionStatusType.class), 1, 1);
// PrismProperty<TaskExecutionStatusType> executionStatusProperty = task.findProperty(TaskType.F_EXECUTION_STATUS);
// PrismPropertyValue<TaskExecutionStatusType> executionStatusValue = executionStatusProperty.getValue();
// TaskExecutionStatusType executionStatus = executionStatusValue.getValue();
// assertEquals("Wrong execution status", TaskExecutionStatusType.RUNNABLE, executionStatus);
//
// PrismContainer extension = task.getExtension();
// PrismContainerValue extensionValue = extension.getValue();
// assertTrue("Extension parent", extensionValue.getParent() == extension);
// assertNull("Extension ID", extensionValue.getId());

}

// private void assertPropertyDefinition(PrismContainer<?> container, String propName, QName xsdType, int minOccurs,
// int maxOccurs) {
// QName propQName = new QName(SchemaConstantsGenerated.NS_COMMON, propName);
// PrismAsserts.assertPropertyDefinition(container, propQName, xsdType, minOccurs, maxOccurs);
// }

// public static void assertPropertyValue(PrismContainer<?> container, String propName, Object propValue) {
// QName propQName = new QName(SchemaConstantsGenerated.NS_COMMON, propName);
// PrismAsserts.assertPropertyValue(container, propQName, propValue);
// }

}
66 changes: 66 additions & 0 deletions infra/schema/src/test/resources/common/task-bulk-action-2.xml
@@ -0,0 +1,66 @@
<!--
~ Copyright (c) 2010-2017 Evolveum
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->

<!--
~ Copyright (c) 2010-2017 Evolveum
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->

<task xmlns="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
xmlns:c="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
xmlns:org="http://midpoint.evolveum.com/xml/ns/public/common/org-3"
oid="829c2d59-91c0-493f-9501-afc336e991c8"
version="14">
<name>Create user</name>
<extension xmlns:se="http://midpoint.evolveum.com/xml/ns/public/model/scripting/extension-3"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:type="c:ExtensionType">
<se:executeScript xmlns:s="http://midpoint.evolveum.com/xml/ns/public/model/scripting-3">
<s:action>
<s:type>add</s:type>
</s:action>
<s:input>
<s:value xsi:type="c:UserType">
<name>joe</name>
<fullName>Joe Doe</fullName>
<givenName>Joe</givenName>
<familyName>Doe</familyName>
</s:value>
</s:input>
</se:executeScript>
</extension>
<taskIdentifier>1507208317101:451769069</taskIdentifier>
<ownerRef xmlns:tns="http://midpoint.evolveum.com/xml/ns/public/common/common-3"
oid="00000000-0000-0000-0000-000000000002"
relation="org:default"
type="tns:UserType"><!-- administrator --></ownerRef>
<executionStatus>closed</executionStatus>
<category>BulkActions</category>
<handlerUri>http://midpoint.evolveum.com/xml/ns/public/model/scripting/handler-3</handlerUri>
<recurrence>single</recurrence>
<binding>tight</binding>
</task>
1 change: 1 addition & 0 deletions infra/schema/testng-unit.xml
Expand Up @@ -91,6 +91,7 @@
<class name="com.evolveum.midpoint.schema.TestParseTask"/>
<class name="com.evolveum.midpoint.schema.TestParseLookupTable"/>
<class name="com.evolveum.midpoint.schema.TestParseTaskBulkAction"/>
<class name="com.evolveum.midpoint.schema.TestParseTaskBulkAction2"/>
<class name="com.evolveum.midpoint.schema.TestParseGenericObject"/>
<class name="com.evolveum.midpoint.schema.TestParseObjectTemplate"/>
<class name="com.evolveum.midpoint.schema.TestParsePasswordPolicy"/>
Expand Down

0 comments on commit 6d00fea

Please sign in to comment.