Skip to content

Commit

Permalink
MID-8842 ninja - initial objects update action impl started
Browse files Browse the repository at this point in the history
  • Loading branch information
1azyman committed Sep 4, 2023
1 parent 3f5dd65 commit 3c36b34
Show file tree
Hide file tree
Showing 5 changed files with 216 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,164 @@

import com.evolveum.midpoint.ninja.action.Action;
import com.evolveum.midpoint.ninja.action.ActionResult;
import com.evolveum.midpoint.ninja.util.ConsoleFormat;
import com.evolveum.midpoint.ninja.util.NinjaUtils;
import com.evolveum.midpoint.prism.PrismContext;
import com.evolveum.midpoint.prism.PrismObject;
import com.evolveum.midpoint.prism.delta.ObjectDelta;
import com.evolveum.midpoint.repo.api.RepoAddOptions;
import com.evolveum.midpoint.repo.api.RepositoryService;
import com.evolveum.midpoint.schema.constants.SchemaConstants;
import com.evolveum.midpoint.schema.result.OperationResult;
import com.evolveum.midpoint.util.MiscUtil;
import com.evolveum.midpoint.util.exception.ObjectAlreadyExistsException;
import com.evolveum.midpoint.util.exception.ObjectNotFoundException;
import com.evolveum.midpoint.util.exception.SchemaException;
import com.evolveum.midpoint.xml.ns._public.common.common_3.ObjectType;
import com.evolveum.midpoint.xml.ns._public.common.common_3.TriggerType;

import org.apache.commons.io.IOUtils;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Comparator;

