Skip to content

Commit d117004

Browse files
author
jkamenicky
committed
Smart integration: add SCIM-specific field handling in BaseUrlConnectorStepPanel
Show scimBaseUrl and developmentMode fields for SCIM integration type, and baseAddress for REST. Suggested URL is pre-filled into the correct field based on integration type. Completion check and mandatory handling updated accordingly. Fix reference to renamed BASE_ADDRESS_ITEM_NAME in ConnectorDevelopmentWizardSummaryPanel. Preserve non-SCIM processed documentation when refreshing SCIM docs; refactor loadShadowsAsDocumentation to return one entry per shadow.
1 parent e580acc commit d117004

File tree

3 files changed

+71
-28
lines changed

3 files changed

+71
-28
lines changed

gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/page/admin/connector/development/component/wizard/scimrest/connection/BaseUrlConnectorStepPanel.java

Lines changed: 44 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import com.evolveum.midpoint.xml.ns._public.common.common_3.*;
3535

3636
import org.apache.commons.lang3.StringUtils;
37+
import java.util.List;
3738
import org.apache.wicket.ajax.AjaxRequestTarget;
3839
import org.apache.wicket.behavior.AttributeAppender;
3940
import org.apache.wicket.markup.html.WebMarkupContainer;
@@ -51,7 +52,9 @@
5152
public class BaseUrlConnectorStepPanel extends AbstractFormWizardStepPanel<ConnectorDevelopmentDetailsModel> {
5253

5354
private static final String PANEL_TYPE = "cdw-base-url";
54-
public static final ItemName PROPERTY_ITEM_NAME = ItemName.from("", "baseAddress");
55+
public static final ItemName BASE_ADDRESS_ITEM_NAME = ItemName.from("", "baseAddress");
56+
public static final ItemName DEVELOPMENT_MODE_ITEM_NAME = ItemName.from("", "developmentMode");
57+
public static final ItemName SCIM_BASE_URL_ITEM_NAME = ItemName.from("", "scimBaseUrl");
5558

5659
private static final String ID_AI_ALERT = "aiAlert";
5760

@@ -83,12 +86,14 @@ protected IModel<? extends PrismContainerWrapper> getContainerFormModel() {
8386
protected void onInitialize() {
8487
super.onInitialize();
8588
try {
86-
PrismPropertyValueWrapper<Object> suggestedValue = getDetailsModel().getObjectWrapper().findProperty(
87-
ItemPath.create(ConnectorDevelopmentType.F_APPLICATION, ConnDevApplicationInfoType.F_BASE_API_ENDPOINT)).getValue();
88-
if (StringUtils.isNotEmpty((String) suggestedValue.getRealValue())) {
89-
PrismPropertyValueWrapper<String> configurationValue = (PrismPropertyValueWrapper<String>) getContainerFormModel().getObject().findProperty(PROPERTY_ITEM_NAME).getValue();
90-
if (StringUtils.isEmpty(configurationValue.getRealValue())) {
91-
configurationValue.setRealValue((String) suggestedValue.getRealValue());
89+
String suggestedUrl = (String) getDetailsModel().getObjectWrapper().findProperty(
90+
ItemPath.create(ConnectorDevelopmentType.F_APPLICATION, ConnDevApplicationInfoType.F_BASE_API_ENDPOINT))
91+
.getValue().getRealValue();
92+
if (StringUtils.isNotEmpty(suggestedUrl)) {
93+
ItemName urlField = isScim() ? SCIM_BASE_URL_ITEM_NAME : BASE_ADDRESS_ITEM_NAME;
94+
PrismPropertyValueWrapper<String> fieldValue = (PrismPropertyValueWrapper<String>) getContainerFormModel().getObject().findProperty(urlField).getValue();
95+
if (StringUtils.isEmpty(fieldValue.getRealValue())) {
96+
fieldValue.setRealValue(suggestedUrl);
9297
}
9398
}
9499
} catch (SchemaException e) {
@@ -186,22 +191,48 @@ protected IModel<?> getSubTextModel() {
186191
}
187192

188193
protected boolean checkMandatory(ItemWrapper wrapper) {
189-
if (QNameUtil.match(wrapper.getItemName(), PROPERTY_ITEM_NAME)) {
190-
return true;
194+
if (isScim()) {
195+
if (QNameUtil.match(wrapper.getItemName(), SCIM_BASE_URL_ITEM_NAME)) {
196+
return true;
197+
}
198+
} else {
199+
if (QNameUtil.match(wrapper.getItemName(), BASE_ADDRESS_ITEM_NAME)) {
200+
return true;
201+
}
191202
}
192203
return wrapper.isMandatory();
193204
}
194205

195206
@Override
196207
protected ItemVisibilityHandler getVisibilityHandler() {
197208
return wrapper -> {
198-
if (QNameUtil.match(wrapper.getItemName(), PROPERTY_ITEM_NAME)) {
199-
return ItemVisibility.AUTO;
209+
if (isScim()) {
210+
if (scimItemNames().stream().anyMatch(name -> QNameUtil.match(wrapper.getItemName(), name))) {
211+
return ItemVisibility.AUTO;
212+
}
213+
} else {
214+
if (QNameUtil.match(wrapper.getItemName(), BASE_ADDRESS_ITEM_NAME)) {
215+
return ItemVisibility.AUTO;
216+
}
200217
}
201218
return ItemVisibility.HIDDEN;
202219
};
203220
}
204221

222+
private List<ItemName> scimItemNames() {
223+
return List.of(SCIM_BASE_URL_ITEM_NAME, DEVELOPMENT_MODE_ITEM_NAME);
224+
}
225+
226+
private boolean isScim() {
227+
try {
228+
PrismPropertyWrapper<ConnDevIntegrationType> integrationType = getDetailsModel().getObjectWrapper().findProperty(
229+
ItemPath.create(ConnectorDevelopmentType.F_CONNECTOR, ConnDevConnectorType.F_INTEGRATION_TYPE));
230+
return ConnDevIntegrationType.SCIM.equals(integrationType.getValue().getRealValue());
231+
} catch (SchemaException e) {
232+
return false;
233+
}
234+
}
235+
205236
@Override
206237
public String getStepId() {
207238
return PANEL_TYPE;
@@ -236,7 +267,8 @@ public boolean onNextPerformed(AjaxRequestTarget target) {
236267

237268
@Override
238269
public boolean isCompleted() {
270+
ItemName fieldToCheck = isScim() ? SCIM_BASE_URL_ITEM_NAME : BASE_ADDRESS_ITEM_NAME;
239271
return ConnectorDevelopmentWizardUtil.existTestingResourcePropertyValue(
240-
getDetailsModel(), getPanelType(), PROPERTY_ITEM_NAME);
272+
getDetailsModel(), getPanelType(), fieldToCheck);
241273
}
242274
}

gui/admin-gui/src/main/java/com/evolveum/midpoint/gui/impl/page/admin/connector/development/component/wizard/summary/ConnectorDevelopmentWizardSummaryPanel.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ protected StringValuesWidgetDetailsDto load() {
255255
values.put(
256256
createStringResource("ConnectorDevelopmentWizardSummaryPanel.baseUrl"),
257257
defineValueModel((String) ConnectorDevelopmentWizardUtil.getTestingResourcePropertyValue(
258-
detailsModel, null, BaseUrlConnectorStepPanel.PROPERTY_ITEM_NAME)));
258+
detailsModel, null, BaseUrlConnectorStepPanel.BASE_ADDRESS_ITEM_NAME)));
259259
values.put(
260260
createStringResource("ConnectorDevelopmentWizardSummaryPanel.testEndpoint"),
261261
defineValueModel((String) ConnectorDevelopmentWizardUtil.getTestingResourcePropertyValue(

model/smart-impl/src/main/java/com/evolveum/midpoint/smart/impl/conndev/ScimBackend.java

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import com.evolveum.midpoint.xml.ns._public.common.common_3.ConnDevDocumentationSourceType;
1515
import com.fasterxml.jackson.databind.ObjectMapper;
1616
import com.evolveum.midpoint.xml.ns._public.common.common_3.ConnectorDevelopmentType;
17+
import com.evolveum.midpoint.xml.ns._public.common.common_3.ProcessedDocumentationType;
1718
import com.evolveum.midpoint.xml.ns._public.common.common_3.ResourceType;
1819
import com.evolveum.midpoint.xml.ns._public.common.common_3.ShadowType;
1920

@@ -28,8 +29,7 @@ public class ScimBackend extends RestBackend {
2829

2930
private static final Trace LOGGER = TraceManager.getTrace(ScimBackend.class);
3031

31-
private static final String SCIM_SCHEMA_OBJECT_CLASS = "conndev_ScimSchema";
32-
private static final String SCIM_RESOURCE_OBJECT_CLASS = "conndev_ScimResource";
32+
private static final List<String> SCIM_OBJECT_CLASSES = List.of("conndev_ScimSchema", "conndev_ScimResource");
3333

3434
public ScimBackend(ConnDevBeans beans, ConnectorDevelopmentType connDev, Task task, OperationResult result) {
3535
super(beans, connDev, task, result);
@@ -59,22 +59,32 @@ private void refreshScimDocumentation() throws SchemaException, ExpressionEvalua
5959
ResourceUtils.deleteSchema(testingResourceOid, beans.modelService, task, result);
6060
beans.provisioningService.testResource(testingResourceOid, task, result);
6161

62-
var docs = Stream.of(SCIM_SCHEMA_OBJECT_CLASS, SCIM_RESOURCE_OBJECT_CLASS)
63-
.map(objectClass -> loadShadowsAsDocumentation(testingResourceOid, objectClass))
64-
.filter(Objects::nonNull)
62+
var newScimDocs = SCIM_OBJECT_CLASSES
63+
.stream()
64+
.flatMap(objectClass -> loadShadowsAsDocumentation(testingResourceOid, objectClass).stream())
6565
.map(ProcessedDocumentation::toBean)
6666
.toList();
6767

68+
var mergedDocs = new ArrayList<>(
69+
developmentObject()
70+
.getProcessedDocumentation()
71+
.stream()
72+
.filter(d -> SCIM_OBJECT_CLASSES.stream().noneMatch(c -> d.getUri().startsWith(c)))
73+
.map(ProcessedDocumentationType::clone)
74+
.toList()
75+
);
76+
mergedDocs.addAll(newScimDocs);
77+
6878
var delta = PrismContext.get().deltaFor(ConnectorDevelopmentType.class)
6979
.item(ConnectorDevelopmentType.F_PROCESSED_DOCUMENTATION)
70-
.replaceRealValues(docs)
80+
.replaceRealValues(mergedDocs)
7181
.<ConnectorDevelopmentType>asObjectDelta(developmentObject().getOid());
7282
beans.modelService.executeChanges(List.of(delta), null, task, result);
7383
reload();
7484
ensureDocumentationIsUploaded(client().synchronizationClient());
7585
}
7686

77-
private ProcessedDocumentation loadShadowsAsDocumentation(String resourceOid, String objectClassLocalName) {
87+
private List<ProcessedDocumentation> loadShadowsAsDocumentation(String resourceOid, String objectClassLocalName) {
7888
try {
7989
var objectClass = new QName(SchemaConstants.NS_RI, objectClassLocalName);
8090
var query = PrismContext.get().queryFor(ShadowType.class)
@@ -85,24 +95,25 @@ private ProcessedDocumentation loadShadowsAsDocumentation(String resourceOid, St
8595
var shadows = beans.provisioningService.searchObjects(ShadowType.class, query, null, task, result);
8696
if (shadows.isEmpty()) {
8797
LOGGER.warn("No shadows found for object class {} on resource {}", objectClassLocalName, resourceOid);
88-
return null;
98+
return List.of();
8999
}
90100

91-
LOGGER.info("Loaded {} shadow(s) for {}", shadows.size(), objectClassLocalName);
92101
var serializer = PrismContext.get().jsonSerializer();
93102
var mapper = new ObjectMapper();
94-
var schemas = new ArrayList<String>();
103+
var docs = new ArrayList<ProcessedDocumentation>();
95104
for (var shadow : shadows) {
96105
var attrs = shadow.findContainer(ShadowType.F_ATTRIBUTES);
97106
if (attrs != null && !attrs.isEmpty()) {
98107
var json = serializer.serialize(attrs.getValue());
99-
schemas.add(mapper.readTree(json).get("attributes").toString());
108+
var parsedAttrs = mapper.readTree(json).get("attributes");
109+
var nameNode = parsedAttrs.get("name");
110+
var name = nameNode != null ? nameNode.asText() : shadow.getOid();
111+
var doc = new ProcessedDocumentation(UUID.randomUUID().toString(), objectClassLocalName + "_" + name);
112+
doc.write(parsedAttrs.toString());
113+
docs.add(doc);
100114
}
101115
}
102-
var serialized = "{\"schemas\":[" + String.join(",", schemas) + "]}";
103-
var doc = new ProcessedDocumentation(UUID.randomUUID().toString(), objectClassLocalName);
104-
doc.write(serialized);
105-
return doc;
116+
return docs;
106117
} catch (Exception e) {
107118
throw new SystemException("Could not load shadow documentation for " + objectClassLocalName, e);
108119
}

0 commit comments

Comments
 (0)