release version 1.10.0

This commit is contained in:
2024-10-07 18:42:55 +03:00
parent 2034182607
commit a5088587f7
1501 changed files with 28818 additions and 59966 deletions

View File

@ -3,7 +3,7 @@
<parent>
<groupId>ru.entaxy.esb.platform.runtime.core</groupId>
<artifactId>object-producing</artifactId>
<version>1.9.0</version>
<version>1.10.0</version>
</parent>
<groupId>ru.entaxy.esb.platform.runtime.core.object-producing</groupId>
<artifactId>object-producer-api</artifactId>

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* object-producer-api
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
@ -25,67 +25,114 @@
*/
package ru.entaxy.platform.core.producer.api;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.osgi.framework.Filter;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.InvalidSyntaxException;
import org.slf4j.LoggerFactory;
import com.google.gson.JsonObject;
import ru.entaxy.platform.base.objects.factory.EntaxyFactory;
import ru.entaxy.platform.base.support.CommonUtils;
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 DIRECTIVES {
/*
* usage: {"@CONTINUE_ON_EXCEPTION": ['command1', 'command2-', 'command3+']}
* where
* 'command1' - continue after exception in command1
* 'command2-' - continue after exception in ANY command BEFORE command2
* 'command3+' - continue after exception in ANY command AFTER command3
*/
String CONTINUE_ON_EXCEPTION = "@CONTINUE_ON_EXCEPTION";
};
public static interface INSTRUCTIONS {
String PRINT_OUTPUT = "printOutput";
String SKIP = "skip";
String CONTINUE_ON_EXCEPTION = "continueOnException";
String MAX_COUNT = "maxCount";
String CURRENT_ITERATION = "currentCount";
public static interface ARTIFACT {
String LIFECYCLE = "@LIFECYCLE";
public static final String VERSION = "artifact.version";
public static final String TIMESTAMP = "artifact.timestamp";
public static final String VERSION_POLICY = "artifact.version.policy";
}
};
public ProducerResult produce(String configuration);
public ProducerResult produce(JsonObject configuration);
/*
* usage: {"@SKIP": ['command1', 'command2-', 'command3+']}
* where
* 'command1' - skip command1
* 'command2-' - skip ALL BEFORE command2
* 'command3+' - skip ALL AFTER command3
*/
String SKIP = "@SKIP";
public ProducerResult produce(String configuration, String instructions);
public ProducerResult produce(JsonObject configuration, String instructions);
public List<EntaxyProducer> getAllProducers();
public EntaxyProducer getProducerForType(String type);
public EntaxyFactory findFactoryById(String factoryId);
public List<ProducingCommandExecutor> getAvailableCommands();
public void registerCommand(ProducingCommandExecutor commandExecutor);
public ProducingCommandExecutor getCommandById(String id);
/*
* usage: {"@CONTINUE_ON_EXCEPTION": ['command1', 'command2-', 'command3+']}
* where
* 'command1' - continue after exception in command1
* 'command2-' - continue after exception in ANY command BEFORE command2
* 'command3+' - continue after exception in ANY command AFTER command3
*/
String CONTINUE_ON_EXCEPTION = "@CONTINUE_ON_EXCEPTION";
};
public static interface INSTRUCTIONS {
String PRINT_OUTPUT = "printOutput";
String SKIP = "skip";
String CONTINUE_ON_EXCEPTION = "continueOnException";
String MAX_COUNT = "maxCount";
String CURRENT_ITERATION = "currentCount";
public static interface ARTIFACT {
public static final String VERSION = "artifact.version";
public static final String TIMESTAMP = "artifact.timestamp";
public static final String VERSION_POLICY = "artifact.version.policy";
}
};
public ProducerResult produce(String configuration);
public ProducerResult produce(JsonObject configuration);
public ProducerResult produce(String configuration, String instructions);
public ProducerResult produce(JsonObject configuration, String instructions);
public List<EntaxyProducer> getAllProducers();
public EntaxyProducer getProducerForType(String type);
public EntaxyFactory findFactoryById(String factoryId);
default public boolean isFactoryOfType(String factoryId, String type) {
EntaxyFactory f = findFactoryById(factoryId);
while (f != null) {
if (f.getType().equals(type))
return true;
if (!CommonUtils.isValid(f.getParent()))
return false;
f = findFactoryById(f.getParent());
}
return false;
}
default public List<EntaxyFactory> findFactories(String filter) {
try {
Filter osgiFilter = FrameworkUtil.createFilter(filter);
return findFactories(osgiFilter);
} catch (InvalidSyntaxException e) {
LoggerFactory.getLogger(EntaxyProducerService.class).error(String.format("Invalid filter [%s]", filter));
return new ArrayList<>();
}
};
default public List<EntaxyFactory> findFactories(Filter filter) {
List<EntaxyFactory> allFactories = new ArrayList<>();
for (EntaxyProducer producer : getAllProducers())
allFactories.addAll(producer.getAllFactories());
return EntaxyProducerUtils.filterFactories(filter, allFactories);
};
public List<ProducingCommandExecutor> getAvailableCommands();
public void registerCommand(ProducingCommandExecutor commandExecutor);
public void extendLifecycle(String lifecycle, ProducingCommandExecutor commandExecutor,
Map<String, Object> parameters);
public ProducingCommandExecutor getCommandById(String id);
}

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* object-producer-api
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
@ -25,123 +25,203 @@
*/
package ru.entaxy.platform.core.producer.api;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import org.osgi.framework.Filter;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.InvalidSyntaxException;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import ru.entaxy.platform.base.objects.EntaxyObjectService;
import ru.entaxy.platform.base.objects.factory.EntaxyFactory;
import ru.entaxy.platform.base.support.JSONUtils;
public class EntaxyProducerUtils {
protected static Gson sharedGson = new Gson();
//INSTRUCTIONS BUILDER
protected static class InstructionsItemBuilder {
protected JsonObject instructionsJson;
protected InstructionsItemBuilder(JsonObject jsonObject) {
this.instructionsJson = jsonObject;
}
}
public static class InstructionsBuilder extends InstructionsItemBuilder {
protected static Gson sharedGson = new Gson();
protected InstructionsBuilder(JsonObject jsonObject) {
super(jsonObject);
}
// INSTRUCTIONS BUILDER
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))
instructionsJson.add(commandName, new JsonObject());
if ("*".equals(commandName))
return new AnyCommandBuilder(instructionsJson, instructionsJson.get(commandName).getAsJsonObject());
else
return new CommandBuilder(instructionsJson, instructionsJson.get(commandName).getAsJsonObject());
protected static class InstructionsItemBuilder {
}
protected JsonObject instructionsJson;
public AnyCommandBuilder any() {
return (AnyCommandBuilder)this.command("*");
}
public JsonObject getInstructions() {
return this.instructionsJson;
}
public String getInstructionsString() {
return getInstructions().toString();
}
}
public static class CommandBuilder extends InstructionsBuilder {
protected InstructionsItemBuilder(JsonObject jsonObject) {
this.instructionsJson = jsonObject;
}
protected JsonObject commandJson;
protected CommandBuilder(JsonObject instructionsObject, JsonObject commandObject) {
super(instructionsObject);
commandJson = commandObject;
}
public CommandBuilder set(String name, Object value) {
this.commandJson.remove(name);
this.commandJson.add(name, sharedGson.toJsonTree(value));
return this;
}
}
public static class AnyCommandBuilder extends CommandBuilder {
}
protected AnyCommandBuilder(JsonObject instructionsObject, JsonObject commandObject) {
super(instructionsObject, commandObject);
}
public static class InstructionsBuilder extends InstructionsItemBuilder {
public AnyCommandBuilder skip(String commandExprssion) {
if (!this.commandJson.has(EntaxyProducerService.DIRECTIVES.SKIP))
this.commandJson.add(EntaxyProducerService.DIRECTIVES.SKIP, new JsonArray());
this.commandJson.get(EntaxyProducerService.DIRECTIVES.SKIP).getAsJsonArray().add(commandExprssion);
return this;
}
}
public static InstructionsBuilder instructions() {
return instructions(new JsonObject());
}
protected InstructionsBuilder(JsonObject jsonObject) {
super(jsonObject);
}
public static InstructionsBuilder instructions(JsonObject jsonObject) {
return new InstructionsBuilder(jsonObject);
}
//CONFIGURATION BUILDER
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;
}
// UTILS
public static boolean isPattern(String type) {
return type.contains(EntaxyProducer.PATTERN_CHAR_ANY);
}
public CommandBuilder command(String commandName) {
if (!instructionsJson.has(commandName))
instructionsJson.add(commandName, new JsonObject());
if ("*".equals(commandName))
return new AnyCommandBuilder(instructionsJson, instructionsJson.get(commandName).getAsJsonObject());
else
return new CommandBuilder(instructionsJson, instructionsJson.get(commandName).getAsJsonObject());
public static String toRegexPattern(String type) {
return type.replaceAll("\\.", "\\\\.")
.replaceAll("\\" + EntaxyProducer.PATTERN_CHAR_ANY, "\\.*");
}
public static boolean isMatched(String typePattern, String type) {
return Pattern.matches(toRegexPattern(typePattern), type);
}
}
public AnyCommandBuilder any() {
return (AnyCommandBuilder) this.command("*");
}
public JsonObject getInstructions() {
return this.instructionsJson;
}
public String getInstructionsString() {
return getInstructions().toString();
}
}
public static class CommandBuilder extends InstructionsBuilder {
protected JsonObject commandJson;
protected CommandBuilder(JsonObject instructionsObject, JsonObject commandObject) {
super(instructionsObject);
commandJson = commandObject;
}
public CommandBuilder set(String name, Object value) {
this.commandJson.remove(name);
this.commandJson.add(name, sharedGson.toJsonTree(value));
return this;
}
}
public static class AnyCommandBuilder extends CommandBuilder {
protected AnyCommandBuilder(JsonObject instructionsObject, JsonObject commandObject) {
super(instructionsObject, commandObject);
}
public AnyCommandBuilder skip(String commandExprssion) {
if (!this.commandJson.has(EntaxyProducerService.DIRECTIVES.SKIP))
this.commandJson.add(EntaxyProducerService.DIRECTIVES.SKIP, new JsonArray());
this.commandJson.get(EntaxyProducerService.DIRECTIVES.SKIP).getAsJsonArray().add(commandExprssion);
return this;
}
}
public static InstructionsBuilder instructions() {
return instructions(new JsonObject());
}
public static InstructionsBuilder instructions(JsonObject jsonObject) {
return new InstructionsBuilder(jsonObject);
}
// CONFIGURATION BUILDER
// UTILS
public static boolean isPattern(String type) {
return type.contains(EntaxyProducer.PATTERN_CHAR_ANY);
}
public static String toRegexPattern(String type) {
return type.replaceAll("\\.", "\\\\.")
.replaceAll("\\" + EntaxyProducer.PATTERN_CHAR_ANY, "\\.*");
}
public static boolean isMatched(String typePattern, String type) {
return Pattern.matches(toRegexPattern(typePattern), type);
}
public static Map<String, Object> getFactoryEssence(EntaxyFactory factory) {
return getFactoryEssence(factory, "");
}
@SuppressWarnings("unchecked")
public static Map<String, Object> getFactoryEssence(EntaxyFactory factory, String prefix) {
Map<String, Object> result = new LinkedHashMap<>();
JsonObject config = JSONUtils.getJsonRootObject(factory.getJsonConfiguration());
if (config == null)
return result;
if (!config.has(EntaxyFactory.CONFIGURATION.FACTORY_SECTION_NAME))
return result;
Object obj = JSONUtils.element2object(config.get(EntaxyFactory.CONFIGURATION.FACTORY_SECTION_NAME));
if (!(obj instanceof Map))
return result;
result.putAll((Map<String, Object>) ((Map<String, Object>) obj).entrySet().stream()
.collect(() -> new LinkedHashMap<String, Object>(),
(m, e) -> m.put(String.format("%s%s", prefix, e.getKey()), e.getValue()), HashMap::putAll));
result.putAll(factory.getTypeInfo().entrySet().stream()
.collect(() -> new LinkedHashMap<String, Object>(),
(m, e) -> m.put(String.format("%stypeinfo.%s", prefix, e.getKey()), e.getValue()),
HashMap::putAll)
);
return result;
}
public static boolean factoryMatches(String filter, EntaxyFactory factory) {
try {
return factoryMatchesUnsafe(filter, factory);
} catch (InvalidSyntaxException ignore) {
return false;
}
}
public static boolean factoryMatchesUnsafe(String filter, EntaxyFactory factory) throws InvalidSyntaxException {
return factoryMatches(FrameworkUtil.createFilter(filter), factory);
}
public static boolean factoryMatches(Filter filter, EntaxyFactory factory) {
return filter.matches(getFactoryEssence(factory));
}
public static List<EntaxyFactory> filterFactories(String filter, List<EntaxyFactory> factories) {
try {
return filterFactoriesUnsafe(filter, factories);
} catch (InvalidSyntaxException ignore) {
return new ArrayList<>();
}
}
public static List<EntaxyFactory> filterFactoriesUnsafe(String filter, List<EntaxyFactory> factories)
throws InvalidSyntaxException {
Filter osgiFilter = FrameworkUtil.createFilter(filter);
return filterFactories(osgiFilter, factories);
}
public static List<EntaxyFactory> filterFactories(Filter filter, List<EntaxyFactory> factories) {
return factories.stream().filter(f -> factoryMatches(filter, f)).collect(Collectors.toList());
}
}

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -3,7 +3,7 @@
<parent>
<groupId>ru.entaxy.esb.platform.runtime.core</groupId>
<artifactId>object-producing</artifactId>
<version>1.9.0</version>
<version>1.10.0</version>
</parent>
<groupId>ru.entaxy.esb.platform.runtime.core.object-producing</groupId>
<artifactId>object-producer-core</artifactId>
@ -12,7 +12,13 @@
<description>ENTAXY :: PLATFORM :: CORE :: OBJECT PRODUCING :: PRODUCER CORE</description>
<properties>
<bundle.osgi.export.pkg>ru.entaxy.platform.core.producer.*</bundle.osgi.export.pkg>
<bundle.osgi.export.pkg>
ru.entaxy.platform.core.producer.executor*,
ru.entaxy.platform.core.producer.audit,
ru.entaxy.platform.core.producer.impl,
ru.entaxy.platform.core.producer.support,
ru.entaxy.platform.core.producer.wrapper
</bundle.osgi.export.pkg>
</properties>
<dependencies>
@ -32,6 +38,24 @@
<groupId>org.apache.camel</groupId>
<artifactId>camel-core</artifactId>
</dependency>
<dependency>
<groupId>ru.entaxy.esb.platform.runtime.base</groupId>
<artifactId>base-extensions-support</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>ru.entaxy.platform.logging</groupId>
<artifactId>cef-logger-layout</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>ru.entaxy.platform.logging</groupId>
<artifactId>entaxy-audit</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
<build>

View File

