Skip to content

Commit

Permalink
Archetype ModelInteractionService improvements (MID-3151)
Browse files Browse the repository at this point in the history
  • Loading branch information
semancik committed Dec 3, 2018
1 parent 154bb4d commit 151fdfa
Show file tree
Hide file tree
Showing 13 changed files with 411 additions and 12 deletions.
Expand Up @@ -18,6 +18,7 @@
import com.evolveum.midpoint.gui.api.component.BasePanel;
import com.evolveum.midpoint.gui.api.model.LoadableModel;
import com.evolveum.midpoint.gui.api.util.WebModelServiceUtils;
import com.evolveum.midpoint.model.api.ArchetypeInteractionSpecification;
import com.evolveum.midpoint.model.api.util.ModelContextUtil;
import com.evolveum.midpoint.model.api.util.ModelUtils;
import com.evolveum.midpoint.prism.PrismObject;
Expand Down Expand Up @@ -70,17 +71,17 @@ protected List<ObjectReferenceType> load() {
List<ObjectReferenceType> policyGroupsList = new ArrayList<>();
OperationResult result = new OperationResult(OPERATION_LOAD_SYS_CONFIG);
try {
SystemConfigurationType sysConfig = getPageBase().getModelInteractionService().getSystemConfiguration(result);
if (sysConfig == null){
ArchetypeInteractionSpecification archetypeSpec = getPageBase().getModelInteractionService().getInteractionSpecification(getMainPanelFocusObject(), result);
if (archetypeSpec == null){
return policyGroupsList;
} else {
ObjectPolicyConfigurationType policyConfig = ModelUtils.determineObjectPolicyConfiguration(getMainPanelFocusObject(), sysConfig);
if (policyConfig != null && policyConfig.getApplicablePolicies() != null){
return policyConfig.getApplicablePolicies().getPolicyGroupRef();
ArchetypePolicyType archetypePolicy = archetypeSpec.getArchetypePolicy();
if (archetypePolicy != null && archetypePolicy.getApplicablePolicies() != null){
return archetypePolicy.getApplicablePolicies().getPolicyGroupRef();
}
}
} catch (Exception ex){
LoggingUtils.logUnexpectedException(LOGGER, "Cannot retrieve system configuration", ex);
LoggingUtils.logUnexpectedException(LOGGER, "Cannot retrieve archetype policy for " + getMainPanelFocusObject(), ex);
}
return policyGroupsList;
}
Expand Down
Expand Up @@ -27,6 +27,8 @@
import com.evolveum.midpoint.prism.xnode.RootXNode;
import com.evolveum.midpoint.prism.xnode.XNode;
import com.evolveum.midpoint.util.DOMUtil;
import com.evolveum.midpoint.util.DebugDumpable;
import com.evolveum.midpoint.util.DebugUtil;
import com.evolveum.midpoint.util.exception.SchemaException;
import com.evolveum.prism.xml.ns._public.types_3.PolyStringType;

Expand Down Expand Up @@ -302,4 +304,12 @@ public static MapXNode serializeExpression(ExpressionWrapper expressionWrapper,
xmap.merge(expressionWrapper.getElementName(), xroot.getSubnode());
return xmap;
}

public static void debugDumpWithLabel(StringBuilder sb, String label, Containerable cc, int indent) {
if (cc == null) {
DebugUtil.debugDumpWithLabel(sb, label, (DebugDumpable)null, indent);
} else {
DebugUtil.debugDumpWithLabel(sb, label, cc.asPrismContainerValue(), indent);
}
}
}
Expand Up @@ -15873,6 +15873,22 @@
</xsd:appinfo>
</xsd:annotation>
</xsd:element>
<xsd:element name="color" type="xsd:string" minOccurs="0" maxOccurs="1">
<xsd:annotation>
<xsd:documentation>
Usual color used to render the icon. This color may be used in
situation when colorful presentation is appropriate. The color
may be used to color the icon itself, or it may also color the
background if icon is displayed with "inverted" color.
The color may also be ignored if monochrome presentation is
more appropriate.
Value of this element is HTML-like color name or code.
</xsd:documentation>
<xsd:appinfo>
<a:displayName>IconType.color</a:displayName>
</xsd:appinfo>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
</xsd:complexType>

Expand Down
@@ -0,0 +1,53 @@
/**
* Copyright (c) 2018 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.model.api;

import com.evolveum.midpoint.prism.util.PrismUtil;
import com.evolveum.midpoint.util.DebugDumpable;
import com.evolveum.midpoint.util.DebugUtil;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ArchetypePolicyType;

/**
* Data structure that contains information about all archetype-related interactions for a particular object.
* This include archetype policies, assignments, relations, etc.
* This data structure is supposed to hold all the archetype-related data that the user interface need to
* display the object and to interact with the object. GUI should not need to to any other processing to
* determine archetype-like information.
*
* @author Radovan Semancik
*/
public class ArchetypeInteractionSpecification implements DebugDumpable {

private ArchetypePolicyType archetypePolicy;

public ArchetypePolicyType getArchetypePolicy() {
return archetypePolicy;
}

public void setArchetypePolicy(ArchetypePolicyType archetypePolicy) {
this.archetypePolicy = archetypePolicy;
}

// TODO: assignmentRelation info

@Override
public String debugDump(int indent) {
StringBuilder sb = DebugUtil.createTitleStringBuilderLn(ArchetypeInteractionSpecification.class, indent);
PrismUtil.debugDumpWithLabel(sb, "archetypePolicy", archetypePolicy, indent + 1);
return sb.toString();
}

}
Expand Up @@ -367,4 +367,15 @@ TaskType submitTaskFromTemplate(String templateTaskOid, List<Item<?, ?>> extensi
TaskType submitTaskFromTemplate(String templateTaskOid, Map<QName, Object> extensionValues, Task opTask, OperationResult result)
throws CommunicationException, ObjectNotFoundException, SchemaException, SecurityViolationException,
ConfigurationException, ExpressionEvaluationException, ObjectAlreadyExistsException, PolicyViolationException;

/**
* Efficiently determines information about all archetype-related interactions for a particular object.
* This include archetype policies, assignments, relations, etc. Returns null if no archetype policy is applicable.
* This is a "one stop" method for archetype information in the GUI. The method returns archetype policy even
* for "legacy" situations, e.g. if the policy needs to be determined from system configuration using legacy subtype.
* GUI should not need to to any other processing to determine archetype-like information.
*
* This method is supposed to be very efficient, it should be using caching as much as possible.
*/
<O extends ObjectType> ArchetypeInteractionSpecification getInteractionSpecification(PrismObject<O> object, OperationResult result) throws SchemaException, ConfigurationException;
}
Expand Up @@ -24,6 +24,7 @@
import com.evolveum.midpoint.util.exception.SchemaException;
import com.evolveum.midpoint.util.logging.Trace;
import com.evolveum.midpoint.util.logging.TraceManager;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ArchetypeType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.SystemConfigurationType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.SystemObjectsType;
import org.springframework.beans.factory.annotation.Autowired;
Expand Down Expand Up @@ -119,4 +120,9 @@ private void loadSystemConfiguration(OperationResult result) throws ObjectNotFou
public synchronized void invalidateCaches() {
systemConfiguration = null;
}

public PrismObject<ArchetypeType> getArchetype(String oid, OperationResult result) throws ObjectNotFoundException, SchemaException {
// TODO: make this efficient (use cache)
return cacheRepositoryService.getObject(ArchetypeType.class, oid, null, result);
}
}
Expand Up @@ -49,6 +49,7 @@
import com.evolveum.midpoint.common.refinery.RefinedObjectClassDefinition;
import com.evolveum.midpoint.common.refinery.RefinedResourceSchema;
import com.evolveum.midpoint.common.refinery.RefinedResourceSchemaImpl;
import com.evolveum.midpoint.model.api.ArchetypeInteractionSpecification;
import com.evolveum.midpoint.model.api.ModelAuthorizationAction;
import com.evolveum.midpoint.model.api.ModelExecuteOptions;
import com.evolveum.midpoint.model.api.ModelInteractionService;
Expand All @@ -62,6 +63,7 @@
import com.evolveum.midpoint.model.api.hooks.HookRegistry;
import com.evolveum.midpoint.model.api.util.DeputyUtils;
import com.evolveum.midpoint.model.api.util.MergeDeltas;
import com.evolveum.midpoint.model.api.util.ModelUtils;
import com.evolveum.midpoint.model.api.visualizer.Scene;
import com.evolveum.midpoint.model.common.SystemObjectCache;
import com.evolveum.midpoint.model.common.mapping.MappingFactory;
Expand Down Expand Up @@ -1743,4 +1745,51 @@ public TaskType submitTaskFromTemplate(String templateTaskOid, Map<QName, Object
return submitTaskFromTemplate(templateTaskOid, extensionItems, opTask, parentResult);
}

