ENTAXY-480 release version 1.8.3
This commit is contained in:
@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>ru.entaxy.esb.platform.runtime.core</groupId>
|
||||
<artifactId>object-producing</artifactId>
|
||||
<version>1.8.2.2</version>
|
||||
<version>1.8.3</version>
|
||||
</parent>
|
||||
<groupId>ru.entaxy.esb.platform.runtime.core.object-producing</groupId>
|
||||
<artifactId>object-producer-api</artifactId>
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* test-producers
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* test-producers
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -27,10 +27,27 @@ import ru.entaxy.platform.base.objects.factory.EntaxyFactory;
|
||||
|
||||
public interface EntaxyProducerService {
|
||||
|
||||
public static interface DIRECTIVES {
|
||||
|
||||
String LIFECYCLE = "@LIFECYCLE";
|
||||
|
||||
/*
|
||||
* usage: {"@SKIP": ['command1', 'command2-', 'command3+']}
|
||||
* where
|
||||
* 'command1' - skip command1
|
||||
* 'command2-' - skip ALL BEFORE command2
|
||||
* 'command3+' - skip ALL AFTER command3
|
||||
*/
|
||||
String SKIP = "@SKIP";
|
||||
|
||||
};
|
||||
|
||||
public static interface INSTRUCTIONS {
|
||||
|
||||
public static final String PRINT_OUTPUT = "printOutput";
|
||||
public static final String SKIP = "skip";
|
||||
String PRINT_OUTPUT = "printOutput";
|
||||
String SKIP = "skip";
|
||||
String MAX_COUNT = "maxCount";
|
||||
String CURRENT_ITERATION = "currentCount";
|
||||
|
||||
public static interface ARTIFACT {
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* object-producer-api
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -20,8 +20,11 @@
|
||||
package ru.entaxy.platform.core.producer.api;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import ru.entaxy.platform.base.objects.EntaxyObjectService;
|
||||
|
||||
public class EntaxyProducerUtils {
|
||||
|
||||
protected static Gson sharedGson = new Gson();
|
||||
@ -41,6 +44,14 @@ public class EntaxyProducerUtils {
|
||||
protected InstructionsBuilder(JsonObject jsonObject) {
|
||||
super(jsonObject);
|
||||
}
|
||||
|
||||
public InstructionsBuilder lifecycle(String lifecycle) {
|
||||
if (!instructionsJson.has(EntaxyProducerService.DIRECTIVES.LIFECYCLE))
|
||||
instructionsJson.add(EntaxyProducerService.DIRECTIVES.LIFECYCLE, new JsonArray());
|
||||
JsonArray lc = instructionsJson.get(EntaxyProducerService.DIRECTIVES.LIFECYCLE).getAsJsonArray();
|
||||
lc.add(lifecycle);
|
||||
return this;
|
||||
}
|
||||
|
||||
public CommandBuilder command(String commandName) {
|
||||
if (!instructionsJson.has(commandName))
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* test-producers
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* test-producers
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* test-producers
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* test-producers
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* test-producers
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -23,10 +23,12 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public interface ProducingCommandExecutor {
|
||||
|
||||
public String getId();
|
||||
public List<String> getRequiredPredecessors();
|
||||
public List<String> getDescendants();
|
||||
public List<Class<?>> getAcceptedInputClasses();
|
||||
public List<Class<?>> getProducedOutputClasses();
|
||||
public ProducerResult execute(ProducerResult currentResult, Map<String, Object> parameters);
|
||||
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>ru.entaxy.esb.platform.runtime.core</groupId>
|
||||
<artifactId>object-producing</artifactId>
|
||||
<version>1.8.2.2</version>
|
||||
<version>1.8.3</version>
|
||||
</parent>
|
||||
<groupId>ru.entaxy.esb.platform.runtime.core.object-producing</groupId>
|
||||
<artifactId>object-producer-core</artifactId>
|
||||
@ -28,5 +28,37 @@
|
||||
<artifactId>artifact-management</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.camel</groupId>
|
||||
<artifactId>camel-core</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>build-helper-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-artifacts</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>attach-artifact</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<artifacts>
|
||||
<artifact>
|
||||
<file>src/main/config/producing.lifecycles.json</file>
|
||||
<type>json</type>
|
||||
<classifier>producing.lifecycles</classifier>
|
||||
</artifact>
|
||||
</artifacts>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* test-producers
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -28,16 +28,18 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import ru.entaxy.platform.core.producer.api.EntaxyProducerService;
|
||||
import ru.entaxy.platform.core.producer.api.EntaxyProducerService.INSTRUCTIONS;
|
||||
import ru.entaxy.platform.core.producer.api.ProducerResult;
|
||||
import ru.entaxy.platform.core.producer.api.ProducerResult.CommandResult;
|
||||
import ru.entaxy.platform.core.producer.api.ProducingCommandExecutor;
|
||||
import ru.entaxy.platform.core.producer.executor.support.AbstractPrintOutputSupport;
|
||||
|
||||
public abstract class AbstractCommandExecutor implements ProducingCommandExecutor {
|
||||
public abstract class AbstractCommandExecutor extends AbstractPrintOutputSupport
|
||||
implements ProducingCommandExecutor {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(AbstractCommandExecutor.class);
|
||||
|
||||
public static String SKIP_INSTRUSTION = "skip";
|
||||
public static String PRINT_OUTPUT_INSTRUSTION = "printOutput";
|
||||
public static int DEFAULT_MAX_COUNT = 15;
|
||||
|
||||
protected EntaxyProducerService entaxyProducerService;
|
||||
|
||||
@ -47,8 +49,6 @@ public abstract class AbstractCommandExecutor implements ProducingCommandExecuto
|
||||
protected List<Class<?>> acceptedInputClasses = new ArrayList<>();
|
||||
protected List<Class<?>> producedOutputClasses = new ArrayList<>();
|
||||
|
||||
protected boolean isPrintOutput = false;
|
||||
|
||||
protected Map<String, Object> instructions;
|
||||
|
||||
protected AbstractCommandExecutor(EntaxyProducerService entaxyProducerService) {
|
||||
@ -113,39 +113,69 @@ public abstract class AbstractCommandExecutor implements ProducingCommandExecuto
|
||||
CommandResult cr = new CommandResult(getId());
|
||||
this.instructions = instructions;
|
||||
setPrintOutput(instructions);
|
||||
if (isSkipped(instructions))
|
||||
int maxCount = getMaxCount(instructions);
|
||||
int currentCount = getCurrentCount(instructions);
|
||||
printOutput("\n\n\t== " + getId().toUpperCase() + " == #" + currentCount + " of " + maxCount + " ==\n");
|
||||
if (isSkipped(instructions)) {
|
||||
cr.skipped = true;
|
||||
else
|
||||
printOutput(" :: SKIPPED ");
|
||||
} else {
|
||||
try {
|
||||
cr.result = doExecute(currentResult, cr, instructions);
|
||||
} catch (Exception e) {
|
||||
log.error("Error executing [" + getId() + "]", e);
|
||||
cr.exception(e).result(false);
|
||||
}
|
||||
if (currentCount >= maxCount) {
|
||||
instructions.put(INSTRUCTIONS.SKIP, true);
|
||||
printOutput(" !! Max iteration count of [" + maxCount + "] is reached"
|
||||
+ "\n futher iterations will be skipped ");
|
||||
} else {
|
||||
increaseCurrentCount(instructions);
|
||||
}
|
||||
}
|
||||
printOutput("\n\n\t== /" + getId().toUpperCase() + " == ");
|
||||
currentResult.addCommandResult(cr);
|
||||
return currentResult;
|
||||
}
|
||||
|
||||
protected void setPrintOutput(Map<String, Object> parameters) {
|
||||
if (parameters.containsKey(PRINT_OUTPUT_INSTRUSTION)) {
|
||||
Object val = parameters.get(PRINT_OUTPUT_INSTRUSTION);
|
||||
if (val == null)
|
||||
return;
|
||||
if (val instanceof Boolean)
|
||||
this.isPrintOutput = (Boolean)val;
|
||||
}
|
||||
}
|
||||
|
||||
protected void printOutput(String message) {
|
||||
if (this.isPrintOutput)
|
||||
// OUTPUT TO CONSOLE
|
||||
System.out.println(message);
|
||||
protected int getMaxCount(Map<String, Object> parameters) {
|
||||
int result = DEFAULT_MAX_COUNT;
|
||||
if (parameters.containsKey(INSTRUCTIONS.MAX_COUNT)) {
|
||||
Object val = parameters.get(INSTRUCTIONS.MAX_COUNT);
|
||||
try {
|
||||
result = ((Number)val).intValue();
|
||||
} catch (Exception e) {
|
||||
parameters.put(INSTRUCTIONS.MAX_COUNT, DEFAULT_MAX_COUNT);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
protected int getCurrentCount(Map<String, Object> parameters) {
|
||||
int result = 1;
|
||||
if (parameters.containsKey(INSTRUCTIONS.CURRENT_ITERATION)) {
|
||||
Object val = parameters.get(INSTRUCTIONS.CURRENT_ITERATION);
|
||||
try {
|
||||
result = (Integer)val;
|
||||
} catch (Exception e) {
|
||||
parameters.put(INSTRUCTIONS.CURRENT_ITERATION, 1);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
protected int increaseCurrentCount(Map<String, Object> parameters) {
|
||||
int currentCount = getCurrentCount(parameters);
|
||||
currentCount++;
|
||||
parameters.put(INSTRUCTIONS.CURRENT_ITERATION, currentCount);
|
||||
return getCurrentCount(parameters);
|
||||
}
|
||||
|
||||
protected boolean isSkipped(Map<String, Object> parameters) {
|
||||
if (!parameters.containsKey(SKIP_INSTRUSTION))
|
||||
if (!parameters.containsKey(INSTRUCTIONS.SKIP))
|
||||
return false;
|
||||
Object obj = parameters.get(SKIP_INSTRUSTION);
|
||||
Object obj = parameters.get(INSTRUCTIONS.SKIP);
|
||||
if (obj instanceof Boolean)
|
||||
return (Boolean)obj;
|
||||
if (obj instanceof String)
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* test-producers
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* object-producer-core
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* test-producers
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -26,10 +26,12 @@ import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
@ -37,6 +39,7 @@ import ru.entaxy.platform.base.support.CommonUtils;
|
||||
import ru.entaxy.platform.base.support.DependencySorter;
|
||||
import ru.entaxy.platform.base.support.JSONUtils;
|
||||
import ru.entaxy.platform.core.producer.api.EntaxyProducerService;
|
||||
import ru.entaxy.platform.core.producer.api.EntaxyProducerService.INSTRUCTIONS;
|
||||
import ru.entaxy.platform.core.producer.api.ExecutionPlan;
|
||||
import ru.entaxy.platform.core.producer.api.ExecutionPlan.ExecutionPlanUpdate;
|
||||
import ru.entaxy.platform.core.producer.api.ExecutionPlan.ExecutionPlanUpdate.OPERATIONS;
|
||||
@ -48,6 +51,8 @@ public class ProducingExecutor {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(ProducingExecutor.class);
|
||||
|
||||
public static final String DIRECTIVE_SKIP = EntaxyProducerService.DIRECTIVES.SKIP;
|
||||
|
||||
protected static final String DEFAULT_EXECUTION_PLAN = "{'validate':{}}";
|
||||
|
||||
protected static final String ANY_COMMAND = "*";
|
||||
@ -103,8 +108,24 @@ public class ProducingExecutor {
|
||||
Map<String, ExecutionTask> taskMap = new HashMap<>();
|
||||
|
||||
Map<String, Object> anyCommandInstructions = new HashMap<>();
|
||||
if (executionPlanJSON.has(ANY_COMMAND))
|
||||
anyCommandInstructions = JSONUtils.element2map(executionPlanJSON.get(ANY_COMMAND));
|
||||
JsonObject directives = new JsonObject();
|
||||
if (executionPlanJSON.has(ANY_COMMAND)) {
|
||||
JsonElement anyCommandElement = executionPlanJSON.get(ANY_COMMAND).deepCopy();
|
||||
if (anyCommandElement.isJsonObject()) {
|
||||
JsonObject anyCommandObject = anyCommandElement.getAsJsonObject();
|
||||
List<String> toRemove = new ArrayList<>();
|
||||
for (Entry<String, JsonElement> entry: anyCommandObject.entrySet())
|
||||
if (entry.getKey().startsWith("@")) {
|
||||
directives.add(entry.getKey(), entry.getValue().deepCopy());
|
||||
toRemove.add(entry.getKey());
|
||||
}
|
||||
// remove directives
|
||||
for (String s: toRemove)
|
||||
anyCommandObject.remove(s);
|
||||
}
|
||||
anyCommandInstructions = JSONUtils.element2map(anyCommandElement);
|
||||
}
|
||||
|
||||
|
||||
List<String> neededCommands = new ArrayList<>();
|
||||
for (String id: executionPlanJSON.keySet()) {
|
||||
@ -134,7 +155,7 @@ public class ProducingExecutor {
|
||||
log.debug("Adding command [{}]", s);
|
||||
newCommandsToCheck.add(s);
|
||||
neededCommands.add(s);
|
||||
if (createExecutionTask(taskMap, s, anyCommandInstructions).executor == null) {
|
||||
if (createExecutionTask(taskMap, s, new HashMap<>(anyCommandInstructions)).executor == null) {
|
||||
log.error("Command [{}] not found", s);
|
||||
throw new Exception("Command not found: " + s);
|
||||
}
|
||||
@ -168,7 +189,53 @@ public class ProducingExecutor {
|
||||
|
||||
});
|
||||
executionPlan.tasks = sorted;
|
||||
|
||||
applyDirectives(directives);
|
||||
}
|
||||
|
||||
protected void applyDirectives(JsonObject directives) {
|
||||
// apply @SKIP
|
||||
if (directives.has(DIRECTIVE_SKIP)) {
|
||||
JsonElement je = directives.get(DIRECTIVE_SKIP);
|
||||
List<String> toSkip = new ArrayList<>();
|
||||
if (je.isJsonPrimitive())
|
||||
toSkip.add(je.getAsString());
|
||||
if (je.isJsonArray()) {
|
||||
JsonArray ja = je.getAsJsonArray();
|
||||
for (int i=0; i<ja.size(); i++)
|
||||
toSkip.add(ja.get(i).getAsString());
|
||||
}
|
||||
for (String s: toSkip) {
|
||||
boolean skipBefore = s.endsWith("-");
|
||||
boolean skipAfter = s.endsWith("+");
|
||||
if (skipBefore || skipAfter)
|
||||
s = s.substring(0, s.length()-1);
|
||||
if (skipBefore) {
|
||||
for (ExecutionTask et: executionPlan.tasks) {
|
||||
if (et.commandId.equals(s))
|
||||
break;
|
||||
et.instructions.put(INSTRUCTIONS.SKIP, true);
|
||||
}
|
||||
} else if (skipAfter) {
|
||||
boolean found = false;
|
||||
for (ExecutionTask et: executionPlan.tasks) {
|
||||
if (et.commandId.equals(s)) {
|
||||
found = true;
|
||||
continue;
|
||||
}
|
||||
if (found)
|
||||
et.instructions.put(INSTRUCTIONS.SKIP, true);
|
||||
}
|
||||
|
||||
} else {
|
||||
for (ExecutionTask et: executionPlan.tasks) {
|
||||
if (et.commandId.equals(s)) {
|
||||
et.instructions.put(INSTRUCTIONS.SKIP, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ProducerResult execute() {
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* test-producers
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -47,11 +47,10 @@ public class Analyze extends AbstractCommandExecutor {
|
||||
@Override
|
||||
protected boolean doExecute(ProducerResult currentResult, CommandResult commandResult,
|
||||
Map<String, Object> instructions) throws Exception {
|
||||
log.info("Executing command [{}]", getId());
|
||||
log.debug("Executing command [{}]", getId());
|
||||
|
||||
JsonObject jo = currentResult.findResultObject(JsonObject.class);
|
||||
|
||||
printOutput("\n\n\t== ANALYZE == \n\n");
|
||||
printOutput("\n\tIncoming JSON ::\n\n");
|
||||
printOutput(jo.toString());
|
||||
|
||||
@ -61,7 +60,7 @@ public class Analyze extends AbstractCommandExecutor {
|
||||
|
||||
printOutput("\n\tObjectModel ::\n\n");
|
||||
for (FactoredObject fo: om.objects)
|
||||
printOutput("Object :: [" + fo.getObjectId() + "/" + fo.factoryId + ":" + fo.getObjectType() + "]");
|
||||
printOutput("Object :: [" + fo.getObjectId() + "/" + fo.factoryId + ":" + fo.getObjectType() + "] :: " + fo.getOutputType());
|
||||
for (FactoredObjectRef fo: om.refs)
|
||||
printOutput("Reference :: [" + fo.definedIn.getObjectId() + " -> " + fo.getTargetId()
|
||||
+ "; isLink=" + fo.isLink()
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* test-producers
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -21,27 +21,21 @@ package ru.entaxy.platform.core.producer.executor.commands;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.osgi.framework.Constants;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import ru.entaxy.esb.platform.runtime.base.connecting.generator.Generated;
|
||||
import ru.entaxy.platform.base.support.CommonUtils;
|
||||
import ru.entaxy.platform.core.artifact.Artifact;
|
||||
import ru.entaxy.platform.core.artifact.ArtifactManifest;
|
||||
import ru.entaxy.platform.core.artifact.Artifacts;
|
||||
import ru.entaxy.platform.core.artifact.Manifested;
|
||||
import ru.entaxy.platform.core.artifact.capabilities.ManifestCapabilityHelper;
|
||||
import ru.entaxy.platform.base.objects.EntaxyObject.FIELDS;
|
||||
import ru.entaxy.platform.base.objects.EntaxyObject.HEADERS;
|
||||
import ru.entaxy.platform.core.producer.api.EntaxyProducerService;
|
||||
import ru.entaxy.platform.core.producer.api.ProducerResult;
|
||||
import ru.entaxy.platform.core.producer.api.ProducerResult.CommandResult;
|
||||
import ru.entaxy.platform.core.producer.executor.AbstractCommandExecutor;
|
||||
import ru.entaxy.platform.core.producer.executor.CommandExecutor;
|
||||
import ru.entaxy.platform.core.producer.executor.generationmodel.GeneratedHeaders;
|
||||
import ru.entaxy.platform.core.producer.executor.builder.BuiltObject;
|
||||
import ru.entaxy.platform.core.producer.executor.builder.BuiltObjectList;
|
||||
import ru.entaxy.platform.core.producer.executor.builder.ObjectBuilder;
|
||||
import ru.entaxy.platform.core.producer.executor.generationmodel.GeneratedList;
|
||||
import ru.entaxy.platform.core.producer.executor.support.ArtifactList;
|
||||
import ru.entaxy.platform.core.producer.executor.support.ObjectSupportRegistry;
|
||||
import ru.entaxy.platform.core.producer.executor.support.PrintOutputSupport;
|
||||
|
||||
@CommandExecutor(id = "build", predecessors = {"generate"})
|
||||
public class Build extends AbstractCommandExecutor {
|
||||
@ -55,103 +49,38 @@ public class Build extends AbstractCommandExecutor {
|
||||
@Override
|
||||
protected boolean doExecute(ProducerResult currentResult, CommandResult commandResult,
|
||||
Map<String, Object> instructions) throws Exception {
|
||||
printOutput("\n\t == BUILDING ==\n");
|
||||
GeneratedList generated = currentResult.findResultObject(GeneratedList.class);
|
||||
if (generated == null) {
|
||||
log.info("Nothing to generate");
|
||||
log.info("Nothing to build");
|
||||
return true;
|
||||
}
|
||||
|
||||
ArtifactList artifactList = new ArtifactList();
|
||||
BuiltObjectList resultList = new BuiltObjectList();
|
||||
|
||||
for (Generated g: generated) {
|
||||
if (g == null)
|
||||
continue;
|
||||
Artifact artifact = Artifacts.fromGenerated(g);
|
||||
if ((artifact == null) || Artifact.ARTIFACT_CATEGORY_UNKNOWN.equals(artifact.getCategory())
|
||||
|| !CommonUtils.isValid(artifact.getCategory())) {
|
||||
log.info("Artifact is not buildable");
|
||||
|
||||
printOutput(" = Building for generated of type [" + g.getType() + "]" );
|
||||
|
||||
ObjectBuilder builder = ObjectSupportRegistry.getInstance().findBuilder(g);
|
||||
if (builder == null) {
|
||||
log.warn("ObjectBuilder not found for generated object of type [{}]", g.getType());
|
||||
printOutput(" :: ObjectBuilder not found");
|
||||
continue;
|
||||
}
|
||||
log.info("Built artifact of category [{}]", artifact.getCategory());
|
||||
Map<String, String> headers = GeneratedHeaders.getHeaders(g.getProperties()).getAsStringMap();
|
||||
|
||||
String mainObjectValue = headers.get(HEADERS.MAIN_OBJECT);
|
||||
if (!CommonUtils.isValid(mainObjectValue))
|
||||
throw new Exception("Main object not found");
|
||||
String[] mainObjectData = mainObjectValue.split(":");
|
||||
if (mainObjectData.length<2)
|
||||
throw new Exception("Main object not complete: [" + mainObjectValue + "]");
|
||||
printOutput(" :: ObjectBuilder is: " + builder.getClass().getName());
|
||||
BuiltObject result = builder.build(g, instructions);
|
||||
if (result != null) {
|
||||
resultList.add(result);
|
||||
printOutput(" :: Result is: " + result.getClass().getName());
|
||||
} else
|
||||
printOutput(" :: Result is: NULL");
|
||||
|
||||
String versionPolicy = g.getProperties().getOrDefault(
|
||||
EntaxyProducerService.INSTRUCTIONS.ARTIFACT.VERSION_POLICY,
|
||||
instructions.getOrDefault(
|
||||
EntaxyProducerService.INSTRUCTIONS.ARTIFACT.VERSION_POLICY
|
||||
, ""))
|
||||
.toString();
|
||||
String timestamp = g.getProperties().getOrDefault(
|
||||
EntaxyProducerService.INSTRUCTIONS.ARTIFACT.TIMESTAMP,
|
||||
instructions.getOrDefault(
|
||||
EntaxyProducerService.INSTRUCTIONS.ARTIFACT.TIMESTAMP
|
||||
, ""))
|
||||
.toString();
|
||||
artifact.getCoordinates()
|
||||
.groupId(mainObjectData[1])
|
||||
.artifactId(mainObjectData[0])
|
||||
.version("1")
|
||||
.versionPolicy(versionPolicy)
|
||||
.timestamp(timestamp);
|
||||
|
||||
if (artifact instanceof Manifested) {
|
||||
ArtifactManifest manifest = ((Manifested)artifact).getManifest();
|
||||
manifest.getCustomAttributes().putAll(headers);
|
||||
|
||||
// Generate provided capabilities for every included object
|
||||
ManifestCapabilityHelper helper = new ManifestCapabilityHelper(manifest);
|
||||
|
||||
String objectsValue = headers.getOrDefault(HEADERS.GENERATED_OBJECTS, "");
|
||||
if (CommonUtils.isValid(objectsValue)) {
|
||||
String[] objects = objectsValue.split(",");
|
||||
|
||||
for (int i=0; i<objects.length; i++) {
|
||||
String[] objectData = objects[i].split(":");
|
||||
if (objectData.length<2)
|
||||
continue;
|
||||
String objectId = objectData[0];
|
||||
String objectType = objectData[1];
|
||||
if (!CommonUtils.isValid(objectId) || !CommonUtils.isValid(objectType))
|
||||
continue;
|
||||
objectId = objectId.trim();
|
||||
objectType = objectType.trim();
|
||||
Map<String, Object> attributes = null;
|
||||
if (g.getProperties().containsKey(FIELDS.FIELDS_TO_PUBLISH)) {
|
||||
Object map = g.getProperties().get(FIELDS.FIELDS_TO_PUBLISH);
|
||||
if (map != null) {
|
||||
attributes = (Map<String, Object>)((Map<String, Object>)map).get(objectId);
|
||||
}
|
||||
}
|
||||
helper.provideCapability(objectType).attributes(attributes);
|
||||
}
|
||||
|
||||
helper.save();
|
||||
|
||||
}
|
||||
}
|
||||
artifact.getProperties().putAll(g.getProperties());
|
||||
// TODO get value from manifest
|
||||
// ArtifactManifest must be improved to provide read access to all attributes
|
||||
if (!artifact.getProperties().containsKey(Constants.BUNDLE_SYMBOLICNAME)) {
|
||||
artifact.getProperties().put(Constants.BUNDLE_SYMBOLICNAME
|
||||
, artifact.getCoordinates().getGroupId()
|
||||
+ "." + artifact.getCoordinates().getArtifactId());
|
||||
}
|
||||
artifactList.add(artifact);
|
||||
printOutput("\n\t == " + artifact.getCoordinates().toString() + " ==\n");
|
||||
printOutput(new String(artifact.asByteArray()));
|
||||
printOutput("\n\t == \n");
|
||||
}
|
||||
|
||||
commandResult.resultObject(artifactList);
|
||||
commandResult.resultObject(resultList);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* test-producers
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -20,23 +20,27 @@
|
||||
package ru.entaxy.platform.core.producer.executor.commands;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import ru.entaxy.platform.core.artifact.Artifact;
|
||||
import ru.entaxy.platform.core.artifact.DeployedArtifact;
|
||||
import ru.entaxy.platform.core.artifact.service.ArtifactService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import ru.entaxy.platform.core.producer.api.EntaxyProducerService;
|
||||
import ru.entaxy.platform.core.producer.api.ProducerResult;
|
||||
import ru.entaxy.platform.core.producer.api.ProducerResult.CommandResult;
|
||||
import ru.entaxy.platform.core.producer.executor.AbstractCommandExecutor;
|
||||
import ru.entaxy.platform.core.producer.executor.CommandExecutor;
|
||||
import ru.entaxy.platform.core.producer.executor.support.ArtifactList;
|
||||
import ru.entaxy.platform.core.producer.executor.support.ArtifactsHelper;
|
||||
import ru.entaxy.platform.core.producer.executor.support.DeployedArtifactList;
|
||||
import ru.entaxy.platform.core.producer.executor.builder.BuiltObject;
|
||||
import ru.entaxy.platform.core.producer.executor.builder.BuiltObjectList;
|
||||
import ru.entaxy.platform.core.producer.executor.deployer.DeployedObject;
|
||||
import ru.entaxy.platform.core.producer.executor.deployer.DeployedObjectList;
|
||||
import ru.entaxy.platform.core.producer.executor.deployer.ObjectDeployer;
|
||||
import ru.entaxy.platform.core.producer.executor.support.ObjectSupportRegistry;
|
||||
|
||||
@CommandExecutor(id = "deploy", predecessors = {"build"})
|
||||
public class Deploy extends AbstractCommandExecutor {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(Deploy.class);
|
||||
|
||||
public static final String DEPLOY_LOCAL_INSTRUCTION = "deployLocal";
|
||||
|
||||
public Deploy(EntaxyProducerService entaxyProducerService) {
|
||||
@ -46,32 +50,39 @@ public class Deploy extends AbstractCommandExecutor {
|
||||
@Override
|
||||
protected boolean doExecute(ProducerResult currentResult, CommandResult commandResult,
|
||||
Map<String, Object> instructions) throws Exception {
|
||||
|
||||
boolean deployLocal = false;
|
||||
|
||||
Object deployLocalValue = instructions.get(DEPLOY_LOCAL_INSTRUCTION);
|
||||
if (deployLocalValue != null)
|
||||
if (deployLocalValue instanceof Boolean)
|
||||
deployLocal = (Boolean)deployLocalValue;
|
||||
|
||||
ArtifactList artifactList = currentResult.findResultObject(ArtifactList.class);
|
||||
DeployedArtifactList deployedArtifactList = new DeployedArtifactList();
|
||||
|
||||
ArtifactService artifactService = ArtifactsHelper.getInstance().getArtifactService();
|
||||
|
||||
for (Artifact artifact: artifactList) {
|
||||
DeployedArtifact da = deployLocal
|
||||
?artifactService.deployLocal(artifact)
|
||||
:artifactService.deployShared(artifact);
|
||||
deployedArtifactList.add(da);
|
||||
}
|
||||
|
||||
printOutput("\n\n\t== DEPLOY ==\n");
|
||||
printOutput("DEPLOYED: ["
|
||||
+ deployedArtifactList.stream().map(da->da.getLocation()).collect(Collectors.joining(","))
|
||||
+ "]");
|
||||
BuiltObjectList objectList = currentResult.findResultObject(BuiltObjectList.class);
|
||||
if (objectList == null) {
|
||||
log.info("Nothing to deploy");
|
||||
return true;
|
||||
}
|
||||
|
||||
DeployedObjectList resultList = new DeployedObjectList();
|
||||
|
||||
commandResult.resultObject(deployedArtifactList);
|
||||
for (BuiltObject obj: objectList) {
|
||||
if (obj == null)
|
||||
continue;
|
||||
|
||||
printOutput(" = Deploying for built of type [" + obj.getObject().getClass().getName() + "]" );
|
||||
|
||||
ObjectDeployer deployer = ObjectSupportRegistry.getInstance().findDeployer(obj);
|
||||
if (deployer == null) {
|
||||
log.warn("ObjectDeployer not found for built object of type [{}]", obj.getObject().getClass().getName());
|
||||
printOutput(" :: ObjectDeployer not found");
|
||||
continue;
|
||||
}
|
||||
|
||||
printOutput(" :: ObjectDeployer is: " + deployer.getClass().getName());
|
||||
DeployedObject result = deployer.deploy(obj, instructions);
|
||||
if (result != null) {
|
||||
resultList.add(result);
|
||||
printOutput(" :: Result is: " + result.getClass().getName());
|
||||
} else
|
||||
printOutput(" :: Result is: NULL");
|
||||
|
||||
}
|
||||
|
||||
commandResult.resultObject(resultList);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* test-producers
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -31,8 +31,10 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
|
||||
import ru.entaxy.platform.base.support.CommonUtils;
|
||||
import ru.entaxy.platform.base.support.JSONUtils;
|
||||
@ -47,6 +49,8 @@ import ru.entaxy.platform.core.producer.api.ProducerResult;
|
||||
import ru.entaxy.platform.core.producer.api.ProducerResult.CommandResult;
|
||||
import ru.entaxy.platform.core.producer.executor.AbstractCommandExecutor;
|
||||
import ru.entaxy.platform.core.producer.executor.CommandExecutor;
|
||||
import ru.entaxy.platform.core.producer.executor.objectmodel.AbstractItem;
|
||||
import ru.entaxy.platform.core.producer.executor.objectmodel.Calculation;
|
||||
import ru.entaxy.platform.core.producer.executor.objectmodel.FactoredObject;
|
||||
import ru.entaxy.platform.core.producer.executor.objectmodel.FactoredObjectProxy;
|
||||
import ru.entaxy.platform.core.producer.executor.objectmodel.FactoredObjectRef;
|
||||
@ -58,12 +62,40 @@ import ru.entaxy.platform.core.producer.impl.RefFieldInfoImpl;
|
||||
public class Enrich extends AbstractCommandExecutor {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(Enrich.class);
|
||||
|
||||
|
||||
public Enrich(EntaxyProducerService entaxyProducerService) {
|
||||
super(entaxyProducerService);
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
// TODO move to FieldInfo
|
||||
protected boolean isScoped(FieldInfo fi) {
|
||||
return fi.getJsonOrigin().has(EntaxyFactory.CONFIGURATION.DIRECTIVES.SCOPED);
|
||||
}
|
||||
|
||||
// TODO move to FieldInfo
|
||||
protected boolean isInScope(FieldInfo fi, String currentScope) {
|
||||
if (!isScoped(fi))
|
||||
return true;
|
||||
JsonElement je = fi.getJsonOrigin().get(EntaxyFactory.CONFIGURATION.DIRECTIVES.SCOPED);
|
||||
if (!je.isJsonArray())
|
||||
return true;
|
||||
JsonArray ja = je.getAsJsonArray();
|
||||
if (ja.size() == 0)
|
||||
return true;
|
||||
for (int i=0; i<ja.size(); i++) {
|
||||
JsonElement item = ja.get(i);
|
||||
if (!item.isJsonPrimitive())
|
||||
continue;
|
||||
JsonPrimitive jp = item.getAsJsonPrimitive();
|
||||
if (!jp.isString())
|
||||
continue;
|
||||
if (jp.getAsString().equals(currentScope))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO move to FieldInfo
|
||||
protected boolean isLookup(FieldInfo fi) {
|
||||
if (fi.getJsonOrigin().has("lookup")) {
|
||||
@ -84,19 +116,6 @@ public class Enrich extends AbstractCommandExecutor {
|
||||
protected boolean doExecute(ProducerResult currentResult, CommandResult commandResult,
|
||||
Map<String, Object> instructions) throws Exception {
|
||||
|
||||
int count = 15;
|
||||
if (!instructions.containsKey("_count")) {
|
||||
instructions.put("_count", count);
|
||||
}
|
||||
|
||||
if (instructions.get("_count") instanceof Integer)
|
||||
count = (Integer)instructions.get("_count");
|
||||
else if (instructions.get("_count") instanceof Number)
|
||||
count = ((Number)instructions.get("_count")).intValue();
|
||||
count--;
|
||||
|
||||
printOutput("\n\n\t== ENRICH == #" + count + " ==\n\n");
|
||||
|
||||
ObjectModel objectModel = currentResult.findResultObject(ObjectModel.class);
|
||||
objectModel.startTracking();
|
||||
|
||||
@ -104,7 +123,8 @@ public class Enrich extends AbstractCommandExecutor {
|
||||
|
||||
Gson gson = new Gson();
|
||||
|
||||
// enrich type to ensure we can resolve refs
|
||||
// enrich type to ensure we can resolve refs
|
||||
// and enrich scope
|
||||
|
||||
for (FactoredObject fo: objectModel.objects) {
|
||||
|
||||
@ -123,6 +143,11 @@ public class Enrich extends AbstractCommandExecutor {
|
||||
fo.setObjectType(factory.getFactoryType());
|
||||
objectModel.setDirty();
|
||||
}
|
||||
|
||||
if (!fo.origin.has(FIELDS.SCOPE)) {
|
||||
JSONUtils.setValue(fo.origin, FIELDS.SCOPE, gson.toJsonTree(fo.scope), true);
|
||||
objectModel.setDirty();
|
||||
}
|
||||
}
|
||||
|
||||
// enrich fields
|
||||
@ -148,26 +173,35 @@ public class Enrich extends AbstractCommandExecutor {
|
||||
objectModel.setDirty();
|
||||
}
|
||||
|
||||
JSONUtils.setValue(objectOrigin, FactoredObject.IGNORE_SECTION, new JsonObject(), true);
|
||||
|
||||
JsonObject objectProperties = objectOrigin.get(FIELDS.PROPERTIES).getAsJsonObject();
|
||||
|
||||
List<FieldInfo> factoryFields = factory.getFields(OUTPUTS.OUTPUT_TYPE_INIT);
|
||||
List<FieldInfo> factoryFields = factory.getFields(
|
||||
CommonUtils.getValid(fo.getOutputType(), OUTPUTS.OUTPUT_TYPE_INIT)
|
||||
);
|
||||
|
||||
|
||||
for (FieldInfo fi: factoryFields) {
|
||||
|
||||
FieldInfo fieldInfo = fi;
|
||||
|
||||
log.info("\n ITERATING FOR FIELD: " + fi.getName() + "\n" + fi.getJsonOrigin());
|
||||
log.debug("\n ITERATING FOR FIELD: " + fi.getName() + "\n" + fi.getJsonOrigin());
|
||||
|
||||
|
||||
if (FIELDS.OBJECT_ID.equals(fi.getName())
|
||||
|| FIELDS.OBJECT_TYPE.equals(fi.getName()))
|
||||
continue;
|
||||
|
||||
// check scope
|
||||
if (!isInScope(fi, fo.scope))
|
||||
continue;
|
||||
|
||||
// check if lookup
|
||||
if (isLookup(fi)) {
|
||||
|
||||
String lookup = getLookup(fi);
|
||||
log.info("\n LOOKUP FIELD: " + fi.getName() + " -> " + lookup);
|
||||
log.debug("\n LOOKUP FIELD: " + fi.getName() + " -> " + lookup);
|
||||
|
||||
// replace lookup with corresponding ref
|
||||
Optional<FieldInfo> toLookupOpt = factoryFields.stream()
|
||||
@ -178,7 +212,7 @@ public class Enrich extends AbstractCommandExecutor {
|
||||
log.error("Factory configuration error: loooked up field [{}] referenced by [{}] not found in factory [{}]"
|
||||
, lookup
|
||||
, fi.getName()
|
||||
, factory.getFactoryId());
|
||||
, factory.getId());
|
||||
continue;
|
||||
}
|
||||
FieldInfo toLookup = toLookupOpt.get();
|
||||
@ -208,7 +242,7 @@ public class Enrich extends AbstractCommandExecutor {
|
||||
}
|
||||
fieldInfoImpl.setJsonOrigin(lookupJson);
|
||||
|
||||
log.info("\n LOOKUP FIELD JSON: \n" + lookupJson.toString());
|
||||
log.debug("\n LOOKUP FIELD JSON: \n" + lookupJson.toString());
|
||||
|
||||
fieldInfo = fieldInfoImpl;
|
||||
|
||||
@ -288,12 +322,45 @@ public class Enrich extends AbstractCommandExecutor {
|
||||
delayed.removeAll(toRemove);
|
||||
}
|
||||
|
||||
JsonObject ignores = objectOrigin.get(FactoredObject.IGNORE_SECTION).getAsJsonObject();
|
||||
|
||||
// try to calculate
|
||||
for (AbstractItem ai: fo.getInternals()) {
|
||||
if (!(ai instanceof Calculation))
|
||||
continue;
|
||||
Calculation calc = (Calculation)ai;
|
||||
|
||||
// leave lazy calculations until generation
|
||||
if (calc.isLazy())
|
||||
continue;
|
||||
|
||||
Object result = calc.calculate(objectModel, fo);
|
||||
if (result != Calculation.NOT_ENOUGH_DATA) {
|
||||
printOutput("[CALCULATION] DONE for [" + fo.getObjectId() + "/" + calc.relativePath + "] :: " + result.toString());
|
||||
String currentPath = calc.relativePath;
|
||||
String targetPath = calc.getTargetPath();
|
||||
boolean remove = (!currentPath.equals(targetPath) && calc.isRemoveResolved());
|
||||
targetPath = targetPath.replace("$.", "");
|
||||
JSONUtils.replaceValue(objectOrigin, targetPath, (new Gson()).toJsonTree(result));
|
||||
if (remove) {
|
||||
int ind = currentPath.lastIndexOf(".");
|
||||
String fieldName = ind>=0
|
||||
?currentPath.substring(ind+1)
|
||||
:currentPath;
|
||||
ignores.addProperty(fieldName, true);
|
||||
JSONUtils.replaceValue(objectOrigin, currentPath, (new Gson()).toJsonTree("TO_REMOVE"));
|
||||
}
|
||||
printOutput("[DIRTY] SET CALCULATED [" + result + "] to [" + targetPath + "]");
|
||||
objectModel.setDirty();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if (objectModel.stopTracking() && count>0) {
|
||||
if (objectModel.stopTracking()) {
|
||||
|
||||
// remove ##embedded
|
||||
for (FactoredObject fo: objectModel.objects)
|
||||
@ -305,8 +372,6 @@ public class Enrich extends AbstractCommandExecutor {
|
||||
.reset().target("analyze").complete();
|
||||
}
|
||||
|
||||
instructions.put("_count", count);
|
||||
|
||||
JsonObject outgoingJson = objectModel.getJsonCurrent();
|
||||
|
||||
printOutput("\n== INCOMING JSON ==\n");
|
||||
@ -321,10 +386,10 @@ public class Enrich extends AbstractCommandExecutor {
|
||||
|
||||
protected boolean processField(ObjectModel objectModel, FieldInfo fi, FactoredObject fo, Gson gson) {
|
||||
|
||||
log.info("\nPROCESSING FIELD: " + fi.getName());
|
||||
log.debug("\nPROCESSING FIELD: " + fi.getName());
|
||||
|
||||
if (fi.isRef()) {
|
||||
log.info("\nPROCESSING REF: " + fi.getName());
|
||||
log.debug("\nPROCESSING REF: " + fi.getName());
|
||||
return processRef(objectModel, (RefFieldInfo)fi, fo, gson);
|
||||
}
|
||||
|
||||
@ -332,15 +397,38 @@ public class Enrich extends AbstractCommandExecutor {
|
||||
|
||||
JsonObject objectOrigin = fo.origin;
|
||||
JsonObject objectProperties = objectOrigin.get(FIELDS.PROPERTIES).getAsJsonObject();
|
||||
JsonObject ignores = objectOrigin.get(FactoredObject.IGNORE_SECTION).getAsJsonObject();
|
||||
|
||||
boolean exists = objectProperties.has(fi.getName());
|
||||
if (!exists) {
|
||||
boolean ignored = ignores.has(fi.getName());
|
||||
if (!ignored) {
|
||||
if (fi.isRequired()) {
|
||||
printOutput("[DIRTY] CREATED " + fi.getName() + " for [" + fo.getObjectId() + "/" + fo.getObjectType() + "]");
|
||||
|
||||
objectProperties.add(fi.getName(), fi.getJsonOrigin().get(FIELDS.DEFAULT_VALUE));
|
||||
objectModel.setDirty();
|
||||
result = true;
|
||||
if (exists) {
|
||||
printOutput("[CHECK] IS FIXED VALUE " + fi.getName() + " for [" + fo.getObjectId() + "/" + fo.getObjectType() + "]");
|
||||
if (fi.getJsonOrigin().has("fixedValue")) {
|
||||
JsonElement fixedValue = fi.getJsonOrigin().get("fixedValue");
|
||||
JsonElement currentValue = objectProperties.get(fi.getName());
|
||||
boolean replaceValue = false;
|
||||
if (fixedValue != null) {
|
||||
if (currentValue == null)
|
||||
replaceValue = true;
|
||||
else
|
||||
replaceValue = !fixedValue.toString().equals(currentValue.toString());
|
||||
}
|
||||
if (replaceValue) {
|
||||
printOutput("[DIRTY] REPLACED WITH FIXED VALUE: " + fi.getName() + " for [" + fo.getObjectId() + "/" + fo.getObjectType() + "]");
|
||||
JSONUtils.replaceValue(objectProperties, fi.getName(), fixedValue);
|
||||
objectModel.setDirty();
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
printOutput("[DIRTY] CREATED " + fi.getName() + " for [" + fo.getObjectId() + "/" + fo.getObjectType() + "]");
|
||||
|
||||
objectProperties.add(fi.getName(), fi.getJsonOrigin().get(FIELDS.DEFAULT_VALUE));
|
||||
objectModel.setDirty();
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
@ -351,8 +439,14 @@ public class Enrich extends AbstractCommandExecutor {
|
||||
|
||||
JsonObject objectOrigin = fo.origin;
|
||||
JsonObject objectProperties = objectOrigin.get(FIELDS.PROPERTIES).getAsJsonObject();
|
||||
JsonObject ignores = objectOrigin.get(FactoredObject.IGNORE_SECTION).getAsJsonObject();
|
||||
|
||||
boolean exists = objectProperties.has(fi.getName());
|
||||
boolean ignored = ignores.has(fi.getName());
|
||||
|
||||
if (ignored)
|
||||
return true;
|
||||
|
||||
if (!exists) {
|
||||
if (fi.isRequired()) {
|
||||
|
||||
@ -491,6 +585,11 @@ public class Enrich extends AbstractCommandExecutor {
|
||||
printOutput("[DIRTY] UPDATED " + fi.getName() + " for [" + fo.getObjectId() + "/" + fo.getObjectType() + "]");
|
||||
objectModel.setDirty();
|
||||
}
|
||||
// TODO move to constant
|
||||
if (refCopy.has("resolveAlways")) {
|
||||
currentObject.remove("resolveAlways");
|
||||
currentObject.add("resolveAlways", refCopy.get("resolveAlways"));
|
||||
}
|
||||
if (isLookup(fi)) {
|
||||
String lookup = getLookup(fi);
|
||||
JsonElement lookupValue = objectProperties.get(lookup);
|
||||
@ -534,12 +633,26 @@ public class Enrich extends AbstractCommandExecutor {
|
||||
|
||||
if (!result) {
|
||||
// we have something which is not a ref and not a object to produce
|
||||
// we'll treat it as resolved ref value
|
||||
refCopy.remove(FIELDS.DEFAULT_VALUE);
|
||||
refCopy.add(FactoredObjectRef.TARGET_VALUE_FIELD, currentValue);
|
||||
refCopy.addProperty(FactoredObjectRef.IS_RESOLVED_FIELD, true);
|
||||
printOutput("[DIRTY] CONSIDER VALUE [" + currentValue.toString() + "] AS RESOLVED " + fi.getName() + " for [" + fo.getObjectId() + "/" + fo.getObjectType() + "]");
|
||||
objectModel.setDirty();
|
||||
if (fi.isRefByValueOnly()) {
|
||||
// we'll treat it as resolved ref value
|
||||
ignores.remove(fi.getName());
|
||||
ignores.addProperty(fi.getName(), true);
|
||||
printOutput("[DIRTY] CONSIDER VALUE [" + currentValue.toString() + "] AS RESOLVED; IGNORE " + fi.getName() + " for [" + fo.getObjectId() + "/" + fo.getObjectType() + "]");
|
||||
objectModel.setDirty();
|
||||
} else {
|
||||
// we'll treat current value as targetId if it's not null and not array
|
||||
if (currentValue.isJsonPrimitive()) {
|
||||
refCopy.remove(FIELDS.DEFAULT_VALUE);
|
||||
refCopy.add(FactoredObjectRef.TARGET_ID_FIELD, currentValue);
|
||||
refCopy.remove(FactoredObjectRef.TARGET_TYPE_FIELD);
|
||||
refCopy.addProperty(FactoredObjectRef.TARGET_TYPE_FIELD, fi.getType());
|
||||
printOutput("[DIRTY] CONSIDER VALUE [" + currentValue.toString() + "] AS TARGET ID in " + fi.getName() + " for [" + fo.getObjectId() + "/" + fo.getObjectType() + "]");
|
||||
JSONUtils.replaceValue(objectProperties, fi.getName(), refCopy);
|
||||
objectModel.setDirty();
|
||||
} else {
|
||||
printOutput("[WARN] IGNORE VALUE [" + currentValue.toString() + "] in " + fi.getName() + " for [" + fo.getObjectId() + "/" + fo.getObjectType() + "]");
|
||||
}
|
||||
}
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* test-producers
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -49,6 +49,7 @@ public class Generate extends AbstractCommandExecutor {
|
||||
this.printOutput("\n\t == Execution ==\n");
|
||||
for (AbstractTask at: generationModel.getTasks()) {
|
||||
at.setPrintOutput(isPrintOutput);
|
||||
this.printOutput("\tExecuting: " + at.getInfo());
|
||||
at.execute(currentResult, commandResult, entaxyProducerService, instructions);
|
||||
this.printOutput("\n :: Result ::\n");
|
||||
if (at.getGeneratedResult()==null)
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* test-producers
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -21,30 +21,26 @@ package ru.entaxy.platform.core.producer.executor.commands;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.osgi.framework.Constants;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import ru.entaxy.platform.base.support.CommonUtils;
|
||||
import ru.entaxy.platform.core.artifact.Blueprint;
|
||||
import ru.entaxy.platform.core.artifact.DeployedArtifact;
|
||||
import ru.entaxy.platform.core.artifact.installer.builder.ClusterInstaller;
|
||||
import ru.entaxy.platform.core.artifact.installer.builder.InstallationResult;
|
||||
import ru.entaxy.platform.core.artifact.installer.builder.Installer;
|
||||
import ru.entaxy.platform.core.artifact.installer.builder.LocalInstaller;
|
||||
import ru.entaxy.platform.core.artifact.installer.builder.typed.BlueprintInstaller;
|
||||
import ru.entaxy.platform.core.artifact.service.ArtifactService;
|
||||
import ru.entaxy.platform.core.producer.api.EntaxyProducerService;
|
||||
import ru.entaxy.platform.core.producer.api.ProducerResult;
|
||||
import ru.entaxy.platform.core.producer.api.ProducerResult.CommandResult;
|
||||
import ru.entaxy.platform.core.producer.executor.AbstractCommandExecutor;
|
||||
import ru.entaxy.platform.core.producer.executor.CommandExecutor;
|
||||
import ru.entaxy.platform.core.producer.executor.CommandInstructions;
|
||||
import ru.entaxy.platform.core.producer.executor.support.ArtifactsHelper;
|
||||
import ru.entaxy.platform.core.producer.executor.support.DeployedArtifactList;
|
||||
import ru.entaxy.platform.core.producer.executor.support.InstallationResultList;
|
||||
import ru.entaxy.platform.core.producer.executor.deployer.DeployedObject;
|
||||
import ru.entaxy.platform.core.producer.executor.deployer.DeployedObjectList;
|
||||
import ru.entaxy.platform.core.producer.executor.installer.InstalledObject;
|
||||
import ru.entaxy.platform.core.producer.executor.installer.InstalledObjectList;
|
||||
import ru.entaxy.platform.core.producer.executor.installer.ObjectInstaller;
|
||||
import ru.entaxy.platform.core.producer.executor.support.ObjectSupportRegistry;
|
||||
|
||||
@CommandExecutor(id = "install", predecessors = "deploy")
|
||||
public class Install extends AbstractCommandExecutor {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(Install.class);
|
||||
|
||||
public static final String INSTALL_LOCAL_INSTRUCTION = "installLocal";
|
||||
public static final String UPDATE_INSTRUCTION = "update";
|
||||
public static final String INSTALL_ONLY_IF_MISSING_INSTRUCTION = "installOnlyIfMissing";
|
||||
@ -57,89 +53,39 @@ public class Install extends AbstractCommandExecutor {
|
||||
protected boolean doExecute(ProducerResult currentResult, CommandResult commandResult,
|
||||
Map<String, Object> instructions) throws Exception {
|
||||
|
||||
CommandInstructions commandInstructions = new CommandInstructions(instructions);
|
||||
|
||||
boolean installLocal =
|
||||
commandInstructions.has(INSTALL_LOCAL_INSTRUCTION)
|
||||
?commandInstructions.getBoolean(INSTALL_LOCAL_INSTRUCTION)
|
||||
:false;
|
||||
|
||||
boolean installOnlyIfMissing =
|
||||
commandInstructions.has(INSTALL_ONLY_IF_MISSING_INSTRUCTION)
|
||||
?commandInstructions.getBoolean(INSTALL_ONLY_IF_MISSING_INSTRUCTION)
|
||||
:false;
|
||||
|
||||
String update =
|
||||
commandInstructions.has(UPDATE_INSTRUCTION)
|
||||
?commandInstructions.getString(UPDATE_INSTRUCTION)
|
||||
:null;
|
||||
|
||||
Object installLocalValue = instructions.get(INSTALL_LOCAL_INSTRUCTION);
|
||||
if (installLocalValue != null)
|
||||
if (installLocalValue instanceof Boolean)
|
||||
installLocal = (Boolean)installLocalValue;
|
||||
|
||||
DeployedArtifactList deployedArtifactList = currentResult.findResultObject(DeployedArtifactList.class);
|
||||
InstallationResultList installationResultList = new InstallationResultList();
|
||||
|
||||
ArtifactService artifactService = ArtifactsHelper.getInstance().getArtifactService();
|
||||
|
||||
for (DeployedArtifact da: deployedArtifactList) {
|
||||
|
||||
InstallationResult result = null;
|
||||
|
||||
Installer<?> installer = null;
|
||||
|
||||
String artifactUpdate = update;
|
||||
|
||||
printOutput("-> Installing artifact: [" + da.getArtifact().getCoordinates().toString() + "]");
|
||||
if (installLocal) {
|
||||
LocalInstaller localInstaller = artifactService.installers().local()
|
||||
.artifact(da);
|
||||
installer = localInstaller;
|
||||
printOutput("-> Installing locally");
|
||||
} else {
|
||||
ClusterInstaller clusterInstaller = artifactService.installers().cluster()
|
||||
.artifact(da);
|
||||
installer = clusterInstaller;
|
||||
printOutput("-> Installing clustered");
|
||||
}
|
||||
|
||||
// TODO add support for other types when they appear
|
||||
if (da.getArtifact().getCategory().equals(Blueprint.ARTIFACT_CATEGORY_BLUEPRINT)) {
|
||||
// we're installing blueprint
|
||||
printOutput("-> Installing: " + da.getArtifact().getCategory());
|
||||
BlueprintInstaller blueprintInstaller = installer.typed(BlueprintInstaller.class);
|
||||
if (installOnlyIfMissing)
|
||||
blueprintInstaller.installOnlyIfMissing();
|
||||
if (artifactUpdate != null) {
|
||||
if (!CommonUtils.isValid(artifactUpdate)) {
|
||||
artifactUpdate = da
|
||||
.getArtifact().getProperties()
|
||||
.getOrDefault(Constants.BUNDLE_SYMBOLICNAME, "")
|
||||
.toString();
|
||||
}
|
||||
blueprintInstaller.update(artifactUpdate);
|
||||
}
|
||||
result = blueprintInstaller.start().install();
|
||||
} else {
|
||||
printOutput("-> Unknown category: " + da.getArtifact().getCategory());
|
||||
}
|
||||
|
||||
if (result != null) {
|
||||
for (String key: da.getArtifact().getProperties().keySet())
|
||||
result.getProperties().putIfAbsent(key, da.getArtifact().getProperties().get(key));
|
||||
// TODO imrove Coordinates: add "asMap" method
|
||||
result.getProperties().put("artifact.artifactId", da.getArtifact().getCoordinates().getArtifactId());
|
||||
result.getProperties().put("artifact.groupId", da.getArtifact().getCoordinates().getGroupId());
|
||||
result.getProperties().put("artifact.version", da.getArtifact().getCoordinates().getVersion());
|
||||
result.getProperties().put("artifact.type", da.getArtifact().getCoordinates().getType());
|
||||
result.getProperties().put("artifact.classifier", da.getArtifact().getCoordinates().getClassifier());
|
||||
installationResultList.add(result);
|
||||
}
|
||||
DeployedObjectList objectList = currentResult.findResultObject(DeployedObjectList.class);
|
||||
if (objectList == null) {
|
||||
log.info("Nothing to install");
|
||||
return true;
|
||||
}
|
||||
|
||||
commandResult.resultObject(installationResultList);
|
||||
InstalledObjectList resultList = new InstalledObjectList();
|
||||
|
||||
for (DeployedObject obj: objectList) {
|
||||
|
||||
if (obj == null)
|
||||
continue;
|
||||
|
||||
printOutput(" = Installing for deployed of type [" + obj.getObject().getClass().getName() + "]" );
|
||||
|
||||
|
||||
ObjectInstaller installer = ObjectSupportRegistry.getInstance().findInstaller(obj);
|
||||
if (installer == null) {
|
||||
log.warn("ObjectInstaller not found for deployed object of type [{}]", obj.getObject().getClass().getName());
|
||||
printOutput(" :: ObjectInstaller not found");
|
||||
continue;
|
||||
}
|
||||
|
||||
printOutput(" :: ObjectInstaller is: " + installer.getClass().getName());
|
||||
InstalledObject result = installer.install(obj, instructions);
|
||||
if (result != null) {
|
||||
resultList.add(result);
|
||||
printOutput(" :: Result is: " + result.getClass().getName());
|
||||
} else
|
||||
printOutput(" :: Result is: NULL");
|
||||
}
|
||||
|
||||
commandResult.resultObject(resultList);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* test-producers
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -46,7 +46,6 @@ public class Layout extends AbstractCommandExecutor {
|
||||
log.debug("Executing command [{}]", getId());
|
||||
ObjectModel objectModel = currentResult.findResultObject(ObjectModel.class);
|
||||
|
||||
printOutput("\n\n\t== LAYOUT == \n\n");
|
||||
printOutput("\n\tIncoming JSON ::\n\n");
|
||||
printOutput(objectModel.getJsonCurrent().toString());
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* test-producers
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* test-producers
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -19,6 +19,7 @@
|
||||
*/
|
||||
package ru.entaxy.platform.core.producer.executor.commands;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@ -36,7 +37,9 @@ import ru.entaxy.platform.core.producer.api.ProducerResult;
|
||||
import ru.entaxy.platform.core.producer.api.ProducerResult.CommandResult;
|
||||
import ru.entaxy.platform.core.producer.executor.AbstractCommandExecutor;
|
||||
import ru.entaxy.platform.core.producer.executor.CommandExecutor;
|
||||
import ru.entaxy.platform.core.producer.executor.support.InstallationResultList;
|
||||
import ru.entaxy.platform.core.producer.executor.installer.InstalledObject;
|
||||
import ru.entaxy.platform.core.producer.executor.installer.InstalledObjectList;
|
||||
import ru.entaxy.platform.core.producer.executor.support.EntaxyObjectPropertiesHelper;
|
||||
|
||||
@CommandExecutor(id = "store", predecessors = "install")
|
||||
public class Store extends AbstractCommandExecutor {
|
||||
@ -58,12 +61,15 @@ public class Store extends AbstractCommandExecutor {
|
||||
protected boolean doExecute(ProducerResult currentResult, CommandResult commandResult,
|
||||
Map<String, Object> instructions) throws Exception {
|
||||
|
||||
InstallationResultList installationResultList = currentResult.findResultObject(InstallationResultList.class);
|
||||
InstalledObjectList objectList = currentResult.findResultObject(InstalledObjectList.class);
|
||||
|
||||
if (objectStorageService == null)
|
||||
objectStorageService = OSGIUtils.services().ofClass(EntaxyObjectStorageService.class).get();
|
||||
|
||||
for (InstallationResult installationResult: installationResultList) {
|
||||
for (InstalledObject obj: objectList) {
|
||||
if (!(obj.getObject() instanceof InstallationResult))
|
||||
continue;
|
||||
InstallationResult installationResult = (InstallationResult)obj.getObject();
|
||||
printOutput("\n -- INSTALLATION RESULT ::"
|
||||
+ "\n\t" + installationResult.getResult().toString()
|
||||
+ "\n\tproperties:"
|
||||
@ -91,8 +97,13 @@ public class Store extends AbstractCommandExecutor {
|
||||
)
|
||||
);
|
||||
|
||||
Map<String, Object> objectProperties = new HashMap<>();
|
||||
objectProperties.putAll(installationResult.getProperties());
|
||||
if (EntaxyObjectPropertiesHelper.isMerged(objectProperties))
|
||||
objectProperties.putAll(EntaxyObjectPropertiesHelper.getMainObjectProperties(objectProperties));
|
||||
|
||||
EntaxyObjectStorage objectStorage = objectStorageService.getObjectStorage(
|
||||
installationResult.getProperties()
|
||||
objectProperties
|
||||
.getOrDefault(EntaxyObject.FIELDS.OBJECT_TYPE, "").toString()
|
||||
);
|
||||
|
||||
@ -102,7 +113,7 @@ public class Store extends AbstractCommandExecutor {
|
||||
continue;
|
||||
}
|
||||
|
||||
objectStorage.store(installationResult.getProperties());
|
||||
objectStorage.store(objectProperties);
|
||||
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* test-producers
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -43,7 +43,7 @@ public class Validate extends AbstractCommandExecutor {
|
||||
@Override
|
||||
protected boolean doExecute(ProducerResult currentResult, CommandResult commandResult,
|
||||
Map<String, Object> instructions) throws Exception {
|
||||
log.info("Executing command [{}]", getId());
|
||||
log.debug("Executing command [{}]", getId());
|
||||
ObjectModel objectModel = currentResult.findResultObject(ObjectModel.class);
|
||||
// TODO check ObjectModel.objects & .refs for
|
||||
// - factory exists
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* object-producer-core
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* test-producers
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* test-producers
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* object-producer-core
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -40,6 +40,8 @@ public class CalculateTask extends AbstractObjectTask {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(CalculateTask.class);
|
||||
|
||||
private static Gson GSON = new Gson();
|
||||
|
||||
public static boolean hasCalculations(FactoredObject factoredObject) {
|
||||
return factoredObject.getInternals().stream().filter(obj -> (obj instanceof Calculation))
|
||||
.count() > 0;
|
||||
@ -67,12 +69,19 @@ public class CalculateTask extends AbstractObjectTask {
|
||||
|
||||
for (Calculation calculation: calculations) {
|
||||
Object result = calculation.calculate(objectModel, origin);
|
||||
System.out.println("CALCULATION RESOLVED TO :: " + result);
|
||||
System.out.println("\n REPLACE"
|
||||
printOutput("CALCULATION RESOLVED TO :: " + result);
|
||||
printOutput("\n REPLACE"
|
||||
+ "\n\t" + calculation.origin
|
||||
+ "\n\tWITH :: " + (new Gson()).toJsonTree(result)
|
||||
+ "\n\tWITH :: " + GSON.toJsonTree(result)
|
||||
+ "\n\tAT :: " + calculation.relativePath);
|
||||
JSONUtils.replaceValue(origin.origin, calculation.relativePath, (new Gson()).toJsonTree(result));
|
||||
String currentPath = calculation.relativePath;
|
||||
String targetPath = calculation.getTargetPath();
|
||||
boolean remove = (!currentPath.equals(targetPath) && calculation.isRemoveResolved());
|
||||
targetPath = targetPath.replace("$.", "");
|
||||
JSONUtils.replaceValue(origin.origin, targetPath, GSON.toJsonTree(result));
|
||||
if (remove) {
|
||||
JSONUtils.replaceValue(origin.origin, currentPath, GSON.toJsonTree("TO_REMOVE"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* object-producer-core
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* test-producers
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -91,6 +91,34 @@ public class GenerateRefTask extends AbstractRefTask {
|
||||
, EntaxyFactory.SCOPE.PRIVATE.label
|
||||
, effectiveProperties);
|
||||
|
||||
} else {
|
||||
JsonObject targetConfig = targetObject.origin.deepCopy();
|
||||
JsonObject currentConfig = this.objectRef.origin;
|
||||
JSONUtils.mergeObjects(currentConfig, targetConfig);
|
||||
|
||||
// System.out.println("\n\n\tGENERATING REF WITH CONFIG: \n\t" + targetConfig);
|
||||
|
||||
String factoryId = targetConfig.has(FIELDS.FACTORY_ID)
|
||||
?targetConfig.get(FIELDS.FACTORY_ID).getAsString()
|
||||
:"";
|
||||
|
||||
String factoryType = targetConfig.has(FIELDS.OBJECT_TYPE)
|
||||
?targetConfig.get(FIELDS.OBJECT_TYPE).getAsString()
|
||||
:"";
|
||||
|
||||
if (!CommonUtils.isValid(factoryId) || !CommonUtils.isValid(factoryType))
|
||||
throw new IllegalArgumentException("Factory not defined for object: ["
|
||||
+ this.objectRef.getTargetId()
|
||||
+ ":"
|
||||
+ this.objectRef.getTargetType()
|
||||
+ "]");
|
||||
|
||||
Map<String, Object> effectiveProperties = createEffectiveProperties(targetConfig, instructions);
|
||||
this.generatedResult = producerService.getProducerForType(factoryType).getFactoryById(factoryId)
|
||||
.generate(EntaxyFactory.CONFIGURATION.OUTPUTS.OUTPUT_TYPE_REF
|
||||
, EntaxyFactory.SCOPE.PRIVATE.label
|
||||
, effectiveProperties);
|
||||
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* test-producers
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -21,6 +21,7 @@ package ru.entaxy.platform.core.producer.executor.generationmodel;
|
||||
|
||||
import java.util.Base64;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
@ -35,6 +36,7 @@ import ru.entaxy.platform.base.support.JSONUtils;
|
||||
import ru.entaxy.platform.base.objects.EntaxyObject.FIELDS;
|
||||
import ru.entaxy.platform.base.objects.EntaxyObject.HEADERS;
|
||||
import ru.entaxy.platform.base.objects.factory.EntaxyFactory;
|
||||
import ru.entaxy.platform.base.objects.factory.EntaxyFactory.OutputInfo;
|
||||
import ru.entaxy.platform.core.producer.api.EntaxyProducerService;
|
||||
import ru.entaxy.platform.core.producer.api.ProducerResult;
|
||||
import ru.entaxy.platform.core.producer.api.ProducerResult.CommandResult;
|
||||
@ -46,6 +48,8 @@ public class GenerateTask extends AbstractObjectTask {
|
||||
|
||||
public static final String INSTRUCTIONS_FIELD = "##instructions";
|
||||
public static final String GENERATION_PROPERTIES_FIELD = "##generation";
|
||||
public static final String SKIP_OBJECT_PUBLISHING_FIELD = "##SKIP_OBJECT_PUBLISHING";
|
||||
public static final String DIRECTIVE_SKIP_PUBLISH = "@SKIP_PUBLISH";
|
||||
|
||||
public String factoryId;
|
||||
public String factoryType;
|
||||
@ -71,8 +75,8 @@ public class GenerateTask extends AbstractObjectTask {
|
||||
try {
|
||||
EntaxyFactory f = producerService.findFactoryById(factoryId);
|
||||
if (f != null) {
|
||||
log.debug("Factory found by id [{}] with type [{}]", f.getFactoryId(), f.getFactoryType());
|
||||
factoryType = f.getFactoryType();
|
||||
log.debug("Factory found by id [{}] with type [{}]", f.getId(), f.getType());
|
||||
factoryType = f.getType();
|
||||
} else
|
||||
throw new IllegalArgumentException("Factory not found: " + factoryId);
|
||||
} catch (Exception e) {
|
||||
@ -80,7 +84,8 @@ public class GenerateTask extends AbstractObjectTask {
|
||||
}
|
||||
log.debug("Execute for type [{}] with factoryId [{}]", factoryType, factoryId);
|
||||
Map<String, Object> effectiveProperties = createEffectiveProperties(instructions);
|
||||
this.generatedResult = producerService.getProducerForType(factoryType).getFactoryById(factoryId).generate(outputType, scope, effectiveProperties);
|
||||
EntaxyFactory factory = producerService.getProducerForType(factoryType).getFactoryById(factoryId);
|
||||
this.generatedResult = factory.generate(outputType, scope, effectiveProperties);
|
||||
// objectId could be changed by pre/post processor, so we update it
|
||||
// TODO move string to const
|
||||
String objectId = this.generatedResult.getProperties()
|
||||
@ -89,21 +94,100 @@ public class GenerateTask extends AbstractObjectTask {
|
||||
log.debug("Changing objectId from [{}] to [{}]", origin.getObjectId(), objectId);
|
||||
origin.setObjectId(objectId);
|
||||
}
|
||||
|
||||
boolean publishObject = !isSkipPublish(factory, this.outputType, this.scope);
|
||||
|
||||
// check for old-style configuration
|
||||
// TODO remove in next releases
|
||||
if (publishObject)
|
||||
if (effectiveProperties.containsKey(SKIP_OBJECT_PUBLISHING_FIELD)) {
|
||||
try {
|
||||
publishObject = !((Boolean)effectiveProperties.get(SKIP_OBJECT_PUBLISHING_FIELD));
|
||||
} catch (Exception e) {
|
||||
// NOOP
|
||||
}
|
||||
}
|
||||
|
||||
GeneratedHeaders headers = GeneratedHeaders.getHeaders(this.generatedResult.getProperties());
|
||||
headers.set(HEADERS.MAIN_OBJECT, origin.getObjectId() + ":" + factoryType);
|
||||
headers.append(HEADERS.GENERATED_OBJECTS, origin.getObjectId() + ":" + factoryType);
|
||||
// headers.set(GeneratedHeaders.HEADER_MAIN_OBJECT_TYPE, factoryType);
|
||||
// headers.set(GeneratedHeaders.HEADER_MAIN_OBJECT_FACTORY_ID, factoryId);
|
||||
// headers.append(GeneratedHeaders.HEADER_OBJECT_ID, origin.getObjectId());
|
||||
// headers.append(GeneratedHeaders.HEADER_OBJECT_TYPE, factoryType);
|
||||
headers.append(HEADERS.GENERATED_OBJECTS_CONFIG
|
||||
, Base64.getEncoder().encodeToString(origin.origin.toString().getBytes()));
|
||||
headers.set(HEADERS.ENTAXY_GENERATED, "true");
|
||||
if (publishObject) {
|
||||
headers.set(HEADERS.MAIN_OBJECT, origin.getObjectId() + ":" + factoryType + ":" + scope);
|
||||
headers.append(HEADERS.GENERATED_OBJECTS, origin.getObjectId() + ":" + factoryType + ":" + scope);
|
||||
// headers.set(GeneratedHeaders.HEADER_MAIN_OBJECT_TYPE, factoryType);
|
||||
// headers.set(GeneratedHeaders.HEADER_MAIN_OBJECT_FACTORY_ID, factoryId);
|
||||
// headers.append(GeneratedHeaders.HEADER_OBJECT_ID, origin.getObjectId());
|
||||
// headers.append(GeneratedHeaders.HEADER_OBJECT_TYPE, factoryType);
|
||||
headers.append(HEADERS.GENERATED_OBJECTS_CONFIG
|
||||
, Base64.getEncoder().encodeToString(
|
||||
getFilteredObjectData(origin.origin, factory)
|
||||
.toString().getBytes()));
|
||||
}
|
||||
this.generationProperties.clear();
|
||||
this.generationProperties.putAll(effectiveProperties);
|
||||
this.generatedResult.getProperties().put(GENERATION_PROPERTIES_FIELD, new HashMap<String, Object>(this.generationProperties));
|
||||
return true;
|
||||
}
|
||||
|
||||
protected JsonObject getFilteredObjectData(JsonObject originData, EntaxyFactory factory) {
|
||||
JsonObject result = getFilteredObject(originData, factory);
|
||||
if (result == null)
|
||||
result = new JsonObject();
|
||||
return result;
|
||||
}
|
||||
|
||||
protected JsonObject getFilteredObject(JsonObject originObject, EntaxyFactory factory) {
|
||||
JsonObject result = new JsonObject();
|
||||
for (Entry<String, JsonElement> entry: originObject.entrySet()) {
|
||||
String name = entry.getKey();
|
||||
if (FactoredObject.EMBEDDED_FIELD.equals(name) || FactoredObject.IGNORE_SECTION.equals(name))
|
||||
continue;
|
||||
JsonElement je = entry.getValue();
|
||||
if (je.isJsonObject()) {
|
||||
JsonObject jo = je.getAsJsonObject();
|
||||
if (jo.has(EntaxyFactory.CONFIGURATION.DIRECTIVES.INTERNAL)) {
|
||||
boolean skip = true;
|
||||
try {
|
||||
skip = jo.get(EntaxyFactory.CONFIGURATION.DIRECTIVES.INTERNAL).getAsBoolean();
|
||||
} catch (Exception e) {
|
||||
// NOOP
|
||||
}
|
||||
if (skip)
|
||||
continue;
|
||||
}
|
||||
JsonObject filtered = getFilteredObject(jo, factory);
|
||||
if (filtered != null)
|
||||
result.add(name, filtered);
|
||||
} else {
|
||||
result.add(name, je);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
protected boolean isSkipPublish(EntaxyFactory factory, String outputType, String scope) {
|
||||
OutputInfo info = factory.getOutputByType(outputType);
|
||||
if (info == null)
|
||||
return false;
|
||||
Map<String, Object> config = info.getConfig();
|
||||
if (config == null)
|
||||
return false;
|
||||
if (config.containsKey(DIRECTIVE_SKIP_PUBLISH)) {
|
||||
try {
|
||||
// check scopes
|
||||
Map<String, Object> data = (Map<String, Object>)config.get(DIRECTIVE_SKIP_PUBLISH);
|
||||
if (data.containsKey(EntaxyFactory.CONFIGURATION.OUTPUTS.ATTRIBUTES.SCOPES)) {
|
||||
List<String> scopes = (List<String>)data.get(EntaxyFactory.CONFIGURATION.OUTPUTS.ATTRIBUTES.SCOPES);
|
||||
return scopes.contains(scope);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected Map<String, Object> createEffectiveProperties(Map<String, Object> instructions){
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put(INSTRUCTIONS_FIELD, instructions);
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* test-producers
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -50,6 +50,7 @@ public class GeneratedHeaders {
|
||||
if (!(obj instanceof List<?>)) {
|
||||
List<Object> list = new LinkedList<Object>();
|
||||
list.add(obj);
|
||||
headers.put(name, list);
|
||||
}
|
||||
}
|
||||
List<Object> list = (List<Object>)headers.get(name);
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* test-producers
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* test-producers
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -98,14 +98,15 @@ public class GenerationModel {
|
||||
List<FactoredObjectRef> embeddedRefs = fo.embedded.stream().filter(f->(f instanceof FactoredObjectRef))
|
||||
.map(f -> (FactoredObjectRef)f)
|
||||
.filter(f -> !f.isBackRef())
|
||||
.filter(f -> !f.isLink())
|
||||
.filter(f -> !f.isLink() || f.isResolveAlways())
|
||||
.collect(Collectors.toList());
|
||||
for (FactoredObjectRef embeddedRef: embeddedRefs) {
|
||||
|
||||
if (!embeddedRef.isLink()) {
|
||||
if (!embeddedRef.isLink() || embeddedRef.isResolveAlways()) {
|
||||
localPreTasks.add(new ResolveRefTask(embeddedRef));
|
||||
if (!embeddedRef.isRefByValueOnly())
|
||||
localPreTasks.add(new GenerateRefTask(embeddedRef));
|
||||
if (!embeddedRef.isLink())
|
||||
if (!embeddedRef.isRefByValueOnly())
|
||||
localPreTasks.add(new GenerateRefTask(embeddedRef));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* test-producers
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -31,6 +31,7 @@ import ru.entaxy.platform.core.producer.api.EntaxyProducerService;
|
||||
import ru.entaxy.platform.core.producer.api.ProducerResult;
|
||||
import ru.entaxy.platform.core.producer.api.ProducerResult.CommandResult;
|
||||
import ru.entaxy.platform.core.producer.executor.generationmodel.merge.MergeHelper;
|
||||
import ru.entaxy.platform.core.producer.executor.support.EntaxyObjectPropertiesHelper;
|
||||
|
||||
public class MergeTask extends AbstractTask {
|
||||
|
||||
@ -72,13 +73,16 @@ public class MergeTask extends AbstractTask {
|
||||
GeneratedHeaders sourceGeneratedHeaders = GeneratedHeaders.getHeaders(source.getProperties());
|
||||
GeneratedHeaders targetGeneratedHeaders = GeneratedHeaders.getHeaders(target.getProperties());
|
||||
|
||||
GeneratedHeaders resultGeneratedHeaders = GeneratedHeaders.getHeaders(this.generatedResult.getProperties());
|
||||
GeneratedHeaders resultGeneratedHeaders = GeneratedHeaders.getHeaders(
|
||||
// this.generatedResult.getProperties()
|
||||
EntaxyObjectPropertiesHelper.getMainObjectProperties(this.generatedResult.getProperties())
|
||||
);
|
||||
|
||||
for (String header: targetGeneratedHeaders.headers.keySet())
|
||||
resultGeneratedHeaders.set(header, targetGeneratedHeaders.headers.get(header));
|
||||
|
||||
for (String header: sourceGeneratedHeaders.headers.keySet())
|
||||
if (EntaxyObject.HEADERS.MAIN_OBJECT.equals(header))
|
||||
if (EntaxyObject.HEADERS.MAIN_OBJECT.equals(header) || EntaxyObject.HEADERS.ENTAXY_GENERATED.equals(header))
|
||||
continue;
|
||||
else
|
||||
resultGeneratedHeaders.append(header, sourceGeneratedHeaders.headers.get(header));
|
||||
@ -95,6 +99,9 @@ public class MergeTask extends AbstractTask {
|
||||
this.fromTask.setFinal(false);
|
||||
this.toTask.updateGenerated(generatedResult);
|
||||
|
||||
printOutput("\tMERGE RESULT ::");
|
||||
printOutput(generatedResult.getObject().toString());
|
||||
|
||||
// prevent building result of this task
|
||||
this.generatedResult = null;
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* object-producer-core
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* object-producer-core
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* object-producer-core
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* test-producers
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* object-producer-core
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* object-producer-core
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -19,8 +19,19 @@
|
||||
*/
|
||||
package ru.entaxy.platform.core.producer.executor.generationmodel.merge;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.osgi.framework.Bundle;
|
||||
import org.osgi.service.component.ComponentContext;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@ -28,24 +39,74 @@ import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import ru.entaxy.esb.platform.runtime.base.connecting.generator.Generated;
|
||||
import ru.entaxy.platform.base.support.CommonUtils;
|
||||
import ru.entaxy.platform.base.support.JSONUtils;
|
||||
import ru.entaxy.platform.base.support.xml.CommonXMLUtils;
|
||||
import ru.entaxy.platform.core.producer.executor.generationmodel.merge.MergingMap.Mapping;
|
||||
import ru.entaxy.platform.core.producer.executor.support.EntaxyObjectPropertiesHelper;
|
||||
|
||||
@Component(service = MergeProcessor.class, immediate = true)
|
||||
@MergingMap(mappings = {
|
||||
@Mapping(source = Generated.GENERATED_TYPE_BLUEPRINT_FRAGMENT, targets = {Generated.GENERATED_TYPE_BLUEPRINT})
|
||||
@Mapping(source = Generated.GENERATED_TYPE_BLUEPRINT_FRAGMENT
|
||||
, targets = {Generated.GENERATED_TYPE_BLUEPRINT, Generated.GENERATED_TYPE_BLUEPRINT_FRAGMENT})
|
||||
})
|
||||
public class BlueprintMergeProcessor extends AbstractMergeProcessor {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(BlueprintMergeProcessor.class);
|
||||
|
||||
public static final String FRAGMENT_NAME = "fragment";
|
||||
public static final String FRAGMENT_START = "<" + FRAGMENT_NAME + ">";
|
||||
public static final String FRAGMENT_END = "</" + FRAGMENT_NAME + ">";
|
||||
|
||||
protected MergeProcessor defaultProcessor;
|
||||
|
||||
@Activate
|
||||
public void activate(ComponentContext componentContext) {
|
||||
Bundle bundle = componentContext.getBundleContext().getBundle();
|
||||
URL url = bundle.getEntry("/config/BlueprintMergeProcessor.json");
|
||||
defaultProcessor = new MergeProcessor();
|
||||
try {
|
||||
defaultProcessor.load(url.openStream());
|
||||
} catch (Exception e) {
|
||||
log.error("Error loading configuration", e);
|
||||
defaultProcessor.loadDefaults();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Generated merge(Generated source, Generated target, Map<String, Object> config) {
|
||||
|
||||
MergeProcessor currentProcessor;
|
||||
|
||||
String mergeConfig = config==null
|
||||
?""
|
||||
:config.getOrDefault("merge.config", "").toString();
|
||||
if (CommonUtils.isValid(mergeConfig)) {
|
||||
currentProcessor = new MergeProcessor();
|
||||
try {
|
||||
currentProcessor.load(mergeConfig);
|
||||
} catch (Exception e) {
|
||||
log.error("Invalid merge.config: \n" + mergeConfig, e);
|
||||
currentProcessor = defaultProcessor.createCopy();
|
||||
}
|
||||
} else {
|
||||
currentProcessor = defaultProcessor.createCopy();
|
||||
}
|
||||
|
||||
NodeList sourceNodes = null;
|
||||
if (source.getType().equals(Generated.GENERATED_TYPE_BLUEPRINT_FRAGMENT)) {
|
||||
String toParse = "<fragment>" + source.getObject().toString() + "</fragment>";
|
||||
// remove <?xml .. ?> if present
|
||||
String sourceValue = source.getObject().toString().trim();
|
||||
if (sourceValue.startsWith("<?xml")) {
|
||||
int index = sourceValue.indexOf("?>");
|
||||
sourceValue = sourceValue.substring(index+2);
|
||||
}
|
||||
String toParse = FRAGMENT_START + sourceValue + FRAGMENT_END;
|
||||
try {
|
||||
Document sourceDoc = CommonXMLUtils.parseString(true, toParse);
|
||||
sourceNodes = sourceDoc.getFirstChild().getChildNodes();
|
||||
@ -60,52 +121,568 @@ public class BlueprintMergeProcessor extends AbstractMergeProcessor {
|
||||
if ((sourceNodes == null) || (sourceNodes.getLength()==0))
|
||||
return target;
|
||||
|
||||
if (target.getType().equals(Generated.GENERATED_TYPE_BLUEPRINT)) {
|
||||
return mergeToBlueprint(sourceNodes, source, target, currentProcessor);
|
||||
}
|
||||
|
||||
if (target.getType().equals(Generated.GENERATED_TYPE_BLUEPRINT_FRAGMENT)) {
|
||||
return mergeToFragment(sourceNodes, source, target, currentProcessor);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected Generated mergeToBlueprint(NodeList sourceNodes, Generated source, Generated target, MergeProcessor currentProcessor) {
|
||||
Document targetDoc = null;
|
||||
Node targetNode = null;
|
||||
Node targetNodeBefore = null;
|
||||
if (target.getType().equals(Generated.GENERATED_TYPE_BLUEPRINT)) {
|
||||
try {
|
||||
targetDoc = CommonXMLUtils.parseString(true, target.getObject().toString());
|
||||
targetNode = targetDoc.getFirstChild();
|
||||
|
||||
NodeList manifests = targetDoc.getElementsByTagName("manifest");
|
||||
for (int i=0; i<manifests.getLength(); i++)
|
||||
if ((manifests.item(i).getParentNode() != null) && (manifests.item(i).getParentNode() == targetNode)) {
|
||||
targetNodeBefore = manifests.item(i).getNextSibling();
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("Can't parse: \n" + target.getObject().toString(), e);
|
||||
}
|
||||
}
|
||||
|
||||
if (targetNode == null)
|
||||
try {
|
||||
targetDoc = CommonXMLUtils.parseString(true, target.getObject().toString());
|
||||
targetNode = targetDoc.getFirstChild();
|
||||
|
||||
currentProcessor.setDocument(targetDoc);
|
||||
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("Can't parse: \n" + target.getObject().toString(), e);
|
||||
}
|
||||
|
||||
if (!currentProcessor.hasDocument())
|
||||
return null;
|
||||
|
||||
if (targetNode.getChildNodes().getLength()==0)
|
||||
for (int i=0; i<sourceNodes.getLength(); i++)
|
||||
targetNode.appendChild(targetDoc.adoptNode(sourceNodes.item(i).cloneNode(true)));
|
||||
else {
|
||||
if (targetNodeBefore == null)
|
||||
targetNodeBefore = targetNode.getFirstChild();
|
||||
for (int i=0; i<sourceNodes.getLength(); i++)
|
||||
targetNode.insertBefore(targetDoc.adoptNode(sourceNodes.item(i).cloneNode(true)), targetNodeBefore);
|
||||
|
||||
}
|
||||
currentProcessor.reset();
|
||||
|
||||
/*for (int i=0; i<sourceNodes.getLength(); i++)
|
||||
currentProcessor.mergeNode(sourceNodes.item(i));
|
||||
*/
|
||||
|
||||
currentProcessor.mergeNodes(sourceNodes);
|
||||
|
||||
try {
|
||||
String resultBlueprint = CommonXMLUtils.doc2string(targetDoc);
|
||||
Generated result = Generated.create(Generated.GENERATED_TYPE_BLUEPRINT, resultBlueprint);
|
||||
result.getProperties().putAll(target.getProperties());
|
||||
result.getProperties().putAll(
|
||||
EntaxyObjectPropertiesHelper.merge(source.getProperties(), target.getProperties())
|
||||
);
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
log.error("Can't convert to string", e);
|
||||
}
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected Generated mergeToFragment(NodeList sourceNodes, Generated source, Generated target, MergeProcessor currentProcessor) {
|
||||
|
||||
// remove <?xml .. ?> if present
|
||||
String targetValue = target.getObject().toString().trim();
|
||||
if (targetValue.startsWith("<?xml")) {
|
||||
int index = targetValue.indexOf("?>");
|
||||
targetValue = targetValue.substring(index+2);
|
||||
}
|
||||
String toParse = FRAGMENT_START + targetValue + FRAGMENT_END;
|
||||
|
||||
Document targetDoc = null;
|
||||
|
||||
try {
|
||||
targetDoc = CommonXMLUtils.parseString(true, toParse);
|
||||
for (int i=0; i<sourceNodes.getLength(); i++) {
|
||||
targetDoc.getFirstChild().appendChild(
|
||||
targetDoc.adoptNode(sourceNodes.item(i).cloneNode(true))
|
||||
);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("Can't parse: \n" + toParse, e);
|
||||
}
|
||||
|
||||
try {
|
||||
String resultFragment = CommonXMLUtils.doc2string(targetDoc).trim();
|
||||
|
||||
if (resultFragment.startsWith(FRAGMENT_START))
|
||||
resultFragment = resultFragment.substring(FRAGMENT_START.length());
|
||||
if (resultFragment.endsWith(FRAGMENT_END))
|
||||
resultFragment = resultFragment.substring(0
|
||||
, resultFragment.length() - FRAGMENT_END.length());
|
||||
|
||||
|
||||
|
||||
Generated result = Generated.create(Generated.GENERATED_TYPE_BLUEPRINT_FRAGMENT, resultFragment);
|
||||
result.getProperties().putAll(
|
||||
EntaxyObjectPropertiesHelper.merge(source.getProperties(), target.getProperties())
|
||||
);
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
log.error("Can't convert to string", e);
|
||||
}
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected static class MergeProcessor {
|
||||
|
||||
public static String DEFAULT_CONFIG = "{\"*\":{}}";
|
||||
|
||||
MergeProcessorConfig config = new MergeProcessorConfig();
|
||||
|
||||
Document document;
|
||||
|
||||
Node rootNode;
|
||||
Node manifestNode = null;
|
||||
|
||||
boolean trackOrder = true;
|
||||
List<Node> processedNodes = new ArrayList<>();
|
||||
|
||||
public void load(InputStream inputStream) throws IOException {
|
||||
log.info("loading config");
|
||||
String text = new String(inputStream.readAllBytes(), StandardCharsets.UTF_8);
|
||||
inputStream.close();
|
||||
load(text);
|
||||
}
|
||||
|
||||
public void loadDefaults() {
|
||||
load(DEFAULT_CONFIG);
|
||||
}
|
||||
|
||||
public void load(String jsonData) {
|
||||
config.load(JSONUtils.getJsonRootObject(jsonData));
|
||||
}
|
||||
|
||||
public MergeProcessor createCopy() {
|
||||
MergeProcessor result = new MergeProcessor();
|
||||
result.config.load(this.config.config);
|
||||
return result;
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
processedNodes.clear();
|
||||
}
|
||||
|
||||
public Document getDocument() {
|
||||
return document;
|
||||
}
|
||||
|
||||
public void setDocument(Document document) {
|
||||
this.document = document;
|
||||
|
||||
rootNode = this.document.getFirstChild();
|
||||
|
||||
NodeList manifests = this.document.getElementsByTagName("manifest");
|
||||
for (int i=0; i<manifests.getLength(); i++)
|
||||
if ((manifests.item(i).getParentNode() != null) && (manifests.item(i).getParentNode() == rootNode)) {
|
||||
manifestNode = manifests.item(i);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public boolean hasDocument() {
|
||||
return this.document != null;
|
||||
}
|
||||
|
||||
protected NodeConflict checkNodeConflict(Node newNode, Node targetContainerNode, MERGE_POSITION position, MergeConfig mergeConfig) {
|
||||
|
||||
if ((mergeConfig.unique == null) || mergeConfig.unique.isEmpty())
|
||||
return null;
|
||||
|
||||
String nodeName = newNode.getLocalName();
|
||||
Map<String, String> attributes = new HashMap<>();
|
||||
for (String attrName: mergeConfig.unique) {
|
||||
Node attr = newNode.getAttributes().getNamedItem(attrName);
|
||||
if (attr == null)
|
||||
attributes.put(attrName, null);
|
||||
else
|
||||
attributes.put(attrName, attr.getNodeValue());
|
||||
}
|
||||
|
||||
NodeConflict result = null;
|
||||
|
||||
NodeList testNodes = targetContainerNode.getChildNodes();
|
||||
for (int i=0; i<testNodes.getLength(); i++) {
|
||||
Node item = testNodes.item(i);
|
||||
if (!nodeName.equalsIgnoreCase(item.getLocalName()))
|
||||
continue;
|
||||
boolean found = false;
|
||||
for (Entry<String, String> attributeEntry: attributes.entrySet()) {
|
||||
String attrValue = attributeEntry.getValue();
|
||||
Node testAttr = item.getAttributes().getNamedItem(attributeEntry.getKey());
|
||||
if ((testAttr == null) && (attrValue!=null)) {
|
||||
found = false;
|
||||
break;
|
||||
}
|
||||
if ((testAttr != null) && (attrValue==null)) {
|
||||
found = false;
|
||||
break;
|
||||
}
|
||||
if ((testAttr != null) && (attrValue!=null)) {
|
||||
String testValue = testAttr.getNodeValue();
|
||||
if (testValue==null) {
|
||||
found = false;
|
||||
break;
|
||||
}
|
||||
if (testValue.equalsIgnoreCase(attrValue)) {
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
result = new NodeConflict();
|
||||
result.newNode = newNode;
|
||||
result.oldNode = item;
|
||||
result.conflictResolution =
|
||||
CommonUtils.getValid(mergeConfig.conflict, MergeConfig.CONFLICT_INGORE);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public List<Node> mergeNodes(NodeList sourceNodes){
|
||||
List<Node> result = new ArrayList<>();
|
||||
|
||||
mergeFilteredNodes(sourceNodes, result);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
protected void mergeFilteredNodes(NodeList sourceNodes, List<Node> toReturn){
|
||||
for (int i=0; i<sourceNodes.getLength(); i++) {
|
||||
Node current = sourceNodes.item(i);
|
||||
MergeConfig mergeConfig = this.config.getConfig(current);
|
||||
if (mergeConfig.isIgnore())
|
||||
continue;
|
||||
if (mergeConfig.isTransparent()) {
|
||||
mergeFilteredNodes(current.getChildNodes(), toReturn);
|
||||
continue;
|
||||
}
|
||||
toReturn.add(this.mergeNode(current));
|
||||
}
|
||||
}
|
||||
|
||||
public Node mergeNode(Node sourceNode) {
|
||||
|
||||
MergeConfig mergeConfig = config.getConfig(sourceNode);
|
||||
Node targetNode = null;
|
||||
if (CommonUtils.isValid(mergeConfig.targetNodeName)) {
|
||||
|
||||
NodeList list = rootNode.getChildNodes();
|
||||
for (int i=0; i<list.getLength(); i++) {
|
||||
Node current = list.item(i);
|
||||
if (!mergeConfig.targetNodeName.equalsIgnoreCase(current.getLocalName()))
|
||||
continue;
|
||||
if (CommonUtils.isValid(mergeConfig.targetNodeNamespace)) {
|
||||
if (!mergeConfig.targetNodeNamespace.equalsIgnoreCase(current.getNamespaceURI()))
|
||||
continue;
|
||||
}
|
||||
targetNode = current;
|
||||
break;
|
||||
}
|
||||
|
||||
} else {
|
||||
targetNode = rootNode;
|
||||
}
|
||||
|
||||
if (targetNode == null) {
|
||||
if (mergeConfig.createTargetNode) {
|
||||
if (!CommonUtils.isValid(mergeConfig.targetNodeXML)) {
|
||||
log.warn("Can't merge node [{}:{}] : target node not found [{} : {}] and targetNodeXML not set"
|
||||
, sourceNode.getLocalName()
|
||||
, sourceNode.getNamespaceURI()
|
||||
, mergeConfig.targetNodeName
|
||||
, mergeConfig.targetNodeNamespace);
|
||||
} else {
|
||||
try {
|
||||
Document d = CommonXMLUtils.parseString(true, mergeConfig.targetNodeXML);
|
||||
Node n = d.getFirstChild();
|
||||
targetNode = this.mergeNode(n);
|
||||
} catch (Exception e) {
|
||||
log.error("Error creating node from XML:\n" + mergeConfig.targetNodeXML
|
||||
, e);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.warn("Can't merge node [{}:{}] : target node not found [{} : {}]"
|
||||
, sourceNode.getLocalName()
|
||||
, sourceNode.getNamespaceURI()
|
||||
, mergeConfig.targetNodeName
|
||||
, mergeConfig.targetNodeNamespace);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if (targetNode == null) {
|
||||
log.warn("Can't merge node [{}:{}] : target node not found [{} : {}]"
|
||||
, sourceNode.getLocalName()
|
||||
, sourceNode.getNamespaceURI()
|
||||
, mergeConfig.targetNodeName
|
||||
, mergeConfig.targetNodeNamespace);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (mergeConfig.position == null)
|
||||
mergeConfig.position = MERGE_POSITION.INSIDE_FIRST.label;
|
||||
|
||||
Node adopted = this.document.adoptNode(sourceNode.cloneNode(true));
|
||||
if (targetNode == rootNode)
|
||||
// we can't add nodes before or after a root node
|
||||
if (mergeConfig.position.equals(MERGE_POSITION.AFTER.label) || mergeConfig.position.equals(MERGE_POSITION.BEFORE.label))
|
||||
mergeConfig.position = MERGE_POSITION.INSIDE_FIRST.label;
|
||||
|
||||
Node currentRef;
|
||||
MERGE_POSITION position = MERGE_POSITION.valueOfLabel(mergeConfig.position);
|
||||
|
||||
NodeConflict nodeConflict;
|
||||
switch (position) {
|
||||
case AFTER:
|
||||
case BEFORE:
|
||||
nodeConflict = checkNodeConflict(adopted, targetNode.getParentNode(), position, mergeConfig);
|
||||
break;
|
||||
default:
|
||||
nodeConflict = checkNodeConflict(adopted, targetNode, position, mergeConfig);
|
||||
}
|
||||
|
||||
if (nodeConflict != null) {
|
||||
if (MergeConfig.CONFLICT_REPLACE.equalsIgnoreCase(nodeConflict.conflictResolution)) {
|
||||
// replace node
|
||||
nodeConflict.oldNode.getParentNode().replaceChild(
|
||||
targetNode.getOwnerDocument().adoptNode(nodeConflict.newNode.cloneNode(true))
|
||||
, nodeConflict.oldNode);
|
||||
} else {
|
||||
// ignore
|
||||
}
|
||||
} else {
|
||||
|
||||
try {
|
||||
switch (position) {
|
||||
case AFTER:
|
||||
currentRef = targetNode.getNextSibling();
|
||||
|
||||
if (trackOrder)
|
||||
while ((currentRef != null) && processedNodes.contains(currentRef))
|
||||
currentRef = currentRef.getNextSibling();
|
||||
|
||||
if (currentRef != null)
|
||||
targetNode.getParentNode().insertBefore(adopted, currentRef);
|
||||
else
|
||||
targetNode.getParentNode().appendChild(adopted);
|
||||
break;
|
||||
case BEFORE:
|
||||
targetNode.getParentNode().insertBefore(adopted, targetNode);
|
||||
break;
|
||||
case INSIDE_FIRST:
|
||||
currentRef = null;
|
||||
|
||||
if ((targetNode == rootNode) && (manifestNode != null))
|
||||
// we assume 'first' as 'first after MANIFEST'
|
||||
currentRef = manifestNode.getNextSibling();
|
||||
else
|
||||
currentRef = targetNode.getFirstChild();
|
||||
|
||||
if (trackOrder)
|
||||
while ((currentRef != null) && processedNodes.contains(currentRef))
|
||||
currentRef = currentRef.getNextSibling();
|
||||
|
||||
if (currentRef == null)
|
||||
targetNode.appendChild(adopted);
|
||||
else
|
||||
targetNode.insertBefore(adopted, currentRef);
|
||||
|
||||
break;
|
||||
case INSIDE_LAST:
|
||||
targetNode.appendChild(adopted);
|
||||
break;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("Error merging node", e);
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (trackOrder)
|
||||
this.processedNodes.add(adopted);
|
||||
|
||||
return adopted;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected static class NodeConflict {
|
||||
|
||||
public Node newNode;
|
||||
public Node oldNode;
|
||||
|
||||
public String conflictResolution;
|
||||
|
||||
}
|
||||
|
||||
protected static class MergeProcessorConfig {
|
||||
|
||||
JsonObject config;
|
||||
|
||||
MergeConfig DEFAULT_CONFIG = new MergeConfig() {{
|
||||
// rootNode
|
||||
targetNodeName = null;
|
||||
// with any namespace
|
||||
targetNodeNamespace = null;
|
||||
// add to the end
|
||||
position = MERGE_POSITION.INSIDE_FIRST.label;
|
||||
}};
|
||||
|
||||
public void load(JsonObject object) {
|
||||
this.config = object.deepCopy();
|
||||
}
|
||||
|
||||
public MergeConfig getConfig(Node sourceNode) {
|
||||
String name = sourceNode.getLocalName();
|
||||
String namespace = sourceNode.getNamespaceURI();
|
||||
JsonElement configElement = null;
|
||||
|
||||
if (config.has(name + ":" + namespace)) {
|
||||
configElement = config.get(name + ":" + namespace);
|
||||
} else {
|
||||
if (config.has(name)) {
|
||||
configElement = config.get(name);
|
||||
} else {
|
||||
if (config.has("*")) {
|
||||
configElement = config.get("*");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (configElement == null)
|
||||
return DEFAULT_CONFIG;
|
||||
|
||||
try {
|
||||
return (new Gson()).fromJson(configElement, MergeConfig.class);
|
||||
} catch (Exception e) {
|
||||
log.error("Error getting merge config", e);
|
||||
return DEFAULT_CONFIG;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected enum MERGE_POSITION {
|
||||
BEFORE("before"),
|
||||
AFTER("after"),
|
||||
INSIDE_FIRST("inside_first"),
|
||||
INSIDE_LAST("inside_last");
|
||||
|
||||
public String label;
|
||||
|
||||
private MERGE_POSITION(String label) {
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
public static MERGE_POSITION valueOfLabel(String label) {
|
||||
for (MERGE_POSITION e : values()) {
|
||||
if (e.label.equals(label)) {
|
||||
return e;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected static class MergeConfig {
|
||||
|
||||
public static final String CONFLICT_INGORE = "ignore";
|
||||
public static final String CONFLICT_REPLACE = "replace";
|
||||
|
||||
String targetNodeName;
|
||||
String targetNodeNamespace;
|
||||
|
||||
String position = MERGE_POSITION.INSIDE_FIRST.label;
|
||||
|
||||
boolean ignore = false;
|
||||
|
||||
boolean isTransparent = false;
|
||||
|
||||
boolean createTargetNode = false;
|
||||
String targetNodeXML;
|
||||
|
||||
List<String> unique = new ArrayList<>();
|
||||
String conflict;
|
||||
|
||||
public String getTargetNodeName() {
|
||||
return targetNodeName;
|
||||
}
|
||||
|
||||
public void setTargetNodeName(String targetNodeName) {
|
||||
this.targetNodeName = targetNodeName;
|
||||
}
|
||||
|
||||
public boolean isCreateTargetNode() {
|
||||
return createTargetNode;
|
||||
}
|
||||
|
||||
public void setCreateTargetNode(boolean createTargetNode) {
|
||||
this.createTargetNode = createTargetNode;
|
||||
}
|
||||
|
||||
public String getTargetNodeXML() {
|
||||
return targetNodeXML;
|
||||
}
|
||||
|
||||
public void setTargetNodXMLe(String targetNodeXML) {
|
||||
this.targetNodeXML = targetNodeXML;
|
||||
}
|
||||
|
||||
public String getTargetNodeNamespace() {
|
||||
return targetNodeNamespace;
|
||||
}
|
||||
|
||||
public void setTargetNodeNamespace(String targetNodeNamespace) {
|
||||
this.targetNodeNamespace = targetNodeNamespace;
|
||||
}
|
||||
|
||||
public MERGE_POSITION getPosition() {
|
||||
return MERGE_POSITION.valueOfLabel(position);
|
||||
}
|
||||
|
||||
public void setPosition(String position) {
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
public boolean isIgnore() {
|
||||
return ignore;
|
||||
}
|
||||
|
||||
public void setIgnore(boolean ignore) {
|
||||
this.ignore = ignore;
|
||||
}
|
||||
|
||||
public boolean isTransparent() {
|
||||
return isTransparent;
|
||||
}
|
||||
|
||||
public void setTransparent(boolean isTransparent) {
|
||||
this.isTransparent = isTransparent;
|
||||
}
|
||||
|
||||
public List<String> getUnique() {
|
||||
return unique;
|
||||
}
|
||||
|
||||
public void setUnique(List<String> unique) {
|
||||
this.unique = unique;
|
||||
}
|
||||
|
||||
public String getConflict() {
|
||||
return conflict;
|
||||
}
|
||||
|
||||
public void setConflict(String conflict) {
|
||||
this.conflict = conflict;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* object-producer-core
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* object-producer-core
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* object-producer-core
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* test-producers
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* object-producer-core
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -21,18 +21,26 @@ package ru.entaxy.platform.core.producer.executor.objectmodel;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import ru.entaxy.platform.base.support.JSONUtils.ObjectWrapper;
|
||||
|
||||
public abstract class AbstractItem extends ObjectWrapper {
|
||||
|
||||
public static final String OBJECT_UUID = "__uuid__";
|
||||
|
||||
public static final String FACTORED_CONTEXT_KEY = "factoredObjects";
|
||||
|
||||
public String jsonPath = "";
|
||||
public String relativePath = "";
|
||||
public JsonObject origin;
|
||||
public FactoredObject definedIn = null;
|
||||
|
||||
protected String uuid = null;
|
||||
|
||||
protected ObjectModel objectModel;
|
||||
|
||||
protected AbstractItem(ObjectModel objectModel) {
|
||||
@ -62,5 +70,23 @@ public abstract class AbstractItem extends ObjectWrapper {
|
||||
public void wrap(JsonObject object, Map<String, Object> context, String path) {
|
||||
this.origin = object;
|
||||
this.jsonPath = path;
|
||||
if (this.origin.has(OBJECT_UUID)) {
|
||||
JsonElement je = this.origin.get(OBJECT_UUID);
|
||||
if (je.isJsonPrimitive())
|
||||
if (je.getAsJsonPrimitive().isString())
|
||||
this.uuid = je.getAsJsonPrimitive().getAsString();
|
||||
}
|
||||
if (this.uuid == null) {
|
||||
this.uuid = UUID.randomUUID().toString();
|
||||
this.origin.addProperty(OBJECT_UUID, this.uuid);
|
||||
}
|
||||
}
|
||||
|
||||
public String getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
public void updateFromOrigin() {
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* object-producer-core
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -26,43 +26,80 @@ import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import ru.entaxy.platform.base.objects.factory.EntaxyFactory;
|
||||
import ru.entaxy.platform.base.support.CommonUtils;
|
||||
import ru.entaxy.platform.base.support.JSONUtils;
|
||||
import ru.entaxy.platform.base.support.osgi.OSGIUtils;
|
||||
import ru.entaxy.platform.core.producer.api.EntaxyProducerService;
|
||||
|
||||
public class Calculation extends AbstractItem {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(Calculation.class);
|
||||
|
||||
// TODO move const to EntaxyObject
|
||||
public static final String FIELD_IS_CALCULATED = "isCalculated";
|
||||
public static final String FIELD_IS_CALCULATED = "isCalculated";
|
||||
|
||||
public static final String OWNER_PREFIX = "#OWNER";
|
||||
public static final String OWNER_OF_TYPE_PREFIX = "#OWNER_OF_TYPE";
|
||||
public static final String FACTORY_PREFIX = "#FACTORY";
|
||||
public static final String TYPE_DATA_PREFIX = "#TYPEINFO";
|
||||
|
||||
public static final String OWNER_TOKEN = "#OWNER#";
|
||||
public static final String FACTORY_TOKEN = "#FACTORY#";
|
||||
public static final String TYPE_DATA_TOKEN = "#TYPEINFO#";
|
||||
|
||||
public static final Object NOT_ENOUGH_DATA = new Object();
|
||||
|
||||
public static boolean isCalculated(JsonObject jsonObject) {
|
||||
if (!jsonObject.has(FIELD_IS_CALCULATED))
|
||||
return false;
|
||||
try {
|
||||
return jsonObject.get(FIELD_IS_CALCULATED).getAsBoolean();
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
boolean result = false;
|
||||
|
||||
// old-style calculated
|
||||
if (jsonObject.has(FIELD_IS_CALCULATED))
|
||||
try {
|
||||
result = jsonObject.get(FIELD_IS_CALCULATED).getAsBoolean();
|
||||
} catch (Exception e) {
|
||||
// return false;
|
||||
}
|
||||
|
||||
// new-style calculated
|
||||
if (jsonObject.has(EntaxyFactory.CONFIGURATION.DIRECTIVES.CALCULATED)) {
|
||||
result = jsonObject.get(EntaxyFactory.CONFIGURATION.DIRECTIVES.CALCULATED).isJsonObject();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
protected ExpressionCalculation expressionCalculation;
|
||||
|
||||
protected String targetPath;
|
||||
protected boolean removeResolved = false;
|
||||
|
||||
protected boolean lazy = true;
|
||||
|
||||
public Calculation(ObjectModel objectModel) {
|
||||
super(objectModel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void wrap(JsonObject object, Map<String, Object> context, String path) {
|
||||
if (!ExpressionCalculation.isExpressionCalculation(object))
|
||||
|
||||
JsonObject content = object;
|
||||
if (object.has(EntaxyFactory.CONFIGURATION.DIRECTIVES.CALCULATED))
|
||||
content = object.get(EntaxyFactory.CONFIGURATION.DIRECTIVES.CALCULATED).getAsJsonObject();
|
||||
|
||||
if (!ExpressionCalculation.isExpressionCalculation(content))
|
||||
return;
|
||||
|
||||
super.wrap(object, context, path);
|
||||
|
||||
|
||||
this.expressionCalculation = new ExpressionCalculation();
|
||||
this.expressionCalculation.init(object);
|
||||
this.expressionCalculation.init(content);
|
||||
|
||||
AbstractFactored contextOwner = AbstractFactored.getContextOwner(context);
|
||||
if (contextOwner instanceof FactoredObject)
|
||||
@ -71,26 +108,98 @@ public class Calculation extends AbstractItem {
|
||||
contextOwner.addInternal(this);
|
||||
|
||||
computeRelativePath(contextOwner.jsonPath);
|
||||
|
||||
if (content.has("targetPath")) {
|
||||
JsonElement tp = content.get("targetPath");
|
||||
if (tp.isJsonNull()) {
|
||||
this.targetPath = this.relativePath;
|
||||
} else {
|
||||
this.targetPath = tp.getAsString();
|
||||
}
|
||||
} else {
|
||||
this.targetPath = this.relativePath;
|
||||
}
|
||||
|
||||
if (content.has("removeResolved"))
|
||||
try {
|
||||
this.removeResolved = content.get("removeResolved").getAsBoolean();
|
||||
} catch (Exception e) {
|
||||
// NOOP
|
||||
}
|
||||
|
||||
if (content.has("lazy"))
|
||||
try {
|
||||
this.lazy = content.get("lazy").getAsBoolean();
|
||||
} catch (Exception e) {
|
||||
// NOOP
|
||||
}
|
||||
|
||||
|
||||
// System.out.println("\n\n===>>>> [CALCULATION] CREATED [" + contextOwner.factoryId + "/" + this.relativePath + "]");
|
||||
|
||||
}
|
||||
public Object calculate(ObjectModel objectModel) {
|
||||
if (this.definedIn == null)
|
||||
return null;
|
||||
return calculate(objectModel, this.definedIn);
|
||||
}
|
||||
|
||||
public Object calculate(ObjectModel objectModel, FactoredObject factoredObject) {
|
||||
return this.expressionCalculation.calculate(objectModel, factoredObject);
|
||||
}
|
||||
|
||||
public String getTargetPath() {
|
||||
return targetPath;
|
||||
}
|
||||
|
||||
public boolean isRemoveResolved() {
|
||||
return removeResolved;
|
||||
}
|
||||
|
||||
public boolean isLazy() {
|
||||
return lazy;
|
||||
}
|
||||
|
||||
public static class ExpressionCalculation {
|
||||
|
||||
// TODO move const to EntaxyObject
|
||||
public static final String ATTR_EXPRESSION = "expression";
|
||||
public static final String ATTR_EXPRESSION = "expression";
|
||||
|
||||
public static final String ATTR_RESULT_TYPE = "resultType";
|
||||
|
||||
public static final String ATTR_ALLOW_OBJECTS = "allowObjects";
|
||||
public static final String ATTR_ALLOW_ARRAYS = "allowArrays";
|
||||
public static final String ATTR_ALLOW_PRIMITIVES = "allowPrimitives";
|
||||
public static final String ATTR_ALLOW_NULLS = "allowNulls";
|
||||
|
||||
protected static final Object TOKEN_NOT_FOUND = new Object();
|
||||
protected static final Object RESULT_NOT_ALLOWED = new Object();
|
||||
|
||||
protected static final RESULT_TYPE DEFAULT_RESULT_TYPE = RESULT_TYPE.STRING;
|
||||
|
||||
public enum RESULT_TYPE {
|
||||
STRING,
|
||||
LIST,
|
||||
LIST_OR_SINGLE,
|
||||
MAP;
|
||||
}
|
||||
|
||||
JsonObject jsonObject;
|
||||
|
||||
String expression;
|
||||
|
||||
String resultTypeValue = "String";
|
||||
|
||||
boolean allowObjects = true;
|
||||
boolean allowArrays = true;
|
||||
boolean allowPrimitives = true;
|
||||
boolean allowNulls = false;
|
||||
|
||||
List<String> toResolve = new ArrayList<>();
|
||||
Map<String, Object> resolved = new HashMap<>();
|
||||
|
||||
protected RESULT_TYPE resultType = DEFAULT_RESULT_TYPE;
|
||||
|
||||
public static boolean isExpressionCalculation(JsonObject jsonObject) {
|
||||
return jsonObject.has(ATTR_EXPRESSION);
|
||||
}
|
||||
@ -98,6 +207,33 @@ public class Calculation extends AbstractItem {
|
||||
public void init(JsonObject jsonObject) {
|
||||
this.jsonObject = jsonObject;
|
||||
this.expression = jsonObject.get(ATTR_EXPRESSION).getAsString();
|
||||
if (jsonObject.has(ATTR_RESULT_TYPE)) {
|
||||
this.resultTypeValue = jsonObject.get(ATTR_RESULT_TYPE).getAsString();
|
||||
if (CommonUtils.isValid(resultTypeValue)) {
|
||||
if (RESULT_TYPE.valueOf(this.resultTypeValue.toUpperCase()) != null)
|
||||
this.resultType = RESULT_TYPE.valueOf(this.resultTypeValue.toUpperCase());
|
||||
}
|
||||
}
|
||||
try {
|
||||
allowObjects = jsonObject.get(ATTR_ALLOW_OBJECTS).getAsBoolean();
|
||||
} catch (Exception e) {
|
||||
// NOOP
|
||||
}
|
||||
try {
|
||||
allowArrays = jsonObject.get(ATTR_ALLOW_ARRAYS).getAsBoolean();
|
||||
} catch (Exception e) {
|
||||
// NOOP
|
||||
}
|
||||
try {
|
||||
allowPrimitives = jsonObject.get(ATTR_ALLOW_PRIMITIVES).getAsBoolean();
|
||||
} catch (Exception e) {
|
||||
// NOOP
|
||||
}
|
||||
try {
|
||||
allowNulls = jsonObject.get(ATTR_ALLOW_NULLS).getAsBoolean();
|
||||
} catch (Exception e) {
|
||||
// NOOP
|
||||
}
|
||||
Pattern pattern = Pattern.compile("\\$\\{.+?\\}");
|
||||
Matcher matcher = pattern.matcher(this.expression);
|
||||
while (matcher.find()) {
|
||||
@ -111,7 +247,7 @@ public class Calculation extends AbstractItem {
|
||||
for (String expr: toResolve) {
|
||||
if (!resolved.containsKey(expr)) {
|
||||
Object result = resolve(expr, objectModel, factoredObject);
|
||||
if (!TOKEN_NOT_FOUND.equals(result)) {
|
||||
if (!TOKEN_NOT_FOUND.equals(result) && !RESULT_NOT_ALLOWED.equals(result)) {
|
||||
resolved.put(expr, result);
|
||||
}
|
||||
}
|
||||
@ -124,28 +260,176 @@ public class Calculation extends AbstractItem {
|
||||
}
|
||||
|
||||
public Object doCalculate() {
|
||||
String result = expression;
|
||||
for (Entry<String, Object> entry: resolved.entrySet()) {
|
||||
Object value = entry.getValue();
|
||||
String val = value==null?"":value.toString();
|
||||
result = result.replace("${" + entry.getKey() + "}", val);
|
||||
String expr = expression;
|
||||
|
||||
Object result = null;
|
||||
List<Object> list = new ArrayList<>();
|
||||
|
||||
switch (this.resultType) {
|
||||
case LIST:
|
||||
list.addAll(resolved.values());
|
||||
result = list;
|
||||
break;
|
||||
case LIST_OR_SINGLE:
|
||||
list.addAll(resolved.values());
|
||||
result = list;
|
||||
if (list.size()==1)
|
||||
result = list.get(0);
|
||||
break;
|
||||
case MAP:
|
||||
// TODO
|
||||
break;
|
||||
default:
|
||||
for (Entry<String, Object> entry: resolved.entrySet()) {
|
||||
Object value = entry.getValue();
|
||||
String val = value==null?"":value.toString();
|
||||
expr = expr.replace("${" + entry.getKey() + "}", val);
|
||||
}
|
||||
result = expr;
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public Object resolve(String token, ObjectModel objectModel, FactoredObject factoredObject) {
|
||||
JsonElement result = findElement(factoredObject.origin, token);
|
||||
if (result == null)
|
||||
return TOKEN_NOT_FOUND;
|
||||
return JSONUtils.element2object(result);
|
||||
}
|
||||
|
||||
public JsonElement findElement(JsonObject jsonObject, String pathFragment) {
|
||||
JsonElement result = findElement(jsonObject, pathFragment, "");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
protected boolean startsWithOwnerPrefix(String token) {
|
||||
if (!CommonUtils.isValid(token))
|
||||
return false;
|
||||
return token.startsWith(OWNER_PREFIX)
|
||||
|| token.startsWith(OWNER_OF_TYPE_PREFIX);
|
||||
}
|
||||
|
||||
public Object resolve(String token, ObjectModel objectModel, FactoredObject factoredObject) {
|
||||
|
||||
FactoredObject currentObject = factoredObject;
|
||||
String currentToken = token;
|
||||
|
||||
while (startsWithOwnerPrefix(currentToken) && currentObject!=null) {
|
||||
int ind = currentToken.substring(1).indexOf("#.");
|
||||
String subtoken;
|
||||
if (ind < 0) {
|
||||
subtoken = currentToken;
|
||||
currentToken = "";
|
||||
} else {
|
||||
subtoken = currentToken.substring(0, ind+2);
|
||||
currentToken = currentToken.substring(ind+3);
|
||||
}
|
||||
if (Calculation.OWNER_TOKEN.equals(subtoken)) {
|
||||
currentObject = currentObject.getOwnerObject();
|
||||
} else
|
||||
if (subtoken.startsWith(Calculation.OWNER_OF_TYPE_PREFIX)) {
|
||||
int i1 = subtoken.indexOf(':');
|
||||
if (i1<0) {
|
||||
log.warn("Incorrect expression: [{}]", subtoken);
|
||||
break;
|
||||
}
|
||||
String typeToFind = subtoken.substring(i1+1, subtoken.length()-1);
|
||||
|
||||
while (currentObject != null) {
|
||||
currentObject = currentObject.getOwnerObject();
|
||||
if (currentObject != null)
|
||||
if (typeToFind.equals(currentObject.getObjectType()))
|
||||
break;
|
||||
}
|
||||
|
||||
} else break;
|
||||
}
|
||||
if (currentObject == null)
|
||||
return TOKEN_NOT_FOUND;
|
||||
if (!CommonUtils.isValid(currentToken))
|
||||
return TOKEN_NOT_FOUND;
|
||||
JsonObject jsonObject = currentObject.origin;
|
||||
if (currentToken.startsWith(FACTORY_TOKEN)) {
|
||||
String factoryId = currentObject.factoryId;
|
||||
try {
|
||||
EntaxyProducerService entaxyProducerService = OSGIUtils.services()
|
||||
.ofClass(EntaxyProducerService.class).get();
|
||||
EntaxyFactory f = entaxyProducerService.findFactoryById(factoryId);
|
||||
jsonObject = JSONUtils.getJsonRootObject(f.getJsonConfiguration());
|
||||
currentToken = currentToken.substring(Calculation.FACTORY_TOKEN.length());
|
||||
if (currentToken.startsWith("."))
|
||||
currentToken = currentToken.substring(1);
|
||||
|
||||
if (currentToken.startsWith(TYPE_DATA_TOKEN)) {
|
||||
JsonElement je = jsonObject.get(f.getType());
|
||||
if ((je != null) && je.isJsonObject() )
|
||||
jsonObject = je.getAsJsonObject();
|
||||
else
|
||||
jsonObject = null;
|
||||
|
||||
currentToken = currentToken.substring(Calculation.TYPE_DATA_TOKEN.length());
|
||||
if (currentToken.startsWith("."))
|
||||
currentToken = currentToken.substring(1);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
return TOKEN_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
JsonElement result = null;
|
||||
if (jsonObject != null)
|
||||
if (CommonUtils.isValid(currentToken))
|
||||
result = findElement(jsonObject, currentToken);
|
||||
else
|
||||
result = jsonObject;
|
||||
|
||||
if (result == null)
|
||||
return TOKEN_NOT_FOUND;
|
||||
if (!valueIsAllowed(result))
|
||||
return RESULT_NOT_ALLOWED;
|
||||
|
||||
|
||||
return JSONUtils.element2object(result);
|
||||
}
|
||||
|
||||
protected boolean valueIsAllowed(JsonElement value) {
|
||||
if (value.isJsonNull() && !allowNulls)
|
||||
return false;
|
||||
if (value.isJsonObject())
|
||||
if (!allowObjects)
|
||||
return false;
|
||||
else {
|
||||
if (value.getAsJsonObject().has(EntaxyFactory.CONFIGURATION.DIRECTIVES.CALCULATED))
|
||||
return false;
|
||||
}
|
||||
if (value.isJsonArray() && !allowArrays)
|
||||
return false;
|
||||
if (value.isJsonPrimitive() && !allowPrimitives)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public JsonElement findElement(JsonObject jsonObject, String pathFragment) {
|
||||
JsonElement result = null;
|
||||
if (pathFragment.startsWith("?.")) {
|
||||
result = findElement(jsonObject, pathFragment.substring(2), "");
|
||||
} else {
|
||||
result = getElement(jsonObject, pathFragment);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
public JsonElement getElement(JsonObject jsonObject, String pathFragment) {
|
||||
int ind = pathFragment.indexOf(".");
|
||||
String currentFragment;
|
||||
String newFragment;
|
||||
if (ind > 0) {
|
||||
currentFragment = pathFragment.substring(0, ind);
|
||||
newFragment = pathFragment.substring(ind+1);
|
||||
} else {
|
||||
currentFragment = pathFragment;
|
||||
newFragment = null;
|
||||
}
|
||||
if (!jsonObject.has(currentFragment))
|
||||
return null;
|
||||
JsonElement je = jsonObject.get(currentFragment);
|
||||
if (newFragment == null)
|
||||
return je;
|
||||
if (!je.isJsonObject())
|
||||
return null;
|
||||
return getElement(je.getAsJsonObject(), newFragment);
|
||||
}
|
||||
|
||||
public JsonElement findElement(JsonObject jsonObject, String pathFragment, String parentPath) {
|
||||
|
||||
for (Entry<String, JsonElement> entry: jsonObject.entrySet()) {
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* test-producers
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -23,6 +23,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@ -31,6 +32,7 @@ import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import ru.entaxy.platform.base.objects.EntaxyObject;
|
||||
import ru.entaxy.platform.base.objects.EntaxyObject.FIELDS;
|
||||
|
||||
|
||||
@ -39,7 +41,9 @@ public class FactoredObject extends AbstractFactored {
|
||||
private static final Logger log = LoggerFactory.getLogger(FactoredObject.class);
|
||||
|
||||
public static String EMBEDDED_FIELD = "##embedded";
|
||||
|
||||
public static final String IGNORE_SECTION = "##ignore";
|
||||
|
||||
|
||||
public static String IS_EMBEDDED_FIELD = "isEmbedded";
|
||||
|
||||
public List<FactoredObject> dependsOn = new ArrayList<>();
|
||||
@ -96,6 +100,11 @@ public class FactoredObject extends AbstractFactored {
|
||||
this.scope = fo.scope;
|
||||
fo.dependsOn(this);
|
||||
this.definedIn = fo;
|
||||
if ("#OWNER#".equals(this.factoryId)) {
|
||||
this.factoryId = fo.factoryId;
|
||||
this.origin.remove(EntaxyObject.FIELDS.FACTORY_ID);
|
||||
this.origin.addProperty(EntaxyObject.FIELDS.FACTORY_ID, this.factoryId);
|
||||
}
|
||||
}
|
||||
log.debug("\t EFFECTIVE SCOPE :: " + this.scope);
|
||||
objectModel.addObject(this);
|
||||
@ -158,4 +167,26 @@ public class FactoredObject extends AbstractFactored {
|
||||
this.origin.addProperty(IS_EMBEDDED_FIELD, isEmbedded);
|
||||
}
|
||||
|
||||
public FactoredObject getOwnerObject() {
|
||||
if (this.definedIn != null)
|
||||
return this.definedIn;
|
||||
if (this.isEmbedded) {
|
||||
List<FactoredObjectRef> refs = this.objectModel.refs.stream()
|
||||
.filter(r->r.isLink)
|
||||
.filter(r->r.targetObject==this)
|
||||
.collect(Collectors.toList());
|
||||
if (!refs.isEmpty())
|
||||
return refs.get(0).definedIn;
|
||||
}
|
||||
// try to find refs with 'isDefinitionOrigin' set to 'true'
|
||||
List<FactoredObjectRef> refs = this.objectModel.refs.stream()
|
||||
.filter(r->r.isDefinitionOrigin())
|
||||
.filter(r->r.targetObject==this)
|
||||
.collect(Collectors.toList());
|
||||
if (!refs.isEmpty())
|
||||
return refs.get(0).definedIn;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* object-producer-core
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* test-producers
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -34,14 +34,18 @@ public class FactoredObjectRef extends AbstractFactored {
|
||||
|
||||
public static String IS_EXTERNAL_FIELD = "isExternal";
|
||||
public static String TARGET_ID_FIELD = "targetId";
|
||||
public static String TARGET_UUID_FIELD = "targetUuid";
|
||||
public static String TARGET_TYPE_FIELD = "targetType";
|
||||
public static String TARGET_VALUE_FIELD = "targetValue";
|
||||
public static String IS_RESOLVED_FIELD = "isResolved";
|
||||
public static String RESOLVE_ALWAYS_FIELD = "resolveAlways";
|
||||
public static String IS_LINK = "isLink";
|
||||
public static String IS_DEFINITION_ORIGIN = "isDefinitionOrigin";
|
||||
|
||||
protected FactoredObject targetObject = null;
|
||||
|
||||
protected String targetId = "";
|
||||
protected String targetUuid = "";
|
||||
protected String targetType = "";
|
||||
|
||||
protected boolean isExternal = true;
|
||||
@ -49,6 +53,8 @@ public class FactoredObjectRef extends AbstractFactored {
|
||||
protected boolean isBackRef = false;
|
||||
protected boolean refByValueOnly = false;
|
||||
protected boolean isLink = false;
|
||||
protected boolean resolveAlways = false;
|
||||
protected boolean isDefinitionOrigin = false;
|
||||
|
||||
public FactoredObjectRef (ObjectModel objectModel) {
|
||||
super(objectModel);
|
||||
@ -56,10 +62,12 @@ public class FactoredObjectRef extends AbstractFactored {
|
||||
this.origin.addProperty(FIELDS.IS_REF, true);
|
||||
this.origin.addProperty(IS_EXTERNAL_FIELD, false);
|
||||
this.origin.addProperty(TARGET_ID_FIELD, getTargetId());
|
||||
this.origin.addProperty(TARGET_UUID_FIELD, getTargetUuid());
|
||||
this.origin.addProperty(TARGET_TYPE_FIELD, getTargetType());
|
||||
this.origin.addProperty(FIELDS.FACTORY_ID, this.factoryId);
|
||||
this.origin.addProperty(FIELDS.SCOPE, this.scope);
|
||||
this.origin.addProperty(IS_RESOLVED_FIELD, this.isResolved);
|
||||
this.origin.addProperty(RESOLVE_ALWAYS_FIELD, this.resolveAlways);
|
||||
this.origin.addProperty(FIELDS.IS_BACK_REF, this.isBackRef);
|
||||
this.origin.addProperty(IS_LINK, false);
|
||||
}
|
||||
@ -81,10 +89,12 @@ public class FactoredObjectRef extends AbstractFactored {
|
||||
this.origin.addProperty(FIELDS.IS_REF, true);
|
||||
this.origin.addProperty(IS_EXTERNAL_FIELD, false);
|
||||
this.origin.addProperty(TARGET_ID_FIELD, getTargetId());
|
||||
this.origin.addProperty(TARGET_UUID_FIELD, getTargetUuid());
|
||||
this.origin.addProperty(TARGET_TYPE_FIELD, getTargetType());
|
||||
this.origin.addProperty(FIELDS.FACTORY_ID, this.factoryId);
|
||||
this.origin.addProperty(FIELDS.SCOPE, this.scope);
|
||||
this.origin.addProperty(IS_RESOLVED_FIELD, this.isResolved);
|
||||
this.origin.addProperty(RESOLVE_ALWAYS_FIELD, this.resolveAlways);
|
||||
this.origin.addProperty(FIELDS.IS_BACK_REF, this.isBackRef);
|
||||
|
||||
this.origin.addProperty(IS_LINK, this.isLink);
|
||||
@ -116,12 +126,38 @@ public class FactoredObjectRef extends AbstractFactored {
|
||||
public void wrap(JsonObject object, Map<String, Object> context, String path) {
|
||||
super.wrap(object, context, path);
|
||||
|
||||
updateFromObject(object);
|
||||
|
||||
AbstractFactored contextOwner = getContextOwner(context);
|
||||
if ((contextOwner != null) && (contextOwner instanceof FactoredObject)) {
|
||||
FactoredObject fo = (FactoredObject)contextOwner;
|
||||
log.debug("\t IN CONTEXT :: " + fo.factoryId + "[" + fo.jsonPath + "]");
|
||||
computeRelativePath(fo.jsonPath);
|
||||
if (null == this.ownScope || this.ownScope.isEmpty())
|
||||
this.scope = fo.scope;
|
||||
this.definedIn = fo;
|
||||
}
|
||||
|
||||
|
||||
objectModel.addRef(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateFromOrigin() {
|
||||
super.updateFromOrigin();
|
||||
updateFromObject(origin);
|
||||
}
|
||||
|
||||
protected void updateFromObject(JsonObject object) {
|
||||
if (object.has(TARGET_ID_FIELD))
|
||||
this.targetId = object.get(TARGET_ID_FIELD).getAsString();
|
||||
|
||||
if (object.has(TARGET_UUID_FIELD))
|
||||
this.targetUuid = object.get(TARGET_UUID_FIELD).getAsString();
|
||||
/*
|
||||
if (object.has(TARGET_VALUE_FIELD))
|
||||
this.targetId = object.get(TARGET_VALUE_FIELD).getAsString();
|
||||
|
||||
this.targetValue = object.get(TARGET_VALUE_FIELD).getAsString();
|
||||
*/
|
||||
if (object.has(TARGET_TYPE_FIELD))
|
||||
this.targetType = object.get(TARGET_TYPE_FIELD).getAsString();
|
||||
|
||||
@ -139,6 +175,20 @@ public class FactoredObjectRef extends AbstractFactored {
|
||||
|
||||
}
|
||||
|
||||
if (object.has(RESOLVE_ALWAYS_FIELD))
|
||||
try{
|
||||
this.resolveAlways = object.get(RESOLVE_ALWAYS_FIELD).getAsBoolean();
|
||||
} catch (Exception e) {
|
||||
|
||||
}
|
||||
|
||||
if (object.has(IS_DEFINITION_ORIGIN))
|
||||
try{
|
||||
this.isDefinitionOrigin = object.get(IS_DEFINITION_ORIGIN).getAsBoolean();
|
||||
} catch (Exception e) {
|
||||
|
||||
}
|
||||
|
||||
if (object.has(FIELDS.IS_BACK_REF))
|
||||
try{
|
||||
this.isBackRef = object.get(FIELDS.IS_BACK_REF).getAsBoolean();
|
||||
@ -162,20 +212,8 @@ public class FactoredObjectRef extends AbstractFactored {
|
||||
}
|
||||
|
||||
|
||||
AbstractFactored contextOwner = getContextOwner(context);
|
||||
if ((contextOwner != null) && (contextOwner instanceof FactoredObject)) {
|
||||
FactoredObject fo = (FactoredObject)contextOwner;
|
||||
log.debug("\t IN CONTEXT :: " + fo.factoryId + "[" + fo.jsonPath + "]");
|
||||
computeRelativePath(fo.jsonPath);
|
||||
if (null == this.ownScope || this.ownScope.isEmpty())
|
||||
this.scope = fo.scope;
|
||||
this.definedIn = fo;
|
||||
}
|
||||
|
||||
|
||||
objectModel.addRef(this);
|
||||
}
|
||||
|
||||
|
||||
public boolean isBackRef() {
|
||||
return isBackRef;
|
||||
}
|
||||
@ -194,6 +232,14 @@ public class FactoredObjectRef extends AbstractFactored {
|
||||
this.origin.addProperty(IS_RESOLVED_FIELD, this.isResolved);
|
||||
}
|
||||
|
||||
public boolean isResolveAlways() {
|
||||
return resolveAlways;
|
||||
}
|
||||
|
||||
public void setResolveAlways(boolean resolveAlways) {
|
||||
this.resolveAlways = resolveAlways;
|
||||
}
|
||||
|
||||
public void setBackRef(boolean isBaskRef) {
|
||||
this.isBackRef = isBaskRef;
|
||||
this.origin.remove(FIELDS.IS_BACK_REF);
|
||||
@ -216,6 +262,14 @@ public class FactoredObjectRef extends AbstractFactored {
|
||||
return isLink;
|
||||
}
|
||||
|
||||
public boolean isDefinitionOrigin() {
|
||||
return isDefinitionOrigin;
|
||||
}
|
||||
|
||||
public void setDefinitionOrigin(boolean isDefinitionOrigin) {
|
||||
this.isDefinitionOrigin = isDefinitionOrigin;
|
||||
}
|
||||
|
||||
public boolean isRefByValueOnly() {
|
||||
return refByValueOnly;
|
||||
}
|
||||
@ -230,6 +284,10 @@ public class FactoredObjectRef extends AbstractFactored {
|
||||
return targetObject.getObjectId();
|
||||
}
|
||||
|
||||
public String getTargetUuid() {
|
||||
return targetUuid;
|
||||
}
|
||||
|
||||
public String getTargetType() {
|
||||
if (targetObject == null)
|
||||
return targetType;
|
||||
@ -244,6 +302,7 @@ public class FactoredObjectRef extends AbstractFactored {
|
||||
if (this.targetObject != null)
|
||||
this.targetObject.references.remove(this);
|
||||
this.targetObject = targetObject;
|
||||
this.targetUuid = this.targetObject.getUuid();
|
||||
this.targetObject.references.add(this);
|
||||
if (this.origin == null)
|
||||
log.debug("ORIGIN IS NULL!!!");
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* test-producers
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* test-producers
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -22,6 +22,7 @@ package ru.entaxy.platform.core.producer.executor.objectmodel;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
@ -81,7 +82,9 @@ public class ObjectModel {
|
||||
.collect(Collectors.toList());
|
||||
for (FactoredObjectRef ref: originRefs) {
|
||||
String targetId = ref.getTargetId();
|
||||
List<FactoredObject> fos = this.objects.stream().filter(fo -> fo.getObjectId().equals(targetId))
|
||||
String targetUuid = ref.getTargetUuid();
|
||||
List<FactoredObject> fos = this.objects.stream()
|
||||
.filter(fo -> (fo.getObjectId().equals(targetId)) || fo.getUuid().equals(targetUuid))
|
||||
.collect(Collectors.toList());
|
||||
if (fos.isEmpty()) {
|
||||
|
||||
@ -225,6 +228,19 @@ public class ObjectModel {
|
||||
continue;
|
||||
} */
|
||||
result.add(fo.origin);
|
||||
|
||||
if (fo.origin.has("refConfig") && fo.origin.get("refConfig").isJsonObject()) {
|
||||
JsonObject refConfig = fo.origin.get("refConfig").getAsJsonObject();
|
||||
for (Entry<String, JsonElement> entry: refConfig.entrySet()) {
|
||||
if (objectRef.origin.has(entry.getKey()))
|
||||
objectRef.origin.remove(entry.getKey());
|
||||
objectRef.origin.add(entry.getKey(), entry.getValue().deepCopy());
|
||||
}
|
||||
objectRef.updateFromOrigin();
|
||||
}
|
||||
|
||||
objectRef.setTraverseMap(JSONUtils.element2map(objectRef.origin), null);
|
||||
|
||||
log.debug("REPLACING :: " + fo.getObjectId());
|
||||
JSONUtils.replaceValue(factoredObject.origin, fo.relativePath, objectRef.origin);
|
||||
log.debug("TOTAL REFS :: " + refs.size());
|
||||
@ -234,6 +250,27 @@ public class ObjectModel {
|
||||
} else {
|
||||
FactoredObjectRef objectRef = new FactoredObjectRef(this, fo);
|
||||
result.add(fo.origin);
|
||||
|
||||
// keep definedIn attribute in ref
|
||||
if (fo.definedIn == factoredObject) {
|
||||
if (objectRef.origin.has(FactoredObjectRef.IS_DEFINITION_ORIGIN))
|
||||
objectRef.origin.remove(FactoredObjectRef.IS_DEFINITION_ORIGIN);
|
||||
objectRef.origin.addProperty(FactoredObjectRef.IS_DEFINITION_ORIGIN, true);
|
||||
} else {
|
||||
objectRef.origin.remove(FactoredObjectRef.IS_DEFINITION_ORIGIN);
|
||||
}
|
||||
|
||||
if (fo.origin.has("refConfig") && fo.origin.get("refConfig").isJsonObject()) {
|
||||
JsonObject refConfig = fo.origin.get("refConfig").getAsJsonObject();
|
||||
for (Entry<String, JsonElement> entry: refConfig.entrySet()) {
|
||||
if (objectRef.origin.has(entry.getKey()))
|
||||
objectRef.origin.remove(entry.getKey());
|
||||
objectRef.origin.add(entry.getKey(), entry.getValue().deepCopy());
|
||||
}
|
||||
objectRef.updateFromOrigin();
|
||||
}
|
||||
objectRef.setTraverseMap(JSONUtils.element2map(objectRef.origin), null);
|
||||
|
||||
JSONUtils.replaceValue(factoredObject.origin, fo.relativePath, objectRef.origin);
|
||||
rootObjects.add(fo);
|
||||
result.addAll(layoutObject(fo, rootObjects));
|
||||
|
@ -1,33 +0,0 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* test-producers
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* ==========
|
||||
* 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.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
package ru.entaxy.platform.core.producer.executor.support;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import org.apache.commons.collections4.list.AbstractLinkedList;
|
||||
|
||||
import ru.entaxy.platform.core.artifact.Artifact;
|
||||
|
||||
public class ArtifactList extends AbstractLinkedList<Artifact> {
|
||||
|
||||
public ArtifactList() {
|
||||
super(Collections.emptyList());
|
||||
}
|
||||
}
|
@ -1,62 +0,0 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* test-producers
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* ==========
|
||||
* 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.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
package ru.entaxy.platform.core.producer.executor.support;
|
||||
|
||||
import org.osgi.service.component.ComponentContext;
|
||||
import org.osgi.service.component.annotations.Activate;
|
||||
import org.osgi.service.component.annotations.CollectionType;
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
import org.osgi.service.component.annotations.ReferenceCardinality;
|
||||
|
||||
import ru.entaxy.platform.core.artifact.service.ArtifactService;
|
||||
|
||||
@Component(immediate = true)
|
||||
public class ArtifactsHelper {
|
||||
|
||||
protected static ArtifactsHelper instance = null;
|
||||
|
||||
public static ArtifactsHelper getInstance() {
|
||||
return ArtifactsHelper.instance;
|
||||
}
|
||||
|
||||
protected ArtifactService artifactService;
|
||||
|
||||
@Activate
|
||||
public void activate(ComponentContext componentContext) {
|
||||
// Artifacts.registerSupport(Blueprint.class);
|
||||
ArtifactsHelper.instance = this;
|
||||
}
|
||||
|
||||
public ArtifactService getArtifactService() {
|
||||
return artifactService;
|
||||
}
|
||||
|
||||
@Reference(unbind = "removeArtifactService", cardinality = ReferenceCardinality.MANDATORY, collectionType = CollectionType.SERVICE)
|
||||
public void setArtifactService(ArtifactService artifactService) {
|
||||
this.artifactService = artifactService;
|
||||
}
|
||||
|
||||
public void removeArtifactService(ArtifactService artifactService) {
|
||||
this.artifactService = null;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* test-producers
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* ==========
|
||||
* 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.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
package ru.entaxy.platform.core.producer.executor.support;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import org.apache.commons.collections4.list.AbstractLinkedList;
|
||||
|
||||
import ru.entaxy.platform.core.artifact.DeployedArtifact;
|
||||
|
||||
public class DeployedArtifactList extends AbstractLinkedList<DeployedArtifact> {
|
||||
|
||||
public DeployedArtifactList() {
|
||||
super(Collections.emptyList());
|
||||
}
|
||||
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
/*-
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* test-producers
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* ==========
|
||||
* 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.
|
||||
* ~~~~~~/licensing~~~~~~
|
||||
*/
|
||||
package ru.entaxy.platform.core.producer.executor.support;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import org.apache.commons.collections4.list.AbstractLinkedList;
|
||||
|
||||
import ru.entaxy.platform.core.artifact.installer.builder.InstallationResult;
|
||||
|
||||
public class InstallationResultList extends AbstractLinkedList<InstallationResult> {
|
||||
|
||||
public InstallationResultList() {
|
||||
super(Collections.emptyList());
|
||||
}
|
||||
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* test-producers
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -46,13 +46,14 @@ public class CommonObjectProducer extends DefaultProducer implements GenerationP
|
||||
@Override
|
||||
protected void addFields(AbstractFactoryWrapper factoryWrapper) {
|
||||
super.addFields(factoryWrapper);
|
||||
factoryWrapper.addField(
|
||||
/*factoryWrapper.addField(
|
||||
(new FieldInfoImpl())
|
||||
.name(FIELDS.OBJECT_ID)
|
||||
.type("String")
|
||||
.required(true)
|
||||
.immutable(true)
|
||||
);
|
||||
*/
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -64,6 +65,15 @@ public class CommonObjectProducer extends DefaultProducer implements GenerationP
|
||||
Map<String, String> publishedFields = getFieldsToPublish(outputType, scope, objectType, objectId);
|
||||
|
||||
Map<String, Object> dataToPublish = new HashMap<>();
|
||||
|
||||
if (parameters.containsKey(FIELDS.FIELDS_TO_PUBLISH)) {
|
||||
Object obj = parameters.get(FIELDS.FIELDS_TO_PUBLISH);
|
||||
if (obj instanceof Map) {
|
||||
Map<String, Object> ownData = (Map)obj;
|
||||
dataToPublish.putAll(ownData);
|
||||
}
|
||||
}
|
||||
|
||||
for (Entry<String, String> entry: publishedFields.entrySet())
|
||||
dataToPublish.put(entry.getKey(), generated.getProperties().get(entry.getValue()));
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* test-producers
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* test-producers
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* test-producers
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -19,6 +19,7 @@
|
||||
*/
|
||||
package ru.entaxy.platform.core.producer.impl;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@ -60,6 +61,14 @@ public class EntaxyProducerServiceImpl implements EntaxyProducerService {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(EntaxyProducerServiceImpl.class);
|
||||
|
||||
private static final String LIFECYCLES_FILE_PATH = System.getProperty("karaf.etc")
|
||||
+ File.separator
|
||||
+ "producing.lifecycles.json";
|
||||
|
||||
protected JsonObject lifecycles = new JsonObject();
|
||||
|
||||
protected InstructionsHelper instructionsHelper;
|
||||
|
||||
protected List<EntaxyProducer> producers = new ArrayList<>();
|
||||
|
||||
protected Map<String, ProducingCommandExecutor> commandExecutors = new HashMap<>();
|
||||
@ -88,6 +97,19 @@ public class EntaxyProducerServiceImpl implements EntaxyProducerService {
|
||||
registerCommand(new Install(this));
|
||||
registerCommand(new Enrich(this));
|
||||
registerCommand(new Store(this));
|
||||
initLifecycles();
|
||||
}
|
||||
|
||||
protected void initLifecycles() {
|
||||
File lc = new File(LIFECYCLES_FILE_PATH);
|
||||
if (lc.exists() && lc.canRead()) {
|
||||
try {
|
||||
this.lifecycles = JSONUtils.getJsonRootObject(lc.toURI().toURL());
|
||||
} catch (Exception e) {
|
||||
log.warn("Eror reading lifecycles config", e);
|
||||
}
|
||||
}
|
||||
this.instructionsHelper = new InstructionsHelper(this.lifecycles);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -113,7 +135,10 @@ public class EntaxyProducerServiceImpl implements EntaxyProducerService {
|
||||
@Override
|
||||
public ProducerResult produce(JsonObject configuration, String instructions) {
|
||||
try {
|
||||
return (new ProducingExecutor(configuration, instructions,this)).execute();
|
||||
return (new ProducingExecutor(configuration
|
||||
, instructionsHelper.prepareInstructions(instructions)
|
||||
,this))
|
||||
.execute();
|
||||
} catch (Exception e) {
|
||||
log.error("Produce failed", e);
|
||||
return ProducerResult.createFailed(e);
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* test-producers
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* test-producers
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* test-producers
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -30,6 +30,9 @@ public abstract class AbstractFactoryWrapper implements EntaxyWrappedFactory {
|
||||
|
||||
public static interface GenerationProcessor {
|
||||
|
||||
String PROP_PROCESSOR_ID = "generation.plugin.id";
|
||||
String PROP_FACTORY_TYPE = "generation.factory.type";
|
||||
|
||||
public default void preGenerate(EntaxyWrappedFactory wrappedFactory, String outputType, String scope
|
||||
, String objectType, Map<String, Object> parameters) throws EntaxyFactoryException{
|
||||
|
||||
@ -52,6 +55,7 @@ public abstract class AbstractFactoryWrapper implements EntaxyWrappedFactory {
|
||||
this.generationProcessor = generationProcessor;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public abstract void addField(FieldInfo fieldInfo);
|
||||
|
||||
public abstract void addField(String outputType, FieldInfo fieldInfo);
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* test-producers
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -35,6 +35,7 @@ import org.slf4j.LoggerFactory;
|
||||
import ru.entaxy.esb.platform.runtime.base.connecting.generator.Generated;
|
||||
import ru.entaxy.platform.base.objects.factory.EntaxyFactory;
|
||||
import ru.entaxy.platform.base.objects.factory.EntaxyFactoryException;
|
||||
import ru.entaxy.platform.base.objects.factory.EntaxyFactoryUtils;
|
||||
import ru.entaxy.platform.core.producer.api.EntaxyWrappedFactory;
|
||||
|
||||
public class DefaultFactoryWrapper extends AbstractFactoryWrapper implements EntaxyWrappedFactory {
|
||||
@ -85,6 +86,11 @@ public class DefaultFactoryWrapper extends AbstractFactoryWrapper implements Ent
|
||||
return origin.getType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayName() {
|
||||
return origin.getDisplayName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return origin.getDescription();
|
||||
@ -199,29 +205,30 @@ public class DefaultFactoryWrapper extends AbstractFactoryWrapper implements Ent
|
||||
|
||||
BundleContext bundleContext = FrameworkUtil.getBundle(this.getClass()).getBundleContext();
|
||||
try {
|
||||
ServiceReference<?>[] refs = bundleContext.getAllServiceReferences(
|
||||
List<ServiceReference<GenerationProcessor>> refs = /*bundleContext.getAllServiceReferences(
|
||||
GenerationProcessor.class.getName()
|
||||
, "(|(generation.factory.type~=*)(generation.factory.type~=" + getFactoryType() + "))");
|
||||
, "(|(generation.factory.type~=*)(generation.factory.type~=" + getFactoryType() + "))");*/
|
||||
GenerationProcessorService.getInstance().getProcessorsRefs(this);
|
||||
|
||||
log.debug("FOUND SERVICES: " + (refs==null?"0":refs.length));
|
||||
log.debug("FOUND SERVICES: " + (refs==null?"0":refs.size()));
|
||||
if (refs == null)
|
||||
return;
|
||||
for (int i=0; i<refs.length; i++) {
|
||||
for (ServiceReference<GenerationProcessor> r: refs) {
|
||||
try {
|
||||
GenerationProcessor processor = (GenerationProcessor)bundleContext.getService(refs[i]);
|
||||
GenerationProcessor processor = (GenerationProcessor)bundleContext.getService(r);
|
||||
processor.preGenerate(this, outputType, scope, getFactoryType(), parameters);
|
||||
} catch (Exception e) {
|
||||
|
||||
} finally {
|
||||
try {
|
||||
bundleContext.ungetService(refs[i]);
|
||||
bundleContext.ungetService(r);
|
||||
} catch (Exception e) {
|
||||
log.warn("Error ungetting service", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} catch (InvalidSyntaxException e) {
|
||||
} catch (Exception e) {
|
||||
log.error("Error getting services", e);
|
||||
}
|
||||
|
||||
@ -230,29 +237,30 @@ public class DefaultFactoryWrapper extends AbstractFactoryWrapper implements Ent
|
||||
protected void postGenerateWithPlugins(String outputType, String scope, Map<String, Object> parameters, Generated generated) {
|
||||
BundleContext bundleContext = FrameworkUtil.getBundle(this.getClass()).getBundleContext();
|
||||
try {
|
||||
ServiceReference<?>[] refs = bundleContext.getAllServiceReferences(
|
||||
List<ServiceReference<GenerationProcessor>> refs = /* bundleContext.getAllServiceReferences(
|
||||
GenerationProcessor.class.getName()
|
||||
, "(|(generation.factory.type~=*)(generation.factory.type~=" + getFactoryType() + "))");
|
||||
, "(|(generation.factory.type~=*)(generation.factory.type~=" + getFactoryType() + "))"); */
|
||||
GenerationProcessorService.getInstance().getProcessorsRefs(this);
|
||||
|
||||
log.debug("FOUND SERVICES: " + (refs==null?"0":refs.length));
|
||||
log.debug("FOUND SERVICES: " + (refs==null?"0":refs.size()));
|
||||
if (refs == null)
|
||||
return;
|
||||
for (int i=0; i<refs.length; i++) {
|
||||
for (ServiceReference<GenerationProcessor> r: refs) {
|
||||
try {
|
||||
GenerationProcessor processor = (GenerationProcessor)bundleContext.getService(refs[i]);
|
||||
GenerationProcessor processor = (GenerationProcessor)bundleContext.getService(r);
|
||||
processor.postGenerate(this, outputType, scope, getFactoryType(), parameters, generated);
|
||||
} catch (Exception e) {
|
||||
|
||||
} finally {
|
||||
try {
|
||||
bundleContext.ungetService(refs[i]);
|
||||
bundleContext.ungetService(r);
|
||||
} catch (Exception e) {
|
||||
log.warn("Error ungetting service", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} catch (InvalidSyntaxException e) {
|
||||
} catch (Exception e) {
|
||||
log.error("Error getting services", e);
|
||||
}
|
||||
}
|
||||
@ -262,5 +270,28 @@ public class DefaultFactoryWrapper extends AbstractFactoryWrapper implements Ent
|
||||
return this.origin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getTypeInfo() {
|
||||
return this.origin.getTypeInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getJsonConfiguration() {
|
||||
return EntaxyFactoryUtils.getEffectiveJson(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getParent() {
|
||||
return this.origin.getParent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAbstract() {
|
||||
return this.origin.isAbstract();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDeprecated() {
|
||||
return this.origin.isDeprecated();
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* test-producers
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -22,6 +22,7 @@ package ru.entaxy.platform.core.producer.wrapper;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import ru.entaxy.platform.base.objects.factory.EntaxyFactory.FieldInfo;
|
||||
import ru.entaxy.platform.core.producer.impl.EntaxyFactoryDataProcessorService;
|
||||
|
||||
public class FieldWrapper implements FieldInfo {
|
||||
|
||||
@ -63,7 +64,7 @@ public class FieldWrapper implements FieldInfo {
|
||||
|
||||
@Override
|
||||
public Object getDefaultValue() {
|
||||
return origin.getDefaultValue();
|
||||
return EntaxyFactoryDataProcessorService.getInstance().processDefaultValue(origin.getDefaultValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* test-producers
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>ru.entaxy.esb.platform.runtime.core</groupId>
|
||||
<artifactId>object-producing</artifactId>
|
||||
<version>1.8.2.2</version>
|
||||
<version>1.8.3</version>
|
||||
</parent>
|
||||
<groupId>ru.entaxy.esb.platform.runtime.core.object-producing</groupId>
|
||||
<artifactId>object-producing-config-support</artifactId>
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* object-producing-config-support
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* object-producing-config-support
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* object-producing-config-support
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* object-producing-config-support
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* object-producing-config-support
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -128,7 +128,7 @@ public class ObjectConfig {
|
||||
}
|
||||
FieldInfo field = fi.get();
|
||||
boolean isConfigurable = true;
|
||||
log.info("\n FIELDNAME:: " + fieldName + " -> " + field.getJsonOrigin());
|
||||
log.debug("\n FIELDNAME:: " + fieldName + " -> " + field.getJsonOrigin());
|
||||
if (field.getJsonOrigin().has(CONFIGURABLE_ATTRIBUTE_NAME))
|
||||
try {
|
||||
isConfigurable = field.getJsonOrigin().get(CONFIGURABLE_ATTRIBUTE_NAME).getAsBoolean();
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* object-producing-config-support
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -19,8 +19,6 @@
|
||||
*/
|
||||
package ru.entaxy.platform.core.producer.config;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.osgi.service.component.annotations.Component;
|
||||
import org.osgi.service.component.annotations.Reference;
|
||||
import org.osgi.service.component.annotations.ReferenceCardinality;
|
||||
@ -47,10 +45,7 @@ public class ObjectConfigHelper {
|
||||
}
|
||||
|
||||
public EntaxyObject findObject(String objectId, String objectType) {
|
||||
Optional<EntaxyObject> object = entaxyObjectService.getObjects().stream()
|
||||
.filter(obj -> (obj.getObjectId().equals(objectId) && obj.getObjectType().equals(objectType)))
|
||||
.findFirst();
|
||||
return object.orElse(null);
|
||||
return entaxyObjectService.findObject(objectId, objectType);
|
||||
}
|
||||
|
||||
public boolean isDirectValueOnly(FactoredObjectRef ref) {
|
||||
|
@ -4,7 +4,7 @@
|
||||
~~~~~~licensing~~~~~~
|
||||
object-producing-config-support
|
||||
==========
|
||||
Copyright (C) 2020 - 2021 EmDev LLC
|
||||
Copyright (C) 2020 - 2023 EmDev LLC
|
||||
==========
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
@ -4,7 +4,7 @@
|
||||
~~~~~~licensing~~~~~~
|
||||
object-producing-config-support
|
||||
==========
|
||||
Copyright (C) 2020 - 2021 EmDev LLC
|
||||
Copyright (C) 2020 - 2023 EmDev LLC
|
||||
==========
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@ -20,7 +20,6 @@
|
||||
~~~~~~/licensing~~~~~~
|
||||
|
||||
--]
|
||||
|
||||
<!--
|
||||
config for
|
||||
objectId: [=configured]
|
||||
|
@ -4,7 +4,7 @@
|
||||
~~~~~~licensing~~~~~~
|
||||
object-producing-config-support
|
||||
==========
|
||||
Copyright (C) 2020 - 2021 EmDev LLC
|
||||
Copyright (C) 2020 - 2023 EmDev LLC
|
||||
==========
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@ -20,7 +20,6 @@
|
||||
~~~~~~/licensing~~~~~~
|
||||
|
||||
--]
|
||||
|
||||
<!--
|
||||
config ref for
|
||||
objectId: [=configured]
|
||||
|
@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>ru.entaxy.esb.platform.runtime.core</groupId>
|
||||
<artifactId>object-producing</artifactId>
|
||||
<version>1.8.2.2</version>
|
||||
<version>1.8.3</version>
|
||||
</parent>
|
||||
<groupId>ru.entaxy.esb.platform.runtime.core.object-producing</groupId>
|
||||
<artifactId>object-producing-management</artifactId>
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* object-producing-management
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* object-producing-management
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -25,6 +25,7 @@ import javax.management.openmbean.OpenDataException;
|
||||
import javax.management.openmbean.TabularData;
|
||||
|
||||
import ru.entaxy.esb.platform.base.management.core.Qualifier;
|
||||
import ru.entaxy.esb.platform.base.management.core.api.Attribute;
|
||||
import ru.entaxy.esb.platform.base.management.core.api.MBeanAnnotated;
|
||||
import ru.entaxy.esb.platform.base.management.core.api.MBeanExportPolicy;
|
||||
import ru.entaxy.esb.platform.base.management.core.api.Operation;
|
||||
@ -41,6 +42,28 @@ public interface FactoryMBean {
|
||||
return ProducerMBean.getQualifier(factoryType).attribute(FACTORY_KEY, factoryId);
|
||||
}
|
||||
|
||||
@Attribute
|
||||
boolean isAbstract();
|
||||
@Attribute
|
||||
boolean isDeprecated();
|
||||
@Attribute
|
||||
String getId();
|
||||
@Attribute
|
||||
String getType();
|
||||
@Attribute
|
||||
String getParent();
|
||||
@Attribute
|
||||
String getDisplayName();
|
||||
@Attribute
|
||||
String getDescription();
|
||||
@Attribute
|
||||
String getCategory();
|
||||
@Attribute
|
||||
String getLabel();
|
||||
|
||||
@Attribute
|
||||
Map<String, Object> getTypeInfo();
|
||||
|
||||
@Operation(desc = "Creates and installs a new object")
|
||||
public TabularData createObject(
|
||||
@Parameter(name = "objectId", desc = "ObjectId for new object, can be omitted in some cases")
|
||||
@ -50,6 +73,18 @@ public interface FactoryMBean {
|
||||
@Parameter(name = "properties", desc = "Properties of the new object in JSON format")
|
||||
Map<String, Object> properties
|
||||
) throws EntaxyFactoryException, OpenDataException;
|
||||
|
||||
@Operation(desc = "Creates and installs a new object")
|
||||
public TabularData createObjectByInstructions(
|
||||
@Parameter(name = "objectId", desc = "ObjectId for new object, can be omitted in some cases")
|
||||
String objectId,
|
||||
@Parameter(name = "scope", desc = "Scope of the new object, 'public' by default")
|
||||
String scope,
|
||||
@Parameter(name = "instructions", desc = "Build instructions in JSON format, {\"install\":{}, \"store\":{}} by default")
|
||||
Map<String, Object> instructions,
|
||||
@Parameter(name = "properties", desc = "Properties of the new object in JSON format")
|
||||
Map<String, Object> properties
|
||||
) throws EntaxyFactoryException, OpenDataException;
|
||||
|
||||
@Operation(desc = "Get fields for creating a new object")
|
||||
public String getFields(@Parameter(name = "outputType", desc = "Type of output") String outputType);
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* object-producing-management
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* object-producing-management
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* object-producing-management
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -19,6 +19,7 @@
|
||||
*/
|
||||
package ru.entaxy.platform.core.producer.management.impl;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
@ -45,6 +46,7 @@ import ru.entaxy.platform.base.objects.EntaxyObject;
|
||||
import ru.entaxy.platform.base.objects.factory.EntaxyFactory;
|
||||
import ru.entaxy.platform.base.objects.factory.EntaxyFactory.SCOPE;
|
||||
import ru.entaxy.platform.base.objects.factory.EntaxyFactoryException;
|
||||
import ru.entaxy.platform.base.objects.factory.exceptions.NotSupportedForAbstractFactory;
|
||||
import ru.entaxy.platform.base.support.CommonUtils;
|
||||
import ru.entaxy.platform.core.producer.api.EntaxyProducerService;
|
||||
import ru.entaxy.platform.core.producer.api.ProducerResult;
|
||||
@ -62,8 +64,69 @@ public class FactoryMBeanImpl extends AnnotatedMBean<FactoryMBean> implements Fa
|
||||
this.entaxyFactory = entaxyFactory;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isAbstract() {
|
||||
return this.entaxyFactory.isAbstract();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDeprecated() {
|
||||
return this.entaxyFactory.isDeprecated();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getId() {
|
||||
return this.entaxyFactory.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return this.entaxyFactory.getType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getParent() {
|
||||
return this.entaxyFactory.getParent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayName() {
|
||||
return this.entaxyFactory.getDisplayName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return this.entaxyFactory.getDescription();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCategory() {
|
||||
return this.entaxyFactory.getCategory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLabel() {
|
||||
return this.entaxyFactory.getLabel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getTypeInfo() {
|
||||
return this.entaxyFactory.getTypeInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TabularData createObject(String objectId, String scope, Map<String, Object> properties) throws EntaxyFactoryException, OpenDataException {
|
||||
return createObjectByInstructions(objectId, scope, Collections.emptyMap(), properties);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TabularData createObjectByInstructions(String objectId, String scope, Map<String, Object> instructions, Map<String, Object> properties) throws EntaxyFactoryException, OpenDataException {
|
||||
|
||||
if (this.isAbstract()) {
|
||||
throw new NotSupportedForAbstractFactory(entaxyFactory, "createObject");
|
||||
}
|
||||
|
||||
log.debug("\n\tCREATE OBJECT with \nid: [{}] \nscope: [{}] \nproperties: [{}]"
|
||||
, CommonUtils.getValid(objectId, "null")
|
||||
, CommonUtils.getValid(scope, SCOPE.PUBLIC.label)
|
||||
@ -79,6 +142,13 @@ public class FactoryMBeanImpl extends AnnotatedMBean<FactoryMBean> implements Fa
|
||||
if (CommonUtils.isValid(objectId))
|
||||
configuration.addProperty(EntaxyObject.FIELDS.OBJECT_ID, objectId);
|
||||
|
||||
String instructionsString = "{\"install\": {}, \"store\":{}}";
|
||||
if ((instructions != null) && !instructions.isEmpty()) {
|
||||
JsonElement jo = (new Gson()).toJsonTree(instructions);
|
||||
if (jo.isJsonObject())
|
||||
instructionsString = jo.toString();
|
||||
}
|
||||
|
||||
configuration.addProperty(EntaxyObject.FIELDS.FACTORY_ID, this.entaxyFactory.getFactoryId());
|
||||
configuration.addProperty(EntaxyObject.FIELDS.OBJECT_TYPE, this.entaxyFactory.getFactoryType());
|
||||
|
||||
@ -87,7 +157,7 @@ public class FactoryMBeanImpl extends AnnotatedMBean<FactoryMBean> implements Fa
|
||||
JsonElement propertiesValue = (new Gson()).toJsonTree(properties);
|
||||
configuration.add(EntaxyObject.FIELDS.PROPERTIES, propertiesValue);
|
||||
|
||||
ProducerResult result = producerService.produce(configuration, "{\"install\": {}, \"store\":{}}");
|
||||
ProducerResult result = producerService.produce(configuration, instructionsString);
|
||||
|
||||
CompositeType compositeType = new CompositeType(
|
||||
"CommandResult"
|
||||
@ -127,4 +197,5 @@ public class FactoryMBeanImpl extends AnnotatedMBean<FactoryMBean> implements Fa
|
||||
}).collect(Collectors.toList()).toString();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* object-producing-management
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -59,7 +59,13 @@ public class FactoryMBeanPublisher {
|
||||
props.put(ManagementCore.JMX_OBJECTNAME
|
||||
, FactoryMBean.getQualifier(factory.getId(), factory.getType()).getValue());
|
||||
|
||||
result.add(this.bundleContext.registerService(FactoryMBean.class, service, props));
|
||||
// catch and ignore exception typical for bundle refreshing process
|
||||
try {
|
||||
result.add(this.bundleContext.registerService(FactoryMBean.class, service, props));
|
||||
} catch (IllegalStateException e) {
|
||||
if (!CommonUtils.isValid(e.getMessage()) || !e.getMessage().contains("Invalid BundleContext"))
|
||||
throw e;
|
||||
}
|
||||
|
||||
if (CommonUtils.isValid(factory.getCategory())) {
|
||||
props.put(ManagementCore.JMX_OBJECTNAME
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* object-producing-management
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* object-producing-management
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* object-producing-management
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* object-producing-management
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* object-producing-management
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>ru.entaxy.esb.platform.runtime.core</groupId>
|
||||
<artifactId>object-producing</artifactId>
|
||||
<version>1.8.2.2</version>
|
||||
<version>1.8.3</version>
|
||||
</parent>
|
||||
<groupId>ru.entaxy.esb.platform.runtime.core.object-producing</groupId>
|
||||
<artifactId>object-producing-shell</artifactId>
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* test-producers
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* test-producers
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* test-producers
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* test-producers
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* test-producers
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* test-producers
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* test-producers
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* test-producers
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -2,7 +2,7 @@
|
||||
* ~~~~~~licensing~~~~~~
|
||||
* test-producers
|
||||
* ==========
|
||||
* Copyright (C) 2020 - 2022 EmDev LLC
|
||||
* Copyright (C) 2020 - 2023 EmDev LLC
|
||||
* ==========
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<groupId>ru.entaxy.esb.platform.runtime</groupId>
|
||||
<artifactId>core</artifactId>
|
||||
<version>1.8.2.2</version>
|
||||
<version>1.8.3</version>
|
||||
</parent>
|
||||
<groupId>ru.entaxy.esb.platform.runtime.core</groupId>
|
||||
<artifactId>object-producing</artifactId>
|
||||
@ -38,7 +38,7 @@
|
||||
ru.entaxy.esb.platform.runtime.base.objects-base
|
||||
</groupId>
|
||||
<artifactId>objects-core</artifactId>
|
||||
<version>1.8.2.2</version>
|
||||
<version>1.8.3</version>
|
||||
<type>bundle</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@ -46,7 +46,7 @@
|
||||
ru.entaxy.esb.platform.runtime.base.objects-base
|
||||
</groupId>
|
||||
<artifactId>object-factory</artifactId>
|
||||
<version>1.8.2.2</version>
|
||||
<version>1.8.3</version>
|
||||
<type>bundle</type>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
@ -57,5 +57,6 @@
|
||||
<module>object-producing-shell</module>
|
||||
<module>object-producing-management</module>
|
||||
<module>object-producing-config-support</module>
|
||||
<module>object-producing-resources-support</module>
|
||||
</modules>
|
||||
</project>
|
Reference in New Issue
Block a user