@ -6,7 +6,7 @@
"validate":{},
"generate":{},
"build":{"artifact.version.policy":"dated-embedded"},
"install":{"installLocal":false, "update":""},
"install":{"installLocal":false, "update":"", "startLevel": 120},
"deploy":{"deployLocal":false},
"store": {}
},

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* object-producer-core
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
@ -26,7 +26,6 @@
package ru.entaxy.platform.core.producer.executor;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
@ -41,6 +40,9 @@ import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import ru.entaxy.esb.platform.runtime.base.extensions.api.EntaxyExtendable;
import ru.entaxy.esb.platform.runtime.base.extensions.api.EntaxyExtension;
import ru.entaxy.esb.platform.runtime.base.extensions.api.EntaxyExtensionsProvider;
import ru.entaxy.platform.base.support.CommonUtils;
import ru.entaxy.platform.base.support.DependencySorter;
import ru.entaxy.platform.base.support.JSONUtils;
@ -72,6 +74,26 @@ public class ProducingExecutor {
protected ExecutionPlan executionPlan = null;
protected final List<EntaxyExtension> extensions = new ArrayList<>();
public static class EntaxyExtensionsProviderImpl implements EntaxyExtensionsProvider {
List<EntaxyExtension> entaxyExtensions;
public EntaxyExtensionsProviderImpl(List<EntaxyExtension> entaxyExtensions) {
if (entaxyExtensions == null)
this.entaxyExtensions = new ArrayList<>();
else
this.entaxyExtensions = entaxyExtensions;
}
@Override
public List<EntaxyExtension> getExtensions() {
return this.entaxyExtensions;
}
}
public ProducingExecutor(JsonObject configuration, String buildInstructions
, EntaxyProducerService producerService) throws Exception {
this.configuration = configuration;
@ -198,6 +220,7 @@ public class ProducingExecutor {
});
executionPlan.tasks = sorted;
applyDirectives(directives);
}
protected void applyDirectives(JsonObject directives) {
@ -261,6 +284,18 @@ public class ProducingExecutor {
producerResult.commandResult("#plan").result(true).resultObject(executionPlan);
producerResult.commandResult("#init").result(true).resultObject(configuration);
// add all awailable extensions to task executors
if (producerService instanceof EntaxyExtendable) {
producerResult.commandResult("#extensions").result(true).resultObject(
(EntaxyExtensionsProvider)new EntaxyExtensionsProviderImpl(((EntaxyExtendable)producerService).getExtensions())
);
} else {
producerResult.commandResult("#extensions").result(true).resultObject(
(EntaxyExtensionsProvider)new EntaxyExtensionsProviderImpl(null)
);
}
return execute(producerResult);
}
@ -295,4 +330,5 @@ public class ProducingExecutor {
return producerResult;
}
}

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* object-producer-core
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* object-producer-core
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* object-producer-core
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* object-producer-core
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* object-producer-core
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* object-producer-core
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* object-producer-core
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* object-producer-core
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* object-producer-core
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
@ -36,60 +36,68 @@ import ru.entaxy.platform.core.producer.api.ProducerResult.CommandResult;
public abstract class AbstractTask {
protected boolean isPrintOutput = false;
protected List<Generated> oldResults = new LinkedList<>();
protected Generated generatedResult = null;
protected AbstractTask mergeTo = null;
protected boolean isFinal = true;
public abstract String getInfo();
protected boolean isPrintOutput = false;
public abstract boolean execute(
ProducerResult currentResult
, CommandResult currentCommand
, EntaxyProducerService producerService
, Map<String, Object> instructions) throws Exception;
protected void printOutput(String message) {
if (this.isPrintOutput)
// OUTPUT TO CONSOLE
System.out.println(message);
}
public boolean isPrintOutput() {
return isPrintOutput;
}
protected List<Generated> oldResults = new LinkedList<>();
public void setPrintOutput(boolean isPrintOutput) {
this.isPrintOutput = isPrintOutput;
}
protected GenerationModel generationModel;
public Generated getGeneratedResult() {
return generatedResult;
}
protected Generated generatedResult = null;
public void mergeTo(AbstractTask abstractTask) {
this.mergeTo = abstractTask;
}
public boolean isToMerge() {
return this.mergeTo != null;
}
protected AbstractTask mergeTo = null;
public boolean isFinal() {
return isFinal;
}
protected boolean isFinal = true;
public void setFinal(boolean isFinal) {
this.isFinal = isFinal;
}
public void updateGenerated(Generated generated) {
oldResults.add(generatedResult);
this.generatedResult = generated;
}
public abstract String getInfo();
public abstract boolean execute(
ProducerResult currentResult, CommandResult currentCommand, EntaxyProducerService producerService,
Map<String, Object> instructions) throws Exception;
public GenerationModel getGenerationModel() {
return generationModel;
}
public void setGenerationModel(GenerationModel generationModel) {
this.generationModel = generationModel;
}
protected void printOutput(String message) {
if (this.isPrintOutput)
// OUTPUT TO CONSOLE
System.out.println(message);
}
public boolean isPrintOutput() {
return isPrintOutput;
}
public void setPrintOutput(boolean isPrintOutput) {
this.isPrintOutput = isPrintOutput;
}
public Generated getGeneratedResult() {
return generatedResult;
}
public void mergeTo(AbstractTask abstractTask) {
this.mergeTo = abstractTask;
}
public boolean isToMerge() {
return this.mergeTo != null;
}
public boolean isFinal() {
return isFinal;
}
public void setFinal(boolean isFinal) {
this.isFinal = isFinal;
}
public void updateGenerated(Generated generated) {
oldResults.add(generatedResult);
this.generatedResult = generated;
}
}

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* object-producer-core
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
@ -44,54 +44,57 @@ import ru.entaxy.platform.core.producer.executor.objectmodel.ObjectModel;
public class CalculateTask extends AbstractObjectTask {
private static final Logger log = LoggerFactory.getLogger(CalculateTask.class);
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;
}
public CalculateTask(FactoredObject factoredObject) {
super(factoredObject);
}
private static Gson GSON = JSONUtils.GSON;
@Override
public String getInfo() {
return "CALCULATE FOR " + "[" + origin.getObjectId() + "]";
}
public static boolean hasCalculations(FactoredObject factoredObject) {
return factoredObject.getInternals().stream().filter(obj -> (obj instanceof Calculation))
.count() > 0;
}
@Override
public boolean execute(ProducerResult currentResult, CommandResult currentCommand,
EntaxyProducerService producerService, Map<String, Object> instructions) throws Exception {
ObjectModel objectModel = currentResult.findResultObject(ObjectModel.class);
List<Calculation> calculations = this.origin.getInternals().stream()
.filter(obj -> (obj instanceof Calculation))
.map(obj -> (Calculation)obj)
.collect(Collectors.toList());
for (Calculation calculation: calculations) {
Object result = calculation.calculate(objectModel, origin);
printOutput("CALCULATION RESOLVED TO :: " + result);
printOutput("\n REPLACE"
+ "\n\t" + calculation.origin
+ "\n\tWITH :: " + GSON.toJsonTree(result)
+ "\n\tAT :: " + calculation.relativePath);
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"));
}
public CalculateTask(FactoredObject factoredObject) {
super(factoredObject);
}
}
return true;
}
@Override
public String getInfo() {
return "CALCULATE FOR " + "[" + origin.getObjectId() + "]";
}
@Override
public boolean execute(ProducerResult currentResult, CommandResult currentCommand,
EntaxyProducerService producerService, Map<String, Object> instructions) throws Exception {
ObjectModel objectModel = currentResult.findResultObject(ObjectModel.class);
List<Calculation> calculations = this.origin.getInternals().stream()
.filter(obj -> (obj instanceof Calculation))
.map(obj -> (Calculation) obj)
.collect(Collectors.toList());
for (Calculation calculation : calculations) {
Object result = calculation.calculate(objectModel, origin, producerService);
if (!Calculation.isValidResult(result))
if (calculation.hasFallbackObject())
result = calculation.getFallbackObject();
printOutput("CALCULATION RESOLVED TO :: " + result);
printOutput("\n REPLACE"
+ "\n\t" + calculation.origin
+ "\n\tWITH :: " + GSON.toJsonTree(result)
+ "\n\tAT :: " + calculation.relativePath);
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"));
}
}
return true;
}
}

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* object-producer-core
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
@ -30,6 +30,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -37,202 +38,337 @@ import org.slf4j.LoggerFactory;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import ru.entaxy.platform.base.support.CommonUtils;
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.base.support.CommonUtils;
import ru.entaxy.platform.base.support.JSONUtils;
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.objectmodel.FactoredObject;
import ru.entaxy.platform.core.producer.executor.objectmodel.FactoredObjectRef;
public class GenerateTask extends AbstractObjectTask {
private static final Logger log = LoggerFactory.getLogger(GenerateTask.class);
public static final String CONTENT_FIELD = "##_CONTENT";
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;
//public String objectId;
public JsonElement properties;
private static final Logger log = LoggerFactory.getLogger(GenerateTask.class);
public String outputType = "init";
public String scope = "public";
public Map<String, Object> generationProperties = new HashMap<>();
public GenerateTask(FactoredObject factoredObject) {
super(factoredObject);
fillFromOrigin();
}
@Override
public boolean execute(ProducerResult currentResult, CommandResult currentCommand,
EntaxyProducerService producerService, Map<String, Object> instructions) throws Exception {
if (!CommonUtils.isValid(factoryId))
throw new IllegalArgumentException("Factory ID is null");
if (!CommonUtils.isValid(factoryType))
try {
EntaxyFactory f = producerService.findFactoryById(factoryId);
if (f != null) {
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) {
throw e;
}
log.debug("Execute for type [{}] with factoryId [{}]", factoryType, factoryId);
Map<String, Object> effectiveProperties = createEffectiveProperties(instructions);
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()
.getOrDefault(FIELDS.OBJECT_ID, origin.getObjectId()).toString();
if (!origin.getObjectId().equals(objectId)) {
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.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;
}
public static final String CONTENT_FIELD = "##_CONTENT";
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;
}
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";
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);
JsonElement effectiveProperties = this.properties.deepCopy();
if (effectiveProperties.isJsonObject()) {
JsonObject jobj = effectiveProperties.getAsJsonObject();
for (Entry<String, JsonElement> entry: origin.origin.entrySet()) {
/*if (entry.getKey().equals(FIELDS.PROPERTIES))
continue;*/
if (jobj.has(entry.getKey()))
continue;
jobj.add(entry.getKey(), entry.getValue());
}
result.putAll(JSONUtils.element2map(effectiveProperties));
}
return result;
}
public void fillFromOrigin() {
this.factoryId = origin.factoryId;
// this.objectId = origin.getObjectId();
this.factoryType = origin.getObjectType();
this.scope = origin.scope;
this.properties = origin.origin.get(FIELDS.PROPERTIES);
if (CommonUtils.isValid(origin.getOutputType()))
this.outputType = origin.getOutputType();
}
public void updateObjectId(String objectId) {
// this.objectId = objectId;
this.origin.setObjectId(objectId);
}
@Override
public String getInfo() {
return "GENERATE " + "[" + origin.getObjectId() + "] :: " + factoryId + "/" + outputType;
}
// TODO move to EntaxyFactory
public static final String HEADER_OBJECT_MAP = "@OBJECT-MAP";
// TODO move to EntaxyFactory
public static final String DIRECTIVE_SKIP_PUBLISH = "@SKIP_PUBLISH";
// TODO move to EntaxyFactory
public static final String DIRECTIVE_PUBLISH_AS = "@PUBLISH_AS";
// TODO move to EntaxyFactory
public static final String DIRECTIVE_SKIP_PROVIDE = "@SKIP_PROVIDE";
public String factoryId;
public String factoryType;
// public String objectId;
public JsonElement properties;
public String outputType = "init";
public String scope = "public";
public Map<String, Object> generationProperties = new HashMap<>();
public FactoredObjectRef originRef = null;
public FactoredObject originObject = null;
public GenerateTask(FactoredObject factoredObject) {
super(factoredObject);
fillFromOrigin();
}
@Override
public boolean execute(ProducerResult currentResult, CommandResult currentCommand,
EntaxyProducerService producerService, Map<String, Object> instructions) throws Exception {
if (!CommonUtils.isValid(factoryId))
throw new IllegalArgumentException("Factory ID is null");
if (!CommonUtils.isValid(factoryType))
try {
EntaxyFactory f = producerService.findFactoryById(factoryId);
if (f != null) {
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) {
throw e;
}
log.debug("Execute for type [{}] with factoryId [{}]/[{}]", factoryType, factoryId, outputType);
Map<String, Object> effectiveProperties = createEffectiveProperties(instructions);
EntaxyFactory factory = producerService.getProducerForType(factoryType).getFactoryById(factoryId);
// check hierarchy
if (factory == null) {
factory = producerService.findFactoryById(factoryId);
boolean typeChecked = false;
EntaxyFactory current = factory;
while (!typeChecked && current != null) {
typeChecked = current.getType().equals(factoryType);
if (typeChecked)
break;
current = producerService.findFactoryById(current.getParent());
}
if (!typeChecked) {
log.error("FAILED producing for output [{}]: factory [{}] is not of type [{}]", outputType, factoryId,
factoryType);
throw new IllegalArgumentException(
String.format("Factory [%s] is not of type [%s]", factoryId, factoryType));
}
}
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()
.getOrDefault(FIELDS.OBJECT_ID, origin.getObjectId()).toString();
if (!origin.getObjectId().equals(objectId)) {
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
}
}
// we prepare publish data for all objects
JsonObject publishData = generationModel.publishDataStorage.generatePublishData(origin, factory, outputType);
GeneratedHeaders headers = GeneratedHeaders.getHeaders(this.generatedResult.getProperties());
headers.set(HEADERS.ENTAXY_GENERATED, "true");
if (publishObject) {
String publishedObjectId = origin.getObjectId();
String publishAsField = getPublishAs(factory, this.outputType, this.scope);
if (CommonUtils.isValid(publishAsField)) {
if (effectiveProperties.containsKey(publishAsField))
publishedObjectId = effectiveProperties.getOrDefault(publishAsField, publishedObjectId).toString();
}
if (!publishedObjectId.equals(origin.getObjectId()))
headers.append(HEADER_OBJECT_MAP,
origin.getObjectId() + ":" + factoryType + "::" + publishedObjectId + ":" + factoryType);
// set @SKIP_PROVIDE property
if (isSkipProvide(factory, this.outputType, this.scope)) {
this.generatedResult.getProperties().put(DIRECTIVE_SKIP_PROVIDE, true);
}
headers.set(HEADERS.MAIN_OBJECT, publishedObjectId + ":" + factoryType + ":" + scope);
headers.append(HEADERS.GENERATED_OBJECTS, publishedObjectId + ":" + 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(
publishData.toString().getBytes()));
}
this.generationProperties.clear();
this.generationProperties.putAll(effectiveProperties);
this.generatedResult.getProperties().put(GENERATION_PROPERTIES_FIELD,
new HashMap<String, Object>(this.generationProperties));
return true;
}
@Deprecated
protected JsonObject getFilteredObjectData(JsonObject originData, EntaxyFactory factory, String outputType) {
JsonObject result = getFilteredObject(originData, factory, outputType);
if (result == null)
result = new JsonObject();
return result;
}
@Deprecated
protected JsonObject getFilteredObject(JsonObject originObject, EntaxyFactory factory, String outputType) {
JsonObject result = new JsonObject();
Map<String, JsonObject> factoryFields = factory.getOutputByType(outputType).getFields().stream()
.collect(Collectors.toMap(fi -> fi.getName(), fi -> fi.getJsonOrigin()));
for (Entry<String, JsonElement> entry : originObject.entrySet()) {
String name = entry.getKey();
if (FactoredObject.EMBEDDED_FIELD.equals(name) || FactoredObject.IGNORE_SECTION.equals(name))
continue;
boolean skip = false;
// check @INTERNAL directive via factory data
JsonObject joField = factoryFields.getOrDefault(name, new JsonObject());
if (joField.has(EntaxyFactory.CONFIGURATION.DIRECTIVES.INTERNAL)) {
try {
skip = joField.get(EntaxyFactory.CONFIGURATION.DIRECTIVES.INTERNAL).getAsBoolean();
} catch (Exception ignore) {
// NOOP
}
}
if (skip)
continue;
JsonElement je = entry.getValue();
if (je.isJsonObject()) {
JsonObject jo = je.getAsJsonObject();
// check @INTERNAL directive via object data
if (jo.has(EntaxyFactory.CONFIGURATION.DIRECTIVES.INTERNAL)) {
try {
skip = jo.get(EntaxyFactory.CONFIGURATION.DIRECTIVES.INTERNAL).getAsBoolean();
} catch (Exception e) {
// NOOP
}
if (skip)
continue;
}
JsonObject filtered = getFilteredObject(jo, factory, outputType);
if (filtered != null)
result.add(name, filtered);
} else {
result.add(name, je);
}
}
return result;
}
protected String getPublishAs(EntaxyFactory factory, String outputType, String scope) {
OutputInfo info = factory.getOutputByType(outputType);
if (info == null)
return null;
Map<String, Object> config = info.getConfig();
if (config == null)
return null;
if (config.containsKey(DIRECTIVE_PUBLISH_AS)) {
try {
// check scopes
Map<String, Object> data = (Map<String, Object>) config.get(DIRECTIVE_PUBLISH_AS);
if (data.containsKey(scope)) {
return data.get(scope).toString();
} else {
if (data.containsKey("*")) {
return data.get("*").toString();
}
}
} catch (Exception e) {
return null;
}
}
return null;
}
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 boolean isSkipProvide(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_PROVIDE)) {
try {
// check scopes
Map<String, Object> data = (Map<String, Object>) config.get(DIRECTIVE_SKIP_PROVIDE);
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);
JsonElement effectiveProperties = this.properties.deepCopy();
if (effectiveProperties.isJsonObject()) {
JsonObject jobj = effectiveProperties.getAsJsonObject();
for (Entry<String, JsonElement> entry : origin.origin.entrySet()) {
/*
* if (entry.getKey().equals(FIELDS.PROPERTIES)) continue;
*/
if (jobj.has(entry.getKey()))
continue;
jobj.add(entry.getKey(), entry.getValue());
}
result.putAll(JSONUtils.element2map(effectiveProperties));
}
return result;
}
public void fillFromOrigin() {
this.factoryId = origin.factoryId;
// this.objectId = origin.getObjectId();
this.factoryType = origin.getObjectType();
this.scope = origin.scope;
this.properties = origin.origin.get(FIELDS.PROPERTIES);
if (CommonUtils.isValid(origin.getOutputType()))
this.outputType = origin.getOutputType();
}
public void updateObjectId(String objectId) {
// this.objectId = objectId;
this.origin.setObjectId(objectId);
}
@Override
public String getInfo() {
return "GENERATE " + "[" + origin.getObjectId() + "] :: " + factoryId + "/" + outputType;
}
}

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
@ -33,6 +33,8 @@ import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import com.google.gson.JsonObject;
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;
@ -40,106 +42,144 @@ import ru.entaxy.platform.core.producer.executor.objectmodel.ObjectModel;
public class GenerationModel {
protected ObjectModel objectModel;
protected List<AbstractTask> tasks = new LinkedList<>();
public Map<Object, List<AbstractTask>> objectToTasksMap = new HashMap<>();
public GenerationModel(ObjectModel objectModel) {
this.objectModel = objectModel;
}
public void load() {
for (FactoredObject fo: objectModel.objects)
if (!fo.isEmbedded())
tasks.addAll(generateTasksForObject(fo));
}
protected List<AbstractTask> generateTasksForObject(FactoredObject fo) {
public static final String DIRECTIVE_SKIP_MERGE = "@SKIP_MERGE";
if (fo instanceof FactoredObjectProxy)
return Collections.singletonList(new ResolveObjectTask((FactoredObjectProxy)fo));
List<AbstractTask> localPreTasks = new LinkedList<>();
List<AbstractTask> localPostTasks = new LinkedList<>();
public static final String DIRECTIVE_PUBLISH_URESOLVED = "@PUBLISH_UNRESOLVED";
// first process embedded objects
public static final String PUBLISH_UNRESOLVED_REF = "ref";
public static final String PUBLISH_UNRESOLVED_OBJECT = "object";
List<FactoredObject> embedded = fo.embedded.stream().filter(f->(f instanceof FactoredObject))
.map(f -> (FactoredObject)f)
.collect(Collectors.toList());
for (FactoredObject embeddedObject: embedded) {
List<AbstractTask> tasksForEmbedded = generateTasksForObject(embeddedObject);
localPreTasks.addAll(tasksForEmbedded);
}
public static final String UNRESOLVED_CONTAINER_NAME = "##_UNRESOLVED";
// process links to externalized embedded objects
protected ObjectModel objectModel;
List<FactoredObjectRef> embeddedLinks = fo.embedded.stream().filter(f->(f instanceof FactoredObjectRef))
.map(f -> (FactoredObjectRef)f)
.filter(f -> !f.isBackRef())
.filter(f -> f.isLink())
.collect(Collectors.toList());
for (FactoredObjectRef embeddedRef: embeddedLinks) {
FactoredObject embeddedObject = embeddedRef.getTargetObject();
List<AbstractTask> tasksForEmbedded = generateTasksForObject(embeddedObject);
// check the dependencies:
// if embedded depends on main
// then it must be generates after the main
List<FactoredObjectRef> refs = objectModel.refs.stream()
.filter(r -> r.isDefinedIn(embeddedObject))
.filter(r -> fo.equals(r.getTargetObject()))
.collect(Collectors.toList());
if (refs.isEmpty())
localPreTasks.addAll(tasksForEmbedded);
else
localPostTasks.addAll(tasksForEmbedded);
}
protected List<AbstractTask> tasks = new LinkedList<>();
// process embedded refs
List<FactoredObjectRef> embeddedRefs = fo.embedded.stream().filter(f->(f instanceof FactoredObjectRef))
.map(f -> (FactoredObjectRef)f)
.filter(f -> !f.isBackRef())
.filter(f -> !f.isLink() || f.isResolveAlways())
.collect(Collectors.toList());
for (FactoredObjectRef embeddedRef: embeddedRefs) {
if (!embeddedRef.isLink() || embeddedRef.isResolveAlways()) {
localPreTasks.add(new ResolveRefTask(embeddedRef));
if (!embeddedRef.isLink())
if (!embeddedRef.isRefByValueOnly())
localPreTasks.add(new GenerateRefTask(embeddedRef));
}
}
List<AbstractTask> currentTasks = new ArrayList<>(localPreTasks);
if (CalculateTask.hasCalculations(fo))
currentTasks.add(new CalculateTask(fo));
GenerateTask generateTask = new GenerateTask(fo);
public Map<Object, List<AbstractTask>> objectToTasksMap = new HashMap<>();
currentTasks.add(generateTask);
public GeneratedObjectsPublishDataStorage publishDataStorage = new GeneratedObjectsPublishDataStorage();
for (AbstractTask at: localPreTasks)
if (((at instanceof GenerateTask) || (at instanceof GenerateRefTask)) && !at.isToMerge() )
currentTasks.add(new MergeTask(at, generateTask));
currentTasks.addAll(localPostTasks);
for (AbstractTask at: localPostTasks)
if (((at instanceof GenerateTask) || (at instanceof GenerateRefTask)) && !at.isToMerge())
currentTasks.add(new MergeTask(at, generateTask));
return currentTasks;
}
public GenerationModel(ObjectModel objectModel) {
this.objectModel = objectModel;
}
public void load() {
for (FactoredObject fo : objectModel.objects)
if (!fo.isEmbedded())
tasks.addAll(generateTasksForObject(fo, null, null));
for (AbstractTask at : tasks)
at.setGenerationModel(this);
}
protected List<AbstractTask> generateTasksForObject(FactoredObject fo, FactoredObjectRef originRef,
FactoredObject originObject) {
if (fo instanceof FactoredObjectProxy)
return Collections.singletonList(new ResolveObjectTask((FactoredObjectProxy) fo));
List<AbstractTask> localPreTasks = new LinkedList<>();
List<AbstractTask> localPostTasks = new LinkedList<>();
// first process embedded objects
List<FactoredObject> embedded = fo.embedded.stream().filter(f -> (f instanceof FactoredObject))
.map(f -> (FactoredObject) f)
.collect(Collectors.toList());
for (FactoredObject embeddedObject : embedded) {
List<AbstractTask> tasksForEmbedded = generateTasksForObject(embeddedObject, null, fo);
localPreTasks.addAll(tasksForEmbedded);
}
// process links to externalized embedded objects
List<FactoredObjectRef> embeddedLinks = fo.embedded.stream().filter(f -> (f instanceof FactoredObjectRef))
.map(f -> (FactoredObjectRef) f)
.filter(f -> !f.isBackRef())
.filter(f -> f.isLink())
.collect(Collectors.toList());
for (FactoredObjectRef embeddedRef : embeddedLinks) {
FactoredObject embeddedObject = embeddedRef.getTargetObject();
List<AbstractTask> tasksForEmbedded = generateTasksForObject(embeddedObject, embeddedRef, fo);
// check the dependencies:
// if embedded depends on main
// then it must be generates after the main
List<FactoredObjectRef> refs = objectModel.refs.stream()
.filter(r -> r.isDefinedIn(embeddedObject))
.filter(r -> fo.equals(r.getTargetObject()))
.collect(Collectors.toList());
if (refs.isEmpty())
localPreTasks.addAll(tasksForEmbedded);
else
localPostTasks.addAll(tasksForEmbedded);
}
// process embedded refs
List<FactoredObjectRef> embeddedRefs = fo.embedded.stream().filter(f -> (f instanceof FactoredObjectRef))
.map(f -> (FactoredObjectRef) f)
.filter(f -> !f.isBackRef())
.filter(f -> !f.isLink() || f.isResolveAlways())
.collect(Collectors.toList());
for (FactoredObjectRef embeddedRef : embeddedRefs) {
if (!embeddedRef.isLink() || embeddedRef.isResolveAlways()) {
localPreTasks.add(new ResolveRefTask(embeddedRef));
if (!embeddedRef.isLink())
if (!embeddedRef.isRefByValueOnly())
localPreTasks.add(new GenerateRefTask(embeddedRef));
}
}
List<AbstractTask> currentTasks = new ArrayList<>(localPreTasks);
if (CalculateTask.hasCalculations(fo))
currentTasks.add(new CalculateTask(fo));
GenerateTask generateTask = new GenerateTask(fo);
generateTask.originRef = originRef;
generateTask.originObject = originObject;
currentTasks.add(generateTask);
for (AbstractTask at : localPreTasks)
if (!at.isToMerge())
if ((at instanceof GenerateTask) && checkDoMerge((GenerateTask) at)) {
currentTasks.add(new MergeTask(at, generateTask));
} else if (at instanceof GenerateRefTask)
currentTasks.add(new MergeTask(at, generateTask));
currentTasks.addAll(localPostTasks);
for (AbstractTask at : localPostTasks)
if (!at.isToMerge())
if ((at instanceof GenerateTask) && checkDoMerge((GenerateTask) at)) {
currentTasks.add(new MergeTask(at, generateTask));
} else if (at instanceof GenerateRefTask)
currentTasks.add(new MergeTask(at, generateTask));
return currentTasks;
}
protected boolean checkDoMerge(GenerateTask generateTask) {
if (generateTask.originRef == null)
return true;
JsonObject jo = generateTask.originRef.origin;
if (!jo.has(DIRECTIVE_SKIP_MERGE))
return true;
try {
return !jo.get(DIRECTIVE_SKIP_MERGE).getAsBoolean();
} catch (Exception ignore) {
return true;
}
}
public List<AbstractTask> getTasks() {
return tasks;
}
public List<AbstractTask> getTasks() {
return tasks;
}
}

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
@ -25,12 +25,14 @@
*/
package ru.entaxy.platform.core.producer.executor.generationmodel;
import java.util.Collections;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ru.entaxy.esb.platform.runtime.base.connecting.generator.Generated;
import ru.entaxy.esb.platform.runtime.base.extensions.api.EntaxyExtensionsProvider;
import ru.entaxy.platform.base.objects.EntaxyObject;
import ru.entaxy.platform.base.objects.factory.EntaxyFactoryException;
import ru.entaxy.platform.core.producer.api.EntaxyProducerService;
@ -41,79 +43,94 @@ import ru.entaxy.platform.core.producer.executor.support.EntaxyObjectPropertiesH
public class MergeTask extends AbstractTask {
private static final Logger log = LoggerFactory.getLogger(MergeTask.class);
protected AbstractTask fromTask;
protected AbstractTask toTask;
public MergeTask(AbstractTask fromTask, AbstractTask toTask) {
this.fromTask = fromTask;
this.toTask = toTask;
this.fromTask.mergeTo(this.toTask);
}
@Override
public String getInfo() {
return "MERGE: " + "\n\t FROM: " + fromTask.getInfo() + "\n\t TO: " + toTask.getInfo();
}
private static final Logger log = LoggerFactory.getLogger(MergeTask.class);
protected AbstractTask fromTask;
protected AbstractTask toTask;
public MergeTask(AbstractTask fromTask, AbstractTask toTask) {
this.fromTask = fromTask;
this.toTask = toTask;
this.fromTask.mergeTo(this.toTask);
}
@Override
public String getInfo() {
return "MERGE: " + "\n\t FROM: " + fromTask.getInfo() + "\n\t TO: " + toTask.getInfo();
}
@Override
public boolean execute(ProducerResult currentResult, CommandResult currentCommand,
EntaxyProducerService producerService, Map<String, Object> instructions) throws Exception {
Generated source = this.fromTask.getGeneratedResult();
Generated target = this.toTask.getGeneratedResult();
if ((source != null) && (target != null)) {
if (!MergeHelper.getInstance().canMerge(source.getType(), target.getType())) {
printOutput("CAN'T MERGE " + source.getType() + " TO " + target.getType());
log.error("CAN'T MERGE " + source.getType() + " TO " + target.getType());
throw new EntaxyFactoryException(
"Can not merge [" + source.getType() + "] to [" + target.getType() + "]");
}
EntaxyExtensionsProvider extensionsProvider =
currentResult.findResultObject(EntaxyExtensionsProvider.class);
if (extensionsProvider == null)
this.generatedResult = MergeHelper.getInstance().merge(source, target, Collections.emptyList());
else
this.generatedResult =
MergeHelper.getInstance().merge(source, target, extensionsProvider.getExtensions());
// merge headers
// GeneratedHeaders sourceGeneratedHeaders =
// GeneratedHeaders.getHeaders(source.getProperties());
// GeneratedHeaders targetGeneratedHeaders =
// GeneratedHeaders.getHeaders(target.getProperties());
GeneratedHeaders sourceGeneratedHeaders = GeneratedHeaders.getHeaders(
EntaxyObjectPropertiesHelper.getMainObjectProperties(source.getProperties()));
GeneratedHeaders targetGeneratedHeaders = GeneratedHeaders.getHeaders(
EntaxyObjectPropertiesHelper.getMainObjectProperties(target.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)
|| EntaxyObject.HEADERS.ENTAXY_GENERATED.equals(header))
continue;
else
resultGeneratedHeaders.append(header, sourceGeneratedHeaders.headers.get(header));
} else {
if (source != null)
this.generatedResult = source;
else if (target != null)
this.generatedResult = target;
else
// nothing to do
return true;
}
this.fromTask.setFinal(false);
this.toTask.updateGenerated(generatedResult);
printOutput("\tMERGE RESULT ::");
printOutput(generatedResult.getObject().toString());
// prevent building result of this task
this.generatedResult = null;
return true;
}
@Override
public boolean execute(ProducerResult currentResult, CommandResult currentCommand,
EntaxyProducerService producerService, Map<String, Object> instructions) throws Exception {
Generated source = this.fromTask.getGeneratedResult();
Generated target = this.toTask.getGeneratedResult();
if ( (source!=null) && (target != null)) {
if (!MergeHelper.getInstance().canMerge(source.getType(), target.getType())) {
printOutput("CAN'T MERGE " + source.getType() + " TO " + target.getType());
log.error("CAN'T MERGE " + source.getType() + " TO " + target.getType());
throw new EntaxyFactoryException("Can not merge [" + source.getType() + "] to [" + target.getType() + "]");
}
this.generatedResult = MergeHelper.getInstance().merge(source, target);
// merge headers
GeneratedHeaders sourceGeneratedHeaders = GeneratedHeaders.getHeaders(source.getProperties());
GeneratedHeaders targetGeneratedHeaders = GeneratedHeaders.getHeaders(target.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) || EntaxyObject.HEADERS.ENTAXY_GENERATED.equals(header))
continue;
else
resultGeneratedHeaders.append(header, sourceGeneratedHeaders.headers.get(header));
} else {
if (source != null)
this.generatedResult = source;
else if (target != null)
this.generatedResult = target;
else
// nothing to do
return true;
}
this.fromTask.setFinal(false);
this.toTask.updateGenerated(generatedResult);
printOutput("\tMERGE RESULT ::");
printOutput(generatedResult.getObject().toString());
// prevent building result of this task
this.generatedResult = null;
return true;
}
}

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* object-producer-core
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* object-producer-core
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* object-producer-core
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
@ -40,74 +40,80 @@ import ru.entaxy.platform.core.producer.executor.objectmodel.FactoredObjectRef;
public class ResolveRefTask extends AbstractRefTask {
protected ResolveRefTask(FactoredObjectRef objectRef) {
super(objectRef);
}
protected ResolveRefTask(FactoredObjectRef objectRef) {
super(objectRef);
}
@Override
public String getInfo() {
return "RESOLVE-REF "
+ "["
+ objectRef.definedIn.getObjectId()
+ "] -> "
+ "["
+ objectRef.getTargetId()
+ "]";
// + objectRef.factoryId;
}
@Override
public String getInfo() {
return "RESOLVE-REF "
+ "["
+ objectRef.definedIn.getObjectId()
+ "] -> "
+ "["
+ objectRef.getTargetId()
+ "]";
// + objectRef.factoryId;
}
@Override
public boolean execute(ProducerResult currentResult, CommandResult currentCommand,
EntaxyProducerService producerService, Map<String, Object> instructions) throws Exception {
GenerationModel generationModel = currentResult.findResultObject(GenerationModel.class);
String fieldName = objectRef.getOrDefault(FIELDS.REF_FIELD, FIELDS.OBJECT_ID).toString();
printOutput("RESOLVING REF TO FIELD [" + fieldName + "]");
List<AbstractTask> generateTasks = generationModel.tasks.stream()
.filter(t->(t instanceof GenerateTask))
.map(t->(GenerateTask)t)
.filter(t->t.origin==objectRef.getTargetObject())
.collect(Collectors.toList());
if (generateTasks.size() == 0)
generateTasks = generationModel.tasks.stream()
.filter(t->(t instanceof ResolveObjectTask))
.map(t->(ResolveObjectTask)t)
.filter(t->t.origin==objectRef.getTargetObject())
.collect(Collectors.toList());
if (generateTasks.size() == 0) {
printOutput("None of GenerateTask or ResolveObjectTask found for [" + objectRef.getTargetId() + "/" + objectRef.getTargetObject().getObjectType() + "]");
return false;
}
AbstractTask provider = generateTasks.get(0);
Object value = null;
if (provider instanceof GenerateTask) {
GenerateTask generateTask = (GenerateTask)provider;
if (GenerateTask.CONTENT_FIELD.equals(fieldName)) {
Object val = generateTask.getGeneratedResult().getObject();
if (val != null)
value = val.toString();
else
value = "";
} else {
value = generateTask.generationProperties.getOrDefault(fieldName, "");
}
} else if (provider instanceof ResolveObjectTask) {
ResolveObjectTask task = (ResolveObjectTask)provider;
value = ObjectResolveHelper.getInstance().resolve(task.targetObject, fieldName);
if (value == null)
value = "";
}
printOutput("RESOLVED REF TO FIELD [" + fieldName + "] to VALUE [" + value.toString() + "]");
printOutput("REPLACE: [" + objectRef.origin.toString() + "] in PATH ["
+ objectRef.relativePath + "] in OBJECT "
+ objectRef.definedIn.origin.toString() );
JSONUtils.replaceValue(objectRef.definedIn.origin, objectRef.relativePath, (new Gson()).toJsonTree(value));
printOutput("AFTER REPLACEMENT: [" + objectRef.definedIn.origin.toString() + "]");
return true;
}
@Override
public boolean execute(ProducerResult currentResult, CommandResult currentCommand,
EntaxyProducerService producerService, Map<String, Object> instructions) throws Exception {
GenerationModel generationModel = currentResult.findResultObject(GenerationModel.class);
String fieldName = objectRef.getOrDefault(FIELDS.REF_FIELD, FIELDS.OBJECT_ID).toString();
printOutput("RESOLVING REF TO FIELD [" + fieldName + "]");
List<AbstractTask> generateTasks = generationModel.tasks.stream()
.filter(t -> (t instanceof GenerateTask))
.map(t -> (GenerateTask) t)
.filter(t -> t.origin == objectRef.getTargetObject())
.collect(Collectors.toList());
if (generateTasks.size() == 0)
generateTasks = generationModel.tasks.stream()
.filter(t -> (t instanceof ResolveObjectTask))
.map(t -> (ResolveObjectTask) t)
.filter(t -> t.origin == objectRef.getTargetObject())
.collect(Collectors.toList());
if (generateTasks.size() == 0) {
printOutput("None of GenerateTask or ResolveObjectTask found for [" + objectRef.getTargetId() + "/"
+ objectRef.getTargetObject().getObjectType() + "]");
return false;
}
AbstractTask provider = generateTasks.get(0);
Object value = null;
if (provider instanceof GenerateTask) {
GenerateTask generateTask = (GenerateTask) provider;
if (GenerateTask.CONTENT_FIELD.equals(fieldName)) {
Object val = generateTask.getGeneratedResult().getObject();
if (val != null)
value = val.toString();
else
value = "";
} else {
value = generateTask.generationProperties.getOrDefault(fieldName, null);
if (value == null)
value = generateTask.getGeneratedResult().getProperties().getOrDefault(fieldName, "");
}
} else if (provider instanceof ResolveObjectTask) {
ResolveObjectTask task = (ResolveObjectTask) provider;
value = ObjectResolveHelper.getInstance().resolve(task.targetObject, fieldName);
if (value == null)
value = "";
}
printOutput("RESOLVED REF TO FIELD [" + fieldName + "] to VALUE [" + value.toString() + "]");
printOutput("REPLACE: [" + objectRef.origin.toString() + "] in PATH ["
+ objectRef.relativePath + "] in OBJECT "
+ objectRef.definedIn.origin.toString());
JSONUtils.setValue(objectRef.definedIn.origin,
GenerationModel.UNRESOLVED_CONTAINER_NAME + "." + objectRef.relativePath, objectRef.origin, false,
true);
JSONUtils.replaceValue(objectRef.definedIn.origin, objectRef.relativePath, (new Gson()).toJsonTree(value));
printOutput("AFTER REPLACEMENT: [" + objectRef.definedIn.origin.toString() + "]");
return true;
}
@Override
public boolean isFinal() {
return false;
}
@Override
public boolean isFinal() {
return false;
}
}

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* object-producer-core
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
@ -25,18 +25,22 @@
*/
package ru.entaxy.platform.core.producer.executor.generationmodel.merge;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import ru.entaxy.esb.platform.runtime.base.extensions.api.EntaxyExtension;
import ru.entaxy.esb.platform.runtime.base.extensions.api.EntaxyExtensionsAware;
import ru.entaxy.platform.core.producer.executor.generationmodel.merge.MergingMap.Mapping;
public abstract class AbstractMergeProcessor implements MergeProcessor {
public abstract class AbstractMergeProcessor implements MergeProcessor, EntaxyExtensionsAware {
protected Map<String, List<String>> mapping;
protected List<EntaxyExtension> entaxyExtensions = new ArrayList<>();
protected AbstractMergeProcessor() {
super();
mapping = new HashMap<>();
@ -59,4 +63,14 @@ public abstract class AbstractMergeProcessor implements MergeProcessor {
return mapping;
}
@Override
public void addExtension(EntaxyExtension entaxyExtension) {
if (!entaxyExtensions.contains(entaxyExtension))
entaxyExtensions.add(entaxyExtension);
}
@Override
public void removeExtension(EntaxyExtension entaxyExtension) {
entaxyExtensions.remove(entaxyExtension);
}
}

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* object-producer-core
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
@ -25,6 +25,7 @@
*/
package ru.entaxy.platform.core.producer.executor.generationmodel.merge;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -39,6 +40,8 @@ import org.osgi.service.component.annotations.ReferencePolicy;
import org.osgi.service.component.annotations.ReferencePolicyOption;
import ru.entaxy.esb.platform.runtime.base.connecting.generator.Generated;
import ru.entaxy.esb.platform.runtime.base.extensions.api.EntaxyExtension;
import ru.entaxy.esb.platform.runtime.base.extensions.api.EntaxyExtensionsAware;
@Component(service = MergeHelper.class, immediate = true)
public class MergeHelper {
@ -57,6 +60,8 @@ public class MergeHelper {
}
}
protected final List<EntaxyExtension> extensions = new ArrayList<>();
protected Map<MergeProcessor, MergeProcessorWrapper> wrappersMap = new HashMap<>();
protected Map<String, Map<String, MergeProcessorWrapper>> processors = new HashMap<>();
@ -104,9 +109,12 @@ public class MergeHelper {
&& processors.get(source).get(target).mergeProcessor != null;
}
public Generated merge(Generated source, Generated target) {
public Generated merge(Generated source, Generated target, List<EntaxyExtension> extensions) {
if (!canMerge(source.getType(), target.getType()))
return null;
return processors.get(source.getType()).get(target.getType()).mergeProcessor.merge(source, target);
MergeProcessor processor = processors.get(source.getType()).get(target.getType()).mergeProcessor;
if (processor instanceof EntaxyExtensionsAware)
((EntaxyExtensionsAware)processor).addExtensions(extensions);
return processor.merge(source, target);
}
}

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* object-producer-core
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* object-producer-core
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* object-producer-core
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* object-producer-core
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* object-producer-core
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* object-producer-core
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* object-producer-core
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* object-producer-core
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
@ -36,284 +36,317 @@ import ru.entaxy.platform.base.objects.EntaxyObject.FIELDS;
public class FactoredObjectRef extends AbstractFactored {
private static final Logger log = LoggerFactory.getLogger(FactoredObjectRef.class);
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";
private static final Logger log = LoggerFactory.getLogger(FactoredObjectRef.class);
protected FactoredObject targetObject = null;
protected String targetId = "";
protected String targetUuid = "";
protected String targetType = "";
protected boolean isExternal = true;
protected boolean isResolved = true;
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);
this.origin = new JsonObject();
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);
}
public FactoredObjectRef (ObjectModel objectModel, FactoredObject targetObject) {
super(objectModel);
this.origin = new JsonObject();
this.setTargetObject(targetObject);
this.definedIn = targetObject.definedIn;
this.scope = targetObject.scope;
this.factoryId = targetObject.factoryId;
this.jsonPath = targetObject.jsonPath;
this.relativePath = targetObject.relativePath;
this.isExternal = false;
this.isLink = false;
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);
objectModel.addRef(this);
}
public static boolean isRef(JsonObject jsonObject) {
try {
// if object has 'targetId' we assume it as a ref
// even if there's no 'isRef'
if (jsonObject.has(TARGET_ID_FIELD))
if (!jsonObject.has(FIELDS.IS_REF))
jsonObject.addProperty(FIELDS.IS_REF, true);
if (!jsonObject.has(TARGET_ID_FIELD) && !AbstractFactored.isFactored(jsonObject))
return false;
if (!jsonObject.has(FIELDS.IS_REF))
return false;
boolean isRef = jsonObject.get(FIELDS.IS_REF).getAsBoolean();
return isRef;
} catch (Exception e) {
return false;
}
}
@Override
public void wrap(JsonObject object, Map<String, Object> context, String path) {
super.wrap(object, context, path);
public static final String DIRECTIVE_AUTO_CREATED = "@AUTOCREATED";
public static final String DIRECTIVE_REF_CONFIG = "@REF_CONFIG";
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);
}
public static final String DIRECTIVE_SOFT_UPDATE = "@SOFT_UPDATE";
@Override
public void updateFromOrigin() {
super.updateFromOrigin();
updateFromObject(origin);
}
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 void updateFromObject(JsonObject object) {
if (object.has(TARGET_ID_FIELD))
this.targetId = object.get(TARGET_ID_FIELD).getAsString();
protected FactoredObject targetObject = null;
if (object.has(TARGET_UUID_FIELD))
this.targetUuid = object.get(TARGET_UUID_FIELD).getAsString();
/*
if (object.has(TARGET_VALUE_FIELD))
this.targetValue = object.get(TARGET_VALUE_FIELD).getAsString();
*/
if (object.has(TARGET_TYPE_FIELD))
this.targetType = object.get(TARGET_TYPE_FIELD).getAsString();
protected String targetId = "";
protected String targetUuid = "";
protected String targetType = "";
if (object.has(IS_EXTERNAL_FIELD))
try{
this.isExternal = object.get(IS_EXTERNAL_FIELD).getAsBoolean();
} catch (Exception e) {
}
protected boolean isExternal = true;
protected boolean isResolved = true;
protected boolean isBackRef = false;
protected boolean refByValueOnly = false;
protected boolean isLink = false;
protected boolean resolveAlways = false;
protected boolean isDefinitionOrigin = false;
if (object.has(IS_RESOLVED_FIELD))
try{
this.isResolved = object.get(IS_RESOLVED_FIELD).getAsBoolean();
} catch (Exception e) {
}
public FactoredObjectRef(ObjectModel objectModel) {
super(objectModel);
this.origin = new JsonObject();
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);
}
if (object.has(RESOLVE_ALWAYS_FIELD))
try{
this.resolveAlways = object.get(RESOLVE_ALWAYS_FIELD).getAsBoolean();
} catch (Exception e) {
}
public FactoredObjectRef(ObjectModel objectModel, FactoredObject targetObject) {
super(objectModel);
this.origin = new JsonObject();
if (object.has(IS_DEFINITION_ORIGIN))
try{
this.isDefinitionOrigin = object.get(IS_DEFINITION_ORIGIN).getAsBoolean();
} catch (Exception e) {
}
this.setTargetObject(targetObject);
this.definedIn = targetObject.definedIn;
this.scope = targetObject.scope;
this.factoryId = targetObject.factoryId;
this.jsonPath = targetObject.jsonPath;
this.relativePath = targetObject.relativePath;
this.isExternal = false;
if (object.has(FIELDS.IS_BACK_REF))
try{
this.isBackRef = object.get(FIELDS.IS_BACK_REF).getAsBoolean();
} catch (Exception e) {
}
this.isLink = false;
if (object.has(IS_LINK))
try{
this.isLink = object.get(IS_LINK).getAsBoolean();
} catch (Exception e) {
}
if (object.has(FIELDS.IS_REF_BY_VALUE_ONLY))
try{
this.refByValueOnly = object.get(FIELDS.IS_REF_BY_VALUE_ONLY).getAsBoolean();
} catch (Exception e) {
}
}
public boolean isBackRef() {
return isBackRef;
}
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);
public boolean isExternal() {
return isExternal;
}
this.origin.addProperty(IS_LINK, this.isLink);
public boolean isResolved() {
return isResolved;
}
objectModel.addRef(this);
}
public void setResolved(boolean isResolved) {
this.isResolved = isResolved;
this.origin.remove(IS_RESOLVED_FIELD);
this.origin.addProperty(IS_RESOLVED_FIELD, this.isResolved);
}
public static boolean isRef(JsonObject jsonObject) {
try {
public boolean isResolveAlways() {
return resolveAlways;
}
// if object has 'targetId' we assume it as a ref
// even if there's no 'isRef'
if (jsonObject.has(TARGET_ID_FIELD))
if (!jsonObject.has(FIELDS.IS_REF))
jsonObject.addProperty(FIELDS.IS_REF, true);
public void setResolveAlways(boolean resolveAlways) {
this.resolveAlways = resolveAlways;
}
if (!jsonObject.has(TARGET_ID_FIELD) && !AbstractFactored.isFactored(jsonObject))
return false;
if (!jsonObject.has(FIELDS.IS_REF))
return false;
boolean isRef = jsonObject.get(FIELDS.IS_REF).getAsBoolean();
return isRef;
} catch (Exception e) {
return false;
}
}
public void setBackRef(boolean isBaskRef) {
this.isBackRef = isBaskRef;
this.origin.remove(FIELDS.IS_BACK_REF);
this.origin.addProperty(FIELDS.IS_BACK_REF, this.isBackRef);
}
@Override
public void wrap(JsonObject object, Map<String, Object> context, String path) {
super.wrap(object, context, path);
public void setExternal(boolean isExternal) {
this.isExternal = isExternal;
this.origin.remove(IS_EXTERNAL_FIELD);
this.origin.addProperty(IS_EXTERNAL_FIELD, this.isExternal);
}
updateFromObject(object);
public void setLink(boolean isLink) {
this.isLink = isLink;
this.origin.remove(IS_LINK);
this.origin.addProperty(IS_LINK, this.isLink);
}
public boolean isLink() {
return isLink;
}
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;
}
public boolean isDefinitionOrigin() {
return isDefinitionOrigin;
}
public void setDefinitionOrigin(boolean isDefinitionOrigin) {
this.isDefinitionOrigin = isDefinitionOrigin;
}
objectModel.addRef(this);
}
public boolean isRefByValueOnly() {
return refByValueOnly;
}
public boolean isAutoGenerated() {
return this.origin.has(DIRECTIVE_AUTO_CREATED);
}
public void setRefByValueOnly(boolean isRefByValueOnly) {
this.refByValueOnly = isRefByValueOnly;
}
public void setAutoGenerated(boolean value) {
this.origin.remove(DIRECTIVE_AUTO_CREATED);
if (value)
this.origin.addProperty(DIRECTIVE_AUTO_CREATED, true);
}
public String getTargetId() {
if (targetObject == null)
return targetId;
return targetObject.getObjectId();
}
@Override
public void updateFromOrigin() {
super.updateFromOrigin();
updateFromObject(origin);
}
public String getTargetUuid() {
return targetUuid;
}
public String getTargetType() {
if (targetObject == null)
return targetType;
return targetObject.getObjectType();
}
protected void updateFromObject(JsonObject object) {
if (object.has(TARGET_ID_FIELD))
this.targetId = object.get(TARGET_ID_FIELD).getAsString();
public FactoredObject getTargetObject() {
return targetObject;
}
if (object.has(TARGET_UUID_FIELD))
this.targetUuid = object.get(TARGET_UUID_FIELD).getAsString();
/*
* if (object.has(TARGET_VALUE_FIELD)) this.targetValue =
* object.get(TARGET_VALUE_FIELD).getAsString();
*/
if (object.has(TARGET_TYPE_FIELD))
this.targetType = object.get(TARGET_TYPE_FIELD).getAsString();
if (object.has(IS_EXTERNAL_FIELD))
try {
this.isExternal = object.get(IS_EXTERNAL_FIELD).getAsBoolean();
} catch (Exception e) {
}
if (object.has(IS_RESOLVED_FIELD))
try {
this.isResolved = object.get(IS_RESOLVED_FIELD).getAsBoolean();
} catch (Exception e) {
}
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();
} catch (Exception e) {
}
if (object.has(IS_LINK))
try {
this.isLink = object.get(IS_LINK).getAsBoolean();
} catch (Exception e) {
}
if (object.has(FIELDS.IS_REF_BY_VALUE_ONLY))
try {
this.refByValueOnly = object.get(FIELDS.IS_REF_BY_VALUE_ONLY).getAsBoolean();
} catch (Exception e) {
}
}
public boolean isBackRef() {
return isBackRef;
}
public boolean isExternal() {
return isExternal;
}
public boolean isResolved() {
return isResolved;
}
public void setResolved(boolean isResolved) {
this.isResolved = isResolved;
this.origin.remove(IS_RESOLVED_FIELD);
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);
this.origin.addProperty(FIELDS.IS_BACK_REF, this.isBackRef);
}
public void setExternal(boolean isExternal) {
this.isExternal = isExternal;
this.origin.remove(IS_EXTERNAL_FIELD);
this.origin.addProperty(IS_EXTERNAL_FIELD, this.isExternal);
}
public void setLink(boolean isLink) {
this.isLink = isLink;
this.origin.remove(IS_LINK);
this.origin.addProperty(IS_LINK, this.isLink);
}
public boolean isLink() {
return isLink;
}
public boolean isDefinitionOrigin() {
return isDefinitionOrigin;
}
public void setDefinitionOrigin(boolean isDefinitionOrigin) {
this.isDefinitionOrigin = isDefinitionOrigin;
}
public boolean isRefByValueOnly() {
return refByValueOnly;
}
public void setRefByValueOnly(boolean isRefByValueOnly) {
this.refByValueOnly = isRefByValueOnly;
}
public String getTargetId() {
if (targetObject == null)
return targetId;
return targetObject.getObjectId();
}
public String getTargetUuid() {
return targetUuid;
}
public String getTargetType() {
if (targetObject == null)
return targetType;
return targetObject.getObjectType();
}
public void setTargetType(String value) {
this.targetType = value;
this.origin.remove(TARGET_TYPE_FIELD);
this.origin.addProperty(TARGET_TYPE_FIELD, value);
}
public void refeshTargetType() {
if (targetObject != null)
setTargetType(targetObject.getObjectType());
}
public FactoredObject getTargetObject() {
return targetObject;
}
public void setTargetObject(FactoredObject targetObject) {
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!!!");
this.origin.remove(TARGET_ID_FIELD);
this.origin.addProperty(TARGET_ID_FIELD, getTargetId());
if (!(targetObject instanceof FactoredObjectProxy)) {
this.targetType = targetObject.getObjectType();
this.origin.remove(TARGET_TYPE_FIELD);
this.origin.addProperty(TARGET_TYPE_FIELD, getTargetType());
}
}
public void setTargetObject(FactoredObject targetObject) {
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!!!");
this.origin.remove(TARGET_ID_FIELD);
this.origin.addProperty(TARGET_ID_FIELD, getTargetId());
}
}

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
@ -45,131 +45,156 @@ import ru.entaxy.platform.base.support.JSONUtils.JsonTraverse;
public class ObjectModel {
private static final Logger log = LoggerFactory.getLogger(ObjectModel.class);
public List<FactoredObject> objects = new ArrayList<>();
public List<FactoredObjectRef> refs = new ArrayList<>();
protected Object rootObject = null;
protected JsonObject jsonCurrent = null;
protected JsonObject jsonOrigin = null;
protected boolean isDirty = false;
protected boolean isTracked = false;
public void addObject(FactoredObject factoredObject) {
this.objects.add(factoredObject);
}
public void addRef(FactoredObjectRef factoredObjectRef) {
this.refs.add(factoredObjectRef);
}
public Object load(JsonElement root) {
if (!root.isJsonObject()) {
log.debug("NOT AN OBJECT!!");
return null;
}
jsonCurrent = root.getAsJsonObject();
jsonOrigin = jsonCurrent.deepCopy();
JsonTraverse jsonTraverse = (new JsonTraverse()).checker(new FactoryChecker(this));
rootObject = jsonTraverse.traverse(jsonCurrent);
return rootObject;
}
public void checkRefs() {
List<FactoredObjectRef> originRefs = this.refs.stream()
.filter(r -> (r.getTargetObject()==null))
.collect(Collectors.toList());
for (FactoredObjectRef ref: originRefs) {
String targetId = ref.getTargetId();
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()) {
// System.out.println("CREATING PROXY FOR [" + targetId + "]");
// create proxy
FactoredObjectProxy proxy = new FactoredObjectProxy(this);
proxy.wrap(FactoredObjectProxy.getDefaultOrigin(), new HashMap<>(), "");
proxy.setObjectId(ref.getTargetId());
proxy.setObjectType(ref.getTargetType());
// update ref
ref.setExternal(true);
ref.setTargetObject(proxy);
} else {
// update objectType for proxy
if (fos.get(0) instanceof FactoredObjectProxy) {
if (!CommonUtils.isValid(fos.get(0).getObjectType()))
fos.get(0).setObjectType(ref.getTargetType());
}
ref.setExternal(fos.get(0) instanceof FactoredObjectProxy);
ref.setTargetObject(fos.get(0));
}
}
}
public void layout() throws Exception {
private static final Logger log = LoggerFactory.getLogger(ObjectModel.class);
public List<FactoredObject> objects = new ArrayList<>();
public List<FactoredObjectRef> refs = new ArrayList<>();
protected Object rootObject = null;
protected JsonObject jsonCurrent = null;
protected JsonObject jsonOrigin = null;
protected boolean isDirty = false;
protected boolean isTracked = false;
public void addObject(FactoredObject factoredObject) {
this.objects.add(factoredObject);
}
public void addRef(FactoredObjectRef factoredObjectRef) {
this.refs.add(factoredObjectRef);
}
public Object load(JsonElement root) {
if (!root.isJsonObject()) {
log.debug("NOT AN OBJECT!!");
return null;
}
jsonCurrent = root.getAsJsonObject();
jsonOrigin = jsonCurrent.deepCopy();
JsonTraverse jsonTraverse = (new JsonTraverse()).checker(new FactoryChecker(this));
rootObject = jsonTraverse.traverse(jsonCurrent);
return rootObject;
}
public void checkRefs() {
List<FactoredObjectRef> originRefs = this.refs.stream()
.filter(r -> (r.getTargetObject() == null))
.collect(Collectors.toList());
for (FactoredObjectRef ref : originRefs) {
String targetId = ref.getTargetId();
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()) {
// System.out.println("CREATING PROXY FOR [" + targetId + "]");
// create proxy
FactoredObjectProxy proxy = new FactoredObjectProxy(this);
proxy.wrap(FactoredObjectProxy.getDefaultOrigin(), new HashMap<>(), "");
proxy.setObjectId(ref.getTargetId());
proxy.setObjectType(ref.getTargetType());
// update ref
ref.setExternal(true);
ref.setTargetObject(proxy);
} else {
// update objectType for proxy
if (fos.get(0) instanceof FactoredObjectProxy) {
if (!CommonUtils.isValid(fos.get(0).getObjectType()))
fos.get(0).setObjectType(ref.getTargetType());
}
ref.setExternal(fos.get(0) instanceof FactoredObjectProxy);
ref.setTargetObject(fos.get(0));
}
}
}
public void layout() throws Exception {
JsonObject effectiveJson = new JsonObject();
// collect root objects
List<FactoredObject> rootObjects =
this.objects.stream().filter(fo -> fo.definedIn == null).collect(Collectors.toList());
JsonArray roots = new JsonArray();
for (FactoredObject fo : rootObjects)
roots.add(fo.origin);
List<FactoredObject> newRoots = new ArrayList<>();
List<JsonElement> movedElements = new ArrayList<>();
for (FactoredObject fo : rootObjects)
movedElements.addAll(layoutObject(fo, newRoots));
rootObjects.addAll(newRoots);
for (JsonElement je : movedElements)
roots.add(je);
embedReferences();
for (FactoredObject fo : objects) {
List<FactoredObjectRef> objrefs = refs.stream()
.filter(r -> r.isDefinedIn(fo))
.filter(r -> !fo.equals(r.getTargetObject()))
.collect(Collectors.toList());
}
List<FactoredObject> sortedRootObjects = DependencySorter.getSortedList(
rootObjects,
new DependencySorter.DependencyProvider<FactoredObject>() {
@Override
public List<FactoredObject> getDependencies(FactoredObject inspectedObject) {
// calculate dependencies based on refs
List<FactoredObject> dependencies =
refs.stream().filter(ref -> ref.isDefinedIn(inspectedObject))
.filter(ref -> !ref.isBackRef())
.filter(ref -> !ref.isLink())
// .filter(ref->!ref.isExternal())
.filter(ref -> !inspectedObject.equals(ref.getTargetObject()))
.map(ref -> ref.getTargetObject())
.collect(Collectors.toList());
// calculate transitive dependencies based on refs in embedded objects
List<FactoredObject> embedded = inspectedObject.embedded.stream()
.filter(obj -> obj instanceof FactoredObjectRef)
.map(obj -> (FactoredObjectRef) obj)
.filter(ref -> ref.isLink())
.map(ref -> ref.getTargetObject())
.collect(Collectors.toList());
for (FactoredObject inspectedEmbedded : embedded) {
List<FactoredObject> transitives =
refs.stream().filter(ref -> ref.isDefinedIn(inspectedEmbedded))
.filter(ref -> !ref.isBackRef())
.filter(ref -> !ref.isLink())
// .filter(ref->!ref.isExternal())
.filter(ref -> !inspectedObject.equals(ref.getTargetObject()))
.filter(ref -> !inspectedEmbedded.equals(ref.getTargetObject()))
.map(ref -> ref.getTargetObject())
.collect(Collectors.toList());
for (FactoredObject t : transitives)
if (!dependencies.contains(t))
dependencies.add(t);
}
return dependencies;
}
});
JsonObject effectiveJson = new JsonObject();
// collect root objects
List<FactoredObject> rootObjects = this.objects.stream().filter(fo -> fo.definedIn==null).collect(Collectors.toList());
JsonArray roots = new JsonArray();
for (FactoredObject fo: rootObjects)
roots.add(fo.origin);
List<FactoredObject> newRoots = new ArrayList<>();
List<JsonElement> movedElements = new ArrayList<>();
for (FactoredObject fo: rootObjects)
movedElements.addAll(layoutObject(fo, newRoots));
rootObjects.addAll(newRoots);
for (JsonElement je: movedElements)
roots.add(je);
embedReferences();
for (FactoredObject fo: objects) {
List<FactoredObjectRef> objrefs = refs.stream()
.filter(r -> r.isDefinedIn(fo))
.filter(r->!fo.equals(r.getTargetObject()))
.collect(Collectors.toList());
}
List<FactoredObject> sortedRootObjects = DependencySorter.getSortedList(
rootObjects,
new DependencySorter.DependencyProvider<FactoredObject>() {
@Override
public List<FactoredObject> getDependencies(FactoredObject inspectedObject) {
// calculate dependencies based on refs
List<FactoredObject> dependencies = refs.stream().filter(ref->ref.isDefinedIn(inspectedObject))
.filter(ref->!ref.isBackRef())
.filter(ref->!ref.isLink())
// .filter(ref->!ref.isExternal())
.filter(ref->!inspectedObject.equals(ref.getTargetObject()))
.map(ref->ref.getTargetObject())
.collect(Collectors.toList());
return dependencies;
}
});
/* new LinkedList<>(rootObjects);
Collections.<FactoredObject>sort(sortedRootObjects, new Comparator<FactoredObject>() {
@ -183,142 +208,144 @@ public class ObjectModel {
}
});
*/
this.objects = sortedRootObjects;
JsonArray sortedRoots = new JsonArray();
for (FactoredObject fo: sortedRootObjects)
sortedRoots.add(fo.origin);
// and finalize json
effectiveJson.add("##objects", sortedRoots);
jsonCurrent = effectiveJson;
log.debug(effectiveJson.toString());
}
protected void embedReferences() {
for (FactoredObjectRef ref: refs) {
FactoredObject fo = ref.definedIn;
/* if ("private".equals(ref.scope))
while ((fo!=null) && "private".equals(fo.scope))
fo = fo.definedIn;
*/
if (fo == null) {
log.debug("Error: orphaned ref: [" + ref.getTargetId() + "]");
continue;
}
fo.embed(ref);
}
}
protected List<JsonElement> layoutObject(FactoredObject factoredObject, List<FactoredObject> rootObjects) {
List<JsonElement> result = new ArrayList<>();
for (FactoredObject fo: factoredObject.dependsOn) {
if ("private".equals(fo.scope) && !fo.isEmbedded()) {
log.debug("FOUND PRIVATE OBJECT :: " + fo.getObjectId());
fo.setEmbedded(true);
log.debug("CREATING REF TO :: " + fo.getObjectId());
FactoredObjectRef objectRef = new FactoredObjectRef(this, fo);
objectRef.setLink(true);
/* FactoredObject owner = fo.definedIn;
// find first non-private object
while ((owner!=null) && "private".equals(owner.scope))
owner = owner.definedIn;
if (owner == null) {
log.debug("Error: orphaned private object: [" + fo.getObjectId() + "]");
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());
rootObjects.add(fo);
// owner.embed(objectRef);
result.addAll(layoutObject(fo, rootObjects));
} 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));
}
}
return result;
}
this.objects = sortedRootObjects;
public JsonObject getJsonCurrent() {
return jsonCurrent;
}
JsonArray sortedRoots = new JsonArray();
for (FactoredObject fo : sortedRootObjects)
sortedRoots.add(fo.origin);
public JsonObject getJsonOrigin() {
return jsonOrigin;
}
public Object getRootObject() {
return rootObject;
}
// and finalize json
effectiveJson.add("##objects", sortedRoots);
jsonCurrent = effectiveJson;
log.debug(effectiveJson.toString());
}
protected void embedReferences() {
for (FactoredObjectRef ref : refs) {
FactoredObject fo = ref.definedIn;
/* if ("private".equals(ref.scope))
while ((fo!=null) && "private".equals(fo.scope))
fo = fo.definedIn;
*/
if (fo == null) {
log.debug("Error: orphaned ref: [" + ref.getTargetId() + "]");
continue;
}
fo.embed(ref);
}
}
protected List<JsonElement> layoutObject(FactoredObject factoredObject, List<FactoredObject> rootObjects) {
List<JsonElement> result = new ArrayList<>();
for (FactoredObject fo : factoredObject.dependsOn) {
if ("private".equals(fo.scope) && !fo.isEmbedded()) {
log.debug("FOUND PRIVATE OBJECT :: " + fo.getObjectId());
fo.setEmbedded(true);
log.debug("CREATING REF TO :: " + fo.getObjectId());
FactoredObjectRef objectRef = new FactoredObjectRef(this, fo);
objectRef.setLink(true);
objectRef.setAutoGenerated(true);
/* FactoredObject owner = fo.definedIn;
// find first non-private object
while ((owner!=null) && "private".equals(owner.scope))
owner = owner.definedIn;
if (owner == null) {
log.debug("Error: orphaned private object: [" + fo.getObjectId() + "]");
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());
rootObjects.add(fo);
// owner.embed(objectRef);
result.addAll(layoutObject(fo, rootObjects));
} else {
FactoredObjectRef objectRef = new FactoredObjectRef(this, fo);
objectRef.setAutoGenerated(true);
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));
}
}
return result;
}
public JsonObject getJsonCurrent() {
return jsonCurrent;
}
public JsonObject getJsonOrigin() {
return jsonOrigin;
}
public Object getRootObject() {
return rootObject;
}
public void startTracking() {
this.isTracked = true;
}
public boolean stopTracking() {
this.isTracked = false;
boolean result = this.isDirty;
this.isDirty = false;
return result;
}
public void setDirty() {
if (this.isTracked)
this.isDirty = true;
}
public boolean isDirty() {
return isDirty;
}
public void startTracking() {
this.isTracked = true;
}
public boolean stopTracking() {
this.isTracked = false;
boolean result = this.isDirty;
this.isDirty = false;
return result;
}
public void setDirty() {
if (this.isTracked)
this.isDirty = true;
}
public boolean isDirty() {
return isDirty;
}
}

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* object-producer-core
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* object-producer-core
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
@ -25,6 +25,7 @@
*/
package ru.entaxy.platform.core.producer.executor.support;
import java.util.HashMap;
import java.util.Map;
import org.osgi.framework.Constants;
@ -67,263 +68,296 @@ import ru.entaxy.platform.core.producer.executor.installer.DefaultInstalledObjec
import ru.entaxy.platform.core.producer.executor.installer.InstalledObject;
import ru.entaxy.platform.core.producer.executor.installer.ObjectInstaller;
@Component (service = { ObjectBuilder.class, ObjectDeployer.class, ObjectInstaller.class}, immediate = true)
@Component(service = {ObjectBuilder.class, ObjectDeployer.class, ObjectInstaller.class}, immediate = true)
public class ArtifactSupport implements ObjectBuilder, ObjectDeployer, ObjectInstaller {
private static final Logger log = LoggerFactory.getLogger(ArtifactSupport.class);
@Reference (cardinality = ReferenceCardinality.MANDATORY)
ArtifactService artifactService;
/*
* ObjectBuilder
*/
@Override
public boolean isBuildable(Generated generated) {
Artifact artifact = Artifacts.fromGenerated(generated);
if ((artifact == null) || Artifact.ARTIFACT_CATEGORY_UNKNOWN.equals(artifact.getCategory())
|| !CommonUtils.isValid(artifact.getCategory())) {
return false;
}
return true;
}
private static final Logger log = LoggerFactory.getLogger(ArtifactSupport.class);
@Override
public BuiltObject build(Generated generated, Map<String, Object> instructions) throws Exception {
LocalPrintOutput printer = new LocalPrintOutput(instructions);
Artifact artifact = Artifacts.fromGenerated(generated);
if ((artifact == null) || Artifact.ARTIFACT_CATEGORY_UNKNOWN.equals(artifact.getCategory())
|| !CommonUtils.isValid(artifact.getCategory())) {
log.info("Artifact is not buildable");
return null;
}
log.info("Built artifact of category [{}]", artifact.getCategory());
Map<String, String> headers = GeneratedHeaders.getHeaders(
//generated.getProperties()
EntaxyObjectPropertiesHelper.getMainObjectProperties(generated.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 + "]");
String versionPolicy = generated.getProperties().getOrDefault(
EntaxyProducerService.INSTRUCTIONS.ARTIFACT.VERSION_POLICY,
instructions.getOrDefault(
EntaxyProducerService.INSTRUCTIONS.ARTIFACT.VERSION_POLICY
, ""))
.toString();
String timestamp = generated.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;
Map<String, Object> objectProperties = EntaxyObjectPropertiesHelper
.getPropertiesFor(objectId, objectType, generated.getProperties());
if (objectProperties.containsKey(FIELDS.FIELDS_TO_PUBLISH)) {
Object map = objectProperties.get(FIELDS.FIELDS_TO_PUBLISH);
if (map != null) {
attributes = (Map<String, Object>)((Map<String, Object>)map).get(objectId);
for (String directive: EntaxyFactory.CONFIGURATION.DIRECTIVES.getDesingDirectives())
attributes.remove(directive);
}
}
helper.provideCapability(objectType).attributes(attributes);
}
helper.save();
}
}
artifact.getProperties().putAll(generated.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());
}
printer.printOutput("\n\t == " + artifact.getCoordinates().toString() + " ==\n");
printer.printOutput(new String(artifact.asByteArray()));
printer.printOutput("\n\t == \n");
return new DefaultBuiltObject(artifact);
}
// TODO move to EntaxyFactory
public static final String DIRECTIVE_SKIP_PROVIDE = "@SKIP_PROVIDE";
/*
* ObjectDeployer
*/
@Override
public boolean isDeployable(BuiltObject object) {
return object.getObject() instanceof Artifact;
}
@Override
public DeployedObject deploy(BuiltObject object, Map<String, Object> instructions) throws Exception {
if (!(object.getObject() instanceof Artifact)) {
return null;
}
LocalPrintOutput printer = new LocalPrintOutput(instructions);
boolean deployLocal = false;
Object deployLocalValue = instructions.get(Deploy.DEPLOY_LOCAL_INSTRUCTION);
if (deployLocalValue != null)
if (deployLocalValue instanceof Boolean)
deployLocal = (Boolean)deployLocalValue;
Artifact artifact = (Artifact)object.getObject();
DeployedArtifact da = deployLocal
?artifactService.deployLocal(artifact)
:artifactService.deployShared(artifact);
// TODO move to EntaxyFactory
public static final String HEADER_OBJECT_MAP = "@OBJECT-MAP";
printer.printOutput("DEPLOYED: ["
+ da.getLocation()
+ "]");
return new DefaultDeployedObject(da);
}
/*
* ObjectInstaller
*/
@Override
public boolean isInstallable(DeployedObject object) {
return object.getObject() instanceof DeployedArtifact;
}
@Override
public InstalledObject install(DeployedObject object, Map<String, Object> instructions) throws Exception {
if (!isInstallable(object))
return null;
LocalPrintOutput printer = new LocalPrintOutput(instructions);
CommandInstructions commandInstructions = new CommandInstructions(instructions);
boolean installLocal =
commandInstructions.has(Install.INSTALL_LOCAL_INSTRUCTION)
?commandInstructions.getBoolean(Install.INSTALL_LOCAL_INSTRUCTION)
:false;
boolean installOnlyIfMissing =
commandInstructions.has(Install.INSTALL_ONLY_IF_MISSING_INSTRUCTION)
?commandInstructions.getBoolean(Install.INSTALL_ONLY_IF_MISSING_INSTRUCTION)
:false;
String update =
commandInstructions.has(Install.UPDATE_INSTRUCTION)
?commandInstructions.getString(Install.UPDATE_INSTRUCTION)
:null;
long startLevelValue =
commandInstructions.has(Install.START_LEVEL_INSTRUCTION)
?commandInstructions.getLong(Install.START_LEVEL_INSTRUCTION)
:-1;
DeployedArtifact da = (DeployedArtifact)object.getObject();
InstallationResult result = null;
Installer<?> installer = null;
String artifactUpdate = update;
printer.printOutput("-> Installing artifact: [" + da.getArtifact().getCoordinates().toString() + "]");
if (installLocal) {
LocalInstaller localInstaller = artifactService.installers().local()
.artifact(da);
installer = localInstaller;
printer.printOutput("-> Installing locally");
} else {
ClusterInstaller clusterInstaller = artifactService.installers().cluster()
.artifact(da);
installer = clusterInstaller;
printer.printOutput("-> Installing clustered");
}
@Reference(cardinality = ReferenceCardinality.MANDATORY)
ArtifactService artifactService;
// TODO add support for other types when they appear
if (da.getArtifact().getCategory().equals(Blueprint.ARTIFACT_CATEGORY_BLUEPRINT)) {
// we're installing blueprint
printer.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);
}
if (startLevelValue > 0)
blueprintInstaller.startLevel((int)startLevelValue);
result = blueprintInstaller.start().install();
} else {
printer.printOutput("-> Unknown category: " + da.getArtifact().getCategory());
}
if (result != null) {
if (result.getResult().equals(InstallationResult.Result.FAILED)) {
if (result.getError() != null)
throw (Exception)result.getError();
throw new RuntimeException(result.getMessage());
} else {
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());
}
}
return new DefaultInstalledObject(result);
}
/*
* ObjectBuilder
*/
@Override
public boolean isBuildable(Generated generated) {
Artifact artifact = Artifacts.fromGenerated(generated);
if ((artifact == null) || Artifact.ARTIFACT_CATEGORY_UNKNOWN.equals(artifact.getCategory())
|| !CommonUtils.isValid(artifact.getCategory())) {
return false;
}
return true;
}
@Override
public BuiltObject build(Generated generated, Map<String, Object> instructions) throws Exception {
LocalPrintOutput printer = new LocalPrintOutput(instructions);
Artifact artifact = Artifacts.fromGenerated(generated);
if ((artifact == null) || Artifact.ARTIFACT_CATEGORY_UNKNOWN.equals(artifact.getCategory())
|| !CommonUtils.isValid(artifact.getCategory())) {
log.info("Artifact is not buildable");
return null;
}
log.info("Built artifact of category [{}]", artifact.getCategory());
Map<String, String> headers = GeneratedHeaders.getHeaders(
// generated.getProperties()
EntaxyObjectPropertiesHelper.getMainObjectProperties(generated.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 + "]");
String versionPolicy = generated.getProperties().getOrDefault(
EntaxyProducerService.INSTRUCTIONS.ARTIFACT.VERSION_POLICY,
instructions.getOrDefault(
EntaxyProducerService.INSTRUCTIONS.ARTIFACT.VERSION_POLICY, ""))
.toString();
String timestamp = generated.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();
// Generate provided capabilities for every included object
ManifestCapabilityHelper helper = new ManifestCapabilityHelper(manifest);
helper.setMultipleNamespacesSupported(true);
Map<String, String> objectMap = new HashMap<>();
String objectMapValue = headers.getOrDefault(HEADER_OBJECT_MAP, "");
if (CommonUtils.isValid(objectMapValue)) {
String[] entries = objectMapValue.split(",");
for (String entry : entries) {
String[] data = entry.split("::");
if (data.length < 2)
continue;
// we invert map from published id to origin id
objectMap.put(data[1], data[0]);
}
}
headers.remove(HEADER_OBJECT_MAP);
manifest.getCustomAttributes().putAll(headers);
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();
if (objectMap.containsKey(objectId + ":" + objectType)) {
String mappedValue = objectMap.get(objectId + ":" + objectType);
String[] mappedData = mappedValue.split(":");
if (mappedData.length > 1) {
objectId = mappedData[0];
objectType = mappedData[1];
}
}
Map<String, Object> attributes = null;
Map<String, Object> objectProperties = EntaxyObjectPropertiesHelper
.getPropertiesFor(objectId, objectType, generated.getProperties());
boolean skipProvide = Boolean.parseBoolean(
objectProperties.getOrDefault(DIRECTIVE_SKIP_PROVIDE, false).toString());
if (skipProvide)
continue;
if (objectProperties.containsKey(FIELDS.FIELDS_TO_PUBLISH)) {
Object map = objectProperties.get(FIELDS.FIELDS_TO_PUBLISH);
if (map != null) {
attributes = (Map<String, Object>) ((Map<String, Object>) map).get(objectId);
for (String directive : EntaxyFactory.CONFIGURATION.DIRECTIVES.getDesignDirectives())
attributes.remove(directive);
}
}
helper.provideCapability(objectType).attributes(attributes);
}
helper.save();
}
}
artifact.getProperties().putAll(generated.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());
}
printer.printOutput("\n\t == " + artifact.getCoordinates().toString() + " ==\n");
printer.printOutput(new String(artifact.asByteArray()));
printer.printOutput("\n\t == \n");
return new DefaultBuiltObject(artifact);
}
/*
* ObjectDeployer
*/
@Override
public boolean isDeployable(BuiltObject object) {
return object.getObject() instanceof Artifact;
}
@Override
public DeployedObject deploy(BuiltObject object, Map<String, Object> instructions) throws Exception {
if (!(object.getObject() instanceof Artifact)) {
return null;
}
LocalPrintOutput printer = new LocalPrintOutput(instructions);
boolean deployLocal = false;
Object deployLocalValue = instructions.get(Deploy.DEPLOY_LOCAL_INSTRUCTION);
if (deployLocalValue != null)
if (deployLocalValue instanceof Boolean)
deployLocal = (Boolean) deployLocalValue;
Artifact artifact = (Artifact) object.getObject();
DeployedArtifact da = deployLocal
? artifactService.deployLocal(artifact)
: artifactService.deployShared(artifact);
printer.printOutput("DEPLOYED: ["
+ da.getLocation()
+ "]");
return new DefaultDeployedObject(da);
}
/*
* ObjectInstaller
*/
@Override
public boolean isInstallable(DeployedObject object) {
return object.getObject() instanceof DeployedArtifact;
}
@Override
public InstalledObject install(DeployedObject object, Map<String, Object> instructions) throws Exception {
if (!isInstallable(object))
return null;
LocalPrintOutput printer = new LocalPrintOutput(instructions);
CommandInstructions commandInstructions = new CommandInstructions(instructions);
boolean installLocal =
commandInstructions.has(Install.INSTALL_LOCAL_INSTRUCTION)
? commandInstructions.getBoolean(Install.INSTALL_LOCAL_INSTRUCTION)
: false;
boolean installOnlyIfMissing =
commandInstructions.has(Install.INSTALL_ONLY_IF_MISSING_INSTRUCTION)
? commandInstructions.getBoolean(Install.INSTALL_ONLY_IF_MISSING_INSTRUCTION)
: false;
String update =
commandInstructions.has(Install.UPDATE_INSTRUCTION)
? commandInstructions.getString(Install.UPDATE_INSTRUCTION)
: null;
long startLevelValue =
commandInstructions.has(Install.START_LEVEL_INSTRUCTION)
? commandInstructions.getLong(Install.START_LEVEL_INSTRUCTION)
: -1;
DeployedArtifact da = (DeployedArtifact) object.getObject();
InstallationResult result = null;
Installer<?> installer = null;
String artifactUpdate = update;
printer.printOutput("-> Installing artifact: [" + da.getArtifact().getCoordinates().toString() + "]");
if (installLocal) {
LocalInstaller localInstaller = artifactService.installers().local()
.artifact(da);
installer = localInstaller;
printer.printOutput("-> Installing locally");
} else {
ClusterInstaller clusterInstaller = artifactService.installers().cluster()
.artifact(da);
installer = clusterInstaller;
printer.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
printer.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);
}
if (startLevelValue > 0)
blueprintInstaller.startLevel((int) startLevelValue);
result = blueprintInstaller.start().install();
} else {
printer.printOutput("-> Unknown category: " + da.getArtifact().getCategory());
}
if (result != null) {
if (result.getResult().equals(InstallationResult.Result.FAILED)) {
if (result.getError() != null)
throw (Exception) result.getError();
throw new RuntimeException(result.getMessage());
} else {
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());
}
}
return new DefaultInstalledObject(result);
}
}

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* object-producer-core
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* object-producer-core
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* object-producer-core
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* object-producer-core
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
@ -37,55 +37,65 @@ import ru.entaxy.platform.core.producer.wrapper.AbstractFactoryWrapper;
import ru.entaxy.platform.core.producer.wrapper.AbstractFactoryWrapper.GenerationProcessor;
public class CommonObjectProducer extends DefaultProducer implements GenerationProcessor {
protected final Map<String, String> defaultFieldsPublished = new HashMap<>() {
private static final long serialVersionUID = 1L;
{
put(FIELDS.OBJECT_ID, FIELDS.OBJECT_ID);
}};
protected Map<String, String> getFieldsToPublish(String outputType, String scope, String objectType, String objectId){
return defaultFieldsPublished;
}
@Override
protected void addFields(AbstractFactoryWrapper factoryWrapper) {
super.addFields(factoryWrapper);
/*factoryWrapper.addField(
(new FieldInfoImpl())
.name(FIELDS.OBJECT_ID)
.type("String")
.required(true)
.immutable(true)
);
*/
}
@Deprecated(since = "1.10", forRemoval = true)
protected final Map<String, String> defaultFieldsPublished = new HashMap<>() {
private static final long serialVersionUID = 1L;
{
put(FIELDS.OBJECT_ID, FIELDS.OBJECT_ID);
}
};
@Deprecated(since = "1.10", forRemoval = true)
protected Map<String, String> getFieldsToPublish(String outputType, String scope, String objectType,
String objectId) {
return defaultFieldsPublished;
}
@Override
protected void addFields(AbstractFactoryWrapper factoryWrapper) {
super.addFields(factoryWrapper);
/*factoryWrapper.addField(
(new FieldInfoImpl())
.name(FIELDS.OBJECT_ID)
.type("String")
.required(true)
.immutable(true)
);
*/
}
@Override
public void postGenerate(EntaxyWrappedFactory wrappedFactory, String outputType, String scope, String objectType,
Map<String, Object> parameters,
Generated generated) throws EntaxyFactoryException {
// BEGIN : deprecated code for publishing properties
// TODO remove
String objectId = parameters.getOrDefault(FIELDS.OBJECT_ID, "").toString();
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.putIfAbsent(entry.getKey(), generated.getProperties().get(entry.getValue()));
generated.getProperties().put(FIELDS.FIELDS_TO_PUBLISH, new HashMap<String, Map<String, Object>>() {
{
put(objectId, dataToPublish);
}
});
// END : deprecated code for publishing properties
}
@Override
public void postGenerate(EntaxyWrappedFactory wrappedFactory, String outputType, String scope, String objectType, Map<String, Object> parameters,
Generated generated) throws EntaxyFactoryException {
String objectId = parameters.getOrDefault(FIELDS.OBJECT_ID, "").toString();
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()));
generated.getProperties().put(FIELDS.FIELDS_TO_PUBLISH, new HashMap<String, Map<String, Object>>() {{
put(objectId, dataToPublish);
}});
}
}

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
@ -45,142 +45,146 @@ import ru.entaxy.platform.core.producer.wrapper.DefaultFactoryWrapper;
public abstract class DefaultProducer implements EntaxyProducer {
private static final Logger log = LoggerFactory.getLogger(DefaultProducer.class);
private static final Logger log = LoggerFactory.getLogger(DefaultProducer.class);
protected Class<? extends AbstractFactoryWrapper> factoryWrapperClass = DefaultFactoryWrapper.class;
protected Map<EntaxyFactory, AbstractFactoryWrapper> factories = new HashMap<>();
protected Class<? extends AbstractFactoryWrapper> factoryWrapperClass = DefaultFactoryWrapper.class;
protected List<String> supportedTypesOrigin = new ArrayList<>();
protected List<String> supportedTypes = new ArrayList<>();
protected List<String> supportedTypesPatterns = new ArrayList<>();
protected List<EntaxyProducerListener> listeners = new ArrayList<>();
public DefaultProducer() {
if (this.getClass().isAnnotationPresent(EntaxyProducerInfo.class)) {
EntaxyProducerInfo info = this.getClass().getAnnotation(EntaxyProducerInfo.class);
setSupportedTypes(Arrays.asList(info.supportedTypes()));
this.factoryWrapperClass = info.factoryWrapperClass();
}
}
protected void setSupportedTypes(List<String> typesToSet) {
this.supportedTypesOrigin = typesToSet;
for (String s: typesToSet) {
if (EntaxyProducerUtils.isPattern(s)) {
this.supportedTypesPatterns.add(EntaxyProducerUtils.toRegexPattern(s));
} else {
this.supportedTypes.add(s);
}
}
}
@Override
public void addListener(EntaxyProducerListener listener) {
synchronized (this.listeners) {
this.listeners.remove(listener);
this.listeners.add(listener);
}
}
@Override
public void removeListener(EntaxyProducerListener listener) {
synchronized (this.listeners) {
this.listeners.remove(listener);
}
}
protected AbstractFactoryWrapper doAddFactory(EntaxyFactory factory) {
return doAddFactory(factory, factoryWrapperClass);
}
protected AbstractFactoryWrapper doAddFactory(EntaxyFactory factory, Class<? extends AbstractFactoryWrapper> wrapperClass) {
if (isTypeSupported(factory.getType())) {
try {
AbstractFactoryWrapper wrapper = createWrapper(factory, wrapperClass);
addFields(wrapper);
factories.put(factory, wrapper);
synchronized (this.listeners) {
for (EntaxyProducerListener listener: this.listeners)
listener.factoryAdded(wrapper.getId(), wrapper.getType(), this);
}
log.debug("Factory added:" + factory.getId());
return wrapper;
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException
| InvocationTargetException | NoSuchMethodException | SecurityException e) {
log.error("FactoryWrapper creation failed: ", e);
return null;
}
} else {
log.debug("Factory addition ignored: [{}:{}] for types [{}]"
, factory.getId()
, factory.getType()
, getSupportedTypes().stream().collect(Collectors.joining(",")));
return null;
}
}
protected boolean isTypeSupported(String type) {
if (this.supportedTypes.contains(type))
return true;
for (String s: supportedTypesPatterns)
if (Pattern.matches(s, type))
return true;
return false;
}
protected AbstractFactoryWrapper createWrapper(EntaxyFactory factory, Class<? extends AbstractFactoryWrapper> wrapperClass) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
return wrapperClass.getConstructor(EntaxyFactory.class).newInstance(factory);
}
protected void addFields(AbstractFactoryWrapper factoryWrapper) {
}
public void removeFactory(EntaxyFactory factory) {
if (isTypeSupported(factory.getType())) {
factories.remove(factory);
synchronized (this.listeners) {
for (EntaxyProducerListener listener: this.listeners)
listener.factoryRemoved(factory.getFactoryId(), factory.getFactoryType(), this);
}
log.debug("Factory removed:" + factory.getFactoryId());
} else {
log.debug("Factory removal ignored:" + factory.getFactoryId());
}
}
@Override
public String getProducerId() {
return this.getClass().getName();
}
protected Map<String, AbstractFactoryWrapper> factories = new HashMap<>();
@Override
public List<EntaxyFactory> getAllFactories() {
return new ArrayList<>(factories.values());
}
protected List<String> supportedTypesOrigin = new ArrayList<>();
@Override
public List<EntaxyFactory> getFactoriesForType(String factoryType) {
return factories.values().stream().filter((f)->{return f.getFactoryType().equals(factoryType);})
.collect(Collectors.toList());
}
protected List<String> supportedTypes = new ArrayList<>();
protected List<String> supportedTypesPatterns = new ArrayList<>();
@Override
public EntaxyFactory getFactoryById(String factoryId) {
for (EntaxyFactory f: factories.values())
if (f.getFactoryId().equals(factoryId))
return f;
return null;
}
protected List<EntaxyProducerListener> listeners = new ArrayList<>();
@Override
public List<String> getSupportedTypes() {
return this.supportedTypesOrigin;
}
public DefaultProducer() {
if (this.getClass().isAnnotationPresent(EntaxyProducerInfo.class)) {
EntaxyProducerInfo info = this.getClass().getAnnotation(EntaxyProducerInfo.class);
setSupportedTypes(Arrays.asList(info.supportedTypes()));
this.factoryWrapperClass = info.factoryWrapperClass();
}
}
protected void setSupportedTypes(List<String> typesToSet) {
this.supportedTypesOrigin = typesToSet;
for (String s : typesToSet) {
if (EntaxyProducerUtils.isPattern(s)) {
this.supportedTypesPatterns.add(EntaxyProducerUtils.toRegexPattern(s));
} else {
this.supportedTypes.add(s);
}
}
}
@Override
public void addListener(EntaxyProducerListener listener) {
synchronized (this.listeners) {
this.listeners.remove(listener);
this.listeners.add(listener);
}
}
@Override
public void removeListener(EntaxyProducerListener listener) {
synchronized (this.listeners) {
this.listeners.remove(listener);
}
}
protected AbstractFactoryWrapper doAddFactory(EntaxyFactory factory) {
return doAddFactory(factory, factoryWrapperClass);
}
protected AbstractFactoryWrapper doAddFactory(EntaxyFactory factory,
Class<? extends AbstractFactoryWrapper> wrapperClass) {
if (isTypeSupported(factory.getType())) {
try {
AbstractFactoryWrapper wrapper = createWrapper(factory, wrapperClass);
addFields(wrapper);
factories.put(factory.getId(), wrapper);
synchronized (this.listeners) {
for (EntaxyProducerListener listener : this.listeners)
listener.factoryAdded(wrapper.getId(), wrapper.getType(), this);
}
log.debug("Factory added:" + factory.getId());
return wrapper;
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException
| InvocationTargetException | NoSuchMethodException | SecurityException e) {
log.error("FactoryWrapper creation failed: ", e);
return null;
}
} else {
log.debug("Factory addition ignored: [{}:{}] for types [{}]", factory.getId(), factory.getType(),
getSupportedTypes().stream().collect(Collectors.joining(",")));
return null;
}
}
protected boolean isTypeSupported(String type) {
if (this.supportedTypes.contains(type))
return true;
for (String s : supportedTypesPatterns)
if (Pattern.matches(s, type))
return true;
return false;
}
protected AbstractFactoryWrapper createWrapper(EntaxyFactory factory,
Class<? extends AbstractFactoryWrapper> wrapperClass) throws InstantiationException, IllegalAccessException,
IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException {
return wrapperClass.getConstructor(EntaxyFactory.class).newInstance(factory);
}
protected void addFields(AbstractFactoryWrapper factoryWrapper) {
}
public void removeFactory(EntaxyFactory factory) {
if (isTypeSupported(factory.getType())) {
factories.remove(factory);
synchronized (this.listeners) {
for (EntaxyProducerListener listener : this.listeners)
listener.factoryRemoved(factory.getFactoryId(), factory.getFactoryType(), this);
}
log.debug("Factory removed:" + factory.getFactoryId());
} else {
log.debug("Factory removal ignored:" + factory.getFactoryId());
}
}
@Override
public String getProducerId() {
return this.getClass().getName();
}
@Override
public List<EntaxyFactory> getAllFactories() {
return new ArrayList<>(factories.values());
}
@Override
public List<EntaxyFactory> getFactoriesForType(String factoryType) {
return factories.values().stream().filter((f) -> {
return f.getFactoryType().equals(factoryType);
})
.collect(Collectors.toList());
}
@Override
public EntaxyFactory getFactoryById(String factoryId) {
for (EntaxyFactory f : factories.values())
if (f.getFactoryId().equals(factoryId))
return f;
return null;
}
@Override
public List<String> getSupportedTypes() {
return this.supportedTypesOrigin;
}
}

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* object-producer-core
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
@ -44,6 +44,10 @@ import org.slf4j.LoggerFactory;
import com.google.gson.JsonObject;
import ru.entaxy.esb.platform.runtime.base.extensions.api.EntaxyExtendable;
import ru.entaxy.esb.platform.runtime.base.extensions.api.EntaxyExtension;
import ru.entaxy.esb.platform.runtime.base.extensions.api.EntaxyExtensionsAware;
import ru.entaxy.esb.platform.runtime.base.extensions.api.Extendable;
import ru.entaxy.platform.base.objects.factory.EntaxyFactory;
import ru.entaxy.platform.base.support.JSONUtils;
import ru.entaxy.platform.core.producer.api.EntaxyProducer;
@ -63,138 +67,185 @@ import ru.entaxy.platform.core.producer.executor.commands.PrepareGenerate;
import ru.entaxy.platform.core.producer.executor.commands.Store;
import ru.entaxy.platform.core.producer.executor.commands.Validate;
@Component (service = {EntaxyProducerService.class}, immediate = true)
public class EntaxyProducerServiceImpl implements EntaxyProducerService {
@Component(service = {EntaxyProducerService.class, EntaxyExtendable.class}, immediate = true)
@Extendable("objectproducer")
public class EntaxyProducerServiceImpl implements EntaxyProducerService, EntaxyExtendable {
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";
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<>();
@Reference (bind = "addProducer", unbind = "removeProducer", cardinality = ReferenceCardinality.MULTIPLE
, collectionType = CollectionType.SERVICE, policy = ReferencePolicy.DYNAMIC, policyOption = ReferencePolicyOption.GREEDY)
public void addProducer(EntaxyProducer producer) {
producers.add(producer);
log.debug("Producer added: " + producer.getProducerId());
}
public void removeProducer(EntaxyProducer producer) {
producers.remove(producer);
log.debug("Producer removed: " + producer.getProducerId());
}
@Activate
public void activate(ComponentContext componentContext) {
registerCommand(new Analyze(this));
registerCommand(new Layout(this));
registerCommand(new Validate(this));
registerCommand(new PrepareGenerate(this));
registerCommand(new Generate(this));
registerCommand(new Build(this));
registerCommand(new Deploy(this));
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
public void registerCommand(ProducingCommandExecutor commandExecutor) {
this.commandExecutors.put(commandExecutor.getId(), commandExecutor);
}
@Override
public ProducerResult produce(String configuration) {
return this.produce(configuration, "{}");
}
protected List<EntaxyProducer> producers = new ArrayList<>();
@Override
public ProducerResult produce(String configuration, String instructions) {
return produce(JSONUtils.getJsonRootObject(configuration), instructions);
}
protected Map<String, ProducingCommandExecutor> commandExecutors = new HashMap<>();
@Override
public ProducerResult produce(JsonObject configuration) {
return produce(configuration, "{}");
}
protected Map<String, Map<String, Map<String, Object>>> lifecycleExtensions = new HashMap<>();
@Override
public ProducerResult produce(JsonObject configuration, String instructions) {
try {
return (new ProducingExecutor(configuration
, instructionsHelper.prepareInstructions(instructions)
,this))
.execute();
} catch (Exception e) {
log.error("Produce failed", e);
return ProducerResult.createFailed(e);
}
}
@Override
public List<EntaxyProducer> getAllProducers() {
return producers;
}
protected Object lifecycleExtensionsLock = new Object();
@Override
public EntaxyProducer getProducerForType(String type) {
List<EntaxyProducer> directSupport = new ArrayList<>();
List<EntaxyProducer> patternSupport = new ArrayList<>();
for (EntaxyProducer p: producers)
for (String s: p.getSupportedTypes()) {
if (EntaxyProducerUtils.isPattern(s)) {
if (EntaxyProducerUtils.isMatched(s, type))
patternSupport.add(p);
} else
if (s.equalsIgnoreCase(type))
directSupport.add(p);
}
if (!directSupport.isEmpty())
return directSupport.get(0);
if (!patternSupport.isEmpty())
return patternSupport.get(0);
return null;
}
protected final List<EntaxyExtension> entaxyExtensions = new ArrayList<>();
@Override
public List<ProducingCommandExecutor> getAvailableCommands() {
return new ArrayList<>(commandExecutors.values());
}
@Override
public ProducingCommandExecutor getCommandById(String id) {
return this.commandExecutors.get(id);
}
@Reference(bind = "addProducer", unbind = "removeProducer", cardinality = ReferenceCardinality.MULTIPLE,
collectionType = CollectionType.SERVICE, policy = ReferencePolicy.DYNAMIC,
policyOption = ReferencePolicyOption.GREEDY)
public void addProducer(EntaxyProducer producer) {
producers.add(producer);
if (producer instanceof EntaxyExtensionsAware)
((EntaxyExtensionsAware) producer).addExtensions(entaxyExtensions);
log.debug("Producer added: " + producer.getProducerId());
}
@Override
public EntaxyFactory findFactoryById(String factoryId) {
for (EntaxyProducer p: getAllProducers()) {
EntaxyFactory f = p.getFactoryById(factoryId);
if (f != null)
return f;
}
return null;
}
public void removeProducer(EntaxyProducer producer) {
producers.remove(producer);
log.debug("Producer removed: " + producer.getProducerId());
}
@Activate
public void activate(ComponentContext componentContext) {
registerCommand(new Analyze(this));
registerCommand(new Layout(this));
registerCommand(new Validate(this));
registerCommand(new PrepareGenerate(this));
registerCommand(new Generate(this));
registerCommand(new Build(this));
registerCommand(new Deploy(this));
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("Error reading lifecycles config", e);
}
}
this.instructionsHelper = new InstructionsHelper(this.lifecycles);
}
@Override
public void registerCommand(ProducingCommandExecutor commandExecutor) {
this.commandExecutors.put(commandExecutor.getId(), commandExecutor);
}
@Override
public void extendLifecycle(String lifecycle, ProducingCommandExecutor commandExecutor,
Map<String, Object> parameters) {
synchronized (lifecycleExtensionsLock) {
if (!lifecycleExtensions.containsKey(lifecycle))
lifecycleExtensions.put(lifecycle, new HashMap<String, Map<String, Object>>());
Map<String, Map<String, Object>> lifecycleExtension =
lifecycleExtensions.get(lifecycle);
lifecycleExtension.put(commandExecutor.getId(), parameters);
this.instructionsHelper.setLifecycleExtensions(lifecycleExtensions);
}
}
@Override
public ProducerResult produce(String configuration) {
return this.produce(configuration, "{}");
}
@Override
public ProducerResult produce(String configuration, String instructions) {
return produce(JSONUtils.getJsonRootObject(configuration), instructions);
}
@Override
public ProducerResult produce(JsonObject configuration) {
return produce(configuration, "{}");
}
@Override
public ProducerResult produce(JsonObject configuration, String instructions) {
try {
return (new ProducingExecutor(configuration, instructionsHelper.prepareInstructions(instructions), this))
.execute();
} catch (Exception e) {
log.error("Produce failed", e);
return ProducerResult.createFailed(e);
}
}
@Override
public List<EntaxyProducer> getAllProducers() {
return producers;
}
@Override
public EntaxyProducer getProducerForType(String type) {
List<EntaxyProducer> directSupport = new ArrayList<>();
List<EntaxyProducer> patternSupport = new ArrayList<>();
for (EntaxyProducer p : producers)
for (String s : p.getSupportedTypes()) {
if (EntaxyProducerUtils.isPattern(s)) {
if (EntaxyProducerUtils.isMatched(s, type))
patternSupport.add(p);
} else if (s.equalsIgnoreCase(type))
directSupport.add(p);
}
if (!directSupport.isEmpty())
return directSupport.get(0);
if (!patternSupport.isEmpty())
return patternSupport.get(0);
return null;
}
@Override
public List<ProducingCommandExecutor> getAvailableCommands() {
return new ArrayList<>(commandExecutors.values());
}
@Override
public ProducingCommandExecutor getCommandById(String id) {
return this.commandExecutors.get(id);
}
@Override
public EntaxyFactory findFactoryById(String factoryId) {
for (EntaxyProducer p : getAllProducers()) {
EntaxyFactory f = p.getFactoryById(factoryId);
if (f != null)
return f;
}
return null;
}
@Override
public void addExtension(EntaxyExtension entaxyExtension) {
if (!entaxyExtensions.contains(entaxyExtension)) {
entaxyExtensions.add(entaxyExtension);
producers.stream()
.filter(p -> (p instanceof EntaxyExtensionsAware))
.map(p -> (EntaxyExtensionsAware) p)
.forEach(p -> p.addExtension(entaxyExtension));
}
}
@Override
public void removeExtension(EntaxyExtension entaxyExtension) {
entaxyExtensions.remove(entaxyExtension);
producers.stream()
.filter(p -> (p instanceof EntaxyExtensionsAware))
.map(p -> (EntaxyExtensionsAware) p)
.forEach(p -> p.removeExtension(entaxyExtension));
}
@Override
public List<EntaxyExtension> getExtensions() {
return entaxyExtensions;
}
}

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* object-producer-core
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
@ -42,52 +42,72 @@ import ru.entaxy.platform.core.producer.api.EntaxyProducerService;
public class InstructionsHelper {
public static final String DEFAULT_INSTRUCTIONS = "{'validate':{}}";
public static final String LIFECYCLE_DIRECTIVE = EntaxyProducerService.DIRECTIVES.LIFECYCLE;
protected JsonObject lifecyclesOrigin;
protected Map<String, JsonObject> lifecycles = new HashMap<>();
public InstructionsHelper(JsonObject lifecycles) {
super();
this.lifecyclesOrigin = lifecycles.deepCopy();
fillMap(this.lifecyclesOrigin);
}
protected void fillMap(JsonObject origin) {
for (Entry<String, JsonElement> entry: origin.entrySet())
if (entry.getValue().isJsonObject())
this.lifecycles.put(entry.getKey(), entry.getValue().getAsJsonObject().deepCopy());
}
public String prepareInstructions(String originalInstructions) {
JsonObject origin = JSONUtils.getJsonRootObject(originalInstructions);
JsonObject result = new JsonObject();
if (origin.has(LIFECYCLE_DIRECTIVE)) {
JsonElement directiveValue = origin.get(LIFECYCLE_DIRECTIVE);
List<String> lcIdToApply = new ArrayList<>();
List<JsonObject> lcToApply = new ArrayList<>();
if (directiveValue.isJsonPrimitive())
lcIdToApply.add(directiveValue.getAsString());
if (directiveValue.isJsonArray()) {
JsonArray ja = directiveValue.getAsJsonArray();
for (int i=0; i<ja.size(); i++)
lcIdToApply.add(ja.get(i).getAsString());
}
origin.remove(LIFECYCLE_DIRECTIVE);
for (String id: lcIdToApply)
if (this.lifecycles.containsKey(id))
EntaxyFactoryUtils.processObjectOverriding(
result
, this.lifecycles.get(id)
, OVERRIDE_MODE.UPDATE);
}
EntaxyFactoryUtils.processObjectOverriding(
result
, origin
, OVERRIDE_MODE.UPDATE);
return result.toString();
}
public static final String DEFAULT_INSTRUCTIONS = "{'validate':{}}";
public static final String LIFECYCLE_DIRECTIVE = EntaxyProducerService.DIRECTIVES.LIFECYCLE;
protected JsonObject lifecyclesOrigin;
protected Map<String, JsonObject> lifecycles = new HashMap<>();
protected Map<String, JsonObject> lifecycleExtensions = new HashMap<>();
protected Object lifecycleExtensionsLock = new Object();
public InstructionsHelper(JsonObject lifecycles) {
super();
this.lifecyclesOrigin = lifecycles.deepCopy();
fillMap(this.lifecyclesOrigin);
}
protected void fillMap(JsonObject origin) {
for (Entry<String, JsonElement> entry : origin.entrySet())
if (entry.getValue().isJsonObject())
this.lifecycles.put(entry.getKey(), entry.getValue().getAsJsonObject().deepCopy());
}
public String prepareInstructions(String originalInstructions) {
JsonObject origin = JSONUtils.getJsonRootObject(originalInstructions);
JsonObject result = new JsonObject();
if (origin.has(LIFECYCLE_DIRECTIVE)) {
JsonElement directiveValue = origin.get(LIFECYCLE_DIRECTIVE);
List<String> lcIdToApply = new ArrayList<>();
List<JsonObject> lcToApply = new ArrayList<>();
if (directiveValue.isJsonPrimitive())
lcIdToApply.add(directiveValue.getAsString());
if (directiveValue.isJsonArray()) {
JsonArray ja = directiveValue.getAsJsonArray();
for (int i = 0; i < ja.size(); i++)
lcIdToApply.add(ja.get(i).getAsString());
}
origin.remove(LIFECYCLE_DIRECTIVE);
for (String id : lcIdToApply)
if (this.lifecycles.containsKey(id)) {
EntaxyFactoryUtils.processObjectOverriding(
result, this.lifecycles.get(id), OVERRIDE_MODE.UPDATE);
synchronized (lifecycleExtensionsLock) {
if (lifecycleExtensions.containsKey(id))
EntaxyFactoryUtils.processObjectOverriding(result, this.lifecycleExtensions.get(id),
OVERRIDE_MODE.UPDATE);
}
}
}
EntaxyFactoryUtils.processObjectOverriding(
result, origin, OVERRIDE_MODE.UPDATE);
return result.toString();
}
public void setLifecycleExtensions(Map<String, Map<String, Map<String, Object>>> lcExtensions) {
synchronized (lifecycleExtensionsLock) {
this.lifecycleExtensions = new HashMap<>();
for (String lc : lcExtensions.keySet()) {
Map<String, Map<String, Object>> lcContent = lcExtensions.get(lc);
JsonObject jo =
lcContent == null ? new JsonObject() : JSONUtils.GSON.toJsonTree(lcContent).getAsJsonObject();
this.lifecycleExtensions.put(lc, jo);
}
}
}
}

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* object-producer-core
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* object-producer-core
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* object-producer-core
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* object-producer-core
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* object-producer-core
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* object-producer-core
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* object-producer-core
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* object-producer-core
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
@ -44,259 +44,275 @@ import ru.entaxy.platform.base.objects.factory.EntaxyFactoryUtils;
import ru.entaxy.platform.core.producer.api.EntaxyWrappedFactory;
public class DefaultFactoryWrapper extends AbstractFactoryWrapper implements EntaxyWrappedFactory {
private static final Logger log = LoggerFactory.getLogger(DefaultFactoryWrapper.class);
public static final String ANY_OUTPUT_TYPE = "__all";
protected EntaxyFactory origin;
// outputType -> extrafields map
protected Map<String, Map<String, FieldInfo>> extraFields = new HashMap<>();
protected Map<String, List<FieldInfo>> wrappedFieldsCache = new HashMap<>();
public DefaultFactoryWrapper(EntaxyFactory origin) {
super(origin);
this.origin = origin;
}
private static final Logger log = LoggerFactory.getLogger(DefaultFactoryWrapper.class);
@Override
public void addField(String outputType, FieldInfo fieldInfo) {
if (!extraFields.containsKey(outputType))
extraFields.put(outputType, new HashMap<>());
this.extraFields.get(outputType).put(fieldInfo.getName(), fieldInfo);
clearCache();
}
public static final String ANY_OUTPUT_TYPE = "__all";
@Override
public void addField(FieldInfo fieldInfo) {
this.addField(ANY_OUTPUT_TYPE, fieldInfo);
clearCache();
}
protected void clearCache() {
synchronized (wrappedFieldsCache) {
wrappedFieldsCache.clear();
}
}
@Override
public String getId() {
return origin.getId();
}
protected EntaxyFactory origin;
@Override
public String getType() {
return origin.getType();
}
// outputType -> extrafields map
protected Map<String, Map<String, FieldInfo>> extraFields = new HashMap<>();
@Override
public String getDisplayName() {
return origin.getDisplayName();
}
@Override
public String getDescription() {
return origin.getDescription();
}
@Override
public String getCategory() {
return origin.getCategory();
}
@Override
public String getLabel() {
return origin.getLabel();
}
@Override
public List<OutputInfo> getOutputs() {
return origin.getOutputs();
}
protected Map<String, List<FieldInfo>> wrappedFieldsCache = new HashMap<>();
@Override
public OutputInfo getDefaultOutput() {
return origin.getDefaultOutput();
}
@Override
public OutputInfo getOutputByType(String outputType) {
return origin.getOutputByType(outputType);
}
public DefaultFactoryWrapper(EntaxyFactory origin) {
super(origin);
this.origin = origin;
}
@Override
public List<FieldInfo> getFields() {
return getFields(getDefaultOutput().getType());
}
@Override
public void addField(String outputType, FieldInfo fieldInfo) {
if (!extraFields.containsKey(outputType))
extraFields.put(outputType, new HashMap<>());
this.extraFields.get(outputType).put(fieldInfo.getName(), fieldInfo);
clearCache();
}
@Override
public List<FieldInfo> getFields(String outputType) {
if (!wrappedFieldsCache.containsKey(outputType))
wrapFields(outputType);
return wrappedFieldsCache.get(outputType);
}
protected void wrapFields(String outputType) {
List<FieldInfo> result = new ArrayList<>();
if (origin.getOutputByType(outputType) != null) {
@Override
public void addField(FieldInfo fieldInfo) {
this.addField(ANY_OUTPUT_TYPE, fieldInfo);
clearCache();
}
Map<String, FieldInfo> extras = new HashMap<>();
if (extraFields.containsKey(ANY_OUTPUT_TYPE))
extras.putAll(extraFields.get(ANY_OUTPUT_TYPE));
if (extraFields.containsKey(outputType))
extras.putAll(extraFields.get(outputType));
result.addAll(extras.values());
result.addAll(origin.getFields(outputType));
}
List<FieldInfo> wrappers = new LinkedList<>();
for (FieldInfo fi: result) {
if (fi.isRef())
wrappers.add(new RefFieldWrapper((RefFieldInfo)fi));
else
wrappers.add(new FieldWrapper(fi));
}
wrappedFieldsCache.put(outputType, wrappers);
}
protected Map<String, Object> wrapParameters(Map<String, Object> parameters){
Map<String, Object> result = new HashMap<>(parameters);
Map<String, Object> properties = new HashMap<>(parameters);
result.put("allProperties", properties);
return result;
}
@Override
public Generated generate(Map<String, Object> parameters) throws EntaxyFactoryException {
/* if (generationProcessor != null)
generationProcessor.preGenerate(this, null, null, getFactoryType(), parameters);
Generated g = origin.generate(wrapParameters(parameters));
if (generationProcessor != null)
generationProcessor.postGenerate(this, null, null, getFactoryType(), parameters, g);
return g;
*/
return generate(null, parameters);
}
protected void clearCache() {
synchronized (wrappedFieldsCache) {
wrappedFieldsCache.clear();
}
}
@Override
public Generated generate(String outputType, Map<String, Object> parameters) throws EntaxyFactoryException {
/* if (generationProcessor != null)
generationProcessor.preGenerate(this, outputType, null, getFactoryType(), parameters);
Generated g = origin.generate(outputType, wrapParameters(parameters));
if (generationProcessor != null)
generationProcessor.postGenerate(this, outputType, null, getFactoryType(), parameters, g);
return g;
*/
return generate(outputType, null, parameters);
}
@Override
public String getId() {
return origin.getId();
}
@Override
public Generated generate(String outputType, String scope, Map<String, Object> parameters)
throws EntaxyFactoryException {
log.debug("generate :: processor is [{}]", (generationProcessor==null?"":"NOT ")+"null");
if (generationProcessor != null)
generationProcessor.preGenerate(this, outputType, scope, getFactoryType(), parameters);
preGenerateWithPlugins(outputType, scope, parameters);
Generated g = origin.generate(outputType, scope, wrapParameters(parameters));
postGenerateWithPlugins(outputType, scope, parameters, g);
if (generationProcessor != null)
generationProcessor.postGenerate(this, outputType, scope, getFactoryType(), parameters, g);
return g;
}
@Override
public String getType() {
return origin.getType();
}
protected void preGenerateWithPlugins(String outputType, String scope, Map<String, Object> parameters) {
BundleContext bundleContext = FrameworkUtil.getBundle(this.getClass()).getBundleContext();
try {
List<ServiceReference<GenerationProcessor>> refs = /*bundleContext.getAllServiceReferences(
GenerationProcessor.class.getName()
, "(|(generation.factory.type~=*)(generation.factory.type~=" + getFactoryType() + "))");*/
GenerationProcessorService.getInstance().getProcessorsRefs(this);
log.debug("FOUND SERVICES: " + (refs==null?"0":refs.size()));
if (refs == null)
return;
for (ServiceReference<GenerationProcessor> r: refs) {
try {
GenerationProcessor processor = (GenerationProcessor)bundleContext.getService(r);
processor.preGenerate(this, outputType, scope, getFactoryType(), parameters);
} catch (Exception e) {
} finally {
try {
bundleContext.ungetService(r);
} catch (Exception e) {
log.warn("Error ungetting service", e);
}
}
}
} catch (Exception e) {
log.error("Error getting services", e);
}
}
@Override
public String getShortName() {
return origin.getShortName();
}
protected void postGenerateWithPlugins(String outputType, String scope, Map<String, Object> parameters, Generated generated) {
BundleContext bundleContext = FrameworkUtil.getBundle(this.getClass()).getBundleContext();
try {
List<ServiceReference<GenerationProcessor>> refs = /* bundleContext.getAllServiceReferences(
GenerationProcessor.class.getName()
, "(|(generation.factory.type~=*)(generation.factory.type~=" + getFactoryType() + "))"); */
GenerationProcessorService.getInstance().getProcessorsRefs(this);
log.debug("FOUND SERVICES: " + (refs==null?"0":refs.size()));
if (refs == null)
return;
for (ServiceReference<GenerationProcessor> r: refs) {
try {
GenerationProcessor processor = (GenerationProcessor)bundleContext.getService(r);
processor.postGenerate(this, outputType, scope, getFactoryType(), parameters, generated);
} catch (Exception e) {
} finally {
try {
bundleContext.ungetService(r);
} catch (Exception e) {
log.warn("Error ungetting service", e);
}
}
}
} catch (Exception e) {
log.error("Error getting services", e);
}
}
@Override
public EntaxyFactory getOrigin() {
return this.origin;
}
@Override
public Map<String, Object> getTypeInfo() {
return this.origin.getTypeInfo();
}
@Override
public String getJsonConfiguration() {
return EntaxyFactoryUtils.getEffectiveJson(this);
}
@Override
public String getDisplayName() {
return origin.getDisplayName();
}
@Override
public String getParent() {
return this.origin.getParent();
}
@Override
public boolean isAbstract() {
return this.origin.isAbstract();
}
@Override
public boolean isDeprecated() {
return this.origin.isDeprecated();
}
@Override
public String getDescription() {
return origin.getDescription();
}
@Override
public String getCategory() {
return origin.getCategory();
}
@Override
public String getLabel() {
return origin.getLabel();
}
@Override
public List<OutputInfo> getOutputs() {
return origin.getOutputs();
}
@Override
public OutputInfo getDefaultOutput() {
return origin.getDefaultOutput();
}
@Override
public OutputInfo getOutputByType(String outputType) {
return origin.getOutputByType(outputType);
}
@Override
public List<FieldInfo> getFields() {
return getFields(getDefaultOutput().getType());
}
@Override
public List<FieldInfo> getFields(String outputType) {
if (!wrappedFieldsCache.containsKey(outputType))
wrapFields(outputType);
return wrappedFieldsCache.get(outputType);
}
protected void wrapFields(String outputType) {
List<FieldInfo> result = new ArrayList<>();
if (origin.getOutputByType(outputType) != null) {
Map<String, FieldInfo> extras = new HashMap<>();
if (extraFields.containsKey(ANY_OUTPUT_TYPE))
extras.putAll(extraFields.get(ANY_OUTPUT_TYPE));
if (extraFields.containsKey(outputType))
extras.putAll(extraFields.get(outputType));
result.addAll(extras.values());
result.addAll(origin.getFields(outputType));
}
List<FieldInfo> wrappers = new LinkedList<>();
for (FieldInfo fi : result) {
if (fi.isRef())
wrappers.add(new RefFieldWrapper((RefFieldInfo) fi));
else
wrappers.add(new FieldWrapper(fi));
}
wrappedFieldsCache.put(outputType, wrappers);
}
protected Map<String, Object> wrapParameters(Map<String, Object> parameters) {
Map<String, Object> result = new HashMap<>(parameters);
Map<String, Object> properties = new HashMap<>(parameters);
result.put("allProperties", properties);
return result;
}
@Override
public Generated generate(Map<String, Object> parameters) throws EntaxyFactoryException {
/* if (generationProcessor != null)
generationProcessor.preGenerate(this, null, null, getFactoryType(), parameters);
Generated g = origin.generate(wrapParameters(parameters));
if (generationProcessor != null)
generationProcessor.postGenerate(this, null, null, getFactoryType(), parameters, g);
return g;
*/
return generate(null, parameters);
}
@Override
public Generated generate(String outputType, Map<String, Object> parameters) throws EntaxyFactoryException {
/* if (generationProcessor != null)
generationProcessor.preGenerate(this, outputType, null, getFactoryType(), parameters);
Generated g = origin.generate(outputType, wrapParameters(parameters));
if (generationProcessor != null)
generationProcessor.postGenerate(this, outputType, null, getFactoryType(), parameters, g);
return g;
*/
return generate(outputType, null, parameters);
}
@Override
public Generated generate(String outputType, String scope, Map<String, Object> parameters)
throws EntaxyFactoryException {
log.debug("generate :: processor is [{}]", (generationProcessor == null ? "" : "NOT ") + "null");
if (generationProcessor != null)
generationProcessor.preGenerate(this, outputType, scope, getFactoryType(), parameters);
preGenerateWithPlugins(outputType, scope, parameters);
Generated g = origin.generate(outputType, scope, wrapParameters(parameters));
postGenerateWithPlugins(outputType, scope, parameters, g);
if (generationProcessor != null)
generationProcessor.postGenerate(this, outputType, scope, getFactoryType(), parameters, g);
return g;
}
protected void preGenerateWithPlugins(String outputType, String scope, Map<String, Object> parameters) {
BundleContext bundleContext = FrameworkUtil.getBundle(this.getClass()).getBundleContext();
try {
List<ServiceReference<GenerationProcessor>> refs = /*bundleContext.getAllServiceReferences(
GenerationProcessor.class.getName()
, "(|(generation.factory.type~=*)(generation.factory.type~=" + getFactoryType() + "))");*/
GenerationProcessorService.getInstance().getProcessorsRefs(this);
log.debug("FOUND SERVICES: " + (refs == null ? "0" : refs.size()));
if (refs == null)
return;
for (ServiceReference<GenerationProcessor> r : refs) {
try {
GenerationProcessor processor = (GenerationProcessor) bundleContext.getService(r);
processor.preGenerate(this, outputType, scope, getFactoryType(), parameters);
} catch (Exception e) {
} finally {
try {
bundleContext.ungetService(r);
} catch (Exception e) {
log.warn("Error ungetting service", e);
}
}
}
} catch (Exception e) {
log.error("Error getting services", e);
}
}
protected void postGenerateWithPlugins(String outputType, String scope, Map<String, Object> parameters,
Generated generated) {
BundleContext bundleContext = FrameworkUtil.getBundle(this.getClass()).getBundleContext();
try {
List<ServiceReference<GenerationProcessor>> refs = /* bundleContext.getAllServiceReferences(
GenerationProcessor.class.getName()
, "(|(generation.factory.type~=*)(generation.factory.type~=" + getFactoryType() + "))"); */
GenerationProcessorService.getInstance().getProcessorsRefs(this);
log.debug("FOUND SERVICES: " + (refs == null ? "0" : refs.size()));
if (refs == null)
return;
for (ServiceReference<GenerationProcessor> r : refs) {
try {
GenerationProcessor processor = (GenerationProcessor) bundleContext.getService(r);
processor.postGenerate(this, outputType, scope, getFactoryType(), parameters, generated);
} catch (Exception e) {
} finally {
try {
bundleContext.ungetService(r);
} catch (Exception e) {
log.warn("Error ungetting service", e);
}
}
}
} catch (Exception e) {
log.error("Error getting services", e);
}
}
@Override
public EntaxyFactory getOrigin() {
return this.origin;
}
@Override
public Map<String, Object> getTypeInfo() {
return this.origin.getTypeInfo();
}
@Override
public String getJsonConfiguration() {
return EntaxyFactoryUtils.getEffectiveJson(this);
}
@Override
public String getJsonOrigin() {
return this.origin.getJsonOrigin();
}
@Override
public String getParent() {
return this.origin.getParent();
}
@Override
public boolean isAbstract() {
return this.origin.isAbstract();
}
@Override
public boolean isInternal() {
return this.origin.isInternal();
}
@Override
public boolean isDeprecated() {
return this.origin.isDeprecated();
}
}

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* object-producer-core
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* test-producers
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property