@Override
public <O extends ObjectType> ArchetypeInteractionSpecification getInteractionSpecification(PrismObject<O> object, OperationResult result) throws SchemaException, ConfigurationException {
if (object == null) {
return null;
}
if (!object.canRepresent(AssignmentHolderType.class)) {
return getArchetypePolicyLegacy(object, result);
}
List<ObjectReferenceType> archetypeRefs = ((AssignmentHolderType)object.asObjectable()).getArchetypeRef();
if (archetypeRefs == null || archetypeRefs.isEmpty()) {
return getArchetypePolicyLegacy(object, result);
}
if (archetypeRefs.size() > 1) {
throw new SchemaException("Only a single archetype for an object is supported: "+object);
}
ObjectReferenceType archetypeRef = archetypeRefs.get(0);

PrismObject<ArchetypeType> archetype;
try {
archetype = systemObjectCache.getArchetype(archetypeRef.getOid(), result);
} catch (ObjectNotFoundException e) {
LOGGER.warn("Archetype {} for object {} cannot be found", archetypeRef.getOid(), object);
return getArchetypePolicyLegacy(object, result);
}
ArchetypePolicyType archetypePolicy = archetype.asObjectable().getArchetypePolicy();
ArchetypeInteractionSpecification archetypeSpec = new ArchetypeInteractionSpecification();
archetypeSpec.setArchetypePolicy(archetypePolicy);
return archetypeSpec;
}

