Skip to content

Commit

Permalink
cleanup: loading names in configuration dialog
Browse files Browse the repository at this point in the history
  • Loading branch information
1azyman committed Apr 5, 2024
1 parent 21a049c commit 1110075
Show file tree
Hide file tree
Showing 10 changed files with 345 additions and 26 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
package com.evolveum.midpoint.studio.action.task;

import com.evolveum.midpoint.prism.impl.binding.AbstractReferencable;
import com.evolveum.midpoint.prism.query.ObjectQuery;
import com.evolveum.midpoint.studio.client.MidPointObject;
import com.evolveum.midpoint.studio.client.SearchResult;
import com.evolveum.midpoint.studio.impl.MidPointClient;
import com.evolveum.midpoint.studio.impl.configuration.Referencable;
import com.evolveum.midpoint.studio.ui.cleanup.MissingRefNode;
import com.evolveum.midpoint.studio.ui.cleanup.MissingRefObjectsTable;
import com.evolveum.midpoint.studio.util.MidPointUtils;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectReferenceType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType;
import com.intellij.notification.NotificationType;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.project.Project;
import org.jdesktop.swingx.treetable.DefaultMutableTreeTableNode;
import org.jetbrains.annotations.NotNull;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class CleanupReloadNamesTask extends SimpleBackgroundableTask {

public static String TITLE = "Reload names";

public static String NOTIFICATION_KEY = TITLE;

private static final int CHUNK_SIZE = 25;

private final MissingRefObjectsTable table;

public CleanupReloadNamesTask(@NotNull Project project, MissingRefObjectsTable table) {
super(project, TITLE, NOTIFICATION_KEY);

this.table = table;
}

@Override
protected void doRun(ProgressIndicator indicator) {
super.doRun(indicator);

indicator.setIndeterminate(true);

if (client == null) {
MidPointUtils.publishNotification(
getProject(), NOTIFICATION_KEY, TITLE,
"Environment not selected, client not available", NotificationType.WARNING);
return;
}

DefaultMutableTreeTableNode node = (DefaultMutableTreeTableNode) table.getTableModel().getRoot();
Map<ObjectReferenceType, List<DefaultMutableTreeTableNode>> toResolve = listNodesToResolve(node, new HashMap<>());
if (toResolve.isEmpty()) {
return;
}

List<Map<ObjectReferenceType, List<DefaultMutableTreeTableNode>>> chunks = chunkMap(toResolve);

// todo implement only max 4 threads executing at once
for (Map<ObjectReferenceType, List<DefaultMutableTreeTableNode>> chunk : chunks) {
ApplicationManager.getApplication().executeOnPooledThread(
new ResolveChunkRunnable(client, table, chunk));
}
}

private List<Map<ObjectReferenceType, List<DefaultMutableTreeTableNode>>> chunkMap(
Map<ObjectReferenceType, List<DefaultMutableTreeTableNode>> map) {

List<Map<ObjectReferenceType, List<DefaultMutableTreeTableNode>>> chunks = new ArrayList<>();

List<ObjectReferenceType> keys = new ArrayList<>(map.keySet());
for (int i = 0; i < keys.size(); i += CHUNK_SIZE) {
List<ObjectReferenceType> chunkKeys = keys.subList(i, Math.min(keys.size(), i + CHUNK_SIZE));

Map<ObjectReferenceType, List<DefaultMutableTreeTableNode>> chunk = new HashMap<>();
for (ObjectReferenceType key : chunkKeys) {
chunk.put(key, map.get(key));
}
chunks.add(chunk);
}

return chunks;
}

private Map<ObjectReferenceType, List<DefaultMutableTreeTableNode>> listNodesToResolve(
DefaultMutableTreeTableNode node, Map<ObjectReferenceType, List<DefaultMutableTreeTableNode>> toResolve) {

if (node == null) {
return toResolve;
}

Referencable ref = getReferencable(node);

if (ref != null) {
ObjectReferenceType or = ref.toObjectReferenceType();
List<DefaultMutableTreeTableNode> nodes = toResolve.getOrDefault(or, new ArrayList<>());
nodes.add(node);

toResolve.putIfAbsent(or, nodes);
}

for (int i = 0; i < node.getChildCount(); i++) {
DefaultMutableTreeTableNode child = (DefaultMutableTreeTableNode) node.getChildAt(i);
listNodesToResolve(child, toResolve);
}

return toResolve;
}

private Referencable getReferencable(DefaultMutableTreeTableNode node) {
Object userObject = node.getUserObject();
if (userObject instanceof MissingRefNode<?> refNode) {
userObject = refNode.getValue();
}

if (userObject instanceof Referencable ref) {
return ref;
}

return null;
}

private record ResolveChunkRunnable(MidPointClient client,
MissingRefObjectsTable table,
Map<ObjectReferenceType, List<DefaultMutableTreeTableNode>> chunk)
implements Runnable {

private static final Logger LOG = Logger.getInstance(ResolveChunkRunnable.class);

@Override
public void run() {
Class<? extends ObjectType> type = ObjectType.class;

List<String> oids = chunk.keySet().stream().map(AbstractReferencable::getOid).toList();
ObjectQuery query = MidPointUtils.DEFAULT_PRISM_CONTEXT.queryFor(type)
.id(oids.toArray(new String[0]))
.build();

try {
SearchResult result = client.search(type, query, true);
for (MidPointObject object : result.getObjects()) {
ObjectReferenceType key = new ObjectReferenceType()
.oid(object.getOid())
.type(object.getType().getTypeQName());

List<DefaultMutableTreeTableNode> nodes = chunk.getOrDefault(key, List.of());
for (DefaultMutableTreeTableNode node : nodes) {
updateNodeName(node, object.getName());
}
}
} catch (Exception ex) {
LOG.error("Couldn't resolve names", ex);
}
}

private void updateNodeName(DefaultMutableTreeTableNode node, String name) {
Object userObject = node.getUserObject();
if (userObject instanceof MissingRefNode<?> refNode) {
userObject = refNode.getValue();
}

if (userObject instanceof Referencable ref) {
ref.setName(name);
}

ApplicationManager.getApplication().invokeLater(() -> table.getTableModel().nodeChanged(node));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.evolveum.midpoint.studio.util.QNameConverter;
import com.intellij.util.xmlb.annotations.Attribute;
import com.intellij.util.xmlb.annotations.OptionTag;
import com.intellij.util.xmlb.annotations.Tag;
import org.jetbrains.annotations.NotNull;

Expand All @@ -11,17 +12,21 @@
import java.util.Objects;

@Tag("reference")
public class MissingRef implements Serializable, Comparable<MissingRef> {
public class MissingRef implements Serializable, Comparable<MissingRef>, Referencable {

@Attribute
private String oid;

@Attribute(converter = QNameConverter.class)
@OptionTag(tag = "type", nameAttribute = "", converter = QNameConverter.class)
private QName type;

@OptionTag(tag = "name", nameAttribute = "")
private String name;

@Attribute
private MissingRefAction action;

@Override
public String getOid() {
return oid;
}
Expand All @@ -30,6 +35,7 @@ public void setOid(String oid) {
this.oid = oid;
}

@Override
public QName getType() {
return type;
}
Expand All @@ -38,6 +44,16 @@ public void setType(QName type) {
this.type = type;
}

@Override
public String getName() {
return name;
}

@Override
public void setName(String name) {
this.name = name;
}

public MissingRefAction getAction() {
return action;
}
Expand All @@ -53,19 +69,27 @@ public boolean equals(Object o) {
MissingRef that = (MissingRef) o;
return Objects.equals(oid, that.oid)
&& Objects.equals(type, that.type)
&& Objects.equals(name, that.name)
&& action == that.action;
}

@Override
public int hashCode() {
return Objects.hash(oid, type, action);
return Objects.hash(oid, type, name, action);
}

@Override
public int compareTo(@NotNull MissingRef o) {
return Comparator
.comparing(MissingRef::getType, Comparator.nullsLast(Comparator.comparing(QName::toString)))
.thenComparing(MissingRef::getOid, Comparator.nullsLast(Comparator.naturalOrder()))
.comparing(
MissingRef::getName,
Comparator.nullsLast(Comparator.naturalOrder()))
.thenComparing(
MissingRef::getType,
Comparator.nullsLast(Comparator.comparing(QName::toString)))
.thenComparing(
MissingRef::getOid,
Comparator.nullsLast(Comparator.naturalOrder()))
.compare(this, o);

}
Expand All @@ -74,8 +98,19 @@ public MissingRef copy() {
MissingRef copy = new MissingRef();
copy.setOid(oid);
copy.setType(type);
copy.setName(name);
copy.setAction(action);

return copy;
}

@Override
public String toString() {
return "MissingRef{" +
"action=" + action +
", oid='" + oid + '\'' +
", type=" + type +
", name='" + name + '\'' +
'}';
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.evolveum.midpoint.studio.util.QNameConverter;
import com.intellij.util.xmlb.annotations.Attribute;
import com.intellij.util.xmlb.annotations.OptionTag;
import com.intellij.util.xmlb.annotations.Tag;
import com.intellij.util.xmlb.annotations.XCollection;
import org.jetbrains.annotations.NotNull;
Expand All @@ -15,17 +16,21 @@
import java.util.stream.Collectors;

@Tag("object")
public class MissingRefObject implements Serializable, Comparable<MissingRefObject> {
public class MissingRefObject implements Serializable, Comparable<MissingRefObject>, Referencable {

@Attribute
private String oid;

@Attribute(converter = QNameConverter.class)
@OptionTag(tag = "type", nameAttribute = "", converter = QNameConverter.class)
private QName type;

@OptionTag(tag = "name", nameAttribute = "")
private String name;

@XCollection(style = XCollection.Style.v2)
private List<MissingRef> references;

@Override
public String getOid() {
return oid;
}
Expand All @@ -34,6 +39,7 @@ public void setOid(String oid) {
this.oid = oid;
}

@Override
public QName getType() {
return type;
}
Expand All @@ -42,6 +48,16 @@ public void setType(QName type) {
this.type = type;
}

@Override
public String getName() {
return name;
}

@Override
public void setName(String name) {
this.name = name;
}

public List<MissingRef> getReferences() {
if (references == null) {
references = new ArrayList<>();
Expand All @@ -60,18 +76,22 @@ public boolean equals(Object o) {
MissingRefObject that = (MissingRefObject) o;
return Objects.equals(oid, that.oid)
&& Objects.equals(type, that.type)
&& Objects.equals(name, that.name)
&& Objects.equals(references, that.references);
}

@Override
public int hashCode() {
return Objects.hash(oid, type, references);
return Objects.hash(oid, type, name, references);
}

@Override
public int compareTo(@NotNull MissingRefObject o) {
return Comparator
.comparing(
MissingRefObject::getName,
Comparator.nullsLast(Comparator.naturalOrder()))
.thenComparing(
MissingRefObject::getType,
Comparator.nullsLast(Comparator.comparing(QName::toString)))
.thenComparing(
Expand All @@ -84,6 +104,7 @@ public MissingRefObject copy() {
MissingRefObject copy = new MissingRefObject();
copy.setOid(oid);
copy.setType(type);
copy.setName(name);

List<MissingRef> paths = getReferences().stream()
.map(MissingRef::copy)
Expand All @@ -96,4 +117,14 @@ public MissingRefObject copy() {
public boolean isEmpty() {
return references == null || references.isEmpty();
}

@Override
public String toString() {
return "MissingRefObject{" +
"name='" + name + '\'' +
", oid='" + oid + '\'' +
", type=" + type +
", references=" + references.size() +
'}';
}
}

0 comments on commit 1110075

Please sign in to comment.