View File

@ -4,27 +4,72 @@
},
"fragment": {
"isTransparent": true
},
},
"bean": {
"targetNodeName": "##root",
"position": "inside_first",
"unique": ["id"],
"conflict": "ignore" /*[ignore, replace]*/
},
"reference": {
"targetNodeName": "##root",
"position": "inside_first",
"unique": ["id"],
"conflict": "ignore" /*[ignore, replace]*/
},
"globalOptions": {
"targetNodeName": "camelContext",
"position": "inside_first",
"conflict": "ignore" /*[ignore, replace]*/
},
"globalOption": {
"targetNodeName": "camelContext/globalOptions",
"position": "inside_last",
"createTargetNode": true,
"targetNodeXML": "<globalOptions />",
"unique": ["key"],
"conflict": "replace" /*[ignore, replace]*/
},
"propertyPlaceholder": {
"recoursive": true,
"targetNodeName": "camelContext/globalOptions",
"position": "after",
"createTargetNode": true,
"targetNodeXML": "<globalOptions><globalOption key=\"entaxyContext\" value=\"true\"/></globalOptions>",
"unique": ["id"],
"conflict": "ignore" /*[ignore, replace]*/
},
"propertiesFunction": {
"targetNodeName": "camelContext/propertyPlaceholder",
"unique": ["ref"],
"createTargetNode": true,
"targetNodeXML": "<propertyPlaceholder id=\"propertiesForCamel\" xmlns=\"http://camel.apache.org/schema/blueprint\" />"
},
"errorHandler": {
"targetNodeName": "camelContext/propertyPlaceholder",
"position": "after",
"conflict": "ignore" /*[ignore, replace]*/,
"createTargetNode": true,
"targetNodeXML": "<propertyPlaceholder id=\"propertiesForCamel\" xmlns=\"http://camel.apache.org/schema/blueprint\" />"
},
"redeliveryPolicyProfile": {
"targetNodeName": "camelContext/errorHandler",
"position": "after",
"conflict": "ignore" /*[ignore, replace]*/,
"createTargetNode": true,
"targetNodeXML": "<errorHandler />"
},
"errorHandlerRef": {
"targetNodeName": "camelContext",
"targetAttributeName": "errorHandlerRef",
"createTargetNode": true,
"targetNodeXML": "<camelContext xmlns=\"http://camel.apache.org/schema/blueprint\" />"
},
"route": {
"recoursive": true,
"targetNodeName": "camelContext",
"position": "inside_last",
"createTargetNode": true,
"targetNodeXML": "<camelContext xmlns=\"http://camel.apache.org/schema/blueprint\" />"
},
"propertyPlaceholder": {
"recoursive": true,
"targetNodeName": "camelContext",
"unique": ["id"],
"conflict": "ignore" /*[ignore, replace]*/
},
"propertiesFunction": {
"targetNodeName": "camelContext/propertyPlaceholder"
}
}
}