private <O extends ObjectType> ArchetypeInteractionSpecification getArchetypePolicyLegacy(PrismObject<O> object, OperationResult result) throws SchemaException, ConfigurationException {
SystemConfigurationType systemConfiguration;
try {
systemConfiguration = getSystemConfiguration(result);
} catch (ObjectNotFoundException e) {
// This can happen in tests
return null;
}
ObjectPolicyConfigurationType objectPolicyConfiguration = ModelUtils.determineObjectPolicyConfiguration(object, systemConfiguration);
if (objectPolicyConfiguration == null) {
return null;
}
ArchetypeInteractionSpecification archetypeSpec = new ArchetypeInteractionSpecification();
archetypeSpec.setArchetypePolicy(objectPolicyConfiguration);
return archetypeSpec;
}

}
Expand Up @@ -53,13 +53,15 @@ public class TestArchetypes extends AbstractInitializedModelIntegrationTest {

public static final File ARCHETYPE_EMPLOYEE_FILE = new File(TEST_DIR, "archetype-employee.xml");
protected static final String ARCHETYPE_EMPLOYEE_OID = "7135e68c-ee53-11e8-8025-170b77da3fd6";
private static final String ARCHETYPE_EMPLOYEE_DISPLAY_LABEL = "Employee";
private static final String ARCHETYPE_EMPLOYEE_DISPLAY_PLURAL_LABEL = "Employees";

public static final File ARCHETYPE_TEST_FILE = new File(TEST_DIR, "archetype-test.xml");
protected static final String ARCHETYPE_TEST_OID = "a8df34a8-f6f0-11e8-b98e-eb03652d943f";

public static final File ROLE_EMPLOYEE_BASE_FILE = new File(TEST_DIR, "role-employee-base.xml");
protected static final String ROLE_EMPLOYEE_BASE_OID = "e869d6c4-f6ef-11e8-b51f-df3e51bba129";

@Override
public void initSystem(Task initTask, OperationResult initResult) throws Exception {
super.initSystem(initTask, initResult);
Expand Down Expand Up @@ -113,15 +115,23 @@ public void test100AssignJackArchetypeEmployee() throws Exception {
displayThen(TEST_NAME);
assertSuccess(result);

assertUserAfter(USER_JACK_OID)
PrismObject<UserType> userAfter = assertUserAfter(USER_JACK_OID)
.assignments()
.assertAssignments(1)
.assertArchetype(ARCHETYPE_EMPLOYEE_OID)
.end()
.assertArchetypeRef(ARCHETYPE_EMPLOYEE_OID)
.roleMembershipRefs()
.assertRoleMemberhipRefs(1)
.assertArchetype(ARCHETYPE_EMPLOYEE_OID);
.assertArchetype(ARCHETYPE_EMPLOYEE_OID)
.end()
.getObject();

assertArchetypeSpec(userAfter)
.archetypePolicy()
.displayType()
.assertLabel(ARCHETYPE_EMPLOYEE_DISPLAY_LABEL)
.assertPluralLabel(ARCHETYPE_EMPLOYEE_DISPLAY_PLURAL_LABEL);
}

@Test
Expand All @@ -141,13 +151,18 @@ public void test109UnassignJackArchetypeEmployee() throws Exception {
displayThen(TEST_NAME);
assertSuccess(result);

assertUserAfter(USER_JACK_OID)
PrismObject<UserType> userAfter = assertUserAfter(USER_JACK_OID)
.assignments()
.assertAssignments(0)
.end()
.assertNoArchetypeRef()
.roleMembershipRefs()
.assertRoleMemberhipRefs(0);
.assertRoleMemberhipRefs(0)
.end()
.getObject();

assertArchetypeSpec(userAfter)
.assertNull();
}

@Test
Expand Down Expand Up @@ -273,5 +288,10 @@ public void test129UnassignJackArchetypeTest() throws Exception {
// TODO: search by archetypeRef

// TODO: object template in archetype
// TODO: correct application of object template for new object (not yet stored)

// TODO: assertArchetypeSpec() for new object (not yet stored)

// TODO: assignmentRelation (assertArchetypeSpec)

}
Expand Up @@ -19,5 +19,14 @@
xmlns:t="http://prism.evolveum.com/xml/ns/public/types-3"
xmlns:piracy="http://midpoint.evolveum.com/xml/ns/samples/piracy">
<name>Employee</name>
<!-- TODO -->
<archetypePolicy>
<display>
<label>Employee</label>
<pluralLabel>Employees</pluralLabel>
<icon>
<cssClass>fe fe-employee</cssClass>
<color>blue</color>
</icon>
</display>
</archetypePolicy>
</archetype>
Expand Up @@ -85,6 +85,7 @@
import com.evolveum.midpoint.common.refinery.RefinedObjectClassDefinition;
import com.evolveum.midpoint.common.refinery.RefinedResourceSchema;
import com.evolveum.midpoint.common.refinery.RefinedResourceSchemaImpl;
import com.evolveum.midpoint.model.api.ArchetypeInteractionSpecification;
import com.evolveum.midpoint.model.api.ModelAuditService;
import com.evolveum.midpoint.model.api.ModelAuthorizationAction;
import com.evolveum.midpoint.model.api.ModelDiagnosticService;
Expand All @@ -100,6 +101,7 @@
import com.evolveum.midpoint.model.common.SystemObjectCache;
import com.evolveum.midpoint.model.common.stringpolicy.UserValuePolicyOriginResolver;
import com.evolveum.midpoint.model.common.stringpolicy.ValuePolicyProcessor;
import com.evolveum.midpoint.model.test.asserter.ArchetypeInteractionSpecificationAsserter;
import com.evolveum.midpoint.model.test.asserter.ModelContextAsserter;
import com.evolveum.midpoint.notifications.api.NotificationManager;
import com.evolveum.midpoint.notifications.api.transports.Message;
Expand Down Expand Up @@ -157,6 +159,7 @@
import com.evolveum.midpoint.test.DummyResourceContoller;
import com.evolveum.midpoint.test.IntegrationTestTools;
import com.evolveum.midpoint.test.asserter.AbstractAsserter;
import com.evolveum.midpoint.test.asserter.ArchetypePolicyAsserter;
import com.evolveum.midpoint.test.asserter.DummyAccountAsserter;
import com.evolveum.midpoint.test.asserter.DummyGroupAsserter;
import com.evolveum.midpoint.test.asserter.FocusAsserter;
Expand Down Expand Up @@ -184,6 +187,7 @@
import com.evolveum.midpoint.xml.ns._public.common.common_3.ActivationStatusType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ActivationType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.AdminGuiConfigurationType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ArchetypePolicyType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ArchetypeType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentSelectorType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.AssignmentType;
Expand Down Expand Up @@ -6183,5 +6187,14 @@ protected <O extends ObjectType> void failAllow(String action, SecurityViolation
AssertJUnit.fail(msg);
}
}

protected <O extends ObjectType> ArchetypeInteractionSpecificationAsserter<Void> assertArchetypeSpec(PrismObject<O> object) throws SchemaException, ConfigurationException {
OperationResult result = new OperationResult("assertArchetypeSpec");
ArchetypeInteractionSpecification archetypeSpec = modelInteractionService.getInteractionSpecification(object, result);
ArchetypeInteractionSpecificationAsserter<Void> asserter = new ArchetypeInteractionSpecificationAsserter<>(archetypeSpec, null, "for "+object);
initializeAsserter(asserter);
asserter.display();
return asserter;
}

}

0 comments on commit 151fdfa

Please sign in to comment.