ENTAXY-480 release version 1.8.3

This commit is contained in:
2023-08-03 04:44:09 +03:00
parent 603889d627
commit 5844a2e5cf
2546 changed files with 11242 additions and 207556 deletions

View File

@ -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>

View File

@ -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.

View File

@ -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 {

View File

@ -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))

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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);
}

View File

@ -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>

View File

@ -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)

View File

@ -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.

View File

@ -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.

View File

@ -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() {

View File

@ -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()

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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)

View File

@ -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;
}

View File

@ -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());

View File

@ -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.

View File

@ -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);
}

View File

@ -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

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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"));
}
}

View File

@ -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.

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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.

View File

@ -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));
}
}

View File

@ -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;

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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;
}
}
}

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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() {
}
}

View File

@ -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()) {

View File

@ -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;
}
}

View File

@ -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.

View File

@ -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!!!");

View File

@ -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.

View File

@ -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));

View File

@ -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());
}
}

View File

@ -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;
}
}

View File

@ -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());
}
}

View File

@ -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());
}
}

View File

@ -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()));

View File

@ -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.

View File

@ -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.

View File

@ -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);

View File

@ -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.

View File

@ -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.

View File

@ -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);

View File

@ -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();
}
}

View File

@ -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

View File

@ -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.

View File

@ -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>

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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();

View File

@ -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) {

View File

@ -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.

View File

@ -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]

View File

@ -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]

View File

@ -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>

View File

@ -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.

View File

@ -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);

View File

@ -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.

View File

@ -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.

View File

@ -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();
}
}

View File

@ -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

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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>

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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>