View File

@ -3,7 +3,7 @@
<parent>
<groupId>ru.entaxy.esb.platform.runtime.core</groupId>
<artifactId>object-producing</artifactId>
<version>1.9.0</version>
<version>1.10.0</version>
</parent>
<groupId>ru.entaxy.esb.platform.runtime.core.object-producing</groupId>
<artifactId>object-producing-config-support</artifactId>
@ -15,14 +15,33 @@
</properties>
<dependencies>
<dependency>
<groupId>org.apache.karaf.config</groupId>
<artifactId>org.apache.karaf.config.core</artifactId>
<version>${karaf.version}</version>
</dependency>
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.configadmin</artifactId>
<version>${felix.configadmin.version}</version>
</dependency>
<dependency>
<groupId>
ru.entaxy.esb.platform.runtime.core.object-producing
</groupId>
<artifactId>object-producer-core</artifactId>
<version>${project.version}</version>
<type>bundle</type>
</dependency>
<dependency>
<groupId>ru.entaxy.esb.platform.runtime.core</groupId>
<artifactId>object-runtime-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>ru.entaxy.esb.platform.runtime.core.objects-implementations.config-implementation</groupId>
<artifactId>config-runtime</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
<build>
@ -37,6 +56,7 @@
<instructions>
<Entaxy-Factory-Provider>true</Entaxy-Factory-Provider>
<Entaxy-Template-Provider>true</Entaxy-Template-Provider>
<Entaxy-Extensions-Provider>true</Entaxy-Extensions-Provider>
</instructions>
</configuration>
</plugin>

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* object-producing-config-support
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
@ -49,11 +49,13 @@ import ru.entaxy.platform.base.objects.factory.EntaxyFactory.OutputInfo;
import ru.entaxy.platform.base.objects.factory.exceptions.FactoryNotFoundException;
import ru.entaxy.platform.base.support.CommonUtils;
import ru.entaxy.platform.base.support.JSONUtils;
import ru.entaxy.platform.config.runtime.ObjectConfig;
import ru.entaxy.platform.config.runtime.ObjectConfigHelper;
import ru.entaxy.platform.config.runtime.ObjectConfig.FactoryOutputConfiguration;
import ru.entaxy.platform.core.producer.api.EntaxyProducerService;
import ru.entaxy.platform.core.producer.api.ExecutionPlan.ExecutionPlanUpdate;
import ru.entaxy.platform.core.producer.api.ProducerResult;
import ru.entaxy.platform.core.producer.api.ProducerResult.CommandResult;
import ru.entaxy.platform.core.producer.config.ObjectConfig.FactoryOutputConfiguration;
import ru.entaxy.platform.core.producer.api.ProducingCommandExecutor;
import ru.entaxy.platform.core.producer.executor.AbstractCommandExecutor;
import ru.entaxy.platform.core.producer.executor.CommandExecutor;
@ -66,223 +68,251 @@ import ru.entaxy.platform.core.producer.executor.objectmodel.ObjectModel;
@CommandExecutor(id = "add-config", predecessors = {"enrich"}, descendants = {"validate"})
public class AddConfigCommand extends AbstractCommandExecutor implements ProducingCommandExecutor {
private static final Logger log = LoggerFactory.getLogger(AddConfigCommand.class);
@Reference(cardinality = ReferenceCardinality.MANDATORY)
EntaxyProducerService entaxyProducerServiceLocal;
public AddConfigCommand() {
super(null);
}
protected AddConfigCommand(EntaxyProducerService entaxyProducerService) {
super(entaxyProducerService);
}
private static final Logger log = LoggerFactory.getLogger(AddConfigCommand.class);
@Activate
public void activate(ComponentContext componentContext) {
this.entaxyProducerService = this.entaxyProducerServiceLocal;
this.entaxyProducerService.registerCommand(this);
}
@Override
protected boolean doExecute(ProducerResult currentResult, CommandResult commandResult,
Map<String, Object> instructions) throws Exception {
@Reference(cardinality = ReferenceCardinality.MANDATORY)
EntaxyProducerService entaxyProducerServiceLocal;
printOutput("\n\n\t== ADD-CONFIG == \n\n");
ObjectModel objectModel = currentResult.findResultObject(ObjectModel.class);
objectModel.startTracking();
JsonObject incomingJson = objectModel.getJsonCurrent().deepCopy();
for (FactoredObject fo: objectModel.objects) {
// skip proxies
if (fo instanceof FactoredObjectProxy)
continue;
log.debug("OBJECT :: {}/{}", fo.getObjectId(), fo.getObjectType());
String factoryId = fo.factoryId;
EntaxyFactory factory = entaxyProducerService.findFactoryById(factoryId);
if (factory == null)
throw new FactoryNotFoundException(factoryId);
public AddConfigCommand() {
super(null);
}
String output = fo.getOutputType();
log.debug("OUTPUT :: {}", output);
OutputInfo oi = CommonUtils.isValid(output)?factory.getOutputByType(output):factory.getDefaultOutput();
Map<String, Object> config = oi.getConfig();
if ((config == null) || (config.isEmpty()))
continue;
String val = config.getOrDefault(ObjectConfig.CONFIGURABLE_ATTRIBUTE_NAME, "false").toString();
Boolean configurable = Boolean.valueOf(val);
if (!configurable)
continue;
JsonObject objectOrigin = fo.origin;
JsonObject objectProperties = objectOrigin.get(FIELDS.PROPERTIES).getAsJsonObject();
if (objectProperties.has(ObjectConfig.CONFIG_FIELD_NAME))
continue;
@SuppressWarnings("serial")
Generated g = this.entaxyProducerService.findFactoryById("common-config")
.generate("config-field"
, "private", new HashMap<String, Object>(){{
put(FIELDS.FACTORY_ID, "common-config");
put(ObjectConfig.TARGET_FACTORY_FIELD_NAME, fo.factoryId);
put(ObjectConfig.TARGET_TYPE_FIELD_NAME, fo.getObjectType());
put(ObjectConfig.TARGET_ID_FIELD_NAME, fo.getObjectId());
put(ObjectConfig.TARGET_OUTPUT_FIELD_NAME, fo.getOutputType());
}});
objectProperties.add(ObjectConfig.CONFIG_FIELD_NAME, JSONUtils.getJsonRootObject(g.getObject().toString()));
objectModel.setDirty();
}
for (FactoredObjectRef ref: objectModel.refs) {
// process external refs and replace ref to object with ref to config if
// - ref is not marked 'directValueOnly'
// - the referenced object has config
// - the referenced field is configurable
// if (!ref.isExternal())
// continue;
protected AddConfigCommand(EntaxyProducerService entaxyProducerService) {
super(entaxyProducerService);
}
log.debug("REF :: " + ref.relativePath);
if (ObjectConfigHelper.getInstance().isDirectValueOnly(ref))
continue;
String objectId = ref.getTargetId();
String objectType = ref.getTargetType();
@Activate
public void activate(ComponentContext componentContext) {
this.entaxyProducerService = this.entaxyProducerServiceLocal;
this.entaxyProducerService.registerCommand(this);
}
log.debug("TO :: " + objectId + ":" + objectType);
log.debug("DEFINED IN :: " + ref.definedIn.getObjectId());
String refField = ref.getOrDefault(FIELDS.REF_FIELD, FIELDS.OBJECT_ID).toString();
if (FIELDS.OBJECT_ID.equals(refField))
// objectId can't be configured
continue;
// skip if it's already config
if (ObjectConfig.CONFIG_OBJECT_TYPE.equals(objectType))
continue;
@Override
protected boolean doExecute(ProducerResult currentResult, CommandResult commandResult,
Map<String, Object> instructions) throws Exception {
String configurationPid = ObjectConfig.getConfigurationPid(objectId, objectType);
String factoryId = null;
printOutput("\n\n\t== ADD-CONFIG == \n\n");
JsonElement newTargetId = null;
if (ref.isExternal()) {
EntaxyObject theObject = ObjectConfigHelper.getInstance().findObject(objectId, objectType);
if (theObject == null)
// referenced object not found
continue;
factoryId = theObject.getFactoryId();
EntaxyObject configObject = ObjectConfigHelper.getInstance()
.findObject(configurationPid, ObjectConfig.CONFIG_OBJECT_TYPE);
if (configObject == null)
// config for referenced object not found
continue;
newTargetId = new JsonPrimitive(configurationPid);
} else {
ObjectModel objectModel = currentResult.findResultObject(ObjectModel.class);
objectModel.startTracking();
log.debug("EXTERNAL :: false");
Optional<FactoredObject> theObjectOpt = objectModel.objects.stream()
.filter(obj -> objectId.equals(obj.getObjectId())).findFirst();
if (!theObjectOpt.isPresent())
continue;
FactoredObject theObject = theObjectOpt.get();
JsonObject incomingJson = objectModel.getJsonCurrent().deepCopy();
log.debug("TARGET OBJECT :: found");
factoryId = theObject.factoryId;
Optional<FactoredObjectRef> configRefOpt = objectModel.refs.stream()
.filter(r -> r.definedIn.equals(theObject))
.filter(r -> r.relativePath.endsWith(ObjectConfig.CONFIG_FIELD_NAME))
.findFirst();
if (!configRefOpt.isPresent())
continue;
for (FactoredObject fo : objectModel.objects) {
log.debug("REF TO CONFIG :: found; TARGET :: " + configRefOpt.get().getTargetId());
Optional<FactoredObject> configObjectOpt = objectModel.objects.stream()
.filter(obj -> obj.getObjectId().equals(configRefOpt.get().getTargetId()))
.findFirst();
if (!configObjectOpt.isPresent())
continue;
// skip proxies
if (fo instanceof FactoredObjectProxy)
continue;
log.debug("CONFIG OBJECT :: found");
newTargetId = new JsonPrimitive(configObjectOpt.get().getObjectId());
}
log.debug("OBJECT :: {}/{}", fo.getObjectId(), fo.getObjectType());
EntaxyFactory entaxyFactory = entaxyProducerService.findFactoryById(factoryId);
if (entaxyFactory == null)
// factory for referenced object not found
continue;
FactoryOutputConfiguration conf = FactoryOutputConfiguration.read(entaxyFactory, EntaxyFactory.CONFIGURATION.OUTPUTS.OUTPUT_TYPE_INIT);
if (!conf.isConfigurable)
continue;
String factoryId = fo.factoryId;
if (!ObjectConfig.isConfigurable(entaxyFactory
, EntaxyFactory.CONFIGURATION.OUTPUTS.OUTPUT_TYPE_INIT, refField
, conf.defaultFieldsConfigurable, conf.configurations))
// field is not configurable
continue;
JSONUtils.replaceValue(ref.origin, FIELDS.OBJECT_TYPE, new JsonPrimitive(ObjectConfig.CONFIG_OBJECT_TYPE));
JSONUtils.replaceValue(ref.origin, FactoredObjectRef.TARGET_TYPE_FIELD, new JsonPrimitive(ObjectConfig.CONFIG_OBJECT_TYPE));
JSONUtils.replaceValue(ref.origin, FactoredObjectRef.TARGET_ID_FIELD, newTargetId);
EntaxyFactory factory = entaxyProducerService.findFactoryById(factoryId);
if (factory == null)
throw new FactoryNotFoundException(factoryId);
// and we must generate ref to config to merge to main object
JSONUtils.replaceValue(ref.origin, FIELDS.IS_REF_BY_VALUE_ONLY, new JsonPrimitive(false));
objectModel.setDirty();
String output = fo.getOutputType();
log.debug("OUTPUT :: {}", output);
}
if (objectModel.stopTracking()) {
OutputInfo oi = CommonUtils.isValid(output) ? factory.getOutputByType(output) : factory.getDefaultOutput();
Map<String, Object> config = oi.getConfig();
if ((config == null) || (config.isEmpty()))
continue;
// remove ##embedded
for (FactoredObject fo: objectModel.objects)
fo.origin.remove(FactoredObject.EMBEDDED_FIELD);
String val = config.getOrDefault(ObjectConfig.CONFIGURABLE_ATTRIBUTE_NAME, "false").toString();
Boolean configurable = Boolean.valueOf(val);
if (!configurable)
continue;
commandResult.planUpdate = ExecutionPlanUpdate.create()
// .updateInstructions().target("enrich").value("skip", true).complete()
.reset().target("analyze").complete();
}
JsonObject outgoingJson = objectModel.getJsonCurrent();
printOutput("\n== INCOMING JSON ==\n");
printOutput(incomingJson.toString());
printOutput("\n== OUTGOING JSON ==\n");
printOutput(outgoingJson.toString());
commandResult.resultObject(outgoingJson);
JsonObject objectOrigin = fo.origin;
JsonObject objectProperties = objectOrigin.get(FIELDS.PROPERTIES).getAsJsonObject();
return true;
}
if (objectProperties.has(ObjectConfig.CONFIG_FIELD_NAME))
continue;
// add config defaults
@SuppressWarnings("serial")
Generated g = this.entaxyProducerService.findFactoryById("object-config")
.generate("config-defaults-field", "private", new HashMap<String, Object>() {
{
put(FIELDS.FACTORY_ID, "object-config");
put(FIELDS.OBJECT_ID, fo.getObjectId() + "-config");
put(ObjectConfig.CONFIG_PID_FIELD_NAME,
ObjectConfig.getConfigurationPid(fo.getObjectId(), fo.getObjectType()));
put(ObjectConfig.TARGET_FACTORY_FIELD_NAME, fo.factoryId);
put(ObjectConfig.TARGET_TYPE_FIELD_NAME, fo.getObjectType());
put(ObjectConfig.TARGET_ID_FIELD_NAME, fo.getObjectId());
put(ObjectConfig.TARGET_OUTPUT_FIELD_NAME, fo.getOutputType());
}
});
objectProperties.add(ObjectConfig.CONFIG_DEFAULTS_FIELD_NAME,
JSONUtils.getJsonRootObject(g.getObject().toString()));
objectModel.setDirty();
// add config link
@SuppressWarnings("serial")
Generated g1 = this.entaxyProducerService.findFactoryById("object-config")
.generate("config-link-field", "private", new HashMap<String, Object>() {
{
put(FIELDS.FACTORY_ID, "object-config");
put(FIELDS.OBJECT_ID,
ObjectConfig.getConfigurationPid(fo.getObjectId(), fo.getObjectType()));
put(ObjectConfig.CONFIG_PID_FIELD_NAME,
ObjectConfig.getConfigurationPid(fo.getObjectId(), fo.getObjectType()));
put(ObjectConfig.TARGET_FACTORY_FIELD_NAME, fo.factoryId);
put(ObjectConfig.TARGET_TYPE_FIELD_NAME, fo.getObjectType());
put(ObjectConfig.TARGET_ID_FIELD_NAME, fo.getObjectId());
put(ObjectConfig.TARGET_OUTPUT_FIELD_NAME, fo.getOutputType());
}
});
objectProperties.add(ObjectConfig.CONFIG_LINK_FIELD_NAME,
JSONUtils.getJsonRootObject(g1.getObject().toString()));
objectModel.setDirty();
}
for (FactoredObjectRef ref : objectModel.refs) {
// process external refs and replace ref to object with ref to config if
// - ref is not marked 'directValueOnly'
// - the referenced object has config
// - the referenced field is configurable
// if (!ref.isExternal())
// continue;
log.debug("REF :: " + ref.relativePath);
if (ObjectConfigHelper.getInstance().isDirectValueOnly(ref))
continue;
String objectId = ref.getTargetId();
String objectType = ref.getTargetType();
log.debug("TO :: " + objectId + ":" + objectType);
log.debug("DEFINED IN :: " + ref.definedIn.getObjectId());
String refField = ref.getOrDefault(FIELDS.REF_FIELD, FIELDS.OBJECT_ID).toString();
if (FIELDS.OBJECT_ID.equals(refField))
// objectId can't be configured
continue;
// skip if it's already config
if (ObjectConfig.CONFIG_OBJECT_TYPE.equals(objectType))
continue;
String configurationPid = ObjectConfig.getConfigurationPid(objectId, objectType);
String factoryId = null;
JsonElement newTargetId = null;
if (ref.isExternal()) {
EntaxyObject theObject = ObjectConfigHelper.getInstance().findObject(objectId, objectType);
if (theObject == null)
// referenced object not found
continue;
factoryId = theObject.getFactoryId();
EntaxyObject configObject = ObjectConfigHelper.getInstance()
.findObject(configurationPid, ObjectConfig.CONFIG_OBJECT_TYPE);
if (configObject == null)
// config for referenced object not found
continue;
newTargetId = new JsonPrimitive(configurationPid);
} else {
log.debug("EXTERNAL :: false");
Optional<FactoredObject> theObjectOpt = objectModel.objects.stream()
.filter(obj -> objectId.equals(obj.getObjectId())).findFirst();
if (!theObjectOpt.isPresent())
continue;
FactoredObject theObject = theObjectOpt.get();
log.debug("TARGET OBJECT :: found");
factoryId = theObject.factoryId;
Optional<FactoredObjectRef> configRefOpt = objectModel.refs.stream()
.filter(r -> r.definedIn.equals(theObject))
.filter(r -> r.relativePath.endsWith(ObjectConfig.CONFIG_FIELD_NAME))
.findFirst();
if (!configRefOpt.isPresent())
continue;
log.debug("REF TO CONFIG :: found; TARGET :: " + configRefOpt.get().getTargetId());
Optional<FactoredObject> configObjectOpt = objectModel.objects.stream()
.filter(obj -> obj.getObjectId().equals(configRefOpt.get().getTargetId()))
.findFirst();
if (!configObjectOpt.isPresent())
continue;
log.debug("CONFIG OBJECT :: found");
newTargetId = new JsonPrimitive(configObjectOpt.get().getObjectId());
}
EntaxyFactory entaxyFactory = entaxyProducerService.findFactoryById(factoryId);
if (entaxyFactory == null)
// factory for referenced object not found
continue;
FactoryOutputConfiguration conf = FactoryOutputConfiguration.read(entaxyFactory,
EntaxyFactory.CONFIGURATION.OUTPUTS.OUTPUT_TYPE_INIT);
if (!conf.isConfigurable)
continue;
if (!ObjectConfig.isConfigurable(entaxyFactory, EntaxyFactory.CONFIGURATION.OUTPUTS.OUTPUT_TYPE_INIT,
refField, conf.defaultFieldsConfigurable, conf.configurations))
// field is not configurable
continue;
JSONUtils.replaceValue(ref.origin, FIELDS.OBJECT_TYPE, new JsonPrimitive(ObjectConfig.CONFIG_OBJECT_TYPE));
JSONUtils.replaceValue(ref.origin, FactoredObjectRef.TARGET_TYPE_FIELD,
new JsonPrimitive(ObjectConfig.CONFIG_OBJECT_TYPE));
JSONUtils.replaceValue(ref.origin, FactoredObjectRef.TARGET_ID_FIELD, newTargetId);
// and we must generate ref to config to merge to main object
JSONUtils.replaceValue(ref.origin, FIELDS.IS_REF_BY_VALUE_ONLY, new JsonPrimitive(false));
objectModel.setDirty();
}
if (objectModel.stopTracking()) {
// remove ##embedded
for (FactoredObject fo : objectModel.objects)
fo.origin.remove(FactoredObject.EMBEDDED_FIELD);
commandResult.planUpdate = ExecutionPlanUpdate.create()
// .updateInstructions().target("enrich").value("skip", true).complete()
.reset().target("analyze").complete();
}
JsonObject outgoingJson = objectModel.getJsonCurrent();
printOutput("\n== INCOMING JSON ==\n");
printOutput(incomingJson.toString());
printOutput("\n== OUTGOING JSON ==\n");
printOutput(outgoingJson.toString());
commandResult.resultObject(outgoingJson);
return true;
}
}

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* object-producing-config-support
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
@ -32,6 +32,7 @@ import com.google.gson.JsonObject;
import ru.entaxy.platform.base.objects.EntaxyObject;
import ru.entaxy.platform.base.objects.EntaxyObject.FIELDS;
import ru.entaxy.platform.config.runtime.ObjectConfig;
import ru.entaxy.platform.core.producer.executor.generationmodel.DefaultObjectDataResolver;
import ru.entaxy.platform.core.producer.executor.generationmodel.ObjectDataResolver;

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* object-producing-config-support
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
@ -25,8 +25,6 @@
*/
package ru.entaxy.platform.core.producer.config;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.osgi.service.component.annotations.Component;
@ -35,35 +33,32 @@ import org.slf4j.LoggerFactory;
import ru.entaxy.esb.platform.runtime.base.connecting.generator.Generated;
import ru.entaxy.platform.base.objects.EntaxyObject;
import ru.entaxy.platform.base.objects.factory.EntaxyFactory.OutputInfo;
import ru.entaxy.platform.base.objects.factory.EntaxyFactoryException;
import ru.entaxy.platform.config.runtime.ObjectConfig;
import ru.entaxy.platform.config.runtime.ObjectConfig.FactoryOutputConfiguration;
import ru.entaxy.platform.core.producer.api.EntaxyWrappedFactory;
import ru.entaxy.platform.core.producer.config.ObjectConfig.FactoryOutputConfiguration;
import ru.entaxy.platform.core.producer.wrapper.AbstractFactoryWrapper.GenerationProcessor;
@Component (service = GenerationProcessor.class
, property = {
"generation.plugin.id=config-support"
, "generation.factory.type=entaxy.runtime.connection"
, "generation.factory.type=entaxy.runtime.profile"
}
, immediate = true)
@Component(service = GenerationProcessor.class, property = {
"generation.plugin.id=config-support", "generation.factory.type=entaxy.runtime.*",
"generation.factory.type=!entaxy.runtime.config"
}, immediate = true)
public class ConfigProcessor implements GenerationProcessor {
private static final Logger log = LoggerFactory.getLogger(ConfigProcessor.class);
@Override
public void preGenerate(EntaxyWrappedFactory wrappedFactory, String outputType, String scope, String objectType,
Map<String, Object> parameters) throws EntaxyFactoryException {
if (!parameters.containsKey(EntaxyObject.FIELDS.PROPERTIES))
return;
private static final Logger log = LoggerFactory.getLogger(ConfigProcessor.class);
@SuppressWarnings("unchecked")
Map<String, Object> properties = (Map<String, Object>)parameters.get(EntaxyObject.FIELDS.PROPERTIES);
@Override
public void preGenerate(EntaxyWrappedFactory wrappedFactory, String outputType, String scope, String objectType,
Map<String, Object> parameters) throws EntaxyFactoryException {
if (!properties.containsKey(ObjectConfig.CONFIG_FIELD_NAME))
return;
if (!parameters.containsKey(EntaxyObject.FIELDS.PROPERTIES))
return;
@SuppressWarnings("unchecked")
Map<String, Object> properties = (Map<String, Object>) parameters.get(EntaxyObject.FIELDS.PROPERTIES);
if (!properties.containsKey(ObjectConfig.CONFIG_FIELD_NAME))
return;
/*
OutputInfo oi = wrappedFactory.getOutputByType(outputType);
if (oi == null)
@ -115,39 +110,40 @@ public class ConfigProcessor implements GenerationProcessor {
} else {
fieldsConfiguration.add(new ObjectConfig.ConfigurableFieldsConfiguration());
}
*/
FactoryOutputConfiguration conf = FactoryOutputConfiguration.read(wrappedFactory, outputType);
if (!conf.isConfigurable)
return;
ObjectConfig.backupProperties(parameters);
String objectId = parameters.get(EntaxyObject.FIELDS.OBJECT_ID).toString();
for (Map.Entry<String, Object> entry: properties.entrySet()) {
if (entry.getKey().startsWith("#"))
continue;
if (!ObjectConfig.isConfigurable(wrappedFactory, outputType, entry.getKey()
, conf.defaultFieldsConfigurable, conf.configurations))
continue;
properties.put(entry.getKey(), ObjectConfig.getConfigurationPrefix(objectId, objectType) + entry.getKey() + "}");
}
ObjectConfig.removeConfigData(parameters);
log.debug("preGenerate for {}:{}", wrappedFactory.getId(), wrappedFactory.getType());
}
@Override
public void postGenerate(EntaxyWrappedFactory wrappedFactory, String outputType, String scope, String objectType,
Map<String, Object> parameters, Generated generated) throws EntaxyFactoryException {
log.debug("postGenerate for {}:{}", wrappedFactory.getFactoryId(), wrappedFactory.getFactoryType());
// restore initial properties
ObjectConfig.restoreBackupProperties(parameters);
}
*/
FactoryOutputConfiguration conf = FactoryOutputConfiguration.read(wrappedFactory, outputType);
if (!conf.isConfigurable)
return;
ObjectConfig.backupProperties(parameters);
String objectId = parameters.get(EntaxyObject.FIELDS.OBJECT_ID).toString();
for (Map.Entry<String, Object> entry : properties.entrySet()) {
if (entry.getKey().startsWith("#"))
continue;
if (!ObjectConfig.isConfigurable(wrappedFactory, outputType, entry.getKey(), conf.defaultFieldsConfigurable,
conf.configurations))
continue;
properties.put(entry.getKey(),
ObjectConfig.getConfigurationPrefix(objectId, objectType) + entry.getKey() + "}");
}
ObjectConfig.removeConfigData(parameters);
log.debug("preGenerate for {}:{}", wrappedFactory.getId(), wrappedFactory.getType());
}
@Override
public void postGenerate(EntaxyWrappedFactory wrappedFactory, String outputType, String scope, String objectType,
Map<String, Object> parameters, Generated generated) throws EntaxyFactoryException {
log.debug("postGenerate for {}:{}", wrappedFactory.getFactoryId(), wrappedFactory.getFactoryType());
// restore initial properties
ObjectConfig.restoreBackupProperties(parameters);
}
}