// todo action should write XML + maybe csv? for review
public class InitialObjects extends Action<InitialObjectsOptions, ActionResult<InitialObjectsResult>> {

private static final String INITIAL_OBJECTS_RESOURCE_PATTERN = "classpath*:/initial-objects/**/*.xml";

@Override
public String getOperationName() {
return "initial objects";
}

@Override
public ActionResult<InitialObjectsResult> execute() throws Exception {
// todo implement
return null;

InitialObjectsResult actionResult = new InitialObjectsResult();

OperationResult result = new OperationResult("Initial objects update");

Resource[] resources = new PathMatchingResourcePatternResolver()
.getResources(INITIAL_OBJECTS_RESOURCE_PATTERN);
Arrays.sort(resources, Comparator.comparing(Resource::getFilename));

for (Resource resource : resources) {
actionResult.incrementTotal();

processFile(resource, result, actionResult);
}

int status = actionResult.getError() == 0 ? 0 : 1;

log.info("");
log.info(
"Initial objects update finished. {}, {}, {} and {}, total: {} objects processed.",
ConsoleFormat.formatMessageWithSuccessParameters("{} added", actionResult.getAdded()),
ConsoleFormat.formatMessageWithInfoParameters("{} merged", actionResult.getMerged()),
ConsoleFormat.formatMessageWithParameters(
"{} unchanged", new Object[] { actionResult.getUnchanged() }, ConsoleFormat.Color.DEFAULT),
ConsoleFormat.formatMessageWithErrorParameters("{} errors", actionResult.getError()),
actionResult.getTotal());

return new ActionResult<>(actionResult, status);
}

private <O extends ObjectType> void processFile(
Resource resource, OperationResult parentResult, InitialObjectsResult actionResult) {

OperationResult result = parentResult.createSubresult("Process file");

final PrismContext prismContext = context.getPrismContext();
final RepositoryService repository = context.getRepository();

log.debug("File: {}", resource.getFilename());

try (InputStream is = resource.getInputStream()) {
String xml = IOUtils.toString(is, StandardCharsets.UTF_8);
PrismObject<O> object = prismContext.parseObject(xml);

PrismObject<O> existing = null;
try {
existing = repository.getObject(object.getCompileTimeClass(), object.getOid(), null, result);
} catch (ObjectNotFoundException ex) {
// this is ok, object will be added, no merge needed
}

if (existing == null) {
// we'll just import object, since it's new one
addObject(object, result, actionResult);
} else {
mergeObject(object, existing, result, actionResult);
}
} catch (Exception ex) {
log.error("Unexpected exception occurred processing file {}", ex, resource.getFilename());
actionResult.incrementError();
}
}

private <O extends ObjectType> void mergeObject(
PrismObject<O> initial, PrismObject<O> existing, OperationResult result, InitialObjectsResult actionResult) {

log.debug("Merging object {}", NinjaUtils.printObjectNameOidAndType(existing));

final PrismObject<O> merged = existing.clone();

// todo do merge

addTrigger(existing);
ObjectDelta<O> delta = merged.diff(existing);
if (delta.isEmpty()) {
log.debug("Skipping object update, delta is empty");

actionResult.incrementUnchanged();
return;
}

try {
log.debug("Updating object {} in repository", NinjaUtils.printObjectNameOidAndType(existing));

context.getRepository().modifyObject(delta.getObjectTypeClass(), delta.getOid(), delta.getModifications(), result);

actionResult.incrementMerged();
} catch (ObjectNotFoundException | ObjectAlreadyExistsException | SchemaException ex) {
log.error(
"Couldn't modify object {} ({}, {})",
ex, existing.getName(), existing.getOid(), existing.toDebugType());

actionResult.incrementError();
}
}

@Deprecated
private <O extends ObjectType> void addTrigger(PrismObject<O> object) {
// todo fix this hack
// so it's recomputed after midpoint is started
TriggerType trigger = new TriggerType()
.timestamp(MiscUtil.asXMLGregorianCalendar(0L))
.handlerUri(SchemaConstants.NS_MODEL + "/trigger/recompute/handler-3");
object.asObjectable().trigger(trigger);
}

private <O extends ObjectType> void addObject(
PrismObject<O> object, OperationResult result, InitialObjectsResult actionResult) {

addTrigger(object);

try {
log.debug("Adding object {} to repository", NinjaUtils.printObjectNameOidAndType(object));

context.getRepository().addObject(object, RepoAddOptions.createOverwrite(), result);

actionResult.incrementAdded();
} catch (ObjectAlreadyExistsException | SchemaException ex) {
log.error("Couldn't add object {} to repository", ex, NinjaUtils.printObjectNameOidAndType(object));

actionResult.incrementError();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,54 @@
package com.evolveum.midpoint.ninja.action.upgrade.action;

public class InitialObjectsResult {

private int total;

private int added;

private int merged;

private int unchanged;

private int error;

void incrementUnchanged() {
unchanged++;
}

void incrementTotal() {
total++;
}

void incrementAdded() {
added++;
}

void incrementMerged() {
merged++;
}

void incrementError() {
error++;
}

public int getTotal() {
return total;
}

public int getAdded() {
return added;
}

public int getMerged() {
return merged;
}

public int getError() {
return error;
}

public int getUnchanged() {
return unchanged;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,11 @@ private void backupAndUpdateSystemProperty(String key, String value) {
String oldValue = System.getProperty(key);
systemPropertiesBackup.put(key, oldValue);

System.setProperty(key, value);
if (value != null) {
System.setProperty(key, value);
} else {
System.clearProperty(key);
}
}

private void overrideRepoConfiguration(ConnectionOptions options) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ public static String formatMessageWithErrorParameters(String message, Object...
return formatMessageWithParameters(message, parameters, Color.ERROR);
}

public static String formatMessageWithSuccessParameters(String message, Object... parameters) {
return formatMessageWithParameters(message, parameters, Color.SUCCESS);
}

public static String formatMessageWithWarningParameters(String message, Object... parameters) {
return formatMessageWithParameters(message, parameters, Color.WARN);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -335,4 +335,12 @@ public static String createHelp(JCommander jc, String parsedCommand) {

return sb.toString();
}

public static String printObjectNameOidAndType(PrismObject<?> object) {
if (object == null) {
return null;
}

return printFormatted("{} ({}, {})", object.getName(), object.getOid(), object.toDebugType());
}
}

0 comments on commit 3c36b34

Please sign in to comment.