View File

@ -2,7 +2,7 @@
* ~~~~~~licensing~~~~~~
* object-producing-config-support
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* Copyright (C) 2020 - 2024 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
@ -40,11 +40,16 @@ import org.osgi.service.component.annotations.ReferencePolicyOption;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import ru.entaxy.esb.platform.runtime.base.connecting.generator.Generated;
import ru.entaxy.platform.base.objects.EntaxyObject;
import ru.entaxy.platform.base.objects.factory.EntaxyFactory;
import ru.entaxy.platform.base.objects.factory.EntaxyFactoryException;
import ru.entaxy.platform.base.support.CommonUtils;
import ru.entaxy.platform.base.support.JSONUtils;
import ru.entaxy.platform.config.runtime.ObjectConfig;
import ru.entaxy.platform.core.producer.api.EntaxyProducer;
import ru.entaxy.platform.core.producer.api.EntaxyProducerService;
import ru.entaxy.platform.core.producer.api.EntaxyWrappedFactory;
@ -54,139 +59,175 @@ import ru.entaxy.platform.core.producer.impl.EntaxyProducerInfo;
import ru.entaxy.platform.core.producer.wrapper.AbstractFactoryWrapper;
@Component(service = EntaxyProducer.class, immediate = true)
@EntaxyProducerInfo (supportedTypes = {ObjectConfig.CONFIG_OBJECT_TYPE})
@EntaxyProducerInfo(supportedTypes = {ObjectConfig.CONFIG_OBJECT_TYPE})
public class ConfigProducer extends CommonObjectProducer implements EntaxyProducer {
private static final Logger log = LoggerFactory.getLogger(ConfigProducer.class);
@Reference(cardinality = ReferenceCardinality.MANDATORY)
EntaxyProducerService entaxyProducerService;
@Reference(bind = "addFactory", unbind = "removeFactory", cardinality = ReferenceCardinality.MULTIPLE
, collectionType = CollectionType.SERVICE, policy = ReferencePolicy.DYNAMIC, policyOption = ReferencePolicyOption.GREEDY)
public void addFactory(EntaxyFactory factory) {
AbstractFactoryWrapper wrapper = super.doAddFactory(factory);
if (wrapper != null)
wrapper.setGenerationProcessor(this);
}
// WE MUST DECLARE IT for @Reference annotation processor
@Override
public void removeFactory(EntaxyFactory factory) {
super.removeFactory(factory);
}
@Override
public void preGenerate(EntaxyWrappedFactory wrappedFactory, String outputType, String scope, String objectType,
Map<String, Object> parameters) throws EntaxyFactoryException {
super.preGenerate(wrappedFactory, outputType, scope, objectType, parameters);
@SuppressWarnings("unchecked")
Map<String, Object> properties = (Map<String, Object>)parameters.get(EntaxyObject.FIELDS.PROPERTIES);
private static final Logger log = LoggerFactory.getLogger(ConfigProducer.class);
// System.out.println("\n\n\tCONFIG PRODUCER :: preGenerate");
// System.out.println("\t" + parameters.toString());
// properties can be null for 'config-field' output
if (properties != null) {
/* System.out.println("\n\n\tGENERATE CONFIG: "
+ "\noutput: " + outputType
+ "\nscope: " + scope
+ "\nproperties: " + properties.toString()); */
ObjectConfig.backupProperties(parameters, ObjectConfig.CONFIG_PROPERTIES_FIELD_NAME);
ObjectConfig.removeConfigData(parameters, ObjectConfig.CONFIG_PROPERTIES_FIELD_NAME);
Map<String, Object> configurables = new HashMap<>();
Map<String, Object> immutables = new HashMap<>();
String targetFactoryId = properties.get(ObjectConfig.CONFIG_FACTORY_FIELD_NAME).toString();
String targetOutput = properties.get(ObjectConfig.CONFIG_OUTPUT_FIELD_NAME).toString();
EntaxyFactory f = entaxyProducerService.findFactoryById(targetFactoryId);
if (!CommonUtils.isValid(targetOutput))
targetOutput = f.getDefaultOutput().getType();
fillConfigMaps(f, targetOutput, scope, objectType, parameters, configurables, immutables);
parameters.put(ObjectConfig.CONFIGURABLES_FIELD_NAME, configurables);
parameters.put(ObjectConfig.IMMUTABLES_FIELD_NAME, immutables);
String configuredId = parameters.get(ObjectConfig.CONFIG_ID_FIELD_NAME).toString();
String configuredType = parameters.get(ObjectConfig.CONFIG_TYPE_FIELD_NAME).toString();
String configurationPid = ObjectConfig.getConfigurationPid(configuredId, configuredType);
String placeholderPrefix = ObjectConfig.getConfigurationPrefix(configuredId, configuredType);
// set objectId to configurationPid
parameters.put(EntaxyObject.FIELDS.OBJECT_ID, configurationPid);
parameters.put(ObjectConfig.CONFIG_PID_FIELD_NAME, configurationPid);
parameters.put(ObjectConfig.CONFIG_PLACEHOLDER_PREFIX_FIELD_NAME, placeholderPrefix);
protected static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
}
}
@Override
public void postGenerate(EntaxyWrappedFactory wrappedFactory, String outputType, String scope, String objectType,
Map<String, Object> parameters, Generated generated) throws EntaxyFactoryException {
super.postGenerate(wrappedFactory, outputType, scope, objectType, parameters, generated);
ObjectConfig.restoreBackupProperties(parameters, ObjectConfig.CONFIG_PROPERTIES_FIELD_NAME);
protected static final String DIRECTIVE_FILL_CONFIGURABLES = "@FILL_CONFIGURABLES";
@SuppressWarnings("unchecked")
Map<String, Object> properties = (Map<String, Object>)parameters.get(EntaxyObject.FIELDS.PROPERTIES);
@Reference(cardinality = ReferenceCardinality.MANDATORY)
EntaxyProducerService entaxyProducerService;
// properties can be null for 'config-field' output
if (properties != null) {
@Reference(bind = "addFactory", unbind = "removeFactory", cardinality = ReferenceCardinality.MULTIPLE,
collectionType = CollectionType.SERVICE, policy = ReferencePolicy.DYNAMIC,
policyOption = ReferencePolicyOption.GREEDY)
public void addFactory(EntaxyFactory factory) {
AbstractFactoryWrapper wrapper = super.doAddFactory(factory);
if (wrapper != null)
wrapper.setGenerationProcessor(this);
}
// WE MUST DECLARE IT for @Reference annotation processor
@Override
public void removeFactory(EntaxyFactory factory) {
super.removeFactory(factory);
}
@Override
public void preGenerate(EntaxyWrappedFactory wrappedFactory, String outputType, String scope, String objectType,
Map<String, Object> parameters) throws EntaxyFactoryException {
super.preGenerate(wrappedFactory, outputType, scope, objectType, parameters);
@SuppressWarnings("unchecked")
Map<String, Object> properties = (Map<String, Object>) parameters.get(EntaxyObject.FIELDS.PROPERTIES);
// System.out.println("\n\n\tCONFIG PRODUCER :: preGenerate");
// System.out.println("\t" + parameters.toString());
// properties can be null for 'config-field' output
if (properties != null) {
/* System.out.println("\n\n\tGENERATE CONFIG: "
+ "\noutput: " + outputType
+ "\nscope: " + scope
+ "\nproperties: " + properties.toString()); */
ObjectConfig.backupProperties(parameters, ObjectConfig.CONFIG_PROPERTIES_FIELD_NAME);
ObjectConfig.removeConfigData(parameters, ObjectConfig.CONFIG_PROPERTIES_FIELD_NAME);
Map resultMap = properties;
if (parameters.containsKey(DIRECTIVE_FILL_CONFIGURABLES)) {
String targetConfigurables = parameters
.getOrDefault(DIRECTIVE_FILL_CONFIGURABLES, ObjectConfig.CONFIGURABLES_FIELD_NAME).toString();
if (!CommonUtils.isValid(targetConfigurables))
targetConfigurables = ObjectConfig.CONFIGURABLES_FIELD_NAME;
Map<String, Object> configurables = new HashMap<>();
Map<String, Object> immutables = new HashMap<>();
String targetFactoryId = properties.get(ObjectConfig.CONFIG_FACTORY_FIELD_NAME).toString();
String targetOutput = properties.get(ObjectConfig.CONFIG_OUTPUT_FIELD_NAME).toString();
EntaxyFactory f = entaxyProducerService.findFactoryById(targetFactoryId);
if (!CommonUtils.isValid(targetOutput))
targetOutput = f.getDefaultOutput().getType();
fillConfigMaps(f, targetOutput, scope, objectType, parameters, configurables, immutables);
resultMap = configurables;
if (parameters.containsKey(targetConfigurables)) {
Object value = parameters.get(targetConfigurables);
if (value instanceof Map) {
((Map) value).putAll(configurables);
resultMap = (Map) value;
} else {
parameters.put(targetConfigurables, configurables);
}
} else {
parameters.put(targetConfigurables, configurables);
}
parameters.put(ObjectConfig.IMMUTABLES_FIELD_NAME, immutables);
}
parameters.put(ObjectConfig.CONFIGURABLES_FIELD_NAME + "_json",
JSONUtils.GSON.toJsonTree(resultMap).toString());
String configuredId = parameters.get(ObjectConfig.CONFIG_ID_FIELD_NAME).toString();
String configuredType = parameters.get(ObjectConfig.CONFIG_TYPE_FIELD_NAME).toString();
String configurationPid = ObjectConfig.getConfigurationPid(configuredId, configuredType);
String placeholderPrefix = ObjectConfig.getConfigurationPrefix(configuredId, configuredType);
// set objectId to configurationPid
// if not set before
if (!parameters.containsKey(EntaxyObject.FIELDS.OBJECT_ID))
parameters.put(EntaxyObject.FIELDS.OBJECT_ID, configurationPid);
parameters.put(ObjectConfig.CONFIG_PID_FIELD_NAME, configurationPid);
parameters.put(ObjectConfig.CONFIG_PLACEHOLDER_PREFIX_FIELD_NAME, placeholderPrefix);
}
}
@Override
public void postGenerate(EntaxyWrappedFactory wrappedFactory, String outputType, String scope, String objectType,
Map<String, Object> parameters, Generated generated) throws EntaxyFactoryException {
super.postGenerate(wrappedFactory, outputType, scope, objectType, parameters, generated);
ObjectConfig.restoreBackupProperties(parameters, ObjectConfig.CONFIG_PROPERTIES_FIELD_NAME);
@SuppressWarnings("unchecked")
Map<String, Object> properties = (Map<String, Object>) parameters.get(EntaxyObject.FIELDS.PROPERTIES);
// properties can be null for 'config-field' output
if (properties != null) {
// enrich paramaters with configured fields placeholders
String placeholderPrefix = parameters.get(ObjectConfig.CONFIG_PLACEHOLDER_PREFIX_FIELD_NAME).toString();
@SuppressWarnings("unchecked")
Map<String, Object> configuredFields =
(Map<String, Object>) parameters.getOrDefault(ObjectConfig.CONFIGURABLES_FIELD_NAME,
Collections.emptyMap());
// configuredFields.putAll(
// (Map<String, Object>) parameters.getOrDefault(ObjectConfig.IMMUTABLES_FIELD_NAME,
// Collections.emptyMap()));
log.debug("CONFIGURED: \n" + configuredFields);
Map<String, Object> placeholdersMap = configuredFields.entrySet().stream()
// .map(entry -> entry.setValue(placeholderPrefix + entry.getKey() + "}"))
.collect(Collectors.toMap(Map.Entry::getKey, entry -> placeholderPrefix + entry.getKey() + "}"));
log.debug("\n\n\tPLACEHOLDERS: \n" + placeholdersMap);
parameters.putAll(placeholdersMap);
// add headers
String configuredId = parameters.get(ObjectConfig.CONFIG_ID_FIELD_NAME).toString();
String configuredType = parameters.get(ObjectConfig.CONFIG_TYPE_FIELD_NAME).toString();
String configurationPid = ObjectConfig.getConfigurationPid(configuredId, configuredType);
GeneratedHeaders headers = GeneratedHeaders.getHeaders(generated.getProperties());
headers.set(ObjectConfig.HEADER_OBJECT_CONFIG_PID,
configuredId + ":" + configuredType + ":" + configurationPid);
}
}
protected void fillConfigMaps(EntaxyFactory factory, String outputType, String scope, String objectType,
Map<String, Object> parameters, Map<String, Object> configurables, Map<String, Object> immutables) {
@SuppressWarnings("unchecked")
Map<String, Object> properties =
(Map<String, Object>) parameters.get(ObjectConfig.CONFIG_PROPERTIES_FIELD_NAME);
for (Entry<String, Object> entry : properties.entrySet()) {
Map<String, Object> targetMap =
ObjectConfig.getTargetConfigMap(factory, outputType, entry.getKey(), configurables, immutables);
if (targetMap == null) {
continue;
}
targetMap.put(entry.getKey(), entry.getValue());
}
}
// enrich paramaters with configured fields placeholders
String placeholderPrefix = parameters.get(ObjectConfig.CONFIG_PLACEHOLDER_PREFIX_FIELD_NAME).toString();
@SuppressWarnings("unchecked")
Map<String, Object> configuredFields =
(Map<String, Object>)parameters.getOrDefault(ObjectConfig.CONFIGURABLES_FIELD_NAME
, Collections.emptyMap());
configuredFields.putAll(
(Map<String, Object>)parameters.getOrDefault(ObjectConfig.IMMUTABLES_FIELD_NAME
, Collections.emptyMap())
);
log.debug("CONFIGURED: \n" + configuredFields);
Map<String, Object> placeholdersMap = configuredFields.entrySet().stream()
//.map(entry -> entry.setValue(placeholderPrefix + entry.getKey() + "}"))
.collect(Collectors.toMap(Map.Entry::getKey, entry -> placeholderPrefix + entry.getKey() + "}"));
log.debug("\n\n\tPLACEHOLDERS: \n" + placeholdersMap);
parameters.putAll(placeholdersMap);
// add headers
String configuredId = parameters.get(ObjectConfig.CONFIG_ID_FIELD_NAME).toString();
String configuredType = parameters.get(ObjectConfig.CONFIG_TYPE_FIELD_NAME).toString();
String configurationPid = ObjectConfig.getConfigurationPid(configuredId, configuredType);
GeneratedHeaders headers = GeneratedHeaders.getHeaders(generated.getProperties());
headers.set(ObjectConfig.HEADER_OBJECT_CONFIG_PID, configuredId + ":" + configuredType + ":" + configurationPid);
}
}
protected void fillConfigMaps(EntaxyFactory factory, String outputType, String scope, String objectType,
Map<String, Object> parameters, Map<String, Object> configurables, Map<String, Object> immutables) {
@SuppressWarnings("unchecked")
Map<String, Object> properties = (Map<String, Object>)parameters.get(ObjectConfig.CONFIG_PROPERTIES_FIELD_NAME);
for (Entry<String, Object> entry: properties.entrySet()) {
Map<String, Object> targetMap = ObjectConfig.getTargetConfigMap(factory, outputType, entry.getKey(), configurables, immutables);
if (targetMap == null) {
continue;
}
targetMap.put(entry.getKey(), entry.getValue());
}
}
}

View File

@ -1,359 +0,0 @@
/*-
* ~~~~~~licensing~~~~~~
* object-producing-config-support
* ==========
* Copyright (C) 2020 - 2023 EmDev LLC
* ==========
* You may not use this file except in accordance with the License Terms of the Copyright
* Holder located at: https://entaxy.ru/eula . All copyrights, all intellectual property
* rights to the Software and any copies are the property of the Copyright Holder. Unless
* it is explicitly allowed the Copyright Holder, the User is prohibited from using the
* Software for commercial purposes to provide services to third parties.
*
* The Copyright Holder hereby declares that the Software is provided on an "AS IS".
* Under no circumstances does the Copyright Holder guarantee or promise that the
* Software provided by him will be suitable or not suitable for the specific purposes
* of the User, that the Software will meet all commercial and personal subjective
* expectations of the User, that the Software will work properly, without technical
* errors, quickly and uninterruptedly.
*
* Under no circumstances shall the Copyright Holder or its Affiliates is not liable
* to the User for any direct or indirect losses of the User, his expenses or actual
* damage, including, downtime; loss of bussines; lost profit; lost earnings; loss
* or damage to data, property, etc.
* ~~~~~~/licensing~~~~~~
*/
package ru.entaxy.platform.core.producer.config;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.regex.Pattern;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import ru.entaxy.platform.base.objects.EntaxyObject;
import ru.entaxy.platform.base.objects.factory.EntaxyFactory;
import ru.entaxy.platform.base.objects.factory.EntaxyFactory.FieldInfo;
import ru.entaxy.platform.base.objects.factory.EntaxyFactory.OutputInfo;
import ru.entaxy.platform.core.producer.api.EntaxyProducerUtils;
import ru.entaxy.platform.core.producer.api.EntaxyWrappedFactory;
public class ObjectConfig {
private static final Logger log = LoggerFactory.getLogger(ObjectConfig.class);
public static final String CONFIG_OBJECT_TYPE = "entaxy.runtime.config";
public static final String TARGET_FACTORY_FIELD_NAME = "targetObjectFactoryId";
public static final String TARGET_TYPE_FIELD_NAME = "targetObjectType";
public static final String TARGET_ID_FIELD_NAME = "targetObjectId";
public static final String TARGET_OUTPUT_FIELD_NAME = "targetObjectOutput";
public static final String CONFIG_PROPERTIES_FIELD_NAME = "configuredProperties";
public static final String CONFIG_FACTORY_FIELD_NAME = "configuredFactoryId";
public static final String CONFIG_TYPE_FIELD_NAME = "configuredType";
public static final String CONFIG_ID_FIELD_NAME = "configured";
public static final String CONFIG_OUTPUT_FIELD_NAME = "configuredOutput";
public static final String CONFIG_PID_FIELD_NAME = "configurationPid";
public static final String CONFIG_PLACEHOLDER_PREFIX_FIELD_NAME = "placeholderPrefix";
public static final String CONFIG_FIELD_NAME = "##config";
public static final String CONFIGURABLE_ATTRIBUTE_NAME = "configurable";
public static final String DEFAULT_FIELDS_CONFIGURABLE_ATTRIBUTE_NAME = "fieldsConfigurableByDefault";
public static final String CONFIGURABLE_FIELDS_ATTRIBUTE_NAME = "configurableFields";
public static final String PROPERTIES_BACKUP_FIELD = EntaxyObject.FIELDS.PROPERTIES + "_backup";
public static final String DIRECT_VALUE_ONLY_ATTR_NAME = "directValueOnly";
public static final String CONFIGURABLES_FIELD_NAME = "configurables";
public static final String IMMUTABLES_FIELD_NAME = "immutables";
public static final String HEADER_OBJECT_CONFIG_PID = "Entaxy-Generated-Object-Config-Pid";
protected static Gson GSON = new GsonBuilder().create();
public static String getConfigurationPid(String objectId, String type) {
return reduceType(type) + "." + objectId.replace("-", "_");
}
public static String reduceType(String type) {
return type.replace(EntaxyObject.OBJECT_TYPES.ENTAXY_RUNTIME_TYPE_PREFIX, "e_r_").replace("-", "_");
}
public static String getConfigurationPrefix(String objectId, String type) {
return "$" + getConfigurationPid(objectId, type) + "{";
}
public static boolean isConfigurable(EntaxyFactory factory, String outputType, String fieldName
, boolean defaultFieldsConfigurable, List<ConfigurableFieldsConfiguration> configurations) {
Optional<FieldInfo> fi = factory.getOutputByType(outputType).getFields().stream().filter(f -> f.getName().equals(fieldName)).findFirst();
if (!fi.isPresent())
return false;
boolean fieldIsConfigurable = defaultFieldsConfigurable;
try {
fieldIsConfigurable = fi.get().getJsonOrigin().get(CONFIGURABLE_ATTRIBUTE_NAME).getAsBoolean();
} catch (Exception e) {
// usinf default value
}
if (!fieldIsConfigurable)
return false;
for (ConfigurableFieldsConfiguration cfc: configurations)
if (cfc.isConfigurable(factory, outputType, fieldName))
return true;
return false;
}
public static void backupProperties(Map<String, Object> parameters) {
backupProperties(parameters, EntaxyObject.FIELDS.PROPERTIES);
}
@SuppressWarnings("unchecked")
public static void backupProperties(Map<String, Object> parameters, String fieldName) {
if (!parameters.containsKey(fieldName))
return;
Map<String, Object> backup = new HashMap<>();
backup.putAll((Map<String, Object>)parameters.get(fieldName));
parameters.put(ObjectConfig.PROPERTIES_BACKUP_FIELD, backup);
}
public static void restoreBackupProperties(Map<String, Object> parameters) {
restoreBackupProperties(parameters, EntaxyObject.FIELDS.PROPERTIES);
}
public static void restoreBackupProperties(Map<String, Object> parameters, String fieldName) {
if (!parameters.containsKey(ObjectConfig.PROPERTIES_BACKUP_FIELD))
return;
parameters.put(fieldName, parameters.get(ObjectConfig.PROPERTIES_BACKUP_FIELD));
}
public static void removeConfigData(Map<String, Object> parameters) {
removeConfigData(parameters, EntaxyObject.FIELDS.PROPERTIES);
}
@SuppressWarnings("unchecked")
public static void removeConfigData(Map<String, Object> parameters, String fieldName) {
if (!parameters.containsKey(fieldName))
return;
((Map<String, Object>)parameters.get(fieldName)).remove(CONFIG_FIELD_NAME);
}
public static Map<String, Object> getTargetConfigMap(EntaxyFactory factory, String outputType, String fieldName
, Map<String, Object> configurables, Map<String, Object> immutables){
/*
Optional<FieldInfo> fi = factory.getOutputByType(outputType).getFields().stream().filter(f -> f.getName().equals(fieldName)).findFirst();
if (!fi.isPresent()) {
log.debug("FIELD NOT FOUND: " + fieldName);
return null;
}
FieldInfo field = fi.get();
boolean isConfigurable = true;
log.debug("\n FIELDNAME:: " + fieldName + " -> " + field.getJsonOrigin());
if (field.getJsonOrigin().has(CONFIGURABLE_ATTRIBUTE_NAME))
try {
isConfigurable = field.getJsonOrigin().get(CONFIGURABLE_ATTRIBUTE_NAME).getAsBoolean();
} catch (Exception e) {
isConfigurable = true;
}
if (!isConfigurable) {
log.debug("FIELD NOT CONFIGURABLE: " + fieldName);
return null;
}
*/
Optional<FieldInfo> fi = factory.getOutputByType(outputType).getFields().stream().filter(f -> f.getName().equals(fieldName)).findFirst();
if (!fi.isPresent()) {
log.debug("FIELD NOT FOUND: " + fieldName);
return null;
}
FactoryOutputConfiguration conf = FactoryOutputConfiguration.read(factory, outputType);
if (!isConfigurable(factory, outputType, fieldName, conf.defaultFieldsConfigurable, conf.configurations))
return null;
FieldInfo field = fi.get();
if (field.isImmutable())
return immutables;
return configurables;
}
public static class FactoryOutputConfiguration {
public static FactoryOutputConfiguration read(EntaxyFactory factory, String outputType) {
FactoryOutputConfiguration result = new FactoryOutputConfiguration();
OutputInfo oi = factory.getOutputByType(outputType);
if (oi == null)
oi = factory.getDefaultOutput();
Map<String, Object> outputConfig = oi.getConfig();
result.isConfigurable = false;
try {
result.isConfigurable = (Boolean)outputConfig.get(ObjectConfig.CONFIGURABLE_ATTRIBUTE_NAME);
} catch (Exception e) {
log.trace("Parameter [{}] not found in [{}]:[{}]"
, ObjectConfig.CONFIGURABLE_ATTRIBUTE_NAME
, factory.getId()
, outputType);
}
if (!result.isConfigurable)
return result;
result.defaultFieldsConfigurable = false;
try {
result.defaultFieldsConfigurable = (Boolean)outputConfig.get(ObjectConfig.DEFAULT_FIELDS_CONFIGURABLE_ATTRIBUTE_NAME);
} catch (Exception e) {
log.trace("Parameter [{}] not found in [{}]:[{}]"
, ObjectConfig.DEFAULT_FIELDS_CONFIGURABLE_ATTRIBUTE_NAME
, factory.getId()
, outputType);
}
result.configurations = new ArrayList<>();
Object configuration = outputConfig.get(ObjectConfig.CONFIGURABLE_FIELDS_ATTRIBUTE_NAME);
if (configuration != null) {
if (configuration instanceof List) {
List configList = (List)configuration;
for (Object configItem: configList) {
if (configItem instanceof Map) {
ObjectConfig.ConfigurableFieldsConfiguration cnf =
ObjectConfig.ConfigurableFieldsConfiguration.read((Map)configItem);
result.configurations.add(cnf);
}
}
} else
if (configuration instanceof Map) {
ObjectConfig.ConfigurableFieldsConfiguration cnf =
ObjectConfig.ConfigurableFieldsConfiguration.read((Map)configuration);
result.configurations.add(cnf);
}
} else {
result.configurations.add(new ObjectConfig.ConfigurableFieldsConfiguration());
}
return result;
}
boolean isConfigurable;
boolean defaultFieldsConfigurable;
List<ConfigurableFieldsConfiguration> configurations;
}
public static class ConfigurableFieldsConfiguration {
public static ConfigurableFieldsConfiguration read(Map parameters) {
JsonElement obj = GSON.toJsonTree(parameters);
if (obj.isJsonObject()) {
ConfigurableFieldsConfiguration result = GSON.fromJson(obj, ConfigurableFieldsConfiguration.class);
return result;
}
return null;
}
List<String> includeNames = new ArrayList<>();
List<String> includePatterns = new ArrayList<>();
List<String> excludeNames = new ArrayList<>();
List<String> excludePatterns = new ArrayList<>();
List<String> includeTypes = new ArrayList<>();
List<String> excludeTypes = new ArrayList<>();
public ConfigurableFieldsConfiguration() {
includeTypes.add("string");
includeTypes.add("boolean");
includeTypes.add("number");
includePatterns.add("*");
}
public boolean isConfigurable(EntaxyFactory factory, String outputType, String fieldName) {
Optional<FieldInfo> fi = factory.getOutputByType(outputType).getFields().stream().filter(f -> f.getName().equals(fieldName)).findFirst();
if (!fi.isPresent())
return false;
String fieldType = fi.get().getType().toLowerCase();
boolean fieldIsExcluded = false;
for (String name: excludeNames)
if (fieldName.equals(name)) {
fieldIsExcluded = true;
break;
}
if (!fieldIsExcluded) {
for (String pattern: excludePatterns) {
if (Pattern.matches(EntaxyProducerUtils.toRegexPattern(pattern), fieldName)) {
fieldIsExcluded = true;
break;
}
}
}
if (!fieldIsExcluded) {
for (String type: excludeTypes)
if (type.equals(fieldType)) {
fieldIsExcluded = true;
break;
}
}
if (fieldIsExcluded)
return false;
boolean fieldIsIncluded = false;
// first we check types
if (!fieldIsIncluded) {
for (String type: includeTypes)
if (type.equals(fieldType)) {
fieldIsIncluded = true;
break;
}
}
if (!fieldIsIncluded)
return false;
if (!includeNames.isEmpty() || !includePatterns.isEmpty())
fieldIsIncluded = false;
for (String name: includeNames)
if (fieldName.equals(name)) {
fieldIsIncluded = true;
break;
}
if (!fieldIsIncluded) {
for (String pattern: includePatterns) {
if (Pattern.matches(EntaxyProducerUtils.toRegexPattern(pattern), fieldName)) {
fieldIsIncluded = true;
break;
}
}
}
return fieldIsIncluded;
}
}
}

Some files were not shown because too many files have changed in this diff Show More